hexdump.c revision 7680
1218799Snwhitehorn/*-
2218799Snwhitehorn * Copyright (c) 1986, 1988, 1991, 1993
3218799Snwhitehorn *	The Regents of the University of California.  All rights reserved.
4218799Snwhitehorn * (c) UNIX System Laboratories, Inc.
5222468Sbz * All or some portions of this file are derived from material licensed
6222468Sbz * to the University of California by American Telephone and Telegraph
7218799Snwhitehorn * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8222468Sbz * the permission of UNIX System Laboratories, Inc.
9222468Sbz *
10222468Sbz * Redistribution and use in source and binary forms, with or without
11218799Snwhitehorn * modification, are permitted provided that the following conditions
12218799Snwhitehorn * are met:
13218799Snwhitehorn * 1. Redistributions of source code must retain the above copyright
14218799Snwhitehorn *    notice, this list of conditions and the following disclaimer.
15218799Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright
16218799Snwhitehorn *    notice, this list of conditions and the following disclaimer in the
17218799Snwhitehorn *    documentation and/or other materials provided with the distribution.
18218799Snwhitehorn * 3. All advertising materials mentioning features or use of this software
19218799Snwhitehorn *    must display the following acknowledgement:
20218799Snwhitehorn *	This product includes software developed by the University of
21218799Snwhitehorn *	California, Berkeley and its contributors.
22218799Snwhitehorn * 4. Neither the name of the University nor the names of its contributors
23218799Snwhitehorn *    may be used to endorse or promote products derived from this software
24218799Snwhitehorn *    without specific prior written permission.
25218799Snwhitehorn *
26218799Snwhitehorn * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27218799Snwhitehorn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28218799Snwhitehorn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29218799Snwhitehorn * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30218799Snwhitehorn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31218799Snwhitehorn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32218799Snwhitehorn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33218799Snwhitehorn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34218799Snwhitehorn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35218799Snwhitehorn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36218799Snwhitehorn * SUCH DAMAGE.
37218799Snwhitehorn *
38218799Snwhitehorn *	@(#)subr_prf.c	8.3 (Berkeley) 1/21/94
39218799Snwhitehorn * $Id: subr_prf.c,v 1.12 1995/04/01 20:18:43 joerg Exp $
40218799Snwhitehorn */
41218799Snwhitehorn
42218799Snwhitehorn#include <sys/param.h>
43218799Snwhitehorn#include <sys/systm.h>
44218799Snwhitehorn#include <sys/buf.h>
45218799Snwhitehorn#include <sys/conf.h>
46218799Snwhitehorn#include <sys/reboot.h>
47218799Snwhitehorn#include <sys/msgbuf.h>
48218799Snwhitehorn#include <sys/proc.h>
49218799Snwhitehorn#include <sys/ioctl.h>
50218799Snwhitehorn#include <sys/vnode.h>
51218799Snwhitehorn#include <sys/file.h>
52226741Snwhitehorn#include <sys/tty.h>
53226741Snwhitehorn#include <sys/tprintf.h>
54226741Snwhitehorn#include <sys/syslog.h>
55226741Snwhitehorn#include <sys/malloc.h>
56226741Snwhitehorn#include <machine/cons.h>
57226741Snwhitehorn
58226741Snwhitehorn/*
59218799Snwhitehorn * Note that stdarg.h and the ANSI style va_start macro is used for both
60218799Snwhitehorn * ANSI and traditional C compilers.
61218799Snwhitehorn */
62218799Snwhitehorn#include <machine/stdarg.h>
63218799Snwhitehorn
64222619Sbz#ifdef KADB
65222611Sbz#include <machine/kdbparam.h>
66218799Snwhitehorn#endif
67218799Snwhitehorn
68218799Snwhitehorn
69218799Snwhitehorn#define TOCONS	0x01
70218799Snwhitehorn#define TOTTY	0x02
71222619Sbz#define TOLOG	0x04
72218799Snwhitehorn
73218799Snwhitehornstruct	tty *constty;			/* pointer to console "window" tty */
74218799Snwhitehorn
75218799Snwhitehornvoid	(*v_putc)(int) = cnputc;	/* routine to putc on virtual console */
76218799Snwhitehorn
77218799Snwhitehornvoid  logpri __P((int level));
78218799Snwhitehornstatic void  putchar __P((int ch, int flags, struct tty *tp));
79218799Snwhitehornstatic char *ksprintn __P((u_long num, int base, int *len));
80218799Snwhitehorn
81222468Sbzint consintr = 1;			/* Ok to handle console interrupts? */
82222468Sbz
83222468Sbz/*
84222468Sbz * Variable panicstr contains argument to first call to panic; used as flag
85222468Sbz * to indicate that the kernel has already called panic.
86222468Sbz */
87222468Sbzconst char *panicstr;
88222468Sbz
89222468Sbz/*
90222468Sbz * Panic is called on unresolvable fatal errors.  It prints "panic: mesg",
91218799Snwhitehorn * and then reboots.  If we are called twice, then we avoid trying to sync
92222468Sbz * the disks as this often leads to recursive panics.
93222468Sbz */
94222468Sbz#ifdef __GNUC__
95222468Sbz__dead			/* panic() does not return */
96222468Sbz#endif
97222468Sbzvoid
98222468Sbz#ifdef __STDC__
99222468Sbzpanic(const char *fmt, ...)
100218799Snwhitehorn#else
101222468Sbzpanic(fmt, va_alist)
102222468Sbz	char *fmt;
103222468Sbz#endif
104222468Sbz{
105222619Sbz	int bootopt;
106222468Sbz	va_list ap;
107222468Sbz
108222468Sbz	bootopt = RB_AUTOBOOT | RB_DUMP;
109222468Sbz	if (panicstr)
110222468Sbz		bootopt |= RB_NOSYNC;
111222468Sbz	else
112222468Sbz		panicstr = fmt;
113222468Sbz
114222468Sbz	va_start(ap, fmt);
115222468Sbz	printf("panic: %r\n", fmt, ap);
116222468Sbz	va_end(ap);
117222468Sbz
118222468Sbz#ifdef KGDB
119222468Sbz	kgdb_panic();
120222468Sbz#endif
121222468Sbz#ifdef KADB
122222468Sbz	if (boothowto & RB_KDB)
123222468Sbz		kdbpanic();
124222468Sbz#endif
125222468Sbz#ifdef DDB
126222468Sbz	Debugger ("panic");
127222468Sbz#endif
128222468Sbz	boot(bootopt);
129222468Sbz}
130222468Sbz
131222468Sbz/*
132222468Sbz * Warn that a system table is full.
133222468Sbz */
134222468Sbzvoid
135222468Sbztablefull(tab)
136222468Sbz	const char *tab;
137222468Sbz{
138222468Sbz
139222468Sbz	log(LOG_ERR, "%s: table is full\n", tab);
140222468Sbz}
141222468Sbz
142222468Sbz/*
143222468Sbz * Uprintf prints to the controlling terminal for the current process.
144222468Sbz * It may block if the tty queue is overfull.  No message is printed if
145222468Sbz * the queue does not clear in a reasonable time.
146222468Sbz */
147222468Sbzvoid
148222468Sbz#ifdef __STDC__
149222468Sbzuprintf(const char *fmt, ...)
150222468Sbz#else
151222468Sbzuprintf(fmt, va_alist)
152222468Sbz	char *fmt;
153222468Sbz#endif
154222468Sbz{
155222468Sbz	register struct proc *p = curproc;
156222468Sbz	va_list ap;
157222468Sbz
158222468Sbz	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
159222468Sbz		va_start(ap, fmt);
160222468Sbz		kprintf(fmt, TOTTY, p->p_session->s_ttyp, ap);
161222468Sbz		va_end(ap);
162222468Sbz	}
163222468Sbz}
164222468Sbz
165222468Sbztpr_t
166222468Sbztprintf_open(p)
167222468Sbz	register struct proc *p;
168222468Sbz{
169218799Snwhitehorn
170218799Snwhitehorn	if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
171218799Snwhitehorn		SESSHOLD(p->p_session);
172218799Snwhitehorn		return ((tpr_t) p->p_session);
173222468Sbz	}
174222468Sbz	return ((tpr_t) NULL);
175225430Sbz}
176218799Snwhitehorn
177218799Snwhitehornvoid
178218799Snwhitehorntprintf_close(sess)
179218799Snwhitehorn	tpr_t sess;
180222468Sbz{
181222468Sbz
182222468Sbz	if (sess)
183222681Sbz		SESSRELE((struct session *) sess);
184222468Sbz}
185222468Sbz
186222468Sbz/*
187222468Sbz * tprintf prints on the controlling terminal associated
188222468Sbz * with the given session.
189222468Sbz */
190222468Sbzvoid
191222468Sbz#ifdef __STDC__
192222468Sbztprintf(tpr_t tpr, const char *fmt, ...)
193222468Sbz#else
194222681Sbztprintf(tpr, fmt, va_alist)
195222681Sbz	tpr_t tpr;
196222681Sbz	char *fmt;
197222681Sbz#endif
198222468Sbz{
199222681Sbz	register struct session *sess = (struct session *)tpr;
200222681Sbz	struct tty *tp = NULL;
201222468Sbz	int flags = TOLOG;
202222468Sbz	va_list ap;
203222468Sbz
204222468Sbz	logpri(LOG_INFO);
205218799Snwhitehorn	if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) {
206222619Sbz		flags |= TOTTY;
207		tp = sess->s_ttyp;
208	}
209	va_start(ap, fmt);
210	kprintf(fmt, flags, tp, ap);
211	va_end(ap);
212	logwakeup();
213}
214
215/*
216 * Ttyprintf displays a message on a tty; it should be used only by
217 * the tty driver, or anything that knows the underlying tty will not
218 * be revoke(2)'d away.  Other callers should use tprintf.
219 */
220void
221#ifdef __STDC__
222ttyprintf(struct tty *tp, const char *fmt, ...)
223#else
224ttyprintf(tp, fmt, va_alist)
225	struct tty *tp;
226	char *fmt;
227#endif
228{
229	va_list ap;
230
231	va_start(ap, fmt);
232	kprintf(fmt, TOTTY, tp, ap);
233	va_end(ap);
234}
235
236extern	int log_open;
237
238/*
239 * Log writes to the log buffer, and guarantees not to sleep (so can be
240 * called by interrupt routines).  If there is no process reading the
241 * log yet, it writes to the console also.
242 */
243void
244#ifdef __STDC__
245log(int level, const char *fmt, ...)
246#else
247log(level, fmt, va_alist)
248	int level;
249	char *fmt;
250#endif
251{
252	register int s;
253	va_list ap;
254
255	s = splhigh();
256	logpri(level);
257	va_start(ap, fmt);
258	kprintf(fmt, TOLOG, NULL, ap);
259	splx(s);
260	va_end(ap);
261	if (!log_open) {
262		va_start(ap, fmt);
263		kprintf(fmt, TOCONS, NULL, ap);
264		va_end(ap);
265	}
266	logwakeup();
267}
268
269void
270logpri(level)
271	int level;
272{
273	register char *p;
274
275	putchar('<', TOLOG, NULL);
276	for (p = ksprintn((u_long)level, 10, NULL); *p;)
277		putchar(*p--, TOLOG, NULL);
278	putchar('>', TOLOG, NULL);
279}
280
281void
282#ifdef __STDC__
283addlog(const char *fmt, ...)
284#else
285addlog(fmt, va_alist)
286	char *fmt;
287#endif
288{
289	register int s;
290	va_list ap;
291
292	s = splhigh();
293	va_start(ap, fmt);
294	kprintf(fmt, TOLOG, NULL, ap);
295	splx(s);
296	va_end(ap);
297	if (!log_open) {
298		va_start(ap, fmt);
299		kprintf(fmt, TOCONS, NULL, ap);
300		va_end(ap);
301	}
302	logwakeup();
303}
304
305void
306#ifdef __STDC__
307printf(const char *fmt, ...)
308#else
309printf(fmt, va_alist)
310	char *fmt;
311#endif
312{
313	va_list ap;
314	register int savintr;
315
316	savintr = consintr;		/* disable interrupts */
317	consintr = 0;
318	va_start(ap, fmt);
319	kprintf(fmt, TOCONS | TOLOG, NULL, ap);
320	va_end(ap);
321	if (!panicstr)
322		logwakeup();
323	consintr = savintr;		/* reenable interrupts */
324}
325
326/*
327 * Scaled down version of printf(3).
328 *
329 * Two additional formats:
330 *
331 * The format %b is supported to decode error registers.
332 * Its usage is:
333 *
334 *	printf("reg=%b\n", regval, "<base><arg>*");
335 *
336 * where <base> is the output base expressed as a control character, e.g.
337 * \10 gives octal; \20 gives hex.  Each arg is a sequence of characters,
338 * the first of which gives the bit number to be inspected (origin 1), and
339 * the next characters (up to a control character, i.e. a character <= 32),
340 * give the name of the register.  Thus:
341 *
342 *	kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
343 *
344 * would produce output:
345 *
346 *	reg=3<BITTWO,BITONE>
347 *
348 * The format %r passes an additional format string and argument list
349 * recursively.  Its usage is:
350 *
351 * fn(char *fmt, ...)
352 * {
353 *	va_list ap;
354 *	va_start(ap, fmt);
355 *	printf("prefix: %r: suffix\n", fmt, ap);
356 *	va_end(ap);
357 * }
358 *
359 * Space or zero padding and a field width are supported for the numeric
360 * formats only.
361 */
362void
363kprintf(fmt, flags, tp, ap)
364	register const char *fmt;
365	int flags;
366	struct tty *tp;
367	va_list ap;
368{
369	register char *p, *q;
370	register int ch, n;
371	u_long ul;
372	int base, lflag, tmp, width;
373	char padc;
374
375	if (fmt == NULL)
376		fmt = "(fmt null)\n";
377	for (;;) {
378		padc = ' ';
379		width = 0;
380		while ((ch = *(u_char *)fmt++) != '%') {
381			if (ch == '\0')
382				return;
383			putchar(ch, flags, tp);
384		}
385		lflag = 0;
386reswitch:	switch (ch = *(u_char *)fmt++) {
387		case '0':
388			padc = '0';
389			goto reswitch;
390		case '1': case '2': case '3': case '4':
391		case '5': case '6': case '7': case '8': case '9':
392			for (width = 0;; ++fmt) {
393				width = width * 10 + ch - '0';
394				ch = *fmt;
395				if (ch < '0' || ch > '9')
396					break;
397			}
398			goto reswitch;
399		case 'l':
400			lflag = 1;
401			goto reswitch;
402		case 'b':
403			ul = va_arg(ap, int);
404			p = va_arg(ap, char *);
405			for (q = ksprintn(ul, *p++, NULL); *q;)
406				putchar(*q--, flags, tp);
407
408			if (!ul)
409				break;
410
411			for (tmp = 0; *p;) {
412				n = *p++;
413				if (ul & (1 << (n - 1))) {
414					putchar(tmp ? ',' : '<', flags, tp);
415					for (; (n = *p) > ' '; ++p)
416						putchar(n, flags, tp);
417					tmp = 1;
418				} else
419					for (; *p > ' '; ++p)
420						continue;
421			}
422			if (tmp)
423				putchar('>', flags, tp);
424			break;
425		case 'c':
426			putchar(va_arg(ap, int), flags, tp);
427			break;
428		case 'r':
429			p = va_arg(ap, char *);
430			kprintf(p, flags, tp, va_arg(ap, va_list));
431			break;
432		case 's':
433			p = va_arg(ap, char *);
434			if (p == NULL)
435				p = "(null)";
436			while (*p)
437				putchar(*p++, flags, tp);
438			break;
439		case 'd':
440			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
441			if ((long)ul < 0) {
442				putchar('-', flags, tp);
443				ul = -(long)ul;
444			}
445			base = 10;
446			goto number;
447		case 'o':
448			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
449			base = 8;
450			goto number;
451		case 'u':
452			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
453			base = 10;
454			goto number;
455		case 'p':
456			ul = (u_long) va_arg(ap, void *);
457			width=8;
458			base=16;
459			putchar('0',flags,tp);
460			putchar('x',flags,tp);
461			goto number;
462		case 'x':
463			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
464			base = 16;
465number:			p = ksprintn(ul, base, &tmp);
466			if (width && (width -= tmp) > 0)
467				while (width--)
468					putchar(padc, flags, tp);
469			while (*p)
470				putchar(*p--, flags, tp);
471			break;
472		default:
473			putchar('%', flags, tp);
474			if (lflag)
475				putchar('l', flags, tp);
476			/* FALLTHROUGH */
477		case '%':
478			putchar(ch, flags, tp);
479		}
480	}
481}
482
483/*
484 * Print a character on console or users terminal.  If destination is
485 * the console then the last MSGBUFS characters are saved in msgbuf for
486 * inspection later.
487 */
488static void
489putchar(c, flags, tp)
490	register int c;
491	int flags;
492	struct tty *tp;
493{
494	register struct msgbuf *mbp;
495
496	if (panicstr)
497		constty = NULL;
498	if ((flags & TOCONS) && tp == NULL && constty) {
499		tp = constty;
500		flags |= TOTTY;
501	}
502	if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
503	    (flags & TOCONS) && tp == constty)
504		constty = NULL;
505	if ((flags & TOLOG) &&
506	    c != '\0' && c != '\r' && c != 0177 && msgbufmapped) {
507		mbp = msgbufp;
508		if (mbp->msg_magic != MSG_MAGIC) {
509			bzero((caddr_t)mbp, sizeof(*mbp));
510			mbp->msg_magic = MSG_MAGIC;
511		}
512		mbp->msg_bufc[mbp->msg_bufx++] = c;
513		if (mbp->msg_bufx >= MSG_BSIZE)
514			mbp->msg_bufx = 0;
515		if (mbp->msg_bufr == mbp->msg_bufx) {
516			mbp->msg_bufr++;
517			if (mbp->msg_bufr >= MSG_BSIZE)
518				mbp->msg_bufr = 0;
519		}
520	}
521	if ((flags & TOCONS) && constty == NULL && c != '\0')
522		(*v_putc)(c);
523}
524
525/*
526 * Scaled down version of sprintf(3).
527 */
528#ifdef __STDC__
529int
530sprintf(char *buf, const char *cfmt, ...)
531#else
532int
533sprintf(buf, cfmt, va_alist)
534	char *buf, *cfmt;
535#endif
536{
537	register const char *fmt = cfmt;
538	register char *p, *bp;
539	register int ch, base;
540	u_long ul;
541	int lflag;
542	va_list ap;
543
544	va_start(ap, cfmt);
545	for (bp = buf; ; ) {
546		while ((ch = *(u_char *)fmt++) != '%')
547			if ((*bp++ = ch) == '\0')
548				return ((bp - buf) - 1);
549
550		lflag = 0;
551reswitch:	switch (ch = *(u_char *)fmt++) {
552		case 'l':
553			lflag = 1;
554			goto reswitch;
555		case 'c':
556			*bp++ = va_arg(ap, int);
557			break;
558		case 's':
559			p = va_arg(ap, char *);
560			while (*p)
561				*bp++ = *p++;
562			break;
563		case 'd':
564			ul = lflag ? va_arg(ap, long) : va_arg(ap, int);
565			if ((long)ul < 0) {
566				*bp++ = '-';
567				ul = -(long)ul;
568			}
569			base = 10;
570			goto number;
571			break;
572		case 'o':
573			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
574			base = 8;
575			goto number;
576			break;
577		case 'u':
578			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
579			base = 10;
580			goto number;
581			break;
582		case 'x':
583			ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int);
584			base = 16;
585number:			for (p = ksprintn(ul, base, NULL); *p;)
586				*bp++ = *p--;
587			break;
588		default:
589			*bp++ = '%';
590			if (lflag)
591				*bp++ = 'l';
592			/* FALLTHROUGH */
593		case '%':
594			*bp++ = ch;
595		}
596	}
597	va_end(ap);
598}
599
600/*
601 * Put a number (base <= 16) in a buffer in reverse order; return an
602 * optional length and a pointer to the NULL terminated (preceded?)
603 * buffer.
604 */
605static char *
606ksprintn(ul, base, lenp)
607	register u_long ul;
608	register int base, *lenp;
609{					/* A long in base 8, plus NULL. */
610	static char buf[sizeof(long) * NBBY / 3 + 2];
611	register char *p;
612
613	p = buf;
614	do {
615		*++p = "0123456789abcdef"[ul % base];
616	} while (ul /= base);
617	if (lenp)
618		*lenp = p - buf;
619	return (p);
620}
621