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
convarg(char * ap)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 *
getarg(void)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
getid(int ac,char ** av,struct trace_ids * tp)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
main(int ac,char * av[])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
prlog(FILE * log,struct log_ctl * lp,char * dp)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