xref: /illumos-gate/usr/src/cmd/fs.d/ufs/fsdb/fsdb.c (revision 8509e9ca)
17c478bd9Sstevel@tonic-gate /*
267a4bb8fSGary Mills  * Copyright 2015 Gary Mills
385651ed9SJohn.Zolnowsky@Sun.COM  * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*
77c478bd9Sstevel@tonic-gate  * Copyright (c) 1988 Regents of the University of California.
87c478bd9Sstevel@tonic-gate  * All rights reserved.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
117c478bd9Sstevel@tonic-gate  * Computer Consoles Inc.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
147c478bd9Sstevel@tonic-gate  * provided that: (1) source distributions retain this entire copyright
157c478bd9Sstevel@tonic-gate  * notice and comment, and (2) distributions including binaries display
167c478bd9Sstevel@tonic-gate  * the following acknowledgement:  ``This product includes software
177c478bd9Sstevel@tonic-gate  * developed by the University of California, Berkeley and its contributors''
187c478bd9Sstevel@tonic-gate  * in the documentation or other materials provided with the distribution
197c478bd9Sstevel@tonic-gate  * and in all advertising materials mentioning features or use of this
207c478bd9Sstevel@tonic-gate  * software. Neither the name of the University nor the names of its
217c478bd9Sstevel@tonic-gate  * contributors may be used to endorse or promote products derived
227c478bd9Sstevel@tonic-gate  * from this software without specific prior written permission.
237c478bd9Sstevel@tonic-gate  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
247c478bd9Sstevel@tonic-gate  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
257c478bd9Sstevel@tonic-gate  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  *  fsdb - file system debugger
307c478bd9Sstevel@tonic-gate  *
317c478bd9Sstevel@tonic-gate  *  usage: fsdb [-o suboptions] special
327c478bd9Sstevel@tonic-gate  *  options/suboptions:
337c478bd9Sstevel@tonic-gate  *	-o
347c478bd9Sstevel@tonic-gate  *		?		display usage
357c478bd9Sstevel@tonic-gate  *		o		override some error conditions
367c478bd9Sstevel@tonic-gate  *		p="string"	set prompt to string
377c478bd9Sstevel@tonic-gate  *		w		open for write
387c478bd9Sstevel@tonic-gate  */
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #include <sys/param.h>
417c478bd9Sstevel@tonic-gate #include <sys/signal.h>
427c478bd9Sstevel@tonic-gate #include <sys/file.h>
437c478bd9Sstevel@tonic-gate #include <inttypes.h>
447c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #ifdef sun
477c478bd9Sstevel@tonic-gate #include <unistd.h>
487c478bd9Sstevel@tonic-gate #include <stdlib.h>
497c478bd9Sstevel@tonic-gate #include <string.h>
507c478bd9Sstevel@tonic-gate #include <fcntl.h>
517c478bd9Sstevel@tonic-gate #include <signal.h>
527c478bd9Sstevel@tonic-gate #include <sys/types.h>
537c478bd9Sstevel@tonic-gate #include <sys/vnode.h>
547c478bd9Sstevel@tonic-gate #include <sys/mntent.h>
557c478bd9Sstevel@tonic-gate #include <sys/wait.h>
567c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fsdir.h>
577c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_fs.h>
587c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_inode.h>
597c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_acl.h>
607c478bd9Sstevel@tonic-gate #include <sys/fs/ufs_log.h>
617c478bd9Sstevel@tonic-gate #else
627c478bd9Sstevel@tonic-gate #include <sys/dir.h>
637c478bd9Sstevel@tonic-gate #include <ufs/fs.h>
647c478bd9Sstevel@tonic-gate #include <ufs/dinode.h>
657c478bd9Sstevel@tonic-gate #include <paths.h>
667c478bd9Sstevel@tonic-gate #endif /* sun */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate #include <stdio.h>
697c478bd9Sstevel@tonic-gate #include <setjmp.h>
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate #define	OLD_FSDB_COMPATIBILITY	/* To support the obsoleted "-z" option */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #ifndef _PATH_BSHELL
747c478bd9Sstevel@tonic-gate #define	_PATH_BSHELL	"/bin/sh"
757c478bd9Sstevel@tonic-gate #endif /* _PATH_BSHELL */
767c478bd9Sstevel@tonic-gate /*
777c478bd9Sstevel@tonic-gate  * Defines from the 4.3-tahoe file system, for systems with the 4.2 or 4.3
787c478bd9Sstevel@tonic-gate  * file system.
797c478bd9Sstevel@tonic-gate  */
807c478bd9Sstevel@tonic-gate #ifndef FS_42POSTBLFMT
817c478bd9Sstevel@tonic-gate #define	cg_blktot(cgp) (((cgp))->cg_btot)
827c478bd9Sstevel@tonic-gate #define	cg_blks(fs, cgp, cylno) (((cgp))->cg_b[cylno])
837c478bd9Sstevel@tonic-gate #define	cg_inosused(cgp) (((cgp))->cg_iused)
847c478bd9Sstevel@tonic-gate #define	cg_blksfree(cgp) (((cgp))->cg_free)
857c478bd9Sstevel@tonic-gate #define	cg_chkmagic(cgp) ((cgp)->cg_magic == CG_MAGIC)
867c478bd9Sstevel@tonic-gate #endif
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /*
897c478bd9Sstevel@tonic-gate  * Never changing defines.
907c478bd9Sstevel@tonic-gate  */
917c478bd9Sstevel@tonic-gate #define	OCTAL		8		/* octal base */
927c478bd9Sstevel@tonic-gate #define	DECIMAL		10		/* decimal base */
937c478bd9Sstevel@tonic-gate #define	HEX		16		/* hexadecimal base */
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate  * Adjustable defines.
977c478bd9Sstevel@tonic-gate  */
987c478bd9Sstevel@tonic-gate #define	NBUF		10		/* number of cache buffers */
997c478bd9Sstevel@tonic-gate #define	PROMPTSIZE	80		/* size of user definable prompt */
1007c478bd9Sstevel@tonic-gate #define	MAXFILES	40000		/* max number of files ls can handle */
1017c478bd9Sstevel@tonic-gate #define	FIRST_DEPTH	10		/* default depth for find and ls */
1027c478bd9Sstevel@tonic-gate #define	SECOND_DEPTH	100		/* second try at depth (maximum) */
1037c478bd9Sstevel@tonic-gate #define	INPUTBUFFER	1040		/* size of input buffer */
1047c478bd9Sstevel@tonic-gate #define	BYTESPERLINE	16		/* bytes per line of /dxo output */
1057c478bd9Sstevel@tonic-gate #define	NREG		36		/* number of save registers */
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate #define	DEVPREFIX	"/dev/"		/* Uninteresting part of "special" */
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
1107c478bd9Sstevel@tonic-gate #define	FSDB_OPTIONS	"o:wp:z:"
1117c478bd9Sstevel@tonic-gate #else
1127c478bd9Sstevel@tonic-gate #define	FSDB_OPTIONS	"o:wp:"
1137c478bd9Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate  * Values dependent on sizes of structs and such.
1187c478bd9Sstevel@tonic-gate  */
1197c478bd9Sstevel@tonic-gate #define	NUMB		3			/* these three are arbitrary, */
1207c478bd9Sstevel@tonic-gate #define	BLOCK		5			/* but must be different from */
1217c478bd9Sstevel@tonic-gate #define	FRAGMENT	7			/* the rest (hence odd). */
1227c478bd9Sstevel@tonic-gate #define	BITSPERCHAR	8			/* couldn't find it anywhere  */
1237c478bd9Sstevel@tonic-gate #define	CHAR		(sizeof (char))
1247c478bd9Sstevel@tonic-gate #define	SHORT		(sizeof (short))
1257c478bd9Sstevel@tonic-gate #define	LONG		(sizeof (long))
1267c478bd9Sstevel@tonic-gate #define	U_OFFSET_T	(sizeof (u_offset_t))	/* essentially "long long" */
1277c478bd9Sstevel@tonic-gate #define	INODE		(sizeof (struct dinode))
1287c478bd9Sstevel@tonic-gate #define	DIRECTORY	(sizeof (struct direct))
1297c478bd9Sstevel@tonic-gate #define	CGRP		(sizeof (struct cg))
1307c478bd9Sstevel@tonic-gate #define	SB		(sizeof (struct fs))
1317c478bd9Sstevel@tonic-gate #define	BLKSIZE		(fs->fs_bsize)		/* for clarity */
1327c478bd9Sstevel@tonic-gate #define	FRGSIZE		(fs->fs_fsize)
1337c478bd9Sstevel@tonic-gate #define	BLKSHIFT	(fs->fs_bshift)
1347c478bd9Sstevel@tonic-gate #define	FRGSHIFT	(fs->fs_fshift)
1357c478bd9Sstevel@tonic-gate #define	SHADOW_DATA	(sizeof (struct ufs_fsd))
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate /*
1387c478bd9Sstevel@tonic-gate  * Messy macros that would otherwise clutter up such glamorous code.
1397c478bd9Sstevel@tonic-gate  */
1407c478bd9Sstevel@tonic-gate #define	itob(i)		(((u_offset_t)itod(fs, (i)) << \
1417c478bd9Sstevel@tonic-gate 	(u_offset_t)FRGSHIFT) + (u_offset_t)itoo(fs, (i)) * (u_offset_t)INODE)
1427c478bd9Sstevel@tonic-gate #define	min(x, y)	((x) < (y) ? (x) : (y))
1437c478bd9Sstevel@tonic-gate #define	STRINGSIZE(d)	((long)d->d_reclen - \
1447c478bd9Sstevel@tonic-gate 				((long)&d->d_name[0] - (long)&d->d_ino))
1457c478bd9Sstevel@tonic-gate #define	letter(c)	((((c) >= 'a')&&((c) <= 'z')) ||\
1467c478bd9Sstevel@tonic-gate 				(((c) >= 'A')&&((c) <= 'Z')))
1477c478bd9Sstevel@tonic-gate #define	digit(c)	(((c) >= '0') && ((c) <= '9'))
1487c478bd9Sstevel@tonic-gate #define	HEXLETTER(c)	(((c) >= 'A') && ((c) <= 'F'))
1497c478bd9Sstevel@tonic-gate #define	hexletter(c)	(((c) >= 'a') && ((c) <= 'f'))
1507c478bd9Sstevel@tonic-gate #define	octaldigit(c)	(((c) >= '0') && ((c) <= '7'))
1517c478bd9Sstevel@tonic-gate #define	uppertolower(c)	((c) - 'A' + 'a')
1527c478bd9Sstevel@tonic-gate #define	hextodigit(c)	((c) - 'a' + 10)
1537c478bd9Sstevel@tonic-gate #define	numtodigit(c)	((c) - '0')
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate #if !defined(loword)
1567c478bd9Sstevel@tonic-gate #define	loword(X)	(((ushort_t *)&X)[1])
1577c478bd9Sstevel@tonic-gate #endif /* loword */
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate #if !defined(lobyte)
1607c478bd9Sstevel@tonic-gate #define	lobyte(X)	(((unsigned char *)&X)[1])
1617c478bd9Sstevel@tonic-gate #endif /* lobyte */
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate /*
1647c478bd9Sstevel@tonic-gate  * buffer cache structure.
1657c478bd9Sstevel@tonic-gate  */
1667c478bd9Sstevel@tonic-gate static struct lbuf {
1677c478bd9Sstevel@tonic-gate 	struct	lbuf  *fwd;
1687c478bd9Sstevel@tonic-gate 	struct	lbuf  *back;
1697c478bd9Sstevel@tonic-gate 	char	*blkaddr;
1707c478bd9Sstevel@tonic-gate 	short	valid;
1717c478bd9Sstevel@tonic-gate 	u_offset_t	blkno;
1727c478bd9Sstevel@tonic-gate } lbuf[NBUF], bhdr;
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate  * used to hold save registers (see '<' and '>').
1767c478bd9Sstevel@tonic-gate  */
1777c478bd9Sstevel@tonic-gate struct	save_registers {
1787c478bd9Sstevel@tonic-gate 	u_offset_t	sv_addr;
1797c478bd9Sstevel@tonic-gate 	u_offset_t	sv_value;
1807c478bd9Sstevel@tonic-gate 	long		sv_objsz;
1817c478bd9Sstevel@tonic-gate } regs[NREG];
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate /*
1847c478bd9Sstevel@tonic-gate  * cd, find, and ls use this to hold filenames.  Each filename is broken
1857c478bd9Sstevel@tonic-gate  * up by a slash.  In other words, /usr/src/adm would have a len field
1867c478bd9Sstevel@tonic-gate  * of 2 (starting from 0), and filenames->fname[0-2] would hold usr,
1877c478bd9Sstevel@tonic-gate  * src, and adm components of the pathname.
1887c478bd9Sstevel@tonic-gate  */
1897c478bd9Sstevel@tonic-gate static struct filenames {
1907c478bd9Sstevel@tonic-gate 	ino_t	ino;		/* inode */
1917c478bd9Sstevel@tonic-gate 	long	len;		/* number of components */
1927c478bd9Sstevel@tonic-gate 	char	flag;		/* flag if using SECOND_DEPTH allocator */
1937c478bd9Sstevel@tonic-gate 	char	find;		/* flag if found by find */
1947c478bd9Sstevel@tonic-gate 	char	**fname;	/* hold components of pathname */
1957c478bd9Sstevel@tonic-gate } *filenames, *top;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate enum log_enum { LOG_NDELTAS, LOG_ALLDELTAS, LOG_CHECKSCAN };
1987c478bd9Sstevel@tonic-gate #ifdef sun
1997c478bd9Sstevel@tonic-gate struct fs	*fs;
2007c478bd9Sstevel@tonic-gate static union {
2017c478bd9Sstevel@tonic-gate 	struct fs	un_filesystem;
2027c478bd9Sstevel@tonic-gate 	char		un_sbsize[SBSIZE];
2037c478bd9Sstevel@tonic-gate } fs_un;
2047c478bd9Sstevel@tonic-gate #define	filesystem	fs_un.un_filesystem
2057c478bd9Sstevel@tonic-gate #else
2067c478bd9Sstevel@tonic-gate struct fs filesystem, *fs;	/* super block */
2077c478bd9Sstevel@tonic-gate #endif /* sun */
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  * Global data.
2117c478bd9Sstevel@tonic-gate  */
2127c478bd9Sstevel@tonic-gate static char		*input_path[MAXPATHLEN];
2137c478bd9Sstevel@tonic-gate static char		*stack_path[MAXPATHLEN];
2147c478bd9Sstevel@tonic-gate static char		*current_path[MAXPATHLEN];
2157c478bd9Sstevel@tonic-gate static char		input_buffer[INPUTBUFFER];
2167c478bd9Sstevel@tonic-gate static char		*prompt;
2177c478bd9Sstevel@tonic-gate static char		*buffers;
2187c478bd9Sstevel@tonic-gate static char		scratch[64];
2197c478bd9Sstevel@tonic-gate static char		BASE[] = "o u     x";
2207c478bd9Sstevel@tonic-gate static char		PROMPT[PROMPTSIZE];
2217c478bd9Sstevel@tonic-gate static char		laststyle = '/';
2227c478bd9Sstevel@tonic-gate static char		lastpo = 'x';
2237c478bd9Sstevel@tonic-gate static short		input_pointer;
2247c478bd9Sstevel@tonic-gate static short		current_pathp;
2257c478bd9Sstevel@tonic-gate static short		stack_pathp;
2267c478bd9Sstevel@tonic-gate static short		input_pathp;
2277c478bd9Sstevel@tonic-gate static short		cmp_level;
2287c478bd9Sstevel@tonic-gate static int		nfiles;
2297c478bd9Sstevel@tonic-gate static short		type = NUMB;
2307c478bd9Sstevel@tonic-gate static short		dirslot;
2317c478bd9Sstevel@tonic-gate static short		fd;
2327c478bd9Sstevel@tonic-gate static short		c_count;
2337c478bd9Sstevel@tonic-gate static short		error;
2347c478bd9Sstevel@tonic-gate static short		paren;
2357c478bd9Sstevel@tonic-gate static short		trapped;
2367c478bd9Sstevel@tonic-gate static short		doing_cd;
2377c478bd9Sstevel@tonic-gate static short		doing_find;
2387c478bd9Sstevel@tonic-gate static short		find_by_name;
2397c478bd9Sstevel@tonic-gate static short		find_by_inode;
2407c478bd9Sstevel@tonic-gate static short		long_list;
2417c478bd9Sstevel@tonic-gate static short		recursive;
2427c478bd9Sstevel@tonic-gate static short		objsz = SHORT;
2437c478bd9Sstevel@tonic-gate static short		override = 0;
2447c478bd9Sstevel@tonic-gate static short		wrtflag = O_RDONLY;
2457c478bd9Sstevel@tonic-gate static short		base = HEX;
2467c478bd9Sstevel@tonic-gate static short		acting_on_inode;
2477c478bd9Sstevel@tonic-gate static short		acting_on_directory;
2487c478bd9Sstevel@tonic-gate static short		should_print = 1;
2497c478bd9Sstevel@tonic-gate static short		clear;
2507c478bd9Sstevel@tonic-gate static short		star;
2517c478bd9Sstevel@tonic-gate static u_offset_t	addr;
2527c478bd9Sstevel@tonic-gate static u_offset_t	bod_addr;
2537c478bd9Sstevel@tonic-gate static u_offset_t	value;
2547c478bd9Sstevel@tonic-gate static u_offset_t	erraddr;
2557c478bd9Sstevel@tonic-gate static long		errcur_bytes;
2567c478bd9Sstevel@tonic-gate static u_offset_t	errino;
2577c478bd9Sstevel@tonic-gate static long		errinum;
2587c478bd9Sstevel@tonic-gate static long		cur_cgrp;
2597c478bd9Sstevel@tonic-gate static u_offset_t	cur_ino;
2607c478bd9Sstevel@tonic-gate static long		cur_inum;
2617c478bd9Sstevel@tonic-gate static u_offset_t	cur_dir;
2627c478bd9Sstevel@tonic-gate static long		cur_block;
2637c478bd9Sstevel@tonic-gate static long		cur_bytes;
2647c478bd9Sstevel@tonic-gate static long		find_ino;
2657c478bd9Sstevel@tonic-gate static u_offset_t	filesize;
2667c478bd9Sstevel@tonic-gate static u_offset_t	blocksize;
2677c478bd9Sstevel@tonic-gate static long		stringsize;
2687c478bd9Sstevel@tonic-gate static long		count = 1;
2697c478bd9Sstevel@tonic-gate static long		commands;
2707c478bd9Sstevel@tonic-gate static long		read_requests;
2717c478bd9Sstevel@tonic-gate static long		actual_disk_reads;
2727c478bd9Sstevel@tonic-gate static jmp_buf		env;
2737c478bd9Sstevel@tonic-gate static long		maxfiles;
2747c478bd9Sstevel@tonic-gate static long		cur_shad;
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate #ifndef sun
2777c478bd9Sstevel@tonic-gate extern char	*malloc(), *calloc();
2787c478bd9Sstevel@tonic-gate #endif
2797c478bd9Sstevel@tonic-gate static char		getachar();
2807c478bd9Sstevel@tonic-gate static char		*getblk(), *fmtentry();
2817c478bd9Sstevel@tonic-gate 
282d1a180b0Smaheshvs static offset_t		get(short);
2837c478bd9Sstevel@tonic-gate static long		bmap();
2847c478bd9Sstevel@tonic-gate static long		expr();
2857c478bd9Sstevel@tonic-gate static long		term();
2867c478bd9Sstevel@tonic-gate static long		getnumb();
2877c478bd9Sstevel@tonic-gate static u_offset_t	getdirslot();
288d1a180b0Smaheshvs static unsigned long	*print_check(unsigned long *, long *, short, int);
2897c478bd9Sstevel@tonic-gate 
290d1a180b0Smaheshvs static void		usage(char *);
291d1a180b0Smaheshvs static void		ungetachar(char);
2927c478bd9Sstevel@tonic-gate static void		getnextinput();
2937c478bd9Sstevel@tonic-gate static void		eat_spaces();
294d1a180b0Smaheshvs static void		restore_inode(ino_t);
2957c478bd9Sstevel@tonic-gate static void		find();
296d1a180b0Smaheshvs static void		ls(struct filenames *, struct filenames *, short);
297d1a180b0Smaheshvs static void		formatf(struct filenames *, struct filenames *);
2987c478bd9Sstevel@tonic-gate static void		parse();
299d1a180b0Smaheshvs static void		follow_path(long, long);
3007c478bd9Sstevel@tonic-gate static void		getname();
301d1a180b0Smaheshvs static void		freemem(struct filenames *, int);
302d1a180b0Smaheshvs static void		print_path(char **, int);
3037c478bd9Sstevel@tonic-gate static void		fill();
304d1a180b0Smaheshvs static void		put(u_offset_t, short);
305d1a180b0Smaheshvs static void		insert(struct lbuf *);
3067c478bd9Sstevel@tonic-gate static void		puta();
307d1a180b0Smaheshvs static void		fprnt(char, char);
3087c478bd9Sstevel@tonic-gate static void		index();
3097c478bd9Sstevel@tonic-gate #ifdef _LARGEFILE64_SOURCE
3107c478bd9Sstevel@tonic-gate static void		printll
3117c478bd9Sstevel@tonic-gate 	(u_offset_t value, int fieldsz, int digits, int lead);
3127c478bd9Sstevel@tonic-gate #define	print(value, fieldsz, digits, lead) \
3137c478bd9Sstevel@tonic-gate 	printll((u_offset_t)value, fieldsz, digits, lead)
3147c478bd9Sstevel@tonic-gate #else /* !_LARGEFILE64_SOURCE */
3157c478bd9Sstevel@tonic-gate static void		print(long value, int fieldsz, int digits, int lead);
3167c478bd9Sstevel@tonic-gate #endif /* _LARGEFILE64_SOURCE */
317d1a180b0Smaheshvs static void		printsb(struct fs *);
318d1a180b0Smaheshvs static void		printcg(struct cg *);
319d1a180b0Smaheshvs static void		pbits(unsigned char *, int);
320f45bbb21SToomas Soome static void		old_fsdb(int, char *) __NORETURN;	/* For old fsdb functionality */
321d1a180b0Smaheshvs 
322d1a180b0Smaheshvs static int		isnumber(char *);
323d1a180b0Smaheshvs static int		icheck(u_offset_t);
324d1a180b0Smaheshvs static int		cgrp_check(long);
3257c478bd9Sstevel@tonic-gate static int		valid_addr();
326d1a180b0Smaheshvs static int		match(char *, int);
327d1a180b0Smaheshvs static int		devcheck(short);
3287c478bd9Sstevel@tonic-gate static int		bcomp();
329d1a180b0Smaheshvs static int		compare(char *, char *, short);
330d1a180b0Smaheshvs static int		check_addr(short, short *, short *, short);
3317c478bd9Sstevel@tonic-gate static int		fcmp();
3327c478bd9Sstevel@tonic-gate static int		ffcmp();
3337c478bd9Sstevel@tonic-gate 
334d1a180b0Smaheshvs static int		getshadowslot(long);
335d1a180b0Smaheshvs static void		getshadowdata(long *, int);
336d1a180b0Smaheshvs static void		syncshadowscan(int);
337d1a180b0Smaheshvs static void		log_display_header(void);
338d1a180b0Smaheshvs static void		log_show(enum log_enum);
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate #ifdef sun
3417c478bd9Sstevel@tonic-gate static void		err();
3427c478bd9Sstevel@tonic-gate #else
3437c478bd9Sstevel@tonic-gate static int		err();
3447c478bd9Sstevel@tonic-gate #endif /* sun */
3457c478bd9Sstevel@tonic-gate 
3467c478bd9Sstevel@tonic-gate /* Suboption vector */
3477c478bd9Sstevel@tonic-gate static char *subopt_v[] = {
3487c478bd9Sstevel@tonic-gate #define	OVERRIDE	0
3497c478bd9Sstevel@tonic-gate 	"o",
3507c478bd9Sstevel@tonic-gate #define	NEW_PROMPT	1
3517c478bd9Sstevel@tonic-gate 	"p",
3527c478bd9Sstevel@tonic-gate #define	WRITE_ENABLED	2
3537c478bd9Sstevel@tonic-gate 	"w",
3547c478bd9Sstevel@tonic-gate #define	ALT_PROMPT	3
3557c478bd9Sstevel@tonic-gate 	"prompt",
3567c478bd9Sstevel@tonic-gate 	NULL
3577c478bd9Sstevel@tonic-gate };
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate /*
3607c478bd9Sstevel@tonic-gate  * main - lines are read up to the unprotected ('\') newline and
3617c478bd9Sstevel@tonic-gate  *	held in an input buffer.  Characters may be read from the
3627c478bd9Sstevel@tonic-gate  *	input buffer using getachar() and unread using ungetachar().
3637c478bd9Sstevel@tonic-gate  *	Reading the whole line ahead allows the use of debuggers
3647c478bd9Sstevel@tonic-gate  *	which would otherwise be impossible since the debugger
3657c478bd9Sstevel@tonic-gate  *	and fsdb could not share stdin.
3667c478bd9Sstevel@tonic-gate  */
3677c478bd9Sstevel@tonic-gate 
368d1a180b0Smaheshvs int
main(int argc,char * argv[])369d1a180b0Smaheshvs main(int argc, char *argv[])
3707c478bd9Sstevel@tonic-gate {
3717c478bd9Sstevel@tonic-gate 
372d1a180b0Smaheshvs 	char		c, *cptr;
373d1a180b0Smaheshvs 	short		i;
374d1a180b0Smaheshvs 	struct direct	*dirp;
375d1a180b0Smaheshvs 	struct lbuf	*bp;
376d1a180b0Smaheshvs 	char		*progname;
37767a4bb8fSGary Mills 	volatile short	colon;
37867a4bb8fSGary Mills 	short		mode;
379d1a180b0Smaheshvs 	long		temp;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	/* Options/Suboptions processing */
3827c478bd9Sstevel@tonic-gate 	int	opt;
3837c478bd9Sstevel@tonic-gate 	char	*subopts;
3847c478bd9Sstevel@tonic-gate 	char	*optval;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	/*
3877c478bd9Sstevel@tonic-gate 	 * The following are used to support the old fsdb functionality
3887c478bd9Sstevel@tonic-gate 	 * of clearing an inode. It's better to use 'clri'.
3897c478bd9Sstevel@tonic-gate 	 */
3907c478bd9Sstevel@tonic-gate 	int			inum;	/* Inode number to clear */
3917c478bd9Sstevel@tonic-gate 	char			*special;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	setbuf(stdin, NULL);
3947c478bd9Sstevel@tonic-gate 	progname = argv[0];
3957c478bd9Sstevel@tonic-gate 	prompt = &PROMPT[0];
3967c478bd9Sstevel@tonic-gate 	/*
3977c478bd9Sstevel@tonic-gate 	 * Parse options.
3987c478bd9Sstevel@tonic-gate 	 */
3997c478bd9Sstevel@tonic-gate 	while ((opt = getopt(argc, argv, FSDB_OPTIONS)) != EOF) {
4007c478bd9Sstevel@tonic-gate 		switch (opt) {
4017c478bd9Sstevel@tonic-gate #if defined(OLD_FSDB_COMPATIBILITY)
4027c478bd9Sstevel@tonic-gate 		case 'z':	/* Hack - Better to use clri */
4037c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
4047c478bd9Sstevel@tonic-gate "Warning: The '-z' option of 'fsdb_ufs' has been declared obsolete",
4057c478bd9Sstevel@tonic-gate "and may not be supported in a future version of Solaris.",
4067c478bd9Sstevel@tonic-gate "While this functionality is currently still supported, the",
4077c478bd9Sstevel@tonic-gate "recommended procedure to clear an inode is to use clri(1M).");
4087c478bd9Sstevel@tonic-gate 			if (isnumber(optarg)) {
4097c478bd9Sstevel@tonic-gate 				inum = atoi(optarg);
4107c478bd9Sstevel@tonic-gate 				special = argv[optind];
4117c478bd9Sstevel@tonic-gate 				/* Doesn't return */
4127c478bd9Sstevel@tonic-gate 				old_fsdb(inum, special);
4137c478bd9Sstevel@tonic-gate 			} else {
4147c478bd9Sstevel@tonic-gate 				usage(progname);
4157c478bd9Sstevel@tonic-gate 				exit(31+1);
4167c478bd9Sstevel@tonic-gate 			}
4177c478bd9Sstevel@tonic-gate 			/* Should exit() before here */
4187c478bd9Sstevel@tonic-gate 			/*NOTREACHED*/
4197c478bd9Sstevel@tonic-gate #endif /* OLD_FSDB_COMPATIBILITY */
4207c478bd9Sstevel@tonic-gate 		case 'o':
4217c478bd9Sstevel@tonic-gate 			/* UFS Specific Options */
4227c478bd9Sstevel@tonic-gate 			subopts = optarg;
4237c478bd9Sstevel@tonic-gate 			while (*subopts != '\0') {
4247c478bd9Sstevel@tonic-gate 				switch (getsubopt(&subopts, subopt_v,
4257c478bd9Sstevel@tonic-gate 								&optval)) {
4267c478bd9Sstevel@tonic-gate 				case OVERRIDE:
4277c478bd9Sstevel@tonic-gate 					printf("error checking off\n");
4287c478bd9Sstevel@tonic-gate 					override = 1;
4297c478bd9Sstevel@tonic-gate 					break;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 				/*
4327c478bd9Sstevel@tonic-gate 				 * Change the "-o prompt=foo" option to
4337c478bd9Sstevel@tonic-gate 				 * "-o p=foo" to match documentation.
4347c478bd9Sstevel@tonic-gate 				 * ALT_PROMPT continues support for the
4357c478bd9Sstevel@tonic-gate 				 * undocumented "-o prompt=foo" option so
4367c478bd9Sstevel@tonic-gate 				 * that we don't break anyone.
4377c478bd9Sstevel@tonic-gate 				 */
4387c478bd9Sstevel@tonic-gate 				case NEW_PROMPT:
4397c478bd9Sstevel@tonic-gate 				case ALT_PROMPT:
4407c478bd9Sstevel@tonic-gate 					if (optval == NULL) {
4417c478bd9Sstevel@tonic-gate 						(void) fprintf(stderr,
4427c478bd9Sstevel@tonic-gate 							"No prompt string\n");
4437c478bd9Sstevel@tonic-gate 						usage(progname);
4447c478bd9Sstevel@tonic-gate 					}
4457c478bd9Sstevel@tonic-gate 					(void) strncpy(PROMPT, optval,
4467c478bd9Sstevel@tonic-gate 								PROMPTSIZE);
4477c478bd9Sstevel@tonic-gate 					break;
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 				case WRITE_ENABLED:
4507c478bd9Sstevel@tonic-gate 					/* suitable for open */
4517c478bd9Sstevel@tonic-gate 					wrtflag = O_RDWR;
4527c478bd9Sstevel@tonic-gate 					break;
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 				default:
4557c478bd9Sstevel@tonic-gate 					usage(progname);
4567c478bd9Sstevel@tonic-gate 					/* Should exit here */
4577c478bd9Sstevel@tonic-gate 				}
4587c478bd9Sstevel@tonic-gate 			}
4597c478bd9Sstevel@tonic-gate 			break;
4607c478bd9Sstevel@tonic-gate 
4617c478bd9Sstevel@tonic-gate 		default:
4627c478bd9Sstevel@tonic-gate 			usage(progname);
4637c478bd9Sstevel@tonic-gate 		}
4647c478bd9Sstevel@tonic-gate 	}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 	if ((argc - optind) != 1) {	/* Should just have "special" left */
4677c478bd9Sstevel@tonic-gate 		usage(progname);
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 	special = argv[optind];
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	/*
4727c478bd9Sstevel@tonic-gate 	 * Unless it's already been set, the default prompt includes the
4737c478bd9Sstevel@tonic-gate 	 * name of the special device.
4747c478bd9Sstevel@tonic-gate 	 */
475*8509e9caSToomas Soome 	if (*prompt == '\0')
4767c478bd9Sstevel@tonic-gate 		(void) sprintf(prompt, "%s > ", special);
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/*
4797c478bd9Sstevel@tonic-gate 	 * Attempt to open the special file.
4807c478bd9Sstevel@tonic-gate 	 */
4817c478bd9Sstevel@tonic-gate 	if ((fd = open(special, wrtflag)) < 0) {
4827c478bd9Sstevel@tonic-gate 		perror(special);
4837c478bd9Sstevel@tonic-gate 		exit(1);
4847c478bd9Sstevel@tonic-gate 	}
4857c478bd9Sstevel@tonic-gate 	/*
4867c478bd9Sstevel@tonic-gate 	 * Read in the super block and validate (not too picky).
4877c478bd9Sstevel@tonic-gate 	 */
4887c478bd9Sstevel@tonic-gate 	if (llseek(fd, (offset_t)(SBLOCK * DEV_BSIZE), 0) == -1) {
4897c478bd9Sstevel@tonic-gate 		perror(special);
4907c478bd9Sstevel@tonic-gate 		exit(1);
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate #ifdef sun
4947c478bd9Sstevel@tonic-gate 	if (read(fd, &filesystem, SBSIZE) != SBSIZE) {
4957c478bd9Sstevel@tonic-gate 		printf("%s: cannot read superblock\n", special);
4967c478bd9Sstevel@tonic-gate 		exit(1);
4977c478bd9Sstevel@tonic-gate 	}
4987c478bd9Sstevel@tonic-gate #else
4997c478bd9Sstevel@tonic-gate 	if (read(fd, &filesystem, sizeof (filesystem)) != sizeof (filesystem)) {
5007c478bd9Sstevel@tonic-gate 		printf("%s: cannot read superblock\n", special);
5017c478bd9Sstevel@tonic-gate 		exit(1);
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate #endif /* sun */
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	fs = &filesystem;
5067c478bd9Sstevel@tonic-gate 	if ((fs->fs_magic != FS_MAGIC) && (fs->fs_magic != MTB_UFS_MAGIC)) {
5077c478bd9Sstevel@tonic-gate 		if (!override) {
5087c478bd9Sstevel@tonic-gate 			printf("%s: Bad magic number in file system\n",
5097c478bd9Sstevel@tonic-gate 								special);
5107c478bd9Sstevel@tonic-gate 			exit(1);
5117c478bd9Sstevel@tonic-gate 		}
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 		printf("WARNING: Bad magic number in file system. ");
5147c478bd9Sstevel@tonic-gate 		printf("Continue? (y/n): ");
5157c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5167c478bd9Sstevel@tonic-gate 		if (gets(input_buffer) == NULL) {
5177c478bd9Sstevel@tonic-gate 			exit(1);
5187c478bd9Sstevel@tonic-gate 		}
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 		if (*input_buffer != 'y' && *input_buffer != 'Y') {
5217c478bd9Sstevel@tonic-gate 			exit(1);
5227c478bd9Sstevel@tonic-gate 		}
5237c478bd9Sstevel@tonic-gate 	}
5247c478bd9Sstevel@tonic-gate 
5256451fdbcSvsakar 	if ((fs->fs_magic == FS_MAGIC &&
5266451fdbcSvsakar 	    (fs->fs_version != UFS_EFISTYLE4NONEFI_VERSION_2 &&
5276451fdbcSvsakar 	    fs->fs_version != UFS_VERSION_MIN)) ||
5286451fdbcSvsakar 	    (fs->fs_magic == MTB_UFS_MAGIC &&
5297c478bd9Sstevel@tonic-gate 	    (fs->fs_version > MTB_UFS_VERSION_1 ||
5306451fdbcSvsakar 	    fs->fs_version < MTB_UFS_VERSION_MIN))) {
5317c478bd9Sstevel@tonic-gate 		if (!override) {
5327c478bd9Sstevel@tonic-gate 			printf("%s: Unrecognized UFS version number: %d\n",
5337c478bd9Sstevel@tonic-gate 			    special, fs->fs_version);
5347c478bd9Sstevel@tonic-gate 			exit(1);
5357c478bd9Sstevel@tonic-gate 		}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 		printf("WARNING: Unrecognized UFS version number. ");
5387c478bd9Sstevel@tonic-gate 		printf("Continue? (y/n): ");
5397c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5407c478bd9Sstevel@tonic-gate 		if (gets(input_buffer) == NULL) {
5417c478bd9Sstevel@tonic-gate 			exit(1);
5427c478bd9Sstevel@tonic-gate 		}
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		if (*input_buffer != 'y' && *input_buffer != 'Y') {
5457c478bd9Sstevel@tonic-gate 			exit(1);
5467c478bd9Sstevel@tonic-gate 		}
5477c478bd9Sstevel@tonic-gate 	}
5487c478bd9Sstevel@tonic-gate #ifdef FS_42POSTBLFMT
5497c478bd9Sstevel@tonic-gate 	if (fs->fs_postblformat == FS_42POSTBLFMT)
5507c478bd9Sstevel@tonic-gate 		fs->fs_nrpos = 8;
5517c478bd9Sstevel@tonic-gate #endif
5527c478bd9Sstevel@tonic-gate 	printf("fsdb of %s %s -- last mounted on %s\n",
5537c478bd9Sstevel@tonic-gate 		special,
5547c478bd9Sstevel@tonic-gate 		(wrtflag == O_RDWR) ? "(Opened for write)" : "(Read only)",
5557c478bd9Sstevel@tonic-gate 		&fs->fs_fsmnt[0]);
5567c478bd9Sstevel@tonic-gate #ifdef sun
5577c478bd9Sstevel@tonic-gate 	printf("fs_clean is currently set to ");
5587c478bd9Sstevel@tonic-gate 	switch (fs->fs_clean) {
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 	case FSACTIVE:
5617c478bd9Sstevel@tonic-gate 		printf("FSACTIVE\n");
5627c478bd9Sstevel@tonic-gate 		break;
5637c478bd9Sstevel@tonic-gate 	case FSCLEAN:
5647c478bd9Sstevel@tonic-gate 		printf("FSCLEAN\n");
5657c478bd9Sstevel@tonic-gate 		break;
5667c478bd9Sstevel@tonic-gate 	case FSSTABLE:
5677c478bd9Sstevel@tonic-gate 		printf("FSSTABLE\n");
5687c478bd9Sstevel@tonic-gate 		break;
5697c478bd9Sstevel@tonic-gate 	case FSBAD:
5707c478bd9Sstevel@tonic-gate 		printf("FSBAD\n");
5717c478bd9Sstevel@tonic-gate 		break;
5727c478bd9Sstevel@tonic-gate 	case FSSUSPEND:
5737c478bd9Sstevel@tonic-gate 		printf("FSSUSPEND\n");
5747c478bd9Sstevel@tonic-gate 		break;
5757c478bd9Sstevel@tonic-gate 	case FSLOG:
5767c478bd9Sstevel@tonic-gate 		printf("FSLOG\n");
5777c478bd9Sstevel@tonic-gate 		break;
5787c478bd9Sstevel@tonic-gate 	case FSFIX:
5797c478bd9Sstevel@tonic-gate 		printf("FSFIX\n");
5807c478bd9Sstevel@tonic-gate 		if (!override) {
5817c478bd9Sstevel@tonic-gate 			printf("%s: fsck may be running on this file system\n",
5827c478bd9Sstevel@tonic-gate 								special);
5837c478bd9Sstevel@tonic-gate 			exit(1);
5847c478bd9Sstevel@tonic-gate 		}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 		printf("WARNING: fsck may be running on this file system. ");
5877c478bd9Sstevel@tonic-gate 		printf("Continue? (y/n): ");
5887c478bd9Sstevel@tonic-gate 		(void) fflush(stdout);
5897c478bd9Sstevel@tonic-gate 		if (gets(input_buffer) == NULL) {
5907c478bd9Sstevel@tonic-gate 			exit(1);
5917c478bd9Sstevel@tonic-gate 		}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 		if (*input_buffer != 'y' && *input_buffer != 'Y') {
5947c478bd9Sstevel@tonic-gate 			exit(1);
5957c478bd9Sstevel@tonic-gate 		}
5967c478bd9Sstevel@tonic-gate 		break;
5977c478bd9Sstevel@tonic-gate 	default:
5987c478bd9Sstevel@tonic-gate 		printf("an unknown value (0x%x)\n", fs->fs_clean);
5997c478bd9Sstevel@tonic-gate 		break;
6007c478bd9Sstevel@tonic-gate 	}
6017c478bd9Sstevel@tonic-gate 
6027c478bd9Sstevel@tonic-gate 	if (fs->fs_state == (FSOKAY - fs->fs_time)) {
6037c478bd9Sstevel@tonic-gate 		printf("fs_state consistent (fs_clean CAN be trusted)\n");
6047c478bd9Sstevel@tonic-gate 	} else {
6057c478bd9Sstevel@tonic-gate 		printf("fs_state inconsistent (fs_clean CAN'T trusted)\n");
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate #endif /* sun */
6087c478bd9Sstevel@tonic-gate 	/*
6097c478bd9Sstevel@tonic-gate 	 * Malloc buffers and set up cache.
6107c478bd9Sstevel@tonic-gate 	 */
6117c478bd9Sstevel@tonic-gate 	buffers = malloc(NBUF * BLKSIZE);
6127c478bd9Sstevel@tonic-gate 	bhdr.fwd = bhdr.back = &bhdr;
6137c478bd9Sstevel@tonic-gate 	for (i = 0; i < NBUF; i++) {
6147c478bd9Sstevel@tonic-gate 		bp = &lbuf[i];
6157c478bd9Sstevel@tonic-gate 		bp->blkaddr = buffers + (i * BLKSIZE);
6167c478bd9Sstevel@tonic-gate 		bp->valid = 0;
6177c478bd9Sstevel@tonic-gate 		insert(bp);
6187c478bd9Sstevel@tonic-gate 	}
6197c478bd9Sstevel@tonic-gate 	/*
6207c478bd9Sstevel@tonic-gate 	 * Malloc filenames structure.  The space for the actual filenames
6217c478bd9Sstevel@tonic-gate 	 * is allocated as it needs it. We estimate the size based on the
6227c478bd9Sstevel@tonic-gate 	 * number of inodes(objects) in the filesystem and the number of
6237c478bd9Sstevel@tonic-gate 	 * directories.  The number of directories are padded by 3 because
6247c478bd9Sstevel@tonic-gate 	 * each directory traversed during a "find" or "ls -R" needs 3
6257c478bd9Sstevel@tonic-gate 	 * entries.
6267c478bd9Sstevel@tonic-gate 	 */
6277c478bd9Sstevel@tonic-gate 	maxfiles = (long)((((u_offset_t)fs->fs_ncg * (u_offset_t)fs->fs_ipg) -
6287c478bd9Sstevel@tonic-gate 	    (u_offset_t)fs->fs_cstotal.cs_nifree) +
6297c478bd9Sstevel@tonic-gate 	    ((u_offset_t)fs->fs_cstotal.cs_ndir * (u_offset_t)3));
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	filenames = (struct filenames *)calloc(maxfiles,
6327c478bd9Sstevel@tonic-gate 	    sizeof (struct filenames));
6337c478bd9Sstevel@tonic-gate 	if (filenames == NULL) {
6347c478bd9Sstevel@tonic-gate 		/*
6357c478bd9Sstevel@tonic-gate 		 * If we could not allocate memory for all of files
6367c478bd9Sstevel@tonic-gate 		 * in the filesystem then, back off to the old fixed
6377c478bd9Sstevel@tonic-gate 		 * value.
6387c478bd9Sstevel@tonic-gate 		 */
6397c478bd9Sstevel@tonic-gate 		maxfiles = MAXFILES;
6407c478bd9Sstevel@tonic-gate 		filenames = (struct filenames *)calloc(maxfiles,
6417c478bd9Sstevel@tonic-gate 		    sizeof (struct filenames));
6427c478bd9Sstevel@tonic-gate 		if (filenames == NULL) {
6437c478bd9Sstevel@tonic-gate 			printf("out of memory\n");
6447c478bd9Sstevel@tonic-gate 			exit(1);
6457c478bd9Sstevel@tonic-gate 		}
6467c478bd9Sstevel@tonic-gate 	}
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 	restore_inode(2);
6497c478bd9Sstevel@tonic-gate 	/*
6507c478bd9Sstevel@tonic-gate 	 * Malloc a few filenames (needed by pwd for example).
6517c478bd9Sstevel@tonic-gate 	 */
6527c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAXPATHLEN; i++) {
6537c478bd9Sstevel@tonic-gate 		input_path[i] = calloc(1, MAXNAMLEN);
6547c478bd9Sstevel@tonic-gate 		stack_path[i] = calloc(1, MAXNAMLEN);
6557c478bd9Sstevel@tonic-gate 		current_path[i] = calloc(1, MAXNAMLEN);
6567c478bd9Sstevel@tonic-gate 		if (current_path[i] == NULL) {
6577c478bd9Sstevel@tonic-gate 			printf("out of memory\n");
6587c478bd9Sstevel@tonic-gate 			exit(1);
6597c478bd9Sstevel@tonic-gate 		}
6607c478bd9Sstevel@tonic-gate 	}
6617c478bd9Sstevel@tonic-gate 	current_pathp = -1;
6627c478bd9Sstevel@tonic-gate 
6637c478bd9Sstevel@tonic-gate 	(void) signal(2, err);
6647c478bd9Sstevel@tonic-gate 	(void) setjmp(env);
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate 	getnextinput();
6677c478bd9Sstevel@tonic-gate 	/*
6687c478bd9Sstevel@tonic-gate 	 * Main loop and case statement.  If an error condition occurs
6697c478bd9Sstevel@tonic-gate 	 * initialization and recovery is attempted.
6707c478bd9Sstevel@tonic-gate 	 */
6717c478bd9Sstevel@tonic-gate 	for (;;) {
6727c478bd9Sstevel@tonic-gate 		if (error) {
6737c478bd9Sstevel@tonic-gate 			freemem(filenames, nfiles);
6747c478bd9Sstevel@tonic-gate 			nfiles = 0;
6757c478bd9Sstevel@tonic-gate 			c_count = 0;
6767c478bd9Sstevel@tonic-gate 			count = 1;
6777c478bd9Sstevel@tonic-gate 			star = 0;
6787c478bd9Sstevel@tonic-gate 			error = 0;
6797c478bd9Sstevel@tonic-gate 			paren = 0;
6807c478bd9Sstevel@tonic-gate 			acting_on_inode = 0;
6817c478bd9Sstevel@tonic-gate 			acting_on_directory = 0;
6827c478bd9Sstevel@tonic-gate 			should_print = 1;
6837c478bd9Sstevel@tonic-gate 			addr = erraddr;
6847c478bd9Sstevel@tonic-gate 			cur_ino = errino;
6857c478bd9Sstevel@tonic-gate 			cur_inum = errinum;
6867c478bd9Sstevel@tonic-gate 			cur_bytes = errcur_bytes;
6877c478bd9Sstevel@tonic-gate 			printf("?\n");
6887c478bd9Sstevel@tonic-gate 			getnextinput();
6897c478bd9Sstevel@tonic-gate 			if (error)
6907c478bd9Sstevel@tonic-gate 				continue;
6917c478bd9Sstevel@tonic-gate 		}
6927c478bd9Sstevel@tonic-gate 		c_count++;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 		switch (c = getachar()) {
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 		case '\n': /* command end */
6977c478bd9Sstevel@tonic-gate 			freemem(filenames, nfiles);
6987c478bd9Sstevel@tonic-gate 			nfiles = 0;
6997c478bd9Sstevel@tonic-gate 			if (should_print && laststyle == '=') {
7007c478bd9Sstevel@tonic-gate 				ungetachar(c);
7017c478bd9Sstevel@tonic-gate 				goto calc;
7027c478bd9Sstevel@tonic-gate 			}
7037c478bd9Sstevel@tonic-gate 			if (c_count == 1) {
7047c478bd9Sstevel@tonic-gate 				clear = 0;
7057c478bd9Sstevel@tonic-gate 				should_print = 1;
7067c478bd9Sstevel@tonic-gate 				erraddr = addr;
7077c478bd9Sstevel@tonic-gate 				errino = cur_ino;
7087c478bd9Sstevel@tonic-gate 				errinum = cur_inum;
7097c478bd9Sstevel@tonic-gate 				errcur_bytes = cur_bytes;
7107c478bd9Sstevel@tonic-gate 				switch (objsz) {
7117c478bd9Sstevel@tonic-gate 				case DIRECTORY:
7127c478bd9Sstevel@tonic-gate 					if ((addr = getdirslot(
7137c478bd9Sstevel@tonic-gate 							(long)dirslot+1)) == 0)
7147c478bd9Sstevel@tonic-gate 						should_print = 0;
7157c478bd9Sstevel@tonic-gate 					if (error) {
7167c478bd9Sstevel@tonic-gate 						ungetachar(c);
7177c478bd9Sstevel@tonic-gate 						continue;
7187c478bd9Sstevel@tonic-gate 					}
7197c478bd9Sstevel@tonic-gate 					break;
7207c478bd9Sstevel@tonic-gate 				case INODE:
7217c478bd9Sstevel@tonic-gate 					cur_inum++;
7227c478bd9Sstevel@tonic-gate 					addr = itob(cur_inum);
7237c478bd9Sstevel@tonic-gate 					if (!icheck(addr)) {
7247c478bd9Sstevel@tonic-gate 						cur_inum--;
7257c478bd9Sstevel@tonic-gate 						should_print = 0;
7267c478bd9Sstevel@tonic-gate 					}
7277c478bd9Sstevel@tonic-gate 					break;
7287c478bd9Sstevel@tonic-gate 				case CGRP:
7297c478bd9Sstevel@tonic-gate 				case SB:
7307c478bd9Sstevel@tonic-gate 					cur_cgrp++;
7317c478bd9Sstevel@tonic-gate 					addr = cgrp_check(cur_cgrp);
7327c478bd9Sstevel@tonic-gate 					if (addr == 0) {
7337c478bd9Sstevel@tonic-gate 						cur_cgrp--;
7347c478bd9Sstevel@tonic-gate 						continue;
7357c478bd9Sstevel@tonic-gate 					}
7367c478bd9Sstevel@tonic-gate 					break;
7377c478bd9Sstevel@tonic-gate 				case SHADOW_DATA:
7387c478bd9Sstevel@tonic-gate 					if ((addr = getshadowslot(
7397c478bd9Sstevel@tonic-gate 					    (long)cur_shad + 1)) == 0)
7407c478bd9Sstevel@tonic-gate 						should_print = 0;
7417c478bd9Sstevel@tonic-gate 					if (error) {
7427c478bd9Sstevel@tonic-gate 						ungetachar(c);
7437c478bd9Sstevel@tonic-gate 						continue;
7447c478bd9Sstevel@tonic-gate 					}
7457c478bd9Sstevel@tonic-gate 					break;
7467c478bd9Sstevel@tonic-gate 				default:
7477c478bd9Sstevel@tonic-gate 					addr += objsz;
7487c478bd9Sstevel@tonic-gate 					cur_bytes += objsz;
7497c478bd9Sstevel@tonic-gate 					if (valid_addr() == 0)
7507c478bd9Sstevel@tonic-gate 						continue;
7517c478bd9Sstevel@tonic-gate 				}
7527c478bd9Sstevel@tonic-gate 			}
7537c478bd9Sstevel@tonic-gate 			if (type == NUMB)
7547c478bd9Sstevel@tonic-gate 				trapped = 0;
7557c478bd9Sstevel@tonic-gate 			if (should_print)
7567c478bd9Sstevel@tonic-gate 				switch (objsz) {
7577c478bd9Sstevel@tonic-gate 				case DIRECTORY:
7587c478bd9Sstevel@tonic-gate 					fprnt('?', 'd');
7597c478bd9Sstevel@tonic-gate 					break;
7607c478bd9Sstevel@tonic-gate 				case INODE:
7617c478bd9Sstevel@tonic-gate 					fprnt('?', 'i');
7627c478bd9Sstevel@tonic-gate 					if (!error)
7637c478bd9Sstevel@tonic-gate 						cur_ino = addr;
7647c478bd9Sstevel@tonic-gate 					break;
7657c478bd9Sstevel@tonic-gate 				case CGRP:
7667c478bd9Sstevel@tonic-gate 					fprnt('?', 'c');
7677c478bd9Sstevel@tonic-gate 					break;
7687c478bd9Sstevel@tonic-gate 				case SB:
7697c478bd9Sstevel@tonic-gate 					fprnt('?', 's');
7707c478bd9Sstevel@tonic-gate 					break;
7717c478bd9Sstevel@tonic-gate 				case SHADOW_DATA:
7727c478bd9Sstevel@tonic-gate 					fprnt('?', 'S');
7737c478bd9Sstevel@tonic-gate 					break;
7747c478bd9Sstevel@tonic-gate 				case CHAR:
7757c478bd9Sstevel@tonic-gate 				case SHORT:
7767c478bd9Sstevel@tonic-gate 				case LONG:
7777c478bd9Sstevel@tonic-gate 					fprnt(laststyle, lastpo);
7787c478bd9Sstevel@tonic-gate 				}
7797c478bd9Sstevel@tonic-gate 			if (error) {
7807c478bd9Sstevel@tonic-gate 				ungetachar(c);
7817c478bd9Sstevel@tonic-gate 				continue;
7827c478bd9Sstevel@tonic-gate 			}
7837c478bd9Sstevel@tonic-gate 			c_count = colon = acting_on_inode = 0;
7847c478bd9Sstevel@tonic-gate 			acting_on_directory = 0;
7857c478bd9Sstevel@tonic-gate 			should_print = 1;
7867c478bd9Sstevel@tonic-gate 			getnextinput();
7877c478bd9Sstevel@tonic-gate 			if (error)
7887c478bd9Sstevel@tonic-gate 				continue;
7897c478bd9Sstevel@tonic-gate 			erraddr = addr;
7907c478bd9Sstevel@tonic-gate 			errino = cur_ino;
7917c478bd9Sstevel@tonic-gate 			errinum = cur_inum;
7927c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
7937c478bd9Sstevel@tonic-gate 			continue;
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 		case '(': /* numeric expression or unknown command */
7967c478bd9Sstevel@tonic-gate 		default:
7977c478bd9Sstevel@tonic-gate 			colon = 0;
7987c478bd9Sstevel@tonic-gate 			if (digit(c) || c == '(') {
7997c478bd9Sstevel@tonic-gate 				ungetachar(c);
8007c478bd9Sstevel@tonic-gate 				addr = expr();
8017c478bd9Sstevel@tonic-gate 				type = NUMB;
8027c478bd9Sstevel@tonic-gate 				value = addr;
8037c478bd9Sstevel@tonic-gate 				continue;
8047c478bd9Sstevel@tonic-gate 			}
8057c478bd9Sstevel@tonic-gate 			printf("unknown command or bad syntax\n");
8067c478bd9Sstevel@tonic-gate 			error++;
8077c478bd9Sstevel@tonic-gate 			continue;
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 		case '?': /* general print facilities */
8107c478bd9Sstevel@tonic-gate 		case '/':
8117c478bd9Sstevel@tonic-gate 			fprnt(c, getachar());
8127c478bd9Sstevel@tonic-gate 			continue;
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 		case ';': /* command separator and . */
8157c478bd9Sstevel@tonic-gate 		case '\t':
8167c478bd9Sstevel@tonic-gate 		case ' ':
8177c478bd9Sstevel@tonic-gate 		case '.':
8187c478bd9Sstevel@tonic-gate 			continue;
8197c478bd9Sstevel@tonic-gate 
8207c478bd9Sstevel@tonic-gate 		case ':': /* command indicator */
8217c478bd9Sstevel@tonic-gate 			colon++;
8227c478bd9Sstevel@tonic-gate 			commands++;
8237c478bd9Sstevel@tonic-gate 			should_print = 0;
8247c478bd9Sstevel@tonic-gate 			stringsize = 0;
8257c478bd9Sstevel@tonic-gate 			trapped = 0;
8267c478bd9Sstevel@tonic-gate 			continue;
8277c478bd9Sstevel@tonic-gate 
8287c478bd9Sstevel@tonic-gate 		case ',': /* count indicator */
8297c478bd9Sstevel@tonic-gate 			colon = star = 0;
8307c478bd9Sstevel@tonic-gate 			if ((c = getachar()) == '*') {
8317c478bd9Sstevel@tonic-gate 				star = 1;
8327c478bd9Sstevel@tonic-gate 				count = BLKSIZE;
8337c478bd9Sstevel@tonic-gate 			} else {
8347c478bd9Sstevel@tonic-gate 				ungetachar(c);
8357c478bd9Sstevel@tonic-gate 				count = expr();
8367c478bd9Sstevel@tonic-gate 				if (error)
8377c478bd9Sstevel@tonic-gate 					continue;
8387c478bd9Sstevel@tonic-gate 				if (!count)
8397c478bd9Sstevel@tonic-gate 					count = 1;
8407c478bd9Sstevel@tonic-gate 			}
8417c478bd9Sstevel@tonic-gate 			clear = 0;
8427c478bd9Sstevel@tonic-gate 			continue;
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 		case '+': /* address addition */
8457c478bd9Sstevel@tonic-gate 			colon = 0;
8467c478bd9Sstevel@tonic-gate 			c = getachar();
8477c478bd9Sstevel@tonic-gate 			ungetachar(c);
8487c478bd9Sstevel@tonic-gate 			if (c == '\n')
8497c478bd9Sstevel@tonic-gate 				temp = 1;
8507c478bd9Sstevel@tonic-gate 			else {
8517c478bd9Sstevel@tonic-gate 				temp = expr();
8527c478bd9Sstevel@tonic-gate 				if (error)
8537c478bd9Sstevel@tonic-gate 					continue;
8547c478bd9Sstevel@tonic-gate 			}
8557c478bd9Sstevel@tonic-gate 			erraddr = addr;
8567c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
8577c478bd9Sstevel@tonic-gate 			switch (objsz) {
8587c478bd9Sstevel@tonic-gate 			case DIRECTORY:
8597c478bd9Sstevel@tonic-gate 				addr = getdirslot((long)(dirslot + temp));
8607c478bd9Sstevel@tonic-gate 				if (error)
8617c478bd9Sstevel@tonic-gate 					continue;
8627c478bd9Sstevel@tonic-gate 				break;
8637c478bd9Sstevel@tonic-gate 			case INODE:
8647c478bd9Sstevel@tonic-gate 				cur_inum += temp;
8657c478bd9Sstevel@tonic-gate 				addr = itob(cur_inum);
8667c478bd9Sstevel@tonic-gate 				if (!icheck(addr)) {
8677c478bd9Sstevel@tonic-gate 					cur_inum -= temp;
8687c478bd9Sstevel@tonic-gate 					continue;
8697c478bd9Sstevel@tonic-gate 				}
8707c478bd9Sstevel@tonic-gate 				break;
8717c478bd9Sstevel@tonic-gate 			case CGRP:
8727c478bd9Sstevel@tonic-gate 			case SB:
8737c478bd9Sstevel@tonic-gate 				cur_cgrp += temp;
8747c478bd9Sstevel@tonic-gate 				if ((addr = cgrp_check(cur_cgrp)) == 0) {
8757c478bd9Sstevel@tonic-gate 					cur_cgrp -= temp;
8767c478bd9Sstevel@tonic-gate 					continue;
8777c478bd9Sstevel@tonic-gate 				}
8787c478bd9Sstevel@tonic-gate 				break;
8797c478bd9Sstevel@tonic-gate 			case SHADOW_DATA:
8807c478bd9Sstevel@tonic-gate 				addr = getshadowslot((long)(cur_shad + temp));
8817c478bd9Sstevel@tonic-gate 				if (error)
8827c478bd9Sstevel@tonic-gate 				    continue;
8837c478bd9Sstevel@tonic-gate 				break;
8847c478bd9Sstevel@tonic-gate 
8857c478bd9Sstevel@tonic-gate 			default:
8867c478bd9Sstevel@tonic-gate 				laststyle = '/';
8877c478bd9Sstevel@tonic-gate 				addr += temp * objsz;
8887c478bd9Sstevel@tonic-gate 				cur_bytes += temp * objsz;
8897c478bd9Sstevel@tonic-gate 				if (valid_addr() == 0)
8907c478bd9Sstevel@tonic-gate 					continue;
8917c478bd9Sstevel@tonic-gate 			}
8927c478bd9Sstevel@tonic-gate 			value = get(objsz);
8937c478bd9Sstevel@tonic-gate 			continue;
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate 		case '-': /* address subtraction */
8967c478bd9Sstevel@tonic-gate 			colon = 0;
8977c478bd9Sstevel@tonic-gate 			c = getachar();
8987c478bd9Sstevel@tonic-gate 			ungetachar(c);
8997c478bd9Sstevel@tonic-gate 			if (c == '\n')
9007c478bd9Sstevel@tonic-gate 				temp = 1;
9017c478bd9Sstevel@tonic-gate 			else {
9027c478bd9Sstevel@tonic-gate 				temp = expr();
9037c478bd9Sstevel@tonic-gate 				if (error)
9047c478bd9Sstevel@tonic-gate 					continue;
9057c478bd9Sstevel@tonic-gate 			}
9067c478bd9Sstevel@tonic-gate 			erraddr = addr;
9077c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
9087c478bd9Sstevel@tonic-gate 			switch (objsz) {
9097c478bd9Sstevel@tonic-gate 			case DIRECTORY:
9107c478bd9Sstevel@tonic-gate 				addr = getdirslot((long)(dirslot - temp));
9117c478bd9Sstevel@tonic-gate 				if (error)
9127c478bd9Sstevel@tonic-gate 					continue;
9137c478bd9Sstevel@tonic-gate 				break;
9147c478bd9Sstevel@tonic-gate 			case INODE:
9157c478bd9Sstevel@tonic-gate 				cur_inum -= temp;
9167c478bd9Sstevel@tonic-gate 				addr = itob(cur_inum);
9177c478bd9Sstevel@tonic-gate 				if (!icheck(addr)) {
9187c478bd9Sstevel@tonic-gate 					cur_inum += temp;
9197c478bd9Sstevel@tonic-gate 					continue;
9207c478bd9Sstevel@tonic-gate 				}
9217c478bd9Sstevel@tonic-gate 				break;
9227c478bd9Sstevel@tonic-gate 			case CGRP:
9237c478bd9Sstevel@tonic-gate 			case SB:
9247c478bd9Sstevel@tonic-gate 				cur_cgrp -= temp;
9257c478bd9Sstevel@tonic-gate 				if ((addr = cgrp_check(cur_cgrp)) == 0) {
9267c478bd9Sstevel@tonic-gate 					cur_cgrp += temp;
9277c478bd9Sstevel@tonic-gate 					continue;
9287c478bd9Sstevel@tonic-gate 				}
9297c478bd9Sstevel@tonic-gate 				break;
9307c478bd9Sstevel@tonic-gate 			case SHADOW_DATA:
9317c478bd9Sstevel@tonic-gate 				addr = getshadowslot((long)(cur_shad - temp));
9327c478bd9Sstevel@tonic-gate 				if (error)
9337c478bd9Sstevel@tonic-gate 					continue;
9347c478bd9Sstevel@tonic-gate 				break;
9357c478bd9Sstevel@tonic-gate 			default:
9367c478bd9Sstevel@tonic-gate 				laststyle = '/';
9377c478bd9Sstevel@tonic-gate 				addr -= temp * objsz;
9387c478bd9Sstevel@tonic-gate 				cur_bytes -= temp * objsz;
9397c478bd9Sstevel@tonic-gate 				if (valid_addr() == 0)
9407c478bd9Sstevel@tonic-gate 					continue;
9417c478bd9Sstevel@tonic-gate 			}
9427c478bd9Sstevel@tonic-gate 			value = get(objsz);
9437c478bd9Sstevel@tonic-gate 			continue;
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 		case '*': /* address multiplication */
9467c478bd9Sstevel@tonic-gate 			colon = 0;
9477c478bd9Sstevel@tonic-gate 			temp = expr();
9487c478bd9Sstevel@tonic-gate 			if (error)
9497c478bd9Sstevel@tonic-gate 				continue;
9507c478bd9Sstevel@tonic-gate 			if (objsz != INODE && objsz != DIRECTORY)
9517c478bd9Sstevel@tonic-gate 				laststyle = '/';
9527c478bd9Sstevel@tonic-gate 			addr *= temp;
9537c478bd9Sstevel@tonic-gate 			value = get(objsz);
9547c478bd9Sstevel@tonic-gate 			continue;
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 		case '%': /* address division */
9577c478bd9Sstevel@tonic-gate 			colon = 0;
9587c478bd9Sstevel@tonic-gate 			temp = expr();
9597c478bd9Sstevel@tonic-gate 			if (error)
9607c478bd9Sstevel@tonic-gate 				continue;
9617c478bd9Sstevel@tonic-gate 			if (!temp) {
9627c478bd9Sstevel@tonic-gate 				printf("divide by zero\n");
9637c478bd9Sstevel@tonic-gate 				error++;
9647c478bd9Sstevel@tonic-gate 				continue;
9657c478bd9Sstevel@tonic-gate 			}
9667c478bd9Sstevel@tonic-gate 			if (objsz != INODE && objsz != DIRECTORY)
9677c478bd9Sstevel@tonic-gate 				laststyle = '/';
9687c478bd9Sstevel@tonic-gate 			addr /= temp;
9697c478bd9Sstevel@tonic-gate 			value = get(objsz);
9707c478bd9Sstevel@tonic-gate 			continue;
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate 		case '=': { /* assignment operation */
9737c478bd9Sstevel@tonic-gate 			short tbase;
9747c478bd9Sstevel@tonic-gate calc:
9757c478bd9Sstevel@tonic-gate 			tbase = base;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 			c = getachar();
9787c478bd9Sstevel@tonic-gate 			if (c == '\n') {
9797c478bd9Sstevel@tonic-gate 				ungetachar(c);
9807c478bd9Sstevel@tonic-gate 				c = lastpo;
9817c478bd9Sstevel@tonic-gate 				if (acting_on_inode == 1) {
9827c478bd9Sstevel@tonic-gate 					if (c != 'o' && c != 'd' && c != 'x' &&
9837c478bd9Sstevel@tonic-gate 					    c != 'O' && c != 'D' && c != 'X') {
9847c478bd9Sstevel@tonic-gate 						switch (objsz) {
9857c478bd9Sstevel@tonic-gate 						case LONG:
9867c478bd9Sstevel@tonic-gate 							c = lastpo = 'X';
9877c478bd9Sstevel@tonic-gate 							break;
9887c478bd9Sstevel@tonic-gate 						case SHORT:
9897c478bd9Sstevel@tonic-gate 							c = lastpo = 'x';
9907c478bd9Sstevel@tonic-gate 							break;
9917c478bd9Sstevel@tonic-gate 						case CHAR:
9927c478bd9Sstevel@tonic-gate 							c = lastpo = 'c';
9937c478bd9Sstevel@tonic-gate 						}
9947c478bd9Sstevel@tonic-gate 					}
9957c478bd9Sstevel@tonic-gate 				} else {
9967c478bd9Sstevel@tonic-gate 					if (acting_on_inode == 2)
9977c478bd9Sstevel@tonic-gate 						c = lastpo = 't';
9987c478bd9Sstevel@tonic-gate 				}
9997c478bd9Sstevel@tonic-gate 			} else if (acting_on_inode)
10007c478bd9Sstevel@tonic-gate 				lastpo = c;
10017c478bd9Sstevel@tonic-gate 			should_print = star = 0;
10027c478bd9Sstevel@tonic-gate 			count = 1;
10037c478bd9Sstevel@tonic-gate 			erraddr = addr;
10047c478bd9Sstevel@tonic-gate 			errcur_bytes = cur_bytes;
10057c478bd9Sstevel@tonic-gate 			switch (c) {
10067c478bd9Sstevel@tonic-gate 			case '"': /* character string */
10077c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
10087c478bd9Sstevel@tonic-gate 					blocksize = BLKSIZE;
10097c478bd9Sstevel@tonic-gate 					filesize = BLKSIZE * 2;
10107c478bd9Sstevel@tonic-gate 					cur_bytes = blkoff(fs, addr);
10117c478bd9Sstevel@tonic-gate 					if (objsz == DIRECTORY ||
10127c478bd9Sstevel@tonic-gate 								objsz == INODE)
10137c478bd9Sstevel@tonic-gate 						lastpo = 'X';
10147c478bd9Sstevel@tonic-gate 				}
10157c478bd9Sstevel@tonic-gate 				puta();
10167c478bd9Sstevel@tonic-gate 				continue;
10177c478bd9Sstevel@tonic-gate 			case '+': /* =+ operator */
10187c478bd9Sstevel@tonic-gate 				temp = expr();
10197c478bd9Sstevel@tonic-gate 				value = get(objsz);
10207c478bd9Sstevel@tonic-gate 				if (!error)
10217c478bd9Sstevel@tonic-gate 					put(value+temp, objsz);
10227c478bd9Sstevel@tonic-gate 				continue;
10237c478bd9Sstevel@tonic-gate 			case '-': /* =- operator */
10247c478bd9Sstevel@tonic-gate 				temp = expr();
10257c478bd9Sstevel@tonic-gate 				value = get(objsz);
10267c478bd9Sstevel@tonic-gate 				if (!error)
10277c478bd9Sstevel@tonic-gate 					put(value-temp, objsz);
10287c478bd9Sstevel@tonic-gate 				continue;
10297c478bd9Sstevel@tonic-gate 			case 'b':
10307c478bd9Sstevel@tonic-gate 			case 'c':
10317c478bd9Sstevel@tonic-gate 				if (objsz == CGRP)
10327c478bd9Sstevel@tonic-gate 					fprnt('?', c);
10337c478bd9Sstevel@tonic-gate 				else
10347c478bd9Sstevel@tonic-gate 					fprnt('/', c);
10357c478bd9Sstevel@tonic-gate 				continue;
10367c478bd9Sstevel@tonic-gate 			case 'i':
10377c478bd9Sstevel@tonic-gate 				addr = cur_ino;
10387c478bd9Sstevel@tonic-gate 				fprnt('?', 'i');
10397c478bd9Sstevel@tonic-gate 				continue;
10407c478bd9Sstevel@tonic-gate 			case 's':
10417c478bd9Sstevel@tonic-gate 				fprnt('?', 's');
10427c478bd9Sstevel@tonic-gate 				continue;
10437c478bd9Sstevel@tonic-gate 			case 't':
10447c478bd9Sstevel@tonic-gate 			case 'T':
10457c478bd9Sstevel@tonic-gate 				laststyle = '=';
10467c478bd9Sstevel@tonic-gate 				printf("\t\t");
10477c478bd9Sstevel@tonic-gate 				{
10487c478bd9Sstevel@tonic-gate 					/*
10497c478bd9Sstevel@tonic-gate 					 * Truncation is intentional so
10507c478bd9Sstevel@tonic-gate 					 * ctime is happy.
10517c478bd9Sstevel@tonic-gate 					 */
10527c478bd9Sstevel@tonic-gate 					time_t tvalue = (time_t)value;
10537c478bd9Sstevel@tonic-gate 					printf("%s", ctime(&tvalue));
10547c478bd9Sstevel@tonic-gate 				}
10557c478bd9Sstevel@tonic-gate 				continue;
10567c478bd9Sstevel@tonic-gate 			case 'o':
10577c478bd9Sstevel@tonic-gate 				base = OCTAL;
10587c478bd9Sstevel@tonic-gate 				goto otx;
10597c478bd9Sstevel@tonic-gate 			case 'd':
10607c478bd9Sstevel@tonic-gate 				if (objsz == DIRECTORY) {
10617c478bd9Sstevel@tonic-gate 					addr = cur_dir;
10627c478bd9Sstevel@tonic-gate 					fprnt('?', 'd');
10637c478bd9Sstevel@tonic-gate 					continue;
10647c478bd9Sstevel@tonic-gate 				}
10657c478bd9Sstevel@tonic-gate 				base = DECIMAL;
10667c478bd9Sstevel@tonic-gate 				goto otx;
10677c478bd9Sstevel@tonic-gate 			case 'x':
10687c478bd9Sstevel@tonic-gate 				base = HEX;
10697c478bd9Sstevel@tonic-gate otx:
10707c478bd9Sstevel@tonic-gate 				laststyle = '=';
10717c478bd9Sstevel@tonic-gate 				printf("\t\t");
10727c478bd9Sstevel@tonic-gate 				if (acting_on_inode)
10737c478bd9Sstevel@tonic-gate 					print(value & 0177777L, 12, -8, 0);
10747c478bd9Sstevel@tonic-gate 				else
10757c478bd9Sstevel@tonic-gate 					print(addr & 0177777L, 12, -8, 0);
10767c478bd9Sstevel@tonic-gate 				printf("\n");
10777c478bd9Sstevel@tonic-gate 				base = tbase;
10787c478bd9Sstevel@tonic-gate 				continue;
10797c478bd9Sstevel@tonic-gate 			case 'O':
10807c478bd9Sstevel@tonic-gate 				base = OCTAL;
10817c478bd9Sstevel@tonic-gate 				goto OTX;
10827c478bd9Sstevel@tonic-gate 			case 'D':
10837c478bd9Sstevel@tonic-gate 				base = DECIMAL;
10847c478bd9Sstevel@tonic-gate 				goto OTX;
10857c478bd9Sstevel@tonic-gate 			case 'X':
10867c478bd9Sstevel@tonic-gate 				base = HEX;
10877c478bd9Sstevel@tonic-gate OTX:
10887c478bd9Sstevel@tonic-gate 				laststyle = '=';
10897c478bd9Sstevel@tonic-gate 				printf("\t\t");
10907c478bd9Sstevel@tonic-gate 				if (acting_on_inode)
10917c478bd9Sstevel@tonic-gate 					print(value, 12, -8, 0);
10927c478bd9Sstevel@tonic-gate 				else
10937c478bd9Sstevel@tonic-gate 					print(addr, 12, -8, 0);
10947c478bd9Sstevel@tonic-gate 				printf("\n");
10957c478bd9Sstevel@tonic-gate 				base = tbase;
10967c478bd9Sstevel@tonic-gate 				continue;
10977c478bd9Sstevel@tonic-gate 			default: /* regular assignment */
10987c478bd9Sstevel@tonic-gate 				ungetachar(c);
10997c478bd9Sstevel@tonic-gate 				value = expr();
11007c478bd9Sstevel@tonic-gate 				if (error)
11017c478bd9Sstevel@tonic-gate 					printf("syntax error\n");
11027c478bd9Sstevel@tonic-gate 				else
11037c478bd9Sstevel@tonic-gate 					put(value, objsz);
11047c478bd9Sstevel@tonic-gate 				continue;
11057c478bd9Sstevel@tonic-gate 			}
11067c478bd9Sstevel@tonic-gate 		}
11077c478bd9Sstevel@tonic-gate 
11087c478bd9Sstevel@tonic-gate 		case '>': /* save current address */
11097c478bd9Sstevel@tonic-gate 			colon = 0;
11107c478bd9Sstevel@tonic-gate 			should_print = 0;
11117c478bd9Sstevel@tonic-gate 			c = getachar();
11127c478bd9Sstevel@tonic-gate 			if (!letter(c) && !digit(c)) {
11137c478bd9Sstevel@tonic-gate 				printf("invalid register specification, ");
11147c478bd9Sstevel@tonic-gate 				printf("must be letter or digit\n");
11157c478bd9Sstevel@tonic-gate 				error++;
11167c478bd9Sstevel@tonic-gate 				continue;
11177c478bd9Sstevel@tonic-gate 			}
11187c478bd9Sstevel@tonic-gate 			if (letter(c)) {
11197c478bd9Sstevel@tonic-gate 				if (c < 'a')
11207c478bd9Sstevel@tonic-gate 					c = uppertolower(c);
11217c478bd9Sstevel@tonic-gate 				c = hextodigit(c);
11227c478bd9Sstevel@tonic-gate 			} else
11237c478bd9Sstevel@tonic-gate 				c = numtodigit(c);
11247c478bd9Sstevel@tonic-gate 			regs[c].sv_addr = addr;
11257c478bd9Sstevel@tonic-gate 			regs[c].sv_value = value;
11267c478bd9Sstevel@tonic-gate 			regs[c].sv_objsz = objsz;
11277c478bd9Sstevel@tonic-gate 			continue;
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 		case '<': /* restore saved address */
11307c478bd9Sstevel@tonic-gate 			colon = 0;
11317c478bd9Sstevel@tonic-gate 			should_print = 0;
11327c478bd9Sstevel@tonic-gate 			c = getachar();
11337c478bd9Sstevel@tonic-gate 			if (!letter(c) && !digit(c)) {
11347c478bd9Sstevel@tonic-gate 				printf("invalid register specification, ");
11357c478bd9Sstevel@tonic-gate 				printf("must be letter or digit\n");
11367c478bd9Sstevel@tonic-gate 				error++;
11377c478bd9Sstevel@tonic-gate 				continue;
11387c478bd9Sstevel@tonic-gate 			}
11397c478bd9Sstevel@tonic-gate 			if (letter(c)) {
11407c478bd9Sstevel@tonic-gate 				if (c < 'a')
11417c478bd9Sstevel@tonic-gate 					c = uppertolower(c);
11427c478bd9Sstevel@tonic-gate 				c = hextodigit(c);
11437c478bd9Sstevel@tonic-gate 			} else
11447c478bd9Sstevel@tonic-gate 				c = numtodigit(c);
11457c478bd9Sstevel@tonic-gate 			addr = regs[c].sv_addr;
11467c478bd9Sstevel@tonic-gate 			value = regs[c].sv_value;
11477c478bd9Sstevel@tonic-gate 			objsz = regs[c].sv_objsz;
11487c478bd9Sstevel@tonic-gate 			continue;
11497c478bd9Sstevel@tonic-gate 
11507c478bd9Sstevel@tonic-gate 		case 'a':
11517c478bd9Sstevel@tonic-gate 			if (colon)
11527c478bd9Sstevel@tonic-gate 				colon = 0;
11537c478bd9Sstevel@tonic-gate 			else
11547c478bd9Sstevel@tonic-gate 				goto no_colon;
1155*8509e9caSToomas Soome 			if (match("at", 2)) {		/* access time */
11567c478bd9Sstevel@tonic-gate 				acting_on_inode = 2;
11577c478bd9Sstevel@tonic-gate 				should_print = 1;
1158d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1159d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_atime;
11607c478bd9Sstevel@tonic-gate 				value = get(LONG);
1161*8509e9caSToomas Soome 				type = 0;
11627c478bd9Sstevel@tonic-gate 				continue;
11637c478bd9Sstevel@tonic-gate 			}
11647c478bd9Sstevel@tonic-gate 			goto bad_syntax;
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 		case 'b':
11677c478bd9Sstevel@tonic-gate 			if (colon)
11687c478bd9Sstevel@tonic-gate 				colon = 0;
11697c478bd9Sstevel@tonic-gate 			else
11707c478bd9Sstevel@tonic-gate 				goto no_colon;
1171*8509e9caSToomas Soome 			if (match("block", 2)) {	/* block conversion */
11727c478bd9Sstevel@tonic-gate 				if (type == NUMB) {
11737c478bd9Sstevel@tonic-gate 					value = addr;
11747c478bd9Sstevel@tonic-gate 					cur_bytes = 0;
11757c478bd9Sstevel@tonic-gate 					blocksize = BLKSIZE;
11767c478bd9Sstevel@tonic-gate 					filesize = BLKSIZE * 2;
11777c478bd9Sstevel@tonic-gate 				}
11787c478bd9Sstevel@tonic-gate 				addr = value << FRGSHIFT;
11797c478bd9Sstevel@tonic-gate 				bod_addr = addr;
11807c478bd9Sstevel@tonic-gate 				value = get(LONG);
11817c478bd9Sstevel@tonic-gate 				type = BLOCK;
11827c478bd9Sstevel@tonic-gate 				dirslot = 0;
11837c478bd9Sstevel@tonic-gate 				trapped++;
11847c478bd9Sstevel@tonic-gate 				continue;
11857c478bd9Sstevel@tonic-gate 			}
11867c478bd9Sstevel@tonic-gate 			if (match("bs", 2)) {		/* block size */
11877c478bd9Sstevel@tonic-gate 				acting_on_inode = 1;
11887c478bd9Sstevel@tonic-gate 				should_print = 1;
11897c478bd9Sstevel@tonic-gate 				if (icheck(cur_ino) == 0)
11907c478bd9Sstevel@tonic-gate 					continue;
1191d1a180b0Smaheshvs 				addr = (long)&((struct dinode *)
1192d1a180b0Smaheshvs 						(uintptr_t)cur_ino)->di_blocks;
11937c478bd9Sstevel@tonic-gate 				value = get(LONG);
1194*8509e9caSToomas Soome 				type = 0;
11957c478bd9Sstevel@tonic-gate 				continue;
11967c478bd9Sstevel@tonic-gate 			}
11977c478bd9Sstevel@tonic-gate 			if (match("base", 2)) {		/* change/show base */
11987c478bd9Sstevel@tonic-gate showbase:
11997c478bd9Sstevel@tonic-gate 				if ((c = getachar()) == '\n') {
12007c478bd9Sstevel@tonic-gate 					ungetachar(c);
12017c478bd9Sstevel@tonic-gate 					printf("base =\t\t");
12027c478bd9Sstevel@tonic-gate 					switch (base) {
12037c478bd9Sstevel@tonic-gate 					case OCTAL:
12047c478bd9Sstevel@tonic-gate 						printf("OCTAL\n");
12057c478bd9Sstevel@tonic-gate 						continue;
12067c478bd9Sstevel@tonic-gate 					case DECIMAL:
12077c478bd9Sstevel@tonic-gate 						printf("DECIMAL\n");
12087c478bd9Sstevel@tonic-gate 						continue;
12097c478bd9Sstevel@tonic-gate 					case HEX:
12107c478bd9Sstevel@tonic-gate 						printf("HEX\n");
12117c478bd9Sstevel@tonic-gate 						continue;
12127c478bd9Sstevel@tonic-gate 					}
12137c478bd9Sstevel@tonic-gate 				}
12147c478bd9Sstevel@tonic-gate 				if (c != '=') {
12157c478bd9Sstevel@tonic-gate 					printf("missing '='\n");
12167c478bd9Sstevel@tonic-gate 					error++;
12177c478bd9Sstevel@tonic-gate 					continue;
12187c478bd9Sstevel@tonic-gate 				}
12197c478bd9Sstevel@tonic-gate 				value = expr();
12207c478bd9Sstevel@tonic-gate 				switch (value) {
12217c478bd9Sstevel@tonic-gate 				default:
12227c478bd9Sstevel@tonic-gate 					printf("invalid base\n");
12237c478bd9Sstevel@tonic-gate 					error++;
12247c478bd9Sstevel@tonic-gate 					break;
12257c478bd9Sstevel@tonic-gate 				case OCTAL:
12267c478bd9Sstevel@tonic-gate 				case DECIMAL:
12277c478bd9Sstevel@tonic-gate 				case HEX:
12287c478bd9Sstevel@tonic-gate 					base = (short)value;
12297c478bd9Sstevel@tonic-gate 				}
12307c478bd9Sstevel@tonic-gate 				goto showbase;
12317c478bd9Sstevel@tonic-gate 			}
12327c478bd9Sstevel@tonic-gate 			goto bad_syntax;
1233