1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #include <stdio.h> 32 #include <fcntl.h> 33 #include <time.h> 34 #include <stdlib.h> 35 #include <string.h> 36 #include <unistd.h> 37 #include <stropts.h> 38 #include <sys/strlog.h> 39 40 #define CTLSIZE sizeof (struct log_ctl) 41 #define DATSIZE 8192 42 #define LOGDEV "/dev/log" 43 #define MAXTID 50 44 45 static int errflg = 0; /* set if error in argument parsing */ 46 static int infile = 0; /* set if using standard input for arguments */ 47 static int log; 48 49 static void prlog(FILE *log, struct log_ctl *lp, char *dp); 50 static int getid(int ac, char **av, struct trace_ids *tp); 51 static int convarg(char *ap); 52 static char *getarg(void); 53 54 #define numeric(c) ((c <= '9') && (c >= '0')) 55 56 static int 57 convarg(char *ap) 58 { 59 short ids[2]; 60 61 if (!ap) 62 return (-2); 63 if (numeric(*ap)) 64 return (atoi(ap)); 65 if (strcmp(ap, "all") == 0) 66 return (-1); 67 errflg = 1; 68 return (-2); 69 } 70 71 static char * 72 getarg(void) 73 { 74 static char argbuf[40]; 75 static int eofflg = 0; 76 char *ap; 77 int c; 78 79 if (eofflg) { 80 infile = 0; 81 return (NULL); 82 } 83 84 ap = argbuf; 85 86 /* 87 * Scan to first significant character in standard input. 88 * If EOF is encountered turn off standard input scanning and 89 * return NULL 90 */ 91 while ((c = getchar()) == ' ' || c == '\n' || c == '\t') 92 ; 93 if (c == EOF) { 94 infile = 0; 95 eofflg++; 96 return (NULL); 97 } 98 /* 99 * collect token until whitespace is encountered. Don't do anything 100 * with EOF here as it will be caught the next time around. 101 */ 102 while (1) { 103 *ap++ = c; 104 if ((c = getchar()) == ' ' || c == '\n' || 105 c == '\t' || c == EOF) { 106 if (c == EOF) eofflg++; 107 *ap = '\0'; 108 return (argbuf); 109 } 110 } 111 } 112 113 114 static int 115 getid(int ac, char **av, struct trace_ids *tp) 116 { 117 static int index = 1; 118 119 /* 120 * if inside of standard input scan take arguments from there. 121 */ 122 retry: 123 if (infile) { 124 tp->ti_mid = convarg(getarg()); 125 tp->ti_sid = convarg(getarg()); 126 tp->ti_level = convarg(getarg()); 127 if (errflg) 128 return (0); 129 /* 130 * if the previous operations encountered EOF, infile 131 * will be set to zero. The trace_ids structure must 132 * then be loaded from the command line arguments. 133 * Otherwise, the structure is now valid and should 134 * be returned. 135 */ 136 if (infile) 137 return (1); 138 } 139 /* 140 * if we get here we are either taking arguments from the 141 * command line argument list or we hit end of file on standard 142 * input and should return to finish off the command line arguments 143 */ 144 if (index >= ac) 145 return (0); 146 147 /* 148 * if a '-' is present, start parsing from standard input 149 */ 150 if (strcmp(av[index], "-") == 0) { 151 infile = 1; 152 index++; 153 goto retry; 154 } 155 156 /* 157 * Parsing from command line, make sure there are 158 * at least 3 arguments remaining. 159 */ 160 if ((index+2) >= ac) 161 return (0); 162 163 tp->ti_mid = convarg(av[index++]); 164 tp->ti_sid = convarg(av[index++]); 165 tp->ti_level = convarg(av[index++]); 166 167 if (errflg) 168 return (0); 169 return (1); 170 } 171 172 int 173 main(int ac, char *av[]) 174 { 175 int n; 176 char cbuf[CTLSIZE]; 177 char dbuf[DATSIZE]; 178 struct strioctl istr; 179 struct strbuf ctl, dat; 180 struct log_ctl *lp = (struct log_ctl *)cbuf; 181 struct trace_ids tid[MAXTID]; 182 struct trace_ids *tp; 183 int ntid; 184 int val; 185 int flag; 186 187 ctl.buf = cbuf; 188 ctl.maxlen = CTLSIZE; 189 dat.buf = dbuf; 190 dat.len = dat.maxlen = DATSIZE; 191 192 log = open(LOGDEV, O_RDWR); 193 if (log < 0) { 194 fprintf(stderr, "ERROR: unable to open %s\n", LOGDEV); 195 return (1); 196 } 197 198 tp = tid; 199 ntid = 0; 200 201 if (ac == 1) { 202 ntid++; 203 tid[0].ti_mid = -1; 204 tid[0].ti_sid = -1; 205 tid[0].ti_level = -1; 206 } else { 207 while (getid(ac, av, tp)) { 208 ntid++; 209 tp++; 210 } 211 } 212 213 if (errflg) 214 return (errflg); 215 216 istr.ic_cmd = I_TRCLOG; 217 istr.ic_dp = (char *)tid; 218 istr.ic_len = ntid * sizeof (struct trace_ids); 219 istr.ic_timout = 0; 220 if (ioctl(log, I_STR, &istr) < 0) { 221 fprintf(stderr, "ERROR: tracer already exists\n"); 222 return (1); 223 } 224 225 setbuf(stdout, (char *)NULL); 226 flag = 0; 227 while (getmsg(log, &ctl, &dat, &flag) >= 0) { 228 flag = 0; 229 lp = (struct log_ctl *)cbuf; 230 prlog(stdout, lp, dbuf); 231 } 232 233 return (0); 234 } 235 236 static void 237 prlog(FILE *log, struct log_ctl *lp, char *dp) 238 { 239 char *ts; 240 int *args; 241 char *ap; 242 time_t t = (time_t)lp->ttime; 243 244 ts = ctime(&t); 245 ts[19] = '\0'; 246 fprintf(log, "%06d %s %08x %2d %s%s%s %d %d %s\n", 247 lp->seq_no, (ts+11), lp->ltime, lp->level, 248 ((lp->flags & SL_FATAL) ? "F" : "."), 249 ((lp->flags & SL_NOTIFY) ? "N" : "."), 250 ((lp->flags & SL_ERROR) ? "E" : "."), 251 lp->mid, lp->sid, dp); 252 } 253