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 #pragma ident "%Z%%M% %I% %E% SMI"
32
33 #include <stdio.h>
34 #include <fcntl.h>
35 #include <time.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include <stropts.h>
40 #include <sys/strlog.h>
41
42 #define CTLSIZE sizeof (struct log_ctl)
43 #define DATSIZE 8192
44 #define LOGDEV "/dev/log"
45 #define MAXTID 50
46
47 static int errflg = 0; /* set if error in argument parsing */
48 static int infile = 0; /* set if using standard input for arguments */
49 static int log;
50
51 static void prlog(FILE *log, struct log_ctl *lp, char *dp);
52 static int getid(int ac, char **av, struct trace_ids *tp);
53 static int convarg(char *ap);
54 static char *getarg(void);
55
56 #define numeric(c) ((c <= '9') && (c >= '0'))
57
58 static int
convarg(char * ap)59 convarg(char *ap)
60 {
61 short ids[2];
62
63 if (!ap)
64 return (-2);
65 if (numeric(*ap))
66 return (atoi(ap));
67 if (strcmp(ap, "all") == 0)
68 return (-1);
69 errflg = 1;
70 return (-2);
71 }
72
73 static char *
getarg(void)74 getarg(void)
75 {
76 static char argbuf[40];
77 static int eofflg = 0;
78 char *ap;
79 int c;
80
81 if (eofflg) {
82 infile = 0;
83 return (NULL);
84 }
85
86 ap = argbuf;
87
88 /*
89 * Scan to first significant character in standard input.
90 * If EOF is encountered turn off standard input scanning and
91 * return NULL
92 */
93 while ((c = getchar()) == ' ' || c == '\n' || c == '\t')
94 ;
95 if (c == EOF) {
96 infile = 0;
97 eofflg++;
98 return (NULL);
99 }
100 /*
101 * collect token until whitespace is encountered. Don't do anything
102 * with EOF here as it will be caught the next time around.
103 */
104 while (1) {
105 *ap++ = c;
106 if ((c = getchar()) == ' ' || c == '\n' ||
107 c == '\t' || c == EOF) {
108 if (c == EOF) eofflg++;
109 *ap = '\0';
110 return (argbuf);
111 }
112 }
113 }
114
115
116 static int
getid(int ac,char ** av,struct trace_ids * tp)117 getid(int ac, char **av, struct trace_ids *tp)
118 {
119 static int index = 1;
120
121 /*
122 * if inside of standard input scan take arguments from there.
123 */
124 retry:
125 if (infile) {
126 tp->ti_mid = convarg(getarg());
127 tp->ti_sid = convarg(getarg());
128 tp->ti_level = convarg(getarg());
129 if (errflg)
130 return (0);
131 /*
132 * if the previous operations encountered EOF, infile
133 * will be set to zero. The trace_ids structure must
134 * then be loaded from the command line arguments.
135 * Otherwise, the structure is now valid and should
136 * be returned.
137 */
138 if (infile)
139 return (1);
140 }
141 /*
142 * if we get here we are either taking arguments from the
143 * command line argument list or we hit end of file on standard
144 * input and should return to finish off the command line arguments
145 */
146 if (index >= ac)
147 return (0);
148
149 /*
150 * if a '-' is present, start parsing from standard input
151 */
152 if (strcmp(av[index], "-") == 0) {
153 infile = 1;
154 index++;
155 goto retry;
156 }
157
158 /*
159 * Parsing from command line, make sure there are
160 * at least 3 arguments remaining.
161 */
162 if ((index+2) >= ac)
163 return (0);
164
165 tp->ti_mid = convarg(av[index++]);
166 tp->ti_sid = convarg(av[index++]);
167 tp->ti_level = convarg(av[index++]);
168
169 if (errflg)
170 return (0);
171 return (1);
172 }
173
174 int
main(int ac,char * av[])175 main(int ac, char *av[])
176 {
177 int n;
178 char cbuf[CTLSIZE];
179 char dbuf[DATSIZE];
180 struct strioctl istr;
181 struct strbuf ctl, dat;
182 struct log_ctl *lp = (struct log_ctl *)cbuf;
183 struct trace_ids tid[MAXTID];
184 struct trace_ids *tp;
185 int ntid;
186 int val;
187 int flag;
188
189 ctl.buf = cbuf;
190 ctl.maxlen = CTLSIZE;
191 dat.buf = dbuf;
192 dat.len = dat.maxlen = DATSIZE;
193
194 log = open(LOGDEV, O_RDWR);
195 if (log < 0) {
196 fprintf(stderr, "ERROR: unable to open %s\n", LOGDEV);
197 return (1);
198 }
199
200 tp = tid;
201 ntid = 0;
202
203 if (ac == 1) {
204 ntid++;
205 tid[0].ti_mid = -1;
206 tid[0].ti_sid = -1;
207 tid[0].ti_level = -1;
208 } else {
209 while (getid(ac, av, tp)) {
210 ntid++;
211 tp++;
212 }
213 }
214
215 if (errflg)
216 return (errflg);
217
218 istr.ic_cmd = I_TRCLOG;
219 istr.ic_dp = (char *)tid;
220 istr.ic_len = ntid * sizeof (struct trace_ids);
221 istr.ic_timout = 0;
222 if (ioctl(log, I_STR, &istr) < 0) {
223 fprintf(stderr, "ERROR: tracer already exists\n");
224 return (1);
225 }
226
227 setbuf(stdout, (char *)NULL);
228 flag = 0;
229 while (getmsg(log, &ctl, &dat, &flag) >= 0) {
230 flag = 0;
231 lp = (struct log_ctl *)cbuf;
232 prlog(stdout, lp, dbuf);
233 }
234
235 return (0);
236 }
237
238 static void
prlog(FILE * log,struct log_ctl * lp,char * dp)239 prlog(FILE *log, struct log_ctl *lp, char *dp)
240 {
241 char *ts;
242 int *args;
243 char *ap;
244 time_t t = (time_t)lp->ttime;
245
246 ts = ctime(&t);
247 ts[19] = '\0';
248 fprintf(log, "%06d %s %08x %2d %s%s%s %d %d %s\n",
249 lp->seq_no, (ts+11), lp->ltime, lp->level,
250 ((lp->flags & SL_FATAL) ? "F" : "."),
251 ((lp->flags & SL_NOTIFY) ? "N" : "."),
252 ((lp->flags & SL_ERROR) ? "E" : "."),
253 lp->mid, lp->sid, dp);
254 }
255