subr_prf.c revision 1.1.1.2 1 1.1.1.2 fvdl /*-
2 1.1.1.2 fvdl * Copyright (c) 1986, 1988, 1991, 1993
3 1.1.1.2 fvdl * The Regents of the University of California. All rights reserved.
4 1.1.1.2 fvdl * (c) UNIX System Laboratories, Inc.
5 1.1.1.2 fvdl * All or some portions of this file are derived from material licensed
6 1.1.1.2 fvdl * to the University of California by American Telephone and Telegraph
7 1.1.1.2 fvdl * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 1.1.1.2 fvdl * the permission of UNIX System Laboratories, Inc.
9 1.1.1.2 fvdl *
10 1.1.1.2 fvdl * Redistribution and use in source and binary forms, with or without
11 1.1.1.2 fvdl * modification, are permitted provided that the following conditions
12 1.1.1.2 fvdl * are met:
13 1.1.1.2 fvdl * 1. Redistributions of source code must retain the above copyright
14 1.1.1.2 fvdl * notice, this list of conditions and the following disclaimer.
15 1.1.1.2 fvdl * 2. Redistributions in binary form must reproduce the above copyright
16 1.1.1.2 fvdl * notice, this list of conditions and the following disclaimer in the
17 1.1.1.2 fvdl * documentation and/or other materials provided with the distribution.
18 1.1.1.2 fvdl * 3. All advertising materials mentioning features or use of this software
19 1.1.1.2 fvdl * must display the following acknowledgement:
20 1.1.1.2 fvdl * This product includes software developed by the University of
21 1.1.1.2 fvdl * California, Berkeley and its contributors.
22 1.1.1.2 fvdl * 4. Neither the name of the University nor the names of its contributors
23 1.1.1.2 fvdl * may be used to endorse or promote products derived from this software
24 1.1.1.2 fvdl * without specific prior written permission.
25 1.1.1.2 fvdl *
26 1.1.1.2 fvdl * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 1.1.1.2 fvdl * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 1.1.1.2 fvdl * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 1.1.1.2 fvdl * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 1.1.1.2 fvdl * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 1.1.1.2 fvdl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 1.1.1.2 fvdl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 1.1.1.2 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 1.1.1.2 fvdl * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 1.1.1.2 fvdl * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 1.1.1.2 fvdl * SUCH DAMAGE.
37 1.1.1.2 fvdl *
38 1.1.1.2 fvdl * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94
39 1.1.1.2 fvdl */
40 1.1.1.2 fvdl
41 1.1.1.2 fvdl #include <sys/param.h>
42 1.1.1.2 fvdl #include <sys/systm.h>
43 1.1.1.2 fvdl #include <sys/buf.h>
44 1.1.1.2 fvdl #include <sys/conf.h>
45 1.1.1.2 fvdl #include <sys/reboot.h>
46 1.1.1.2 fvdl #include <sys/msgbuf.h>
47 1.1.1.2 fvdl #include <sys/proc.h>
48 1.1.1.2 fvdl #include <sys/ioctl.h>
49 1.1.1.2 fvdl #include <sys/vnode.h>
50 1.1.1.2 fvdl #include <sys/file.h>
51 1.1.1.2 fvdl #include <sys/tty.h>
52 1.1.1.2 fvdl #include <sys/tprintf.h>
53 1.1.1.2 fvdl #include <sys/syslog.h>
54 1.1.1.2 fvdl #include <sys/malloc.h>
55 1.1.1.2 fvdl
56 1.1.1.2 fvdl /*
57 1.1.1.2 fvdl * Note that stdarg.h and the ANSI style va_start macro is used for both
58 1.1.1.2 fvdl * ANSI and traditional C compilers.
59 1.1.1.2 fvdl */
60 1.1.1.2 fvdl #include <machine/stdarg.h>
61 1.1.1.2 fvdl
62 1.1.1.2 fvdl #ifdef KADB
63 1.1.1.2 fvdl #include <machine/kdbparam.h>
64 1.1.1.2 fvdl #endif
65 1.1.1.2 fvdl
66 1.1.1.2 fvdl #define TOCONS 0x01
67 1.1.1.2 fvdl #define TOTTY 0x02
68 1.1.1.2 fvdl #define TOLOG 0x04
69 1.1.1.2 fvdl
70 1.1.1.2 fvdl struct tty *constty; /* pointer to console "window" tty */
71 1.1.1.2 fvdl
72 1.1.1.2 fvdl extern cnputc(); /* standard console putc */
73 1.1.1.2 fvdl int (*v_putc)() = cnputc; /* routine to putc on virtual console */
74 1.1.1.2 fvdl
75 1.1.1.2 fvdl void logpri __P((int level));
76 1.1.1.2 fvdl static void putchar __P((int ch, int flags, struct tty *tp));
77 1.1.1.2 fvdl static char *ksprintn __P((u_long num, int base, int *len));
78 1.1.1.2 fvdl void kprintf __P((const char *fmt, int flags, struct tty *tp, va_list ap));
79 1.1.1.2 fvdl
80 1.1.1.2 fvdl int consintr = 1; /* Ok to handle console interrupts? */
81 1.1.1.2 fvdl
82 1.1.1.2 fvdl /*
83 1.1.1.2 fvdl * Variable panicstr contains argument to first call to panic; used as flag
84 1.1.1.2 fvdl * to indicate that the kernel has already called panic.
85 1.1.1.2 fvdl */
86 1.1.1.2 fvdl const char *panicstr;
87 1.1.1.2 fvdl
88 1.1.1.2 fvdl /*
89 1.1.1.2 fvdl * Panic is called on unresolvable fatal errors. It prints "panic: mesg",
90 1.1.1.2 fvdl * and then reboots. If we are called twice, then we avoid trying to sync
91 1.1.1.2 fvdl * the disks as this often leads to recursive panics.
92 1.1.1.2 fvdl */
93 1.1.1.2 fvdl #ifdef __GNUC__
94 1.1.1.2 fvdl volatile void boot(int flags); /* boot() does not return */
95 1.1.1.2 fvdl volatile /* panic() does not return */
96 1.1.1.2 fvdl #endif
97 1.1.1.2 fvdl void
98 1.1.1.2 fvdl #ifdef __STDC__
99 1.1.1.2 fvdl panic(const char *fmt, ...)
100 1.1.1.2 fvdl #else
101 1.1.1.2 fvdl panic(fmt, va_alist)
102 1.1.1.2 fvdl char *fmt;
103 1.1.1.2 fvdl #endif
104 1.1.1.2 fvdl {
105 1.1.1.2 fvdl int bootopt;
106 1.1.1.2 fvdl va_list ap;
107 1.1.1.2 fvdl
108 1.1.1.2 fvdl bootopt = RB_AUTOBOOT | RB_DUMP;
109 1.1.1.2 fvdl if (panicstr)
110 1.1.1.2 fvdl bootopt |= RB_NOSYNC;
111 1.1.1.2 fvdl else
112 1.1.1.2 fvdl panicstr = fmt;
113 1.1.1.2 fvdl
114 1.1.1.2 fvdl va_start(ap, fmt);
115 1.1.1.2 fvdl printf("panic: %r\n", fmt, ap);
116 1.1.1.2 fvdl va_end(ap);
117 1.1.1.2 fvdl
118 1.1.1.2 fvdl #ifdef KGDB
119 1.1.1.2 fvdl kgdb_panic();
120 1.1.1.2 fvdl #endif
121 1.1.1.2 fvdl #ifdef KADB
122 1.1.1.2 fvdl if (boothowto & RB_KDB)
123 1.1.1.2 fvdl kdbpanic();
124 1.1.1.2 fvdl #endif
125 1.1.1.2 fvdl boot(bootopt);
126 1.1.1.2 fvdl }
127 1.1.1.2 fvdl
128 1.1.1.2 fvdl /*
129 1.1.1.2 fvdl * Warn that a system table is full.
130 1.1.1.2 fvdl */
131 1.1.1.2 fvdl void
132 1.1.1.2 fvdl tablefull(tab)
133 1.1.1.2 fvdl const char *tab;
134 1.1.1.2 fvdl {
135 1.1.1.2 fvdl
136 1.1.1.2 fvdl log(LOG_ERR, "%s: table is full\n", tab);
137 1.1.1.2 fvdl }
138 1.1.1.2 fvdl
139 1.1.1.2 fvdl /*
140 1.1.1.2 fvdl * Uprintf prints to the controlling terminal for the current process.
141 1.1.1.2 fvdl * It may block if the tty queue is overfull. No message is printed if
142 1.1.1.2 fvdl * the queue does not clear in a reasonable time.
143 1.1.1.2 fvdl */
144 1.1.1.2 fvdl void
145 1.1.1.2 fvdl #ifdef __STDC__
146 1.1.1.2 fvdl uprintf(const char *fmt, ...)
147 1.1.1.2 fvdl #else
148 1.1.1.2 fvdl uprintf(fmt, va_alist)
149 1.1.1.2 fvdl char *fmt;
150 1.1.1.2 fvdl #endif
151 1.1.1.2 fvdl {
152 1.1.1.2 fvdl register struct proc *p = curproc;
153 1.1.1.2 fvdl va_list ap;
154 1.1.1.2 fvdl
155 1.1.1.2 fvdl if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
156 1.1.1.2 fvdl va_start(ap, fmt);
157 1.1.1.2 fvdl kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
158 1.1.1.2 fvdl va_end(ap);
159 1.1.1.2 fvdl }
160 1.1.1.2 fvdl }
161 1.1.1.2 fvdl
162 1.1.1.2 fvdl tpr_t
163 1.1.1.2 fvdl tprintf_open(p)
164 1.1.1.2 fvdl register struct proc *p;
165 1.1.1.2 fvdl {
166 1.1.1.2 fvdl
167 1.1.1.2 fvdl if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
168 1.1.1.2 fvdl SESSHOLD(p->p_session);
169 1.1.1.2 fvdl return ((tpr_t) p->p_session);
170 1.1.1.2 fvdl }
171 1.1.1.2 fvdl return ((tpr_t) NULL);
172 1.1.1.2 fvdl }
173 1.1.1.2 fvdl
174 1.1.1.2 fvdl void
175 1.1.1.2 fvdl tprintf_close(sess)
176 1.1.1.2 fvdl tpr_t sess;
177 1.1.1.2 fvdl {
178 1.1.1.2 fvdl
179 1.1.1.2 fvdl if (sess)
180 1.1.1.2 fvdl SESSRELE((struct session *) sess);
181 1.1.1.2 fvdl }
182 1.1.1.2 fvdl
183 1.1.1.2 fvdl /*
184 1.1.1.2 fvdl * tprintf prints on the controlling terminal associated
185 1.1.1.2 fvdl * with the given session.
186 1.1.1.2 fvdl */
187 1.1.1.2 fvdl void
188 1.1.1.2 fvdl #ifdef __STDC__
189 1.1.1.2 fvdl tprintf(tpr_t tpr, const char *fmt, ...)
190 1.1.1.2 fvdl #else
191 1.1.1.2 fvdl tprintf(tpr, fmt, va_alist)
192 1.1.1.2 fvdl tpr_t tpr;
193 1.1.1.2 fvdl char *fmt;
194 1.1.1.2 fvdl #endif
195 1.1.1.2 fvdl {
196 1.1.1.2 fvdl register struct session *sess = (struct session *)tpr;
197 1.1.1.2 fvdl struct tty *tp = NULL;
198 1.1.1.2 fvdl int flags = TOLOG;
199 1.1.1.2 fvdl va_list ap;
200 1.1.1.2 fvdl
201 1.1.1.2 fvdl logpri(LOG_INFO);
202 1.1.1.2 fvdl if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
203 1.1.1.2 fvdl flags |= TOTTY;
204 1.1.1.2 fvdl tp = sess->s_ttyp;
205 1.1.1.2 fvdl }
206 1.1.1.2 fvdl va_start(ap, fmt);
207 1.1.1.2 fvdl kprintf(fmt, flags, tp, ap);
208 1.1.1.2 fvdl va_end(ap);
209 1.1.1.2 fvdl logwakeup();
210 1.1.1.2 fvdl }
211 1.1.1.2 fvdl
212 1.1.1.2 fvdl /*
213 1.1.1.2 fvdl * Ttyprintf displays a message on a tty; it should be used only by
214 1.1.1.2 fvdl * the tty driver, or anything that knows the underlying tty will not
215 1.1.1.2 fvdl * be revoke(2)'d away. Other callers should use tprintf.
216 1.1.1.2 fvdl */
217 1.1.1.2 fvdl void
218 1.1.1.2 fvdl #ifdef __STDC__
219 1.1.1.2 fvdl ttyprintf(struct tty *tp, const char *fmt, ...)
220 1.1.1.2 fvdl #else
221 1.1.1.2 fvdl ttyprintf(tp, fmt, va_alist)
222 1.1.1.2 fvdl struct tty *tp;
223 1.1.1.2 fvdl char *fmt;
224 1.1.1.2 fvdl #endif
225 1.1.1.2 fvdl {
226 1.1.1.2 fvdl va_list ap;
227 1.1.1.2 fvdl
228 1.1.1.2 fvdl va_start(ap, fmt);
229 1.1.1.2 fvdl kprintf(fmt, TOTTY, tp, ap);
230 1.1.1.2 fvdl va_end(ap);
231 1.1.1.2 fvdl }
232 1.1.1.2 fvdl
233 1.1.1.2 fvdl extern int log_open;
234 1.1.1.2 fvdl
235 1.1.1.2 fvdl /*
236 1.1.1.2 fvdl * Log writes to the log buffer, and guarantees not to sleep (so can be
237 1.1.1.2 fvdl * called by interrupt routines). If there is no process reading the
238 1.1.1.2 fvdl * log yet, it writes to the console also.
239 1.1.1.2 fvdl */
240 1.1.1.2 fvdl void
241 1.1.1.2 fvdl #ifdef __STDC__
242 1.1.1.2 fvdl log(int level, const char *fmt, ...)
243 1.1.1.2 fvdl #else
244 1.1.1.2 fvdl log(level, fmt, va_alist)
245 1.1.1.2 fvdl int level;
246 1.1.1.2 fvdl char *fmt;
247 1.1.1.2 fvdl #endif
248 1.1.1.2 fvdl {
249 1.1.1.2 fvdl register int s;
250 1.1.1.2 fvdl va_list ap;
251 1.1.1.2 fvdl
252 1.1.1.2 fvdl s = splhigh();
253 1.1.1.2 fvdl logpri(level);
254 1.1.1.2 fvdl va_start(ap, fmt);
255 1.1.1.2 fvdl kprintf(fmt, TOLOG, NULL, ap);
256 1.1.1.2 fvdl splx(s);
257 1.1.1.2 fvdl va_end(ap);
258 1.1.1.2 fvdl if (!log_open) {
259 1.1.1.2 fvdl va_start(ap, fmt);
260 1.1.1.2 fvdl kprintf(fmt, TOCONS, NULL, ap);
261 1.1.1.2 fvdl va_end(ap);
262 1.1.1.2 fvdl }
263 1.1.1.2 fvdl logwakeup();
264 1.1.1.2 fvdl }
265 1.1.1.2 fvdl
266 1.1.1.2 fvdl void
267 1.1.1.2 fvdl logpri(level)
268 1.1.1.2 fvdl int level;
269 1.1.1.2 fvdl {
270 1.1.1.2 fvdl register int ch;
271 1.1.1.2 fvdl register char *p;
272 1.1.1.2 fvdl
273 1.1.1.2 fvdl putchar('<', TOLOG, NULL);
274 1.1.1.2 fvdl for (p = ksprintn((u_long)level, 10, NULL); ch = *p--;)
275 1.1.1.2 fvdl putchar(ch, TOLOG, NULL);
276 1.1.1.2 fvdl putchar('>', TOLOG, NULL);
277 1.1.1.2 fvdl }
278 1.1.1.2 fvdl
279 1.1.1.2 fvdl void
280 1.1.1.2 fvdl #ifdef __STDC__
281 1.1.1.2 fvdl addlog(const char *fmt, ...)
282 1.1.1.2 fvdl #else
283 1.1.1.2 fvdl addlog(fmt, va_alist)
284 1.1.1.2 fvdl char *fmt;
285 1.1.1.2 fvdl #endif
286 1.1.1.2 fvdl {
287 1.1.1.2 fvdl register int s;
288 1.1.1.2 fvdl va_list ap;
289 1.1.1.2 fvdl
290 1.1.1.2 fvdl s = splhigh();
291 1.1.1.2 fvdl va_start(ap, fmt);
292 1.1.1.2 fvdl kprintf(fmt, TOLOG, NULL, ap);
293 1.1.1.2 fvdl splx(s);
294 1.1.1.2 fvdl va_end(ap);
295 1.1.1.2 fvdl if (!log_open) {
296 1.1.1.2 fvdl va_start(ap, fmt);
297 1.1.1.2 fvdl kprintf(fmt, TOCONS, NULL, ap);
298 1.1.1.2 fvdl va_end(ap);
299 1.1.1.2 fvdl }
300 1.1.1.2 fvdl logwakeup();
301 1.1.1.2 fvdl }
302 1.1.1.2 fvdl
303 1.1.1.2 fvdl void
304 1.1.1.2 fvdl #ifdef __STDC__
305 1.1.1.2 fvdl printf(const char *fmt, ...)
306 1.1.1.2 fvdl #else
307 1.1.1.2 fvdl printf(fmt, va_alist)
308 1.1.1.2 fvdl char *fmt;
309 1.1.1.2 fvdl #endif
310 1.1.1.2 fvdl {
311 1.1.1.2 fvdl va_list ap;
312 1.1.1.2 fvdl register int savintr;
313 1.1.1.2 fvdl
314 1.1.1.2 fvdl savintr = consintr; /* disable interrupts */
315 1.1.1.2 fvdl consintr = 0;
316 1.1.1.2 fvdl va_start(ap, fmt);
317 1.1.1.2 fvdl kprintf(fmt, TOCONS | TOLOG, NULL, ap);
318 1.1.1.2 fvdl va_end(ap);
319 1.1.1.2 fvdl if (!panicstr)
320 1.1.1.2 fvdl logwakeup();
321 1.1.1.2 fvdl consintr = savintr; /* reenable interrupts */
322 1.1.1.2 fvdl }
323 1.1.1.2 fvdl
324 1.1.1.2 fvdl /*
325 1.1.1.2 fvdl * Scaled down version of printf(3).
326 1.1.1.2 fvdl *
327 1.1.1.2 fvdl * Two additional formats:
328 1.1.1.2 fvdl *
329 1.1.1.2 fvdl * The format %b is supported to decode error registers.
330 1.1.1.2 fvdl * Its usage is:
331 1.1.1.2 fvdl *
332 1.1.1.2 fvdl * printf("reg=%b\n", regval, "<base><arg>*");
333 1.1.1.2 fvdl *
334 1.1.1.2 fvdl * where <base> is the output base expressed as a control character, e.g.
335 1.1.1.2 fvdl * \10 gives octal; \20 gives hex. Each arg is a sequence of characters,
336 1.1.1.2 fvdl * the first of which gives the bit number to be inspected (origin 1), and
337 1.1.1.2 fvdl * the next characters (up to a control character, i.e. a character <= 32),
338 1.1.1.2 fvdl * give the name of the register. Thus:
339 1.1.1.2 fvdl *
340 1.1.1.2 fvdl * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
341 1.1.1.2 fvdl *
342 1.1.1.2 fvdl * would produce output:
343 1.1.1.2 fvdl *
344 1.1.1.2 fvdl * reg=3<BITTWO,BITONE>
345 1.1.1.2 fvdl *
346 1.1.1.2 fvdl * The format %r passes an additional format string and argument list
347 1.1.1.2 fvdl * recursively. Its usage is:
348 1.1.1.2 fvdl *
349 1.1.1.2 fvdl * fn(char *fmt, ...)
350 1.1.1.2 fvdl * {
351 1.1.1.2 fvdl * va_list ap;
352 1.1.1.2 fvdl * va_start(ap, fmt);
353 1.1.1.2 fvdl * printf("prefix: %r: suffix\n", fmt, ap);
354 1.1.1.2 fvdl * va_end(ap);
355 1.1.1.2 fvdl * }
356 1.1.1.2 fvdl *
357 1.1.1.2 fvdl * Space or zero padding and a field width are supported for the numeric
358 1.1.1.2 fvdl * formats only.
359 1.1.1.2 fvdl */
360 1.1.1.2 fvdl void
361 1.1.1.2 fvdl kprintf(fmt, flags, tp, ap)
362 1.1.1.2 fvdl register const char *fmt;
363 1.1.1.2 fvdl int flags;
364 1.1.1.2 fvdl struct tty *tp;
365 1.1.1.2 fvdl va_list ap;
366 1.1.1.2 fvdl {
367 1.1.1.2 fvdl register char *p, *q;
368 1.1.1.2 fvdl register int ch, n;
369 1.1.1.2 fvdl u_long ul;
370 1.1.1.2 fvdl int base, lflag, tmp, width;
371 1.1.1.2 fvdl char padc;
372 1.1.1.2 fvdl
373 1.1.1.2 fvdl for (;;) {
374 1.1.1.2 fvdl padc = ' ';
375 1.1.1.2 fvdl width = 0;
376 1.1.1.2 fvdl while ((ch = *(u_char *)fmt++) != '%') {
377 1.1.1.2 fvdl if (ch == '\0')
378 1.1.1.2 fvdl return;
379 1.1.1.2 fvdl putchar(ch, flags, tp);
380 1.1.1.2 fvdl }
381 1.1.1.2 fvdl lflag = 0;
382 1.1.1.2 fvdl reswitch: switch (ch = *(u_char *)fmt++) {
383 1.1.1.2 fvdl case '0':
384 1.1.1.2 fvdl padc = '0';
385 1.1.1.2 fvdl goto reswitch;
386 1.1.1.2 fvdl case '1': case '2': case '3': case '4':
387 1.1.1.2 fvdl case '5': case '6': case '7': case '8': case '9':
388 1.1.1.2 fvdl for (width = 0;; ++fmt) {
389 1.1.1.2 fvdl width = width * 10 + ch - '0';
390 1.1.1.2 fvdl ch = *fmt;
391 1.1.1.2 fvdl if (ch < '0' || ch > '9')
392 1.1.1.2 fvdl break;
393 1.1.1.2 fvdl }
394 1.1.1.2 fvdl goto reswitch;
395 1.1.1.2 fvdl case 'l':
396 1.1.1.2 fvdl lflag = 1;
397 1.1.1.2 fvdl goto reswitch;
398 1.1.1.2 fvdl case 'b':
399 1.1.1.2 fvdl ul = va_arg(ap, int);
400 1.1.1.2 fvdl p = va_arg(ap, char *);
401 1.1.1.2 fvdl for (q = ksprintn(ul, *p++, NULL); ch = *q--;)
402 1.1.1.2 fvdl putchar(ch, flags, tp);
403 1.1.1.2 fvdl
404 1.1.1.2 fvdl if (!ul)
405 1.1.1.2 fvdl break;
406 1.1.1.2 fvdl
407 1.1.1.2 fvdl for (tmp = 0; n = *p++;) {
408 1.1.1.2 fvdl if (ul & (1 << (n - 1))) {
409 1.1.1.2 fvdl putchar(tmp ? ',' : '<', flags, tp);
410 1.1.1.2 fvdl for (; (n = *p) > ' '; ++p)
411 1.1.1.2 fvdl putchar(n, flags, tp);
412 1.1.1.2 fvdl tmp = 1;
413 1.1.1.2 fvdl } else
414 1.1.1.2 fvdl for (; *p > ' '; ++p)
415 1.1.1.2 fvdl continue;
416 1.1.1.2 fvdl }
417 1.1.1.2 fvdl if (tmp)
418 1.1.1.2 fvdl putchar('>', flags, tp);
419 1.1.1.2 fvdl break;
420 1.1.1.2 fvdl case 'c':
421 1.1.1.2 fvdl putchar(va_arg(ap, int), flags, tp);
422 1.1.1.2 fvdl break;
423 1.1.1.2 fvdl case 'r':
424 1.1.1.2 fvdl p = va_arg(ap, char *);
425 1.1.1.2 fvdl kprintf(p, flags, tp, va_arg(ap, va_list));
426 1.1.1.2 fvdl break;
427 1.1.1.2 fvdl case 's':
428 1.1.1.2 fvdl p = va_arg(ap, char *);
429 1.1.1.2 fvdl while (ch = *p++)
430 1.1.1.2 fvdl putchar(ch, flags, tp);
431 1.1.1.2 fvdl break;
432 1.1.1.2 fvdl case 'd':
433 1.1.1.2 fvdl ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
434 1.1.1.2 fvdl if ((long)ul < 0) {
435 1.1.1.2 fvdl putchar('-', flags, tp);
436 1.1.1.2 fvdl ul = -(long)ul;
437 1.1.1.2 fvdl }
438 1.1.1.2 fvdl base = 10;
439 1.1.1.2 fvdl goto number;
440 1.1.1.2 fvdl case 'o':
441 1.1.1.2 fvdl ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
442 1.1.1.2 fvdl base = 8;
443 1.1.1.2 fvdl goto number;
444 1.1.1.2 fvdl case 'u':
445 1.1.1.2 fvdl ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
446 1.1.1.2 fvdl base = 10;
447 1.1.1.2 fvdl goto number;
448 1.1.1.2 fvdl case 'x':
449 1.1.1.2 fvdl ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
450 1.1.1.2 fvdl base = 16;
451 1.1.1.2 fvdl number: p = ksprintn(ul, base, &tmp);
452 1.1.1.2 fvdl if (width && (width -= tmp) > 0)
453 1.1.1.2 fvdl while (width--)
454 1.1.1.2 fvdl putchar(padc, flags, tp);
455 1.1.1.2 fvdl while (ch = *p--)
456 1.1.1.2 fvdl putchar(ch, flags, tp);
457 1.1.1.2 fvdl break;
458 1.1.1.2 fvdl default:
459 1.1.1.2 fvdl putchar('%', flags, tp);
460 1.1.1.2 fvdl if (lflag)
461 1.1.1.2 fvdl putchar('l', flags, tp);
462 1.1.1.2 fvdl /* FALLTHROUGH */
463 1.1.1.2 fvdl case '%':
464 1.1.1.2 fvdl putchar(ch, flags, tp);
465 1.1.1.2 fvdl }
466 1.1.1.2 fvdl }
467 1.1.1.2 fvdl }
468 1.1.1.2 fvdl
469 1.1.1.2 fvdl /*
470 1.1.1.2 fvdl * Print a character on console or users terminal. If destination is
471 1.1.1.2 fvdl * the console then the last MSGBUFS characters are saved in msgbuf for
472 1.1.1.2 fvdl * inspection later.
473 1.1.1.2 fvdl */
474 1.1.1.2 fvdl static void
475 1.1.1.2 fvdl putchar(c, flags, tp)
476 1.1.1.2 fvdl register int c;
477 1.1.1.2 fvdl int flags;
478 1.1.1.2 fvdl struct tty *tp;
479 1.1.1.2 fvdl {
480 1.1.1.2 fvdl extern int msgbufmapped;
481 1.1.1.2 fvdl register struct msgbuf *mbp;
482 1.1.1.2 fvdl
483 1.1.1.2 fvdl if (panicstr)
484 1.1.1.2 fvdl constty = NULL;
485 1.1.1.2 fvdl if ((flags & TOCONS) && tp == NULL && constty) {
486 1.1.1.2 fvdl tp = constty;
487 1.1.1.2 fvdl flags |= TOTTY;
488 1.1.1.2 fvdl }
489 1.1.1.2 fvdl if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
490 1.1.1.2 fvdl (flags & TOCONS) && tp == constty)
491 1.1.1.2 fvdl constty = NULL;
492 1.1.1.2 fvdl if ((flags & TOLOG) &&
493 1.1.1.2 fvdl c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
494 1.1.1.2 fvdl mbp = msgbufp;
495 1.1.1.2 fvdl if (mbp->msg_magic != MSG_MAGIC) {
496 1.1.1.2 fvdl bzero((caddr_t)mbp, sizeof(*mbp));
497 1.1.1.2 fvdl mbp->msg_magic = MSG_MAGIC;
498 1.1.1.2 fvdl }
499 1.1.1.2 fvdl mbp->msg_bufc[mbp->msg_bufx++] = c;
500 1.1.1.2 fvdl if (mbp->msg_bufx < 0 || mbp->msg_bufx >= MSG_BSIZE)
501 1.1.1.2 fvdl mbp->msg_bufx = 0;
502 1.1.1.2 fvdl }
503 1.1.1.2 fvdl if ((flags & TOCONS) && constty == NULL && c != '\0')
504 1.1.1.2 fvdl (*v_putc)(c);
505 1.1.1.2 fvdl }
506 1.1.1.2 fvdl
507 1.1.1.2 fvdl /*
508 1.1.1.2 fvdl * Scaled down version of sprintf(3).
509 1.1.1.2 fvdl */
510 1.1.1.2 fvdl #ifdef __STDC__
511 1.1.1.2 fvdl sprintf(char *buf, const char *cfmt, ...)
512 1.1.1.2 fvdl #else
513 1.1.1.2 fvdl sprintf(buf, cfmt, va_alist)
514 1.1.1.2 fvdl char *buf, *cfmt;
515 1.1.1.2 fvdl #endif
516 1.1.1.2 fvdl {
517 1.1.1.2 fvdl register const char *fmt = cfmt;
518 1.1.1.2 fvdl register char *p, *bp;
519 1.1.1.2 fvdl register int ch, base;
520 1.1.1.2 fvdl u_long ul;
521 1.1.1.2 fvdl int lflag;
522 1.1.1.2 fvdl va_list ap;
523 1.1.1.2 fvdl
524 1.1.1.2 fvdl va_start(ap, cfmt);
525 1.1.1.2 fvdl for (bp = buf; ; ) {
526 1.1.1.2 fvdl while ((ch = *(u_char *)fmt++) != '%')
527 1.1.1.2 fvdl if ((*bp++ = ch) == '\0')
528 1.1.1.2 fvdl return ((bp - buf) - 1);
529 1.1.1.2 fvdl
530 1.1.1.2 fvdl lflag = 0;
531 1.1.1.2 fvdl reswitch: switch (ch = *(u_char *)fmt++) {
532 1.1.1.2 fvdl case 'l':
533 1.1.1.2 fvdl lflag = 1;
534 1.1.1.2 fvdl goto reswitch;
535 1.1.1.2 fvdl case 'c':
536 1.1.1.2 fvdl *bp++ = va_arg(ap, int);
537 1.1.1.2 fvdl break;
538 1.1.1.2 fvdl case 's':
539 1.1.1.2 fvdl p = va_arg(ap, char *);
540 1.1.1.2 fvdl while (*bp++ = *p++)
541 1.1.1.2 fvdl continue;
542 1.1.1.2 fvdl --bp;
543 1.1.1.2 fvdl break;
544 1.1.1.2 fvdl case 'd':
545 1.1.1.2 fvdl ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
546 1.1.1.2 fvdl if ((long)ul < 0) {
547 1.1.1.2 fvdl *bp++ = '-';
548 1.1.1.2 fvdl ul = -(long)ul;
549 1.1.1.2 fvdl }
550 1.1.1.2 fvdl base = 10;
551 1.1.1.2 fvdl goto number;
552 1.1.1.2 fvdl break;
553 1.1.1.2 fvdl case 'o':
554 1.1.1.2 fvdl ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
555 1.1.1.2 fvdl base = 8;
556 1.1.1.2 fvdl goto number;
557 1.1.1.2 fvdl break;
558 1.1.1.2 fvdl case 'u':
559 1.1.1.2 fvdl ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
560 1.1.1.2 fvdl base = 10;
561 1.1.1.2 fvdl goto number;
562 1.1.1.2 fvdl break;
563 1.1.1.2 fvdl case 'x':
564 1.1.1.2 fvdl ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
565 1.1.1.2 fvdl base = 16;
566 1.1.1.2 fvdl number: for (p = ksprintn(ul, base, NULL); ch = *p--;)
567 1.1.1.2 fvdl *bp++ = ch;
568 1.1.1.2 fvdl break;
569 1.1.1.2 fvdl default:
570 1.1.1.2 fvdl *bp++ = '%';
571 1.1.1.2 fvdl if (lflag)
572 1.1.1.2 fvdl *bp++ = 'l';
573 1.1.1.2 fvdl /* FALLTHROUGH */
574 1.1.1.2 fvdl case '%':
575 1.1.1.2 fvdl *bp++ = ch;
576 1.1.1.2 fvdl }
577 1.1.1.2 fvdl }
578 1.1.1.2 fvdl va_end(ap);
579 1.1.1.2 fvdl }
580 1.1.1.2 fvdl
581 1.1.1.2 fvdl /*
582 1.1.1.2 fvdl * Put a number (base <= 16) in a buffer in reverse order; return an
583 1.1.1.2 fvdl * optional length and a pointer to the NULL terminated (preceded?)
584 1.1.1.2 fvdl * buffer.
585 1.1.1.2 fvdl */
586 1.1.1.2 fvdl static char *
587 1.1.1.2 fvdl ksprintn(ul, base, lenp)
588 1.1.1.2 fvdl register u_long ul;
589 1.1.1.2 fvdl register int base, *lenp;
590 1.1.1.2 fvdl { /* A long in base 8, plus NULL. */
591 1.1.1.2 fvdl static char buf[sizeof(long) * NBBY / 3 + 2];
592 1.1.1.2 fvdl register char *p;
593 1.1.1.2 fvdl
594 1.1.1.2 fvdl p = buf;
595 1.1.1.2 fvdl do {
596 1.1.1.2 fvdl *++p = "0123456789abcdef"[ul % base];
597 1.1.1.2 fvdl } while (ul /= base);
598 1.1.1.2 fvdl if (lenp)
599 1.1.1.2 fvdl *lenp = p - buf;
600 1.1.1.2 fvdl return (p);
601 1.1.1.2 fvdl }
602