xref: /illumos-gate/usr/src/cmd/streams/log/strace.c (revision 3d393ee6c37fa10ac512ed6d36109ad616dc7c1a)
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
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 *
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
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
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
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