[comp.os.minix] Interactive FDISK for Hard Disks

misha@nsc.nsc.com (Michael Umansky) (06/29/87)

See README just below for more info ...
---------------------CUT SOMEWHERE ON THIS LINE---------------------------------
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	README
#	Makefile
#	block0.h
#	fdisk.c
#	input.c
#	screen.c
#	test.uu
# This archive created: Mon Jun 29 13:09:22 1987
echo shar: extracting README '(6559 characters)'
sed 's/^XX//' << \SHAR_EOF > README
XX#
XX#	@(#) README: version 1.5 created on 6/29/87 at 13:01:29
XX#
XX
XXINTRO
XX
XXThis is an interactive full screen menu driven hard disk partition manager.
XXIt allows you to allocate and manage any type and size of partition that
XXyour heart may desire.  It will even allow overlapping partitions.
XXIt has some intelligence to provide defaults which are useful.
XXIt works perfectly on a V7 UNIX and also on 4.x BSD UNIX.  It should
XXcompile and run with no problems on MINIX and with minor mods on PC DOS.
XXSee compatability issues below.  From here on 'sector' and 'block' mean the
XXsame thing - a 512 byte area on disk.  Also, 'track' and 'head' also mean
XXthe same thing.
XX
XXGENERAL INFORMATION
XX
XXPhysical block zero (0) on the hard disk is used for bootstrap and for
XXpartition table.  Bootstrap code finds which partition is active and
XXtries to load an OS from that partition and run it.  On the hard and
XXfloppy disks cylinders are numbered from 0 to X, heads are numbered from
XX0 to X, and sectors are numbered from 1 to X.  Partitions are allocated
XXon cylinder boundaries and always have full cylinders allocated.  There
XXshould be only one active partition, although bootstrap code will stop
XXsearch on the first one it finds.  PC DOS has reserved values of 1 and 4
XXfor its operating system types.  Type 1 is generally used for hard disks
XXwhich are less than 10 MB in size and use 12 bit FATs.  Type 4 is used
XXfor hard disks which are more than 10 MB in size and use 16 bit FATs.
XXWhen standard FDISK is run on PC DOS it will set correct partition type
XXbased on how much space is allocated to that partition.
XXThe bootstrap block zero is exactly 512 bytes long.  Last two bytes of
XXthis block are the valid block signature and tell hard disk BIOS that
XXthe boot block is valid.  They must contain value 0xAA55, AA being in the
XX1st byte and 55 in the 2nd byte.  The 64 bytes before the signature bytes
XXcomprise the partition table with 4 entries and 16 bytes per entry.
XXThis table starts at offset 0x01BE or 446 decimal.  See 'block0.h' for
XXlayout of this table.
XX
XXBUILDING FDISK
XX
XXThere are 3 C files and 1 header file.  The header file 'block0.h' contains
XXall of the information about the layout of physical block zero.
XXThe C file 'input.c' contains all of the specific routines for getting
XXinput from user as the program wants it.  The C file 'screen.c' has simple
XXroutines for screen formatting.  The only screen capabilities needed are
XXhome cursor, clear to end of screen, clear to end of line, and absolute
XXcursor positioning.  The attribute handling is optional.  Use of curses
XXor termcap is discouraged because it is just too much unnecessary overhead.
XXThe 'fdisk.c' C file is the main driver.  It checks how it is being called
XXand if it is called as 'ddisk' then it will just dump out the info and quit.
XXThe 'ddisk' is just a link to 'fdisk' if links are allowed on target system.
XXThe only other headers that are needed are 'stdio.h' and 'sgtty.h'.
XXYou can use the simple Makefile to build 'fdisk'.
XX
XXRUNNING FDISK
XX
XXThe usage is simple: 'fdisk filename' or 'ddisk filename', where filename
XXis either a special device which allows access to physical block zero
XX(such as /dev/hd0 on MINIX), or is a dummy file to be used for testing.
XXBefore running 'fdisk' on a live hard disk you should back up all of
XXyour present partitions.  NOTE: if the disk is brand new and has never
XXbeen used by PC DOS then you MUST run FDISK of standard PC DOS.  It doesn't
XXmatter how many or how big partitions you allocate.  This will ensure that
XXthe physical block zero actually has the bootstrap code.  Unless you have
XXyour own bootstrap code and plan to put it into block zero, running MINIX's
XX'fdisk' on the new hard disk will put out a good partition table and good
XXblock zero signature but there will not be the actual bootstrap code.
XXWhen BIOS will load this block zero and jump to it, guess what happens ...
XXThe program will not let you enter bad values and will require correct
XXanswers to prompts.  Also, currently it cannot be killed in the middle;
XXyou must go all the way through the prompts.  There are many safety
XXfeatures built in to allow you to backtrack and correct mistakes and
XXto be able to get out without changing the actual disk information.
XX
XXCOMPATABILITY
XX
XXI tried to make the code as compatible as possible.  The only problems
XXthat could be encountered are the system calls, some of which may not
XXbe supported on some systems or are invoked differently.  There are
XXno special system or library calls in this program.  It should compile
XXand run with almost no mods (see below) on any UNIX/MINIX based system.
XXFor PC DOS, you will need to change the input handling routines, the
XXscreen handling routines, and add code to do reads and writes to physical
XXblock zero of a hard disk.  I may add this later on.  For UNIX/MINIX
XXbased systems, you should make sure that you have TIOC{G|S}ETP ioctl
XXcall or something similar to set input modes to RAW.  Also, the stdin,
XXstdout, and stderr must be unbuffered, else a fflush(stdout) must inserted
XXafter every printf()/putchar()/putc()/puts().  Currently, only VT100 and
XXVenix screen control codes are coded, but it is very easy to add other
XXscreen types.  VT100 type screen assumes 24 lines of 80 columns.  The
XXPC type screens are all 25 lines by 80 columns.  It is also assumed that
XXabsolute cursor positioning is from 1 to 24 for Y and from 1 to 80 for X.
XXThe 'info' structure that is defined in 'block0.h' and is put before
XXthe partition table in block zero, is only for information.  You must
XXmake sure that the bootstrap code doesn't run into the space of this
XXstructure.  You can remove the structure from block zero, but then you
XXmust define it locally to 'fdisk' program because it uses the structure
XXfor important disk info, like number of sectors, heads and cylinders.
XXI use the structure in the kernel disk driver which enables it to
XXautoconfigure on bootup.
XX
XXBUGS
XX
XXA good possibility, although it runs perfectly on 4.x BSD and my V7 UNIX.
XXI have not tried it on MINIX yet because I had no time to setup my hard
XXdisk for adding MINIX to it.  I will make it run on MINIX and on PC DOS
XXlater.  I would appreciate all bug fixes and enhancements to be sent to me.
XX
XXSIGNATURE
XX		NAME:   Michael Umansky (misha)
XX		E-MAIL:
XX			 	sun! ----\
XX				hplabs! --\
XX				pyramid! --+----> nsc!misha
XX				decwrl! --/
XX				amdahl! -/
XX		WORK:
XX			National Semiconductor Corporation
XX			1135 Kern Avenue,  Mail Stop - 7C266
XX			Sunnyvale, CA  94086
XX			(408) 721-8109 (work)
XX		HOME:
XX			4331 Lincoln Way
XX			San Francisco, CA  94122
XX			(415) 564-3921 (home)
SHAR_EOF
if test 6559 -ne "`wc -c README`"
then
echo shar: error transmitting README '(should have been 6559 characters)'
fi
echo shar: extracting Makefile '(844 characters)'
sed 's/^XX//' << \SHAR_EOF > Makefile
XX#
XX#	@(#) Makefile: version 1.5 created on 6/29/87 at 13:00:24
XX#
XXCC	= cc
XXOPTIONS	= -DVT100 -DSCCS
XXCFLAGS	= -O ${OPTIONS}
XX
XXCPP	= cpp
XXCPPFLAGS= -M ${OPTIONS}
XX
XXSOURCES	= fdisk.c input.c screen.c
XX
XXOBJECTS	= fdisk.o input.o screen.o
XX
XXPROG1	= fdisk
XXPROG2	= ddisk
XXPROGS	= $(PROG1) $(PROG2)
XX
XXall:	${PROGS}
XX
XX${PROG1}: ${OBJECTS}
XX	${CC} -o ${PROG1} ${OBJECTS}
XX
XX${PROG2}: ${PROG1}
XX	ln $(PROG1) $(PROG2)
XX
XXfdisk.o: block0.h
XX
XXclean:
XX	rm -f ${OBJECTS} *.o a.out core
XX
XXclobber: clean
XX	rm -f ${PROGS}
XX
XXdepend:
XX	cp Makefile Makefile.bak
XX	echo '# DO NOT DELETE THIS LINE - make depend uses it' >makedep
XX	for i in ${SOURCES} ; \
XX	do \
XX		${CPP} ${CPPFLAGS} $$i >> makedep ; \
XX	done
XX	echo '/^# DO NOT DELETE THIS LINE/,$$d' >eddep
XX	echo '$$r makedep' >>eddep
XX	echo 'w' >>eddep
XX	ed - Makefile < eddep
XX	rm eddep makedep
XX
XX# DO NOT DELETE THIS LINE - make depend uses it
SHAR_EOF
if test 844 -ne "`wc -c Makefile`"
then
echo shar: error transmitting Makefile '(should have been 844 characters)'
fi
echo shar: extracting block0.h '(4273 characters)'
sed 's/^XX//' << \SHAR_EOF > block0.h
XX/*
XX**	@(#) block0.h: version 1.5 created on 6/29/87 at 13:00:25
XX*/
XX
XX/*
XX**	Boot Block Layout as it appears on physical block 0 of a hard disk.
XX**	Size of this structure must be exactly 512 bytes because the block
XX**	signature is in last two bytes.  Do not change the layout of the
XX**	partition structure, however, you can add anything in front of it
XX**	as long as you don't run into the boot code and keep the total
XX**	structure length at 512 bytes.  The partition table starts
XX**	at offset 0x01BE or 446 decimal.  There are four entries and each
XX**	entry is 16 bytes.
XX*/
XXtypedef	struct	blkzero
XX	{
XX		char		blk0_data[510];	/* bootstrap code    */
XX		unsigned short	blk0_sig;	/* block signature   */
XX	} blkzero_t;
XX
XX/*
XX**	The following two structures are not included in the above
XX**	structure definition.  Instead, indirect pointers are used
XX**	to point into the correct location in the block zero data.
XX**	This is done for portability, because some compilers will
XX**	align structures within structures differently from others
XX**	which will result in wrong offsets.
XX*/
XXtypedef	struct	blk0
XX	{
XX		struct	blk0_tab
XX		{
XX			unsigned char   blk0_boot;	/* boot partition    */
XX			unsigned char   blk0_s_h;	/* starting head     */
XX			unsigned char   blk0_s_s;	/* starting sector   */
XX			unsigned char   blk0_s_c;	/* starting cylinder */
XX			unsigned char   blk0_sys;	/* partition type    */
XX			unsigned char   blk0_e_h;	/* ending head       */
XX			unsigned char   blk0_e_s;	/* ending sector     */
XX			unsigned char   blk0_e_c;	/* ending cylinder   */
XX			long            blk0_start;	/* starting sector   */
XX			long            blk0_size;	/* size in sectors   */
XX		} blk0_tab[4];				/* 4 partitions      */
XX	} blk0_t;
XX
XX/*
XX**	This info structure is only for convenience.  The values are
XX**	used in the fdisk program to set some limits.  This is also
XX**	used in hard disk driver to setup parameters on bootup.
XX*/
XXtypedef	struct	info
XX	{
XX		unsigned short	info_sig1;	/* first   signature	*/
XX		unsigned short	info_ndrv;	/* current drive number	*/
XX		char		info_name[8];	/* current drive name	*/
XX		unsigned short	info_npart;	/* physical part/drive	*/
XX		unsigned short	info_nunit;	/* logical  units/drive	*/
XX		unsigned short	info_ntrack;	/* tracks   per drive	*/
XX		unsigned short	info_nhead;	/* heads    per drive	*/
XX		unsigned short	info_sechd;	/* sectors  per head	*/
XX		unsigned short	info_ncyls;	/* cylinders per drive	*/
XX		unsigned short	info_blkscyl;	/* blocks per cylinder	*/
XX		unsigned short	info_blksize;	/* bytes  per block	*/
XX		unsigned short	info_step;	/* head   step rate	*/
XX		unsigned short	info_maxfer;	/* max    DMA size	*/
XX		unsigned short	info_sig2;	/* second signature	*/
XX	} info_t;
XX
XX#define BLK0_SIZE	(sizeof(blk0_t))		/* part table size   */
XX#define BLK0_START	(510 - BLK0_SIZE)		/* start of header   */
XX#define INFO_SIZE	(sizeof(info_t))		/* info header size  */
XX#define INFO_START	(BLK0_START - INFO_SIZE)	/* start of header   */
XX
XX#define INFO_SIG1	0xa5a5				/* magic constant    */
XX#define INFO_SIG2	0x5a5a				/* magic constant    */
XX#define BLK0_SIG	0xaa55				/* magic constant    */
XX
XX/*
XX**	PC DOS knows about these two also.
XX*/
XX#define BLK0_BOOT	0x80				/* active  partition */
XX#define BLK0_NULL	0x00				/* passive partition */
XX
XX/*
XX**	The following are partition types.  Set them to whatever
XX**	values you desire except the DOS partition types.
XX**	Since MINIX currently doesn't check the partition type
XX**	except that it must be non-DOS it really doesn't matter
XX**	what values you assign except when your driver will need
XX**	to know which partition is which.
XX*/
XX#define BLK0_UNUSED	0x00			/* unused system type */
XX
XX#define BLK0_DOS_1	0x01			/* DOS 2.0 up <= 10mb */
XX#define BLK0_DOS_4	0x04			/* DOS 3.0 up >  10mb */
XX
XX#define BLK0_SYS_0	0x10			/* system/swap area	*/
XX#define BLK0_SYS_1	0x11			/* system/swap area	*/
XX#define BLK0_SYS_2	0x12			/* system/swap area	*/
XX#define BLK0_SYS_3	0x14			/* system/swap area	*/
XX
XX#define BLK0_TMP_0	0x20			/* temp/pipe area	*/
XX#define BLK0_TMP_1	0x21			/* temp/pipe area	*/
XX#define BLK0_TMP_2	0x22			/* temp/pipe area	*/
XX#define BLK0_TMP_3	0x24			/* temp/pipe area	*/
XX
XX#define BLK0_USR_0	0x40			/* user area		*/
XX#define BLK0_USR_1	0x41			/* user area		*/
XX#define BLK0_USR_2	0x42			/* user area		*/
XX#define BLK0_USR_3	0x44			/* user area		*/
SHAR_EOF
if test 4273 -ne "`wc -c block0.h`"
then
echo shar: error transmitting block0.h '(should have been 4273 characters)'
fi
echo shar: extracting fdisk.c '(19770 characters)'
sed 's/^XX//' << \SHAR_EOF > fdisk.c
XX/*
XX**	@(#) fdisk.c: version 1.5 created on 6/29/87 at 13:00:29
XX*/
XXstatic	char	_sccs_C_id_[] =
XX	"@(#) fdisk.c: version 1.5 created on 6/29/87 at 13:00:29";
XX
XXstatic	char	_message[] =
XX	"Version 1.5 Updated on 6/29/87 (c) 1987 Michael Umansky";
XX
XX#include	<stdio.h>
XX#include	"block0.h"
XX
XX/*
XX**	The defaults assume a 10 MB, 4 heads, 305 cylinders drive.
XX*/
XX#define	NPART		4		/* # of partitions - DON'T CHANGE */
XX#define	DEF_NDRV	0		/* Whatever you want - Not used	*/
XX#define	DEF_NPART	NPART		/* same as NPART above		*/
XX#define	DEF_NUNIT	8		/* logical units per drive	*/
XX#define	DEF_NHEAD	4		/* # of heads on a drive	*/
XX#define	DEF_NCYLS	305		/* def # cylinders on a drive	*/
XX#define	MAX_NCYLS	999		/* max # cylinders on a drive	*/
XX#define	DEF_SECHD	17		/* # of sectors per track	*/
XX#define	DEF_BLKSIZE	512		/* sector size in bytes		*/
XX#define	DEF_STEP	0x05		/* drive/controller specific	*/
XX#define	DEF_MAXFER	((64*1024)-1)	/* max DMA xfer in single try	*/
XX#define	MAX_MAXFER	((64*1024)-1)	/* max DMA xfer in single try	*/
XX#define	MAX_TYPE	10		/* max partition types known	*/
XX#define	LAST_TYPE	0xFF		/* for partition type table	*/
XX#define	PRIVATE_TYPE	" Private Part "
XX#define	UNKNOWN_TYPE	" Unknown Part "
XX#define	DOS2_TYPE	"  PC DOS 2.x  "
XX#define	DOS3_TYPE	"  PC DOS 3.x  "
XX#define	ROOT_TYPE	"  MINIX Root  "
XX#define	TEMP_TYPE	"  MINIX Temp  "
XX#define	USER_TYPE	"  MINIX User  "
XX#define	UNUSED_TYPE	"  Unused Part "
XX#define	DDISK		"ddisk"		/* how is this program invoked	*/
XX#define	FDISK		"fdisk"		/* how is this program invoked	*/
XX
XX/*
XX**	The defaults assume that your terminal cursor addressing is
XX**	from X position of 1 to 80 and from Y position of 1 to 25.
XX*/
XX#define	X_POS		1	/* start in first column		*/
XX#define	Y_BANNER	1	/* put BANNER on this line		*/
XX#define	Y_PART		3	/* put PARTITION DUMP on this line	*/
XX#define	Y_PARM		11	/* put PARAMETER DUMP on this line	*/
XX#ifdef	VT100
XX#define	Y_QUIT		23	/* put QUIT MESSAGE on this line	*/
XX#define	Y_PROMPT	24	/* put PROMPTS on this line		*/
XX#else	/* VT100 */
XX#define	Y_QUIT		24	/* put QUIT MESSAGE on this line	*/
XX#define	Y_PROMPT	25	/* put PROMPTS on this line		*/
XX#endif	/* VT100 */
XX
XX/*
XX**	These are defined in screen.c and are terminal dependent.
XX*/
XXextern	char	clear[];	/* clear and home cursor	*/
XXextern	char	rvon[];		/* reverse video on		*/
XXextern	char	rvoff[];	/* reverse video off		*/
XXextern	char	hlon[];		/* highlight on			*/
XXextern	char	hloff[];	/* highlight off		*/
XXextern	char	ulon[];		/* underline on			*/
XXextern	char	uloff[];	/* underline off		*/
XXextern	char	blon[];		/* blink on			*/
XXextern	char	bloff[];	/* blink off			*/
XXextern	char	alloff[];	/* all attributes off		*/
XX
XX/*
XX**	Known partition types.  Limit these to 10 because of how
XX**	the screen is organized unless you want to change the
XX**	whole screen managing.  The partition types are defined
XX**	in 'block0.h'; change them to match your system but leave
XX**	the DOS specific defines as they are.  Make the partition
XX**	names exactly 14 characters (see below) so that screen
XX**	layout is matched.  The partinit() routine will add any
XX**	types it finds in a valid block-zero, which are not in this
XX**	table, if there is enough room left in the table.  The
XX**	partition names are only used internally to this program
XX**	and they are not stored anywhere on the disk.  But, you
XX**	can modify the info header to add the names, being
XX**	careful not to overwrite the actual bootstrap code.
XX*/
XXtypedef	struct	p_type
XX	{
XX		unsigned char	type;
XX		char		name[16];
XX	} p_type_t;
XX
XXp_type_t part_type[MAX_TYPE+1] =
XX	{
XX		BLK0_DOS_1,  DOS2_TYPE,
XX		BLK0_DOS_4,  DOS3_TYPE,
XX		BLK0_SYS_0,  ROOT_TYPE,
XX		BLK0_TMP_0,  TEMP_TYPE,
XX		BLK0_USR_0,  USER_TYPE,
XX		BLK0_UNUSED, UNUSED_TYPE,
XX		LAST_TYPE,   UNKNOWN_TYPE
XX	};
XX
XX/*
XX**	Storage and pointer to, for physical block zero.
XX*/
XXblkzero_t	zeroblk;
XXblk0_t		*blk0;
XXinfo_t		*info;
XX
XXint	drv_fd;
XXint	def_start, def_end;
XXint	cyl_start[NPART], cyl_end[NPART], act_part[NPART];
XX
XX/*
XX**	See above defines for description of the following.
XX*/
XXunsigned short	def_ndrv    = DEF_NDRV;
XXunsigned short	def_npart   = DEF_NPART;
XXunsigned short	def_nunit   = DEF_NUNIT;
XXunsigned short	def_nhead   = DEF_NHEAD;
XXunsigned short	def_ncyls   = DEF_NCYLS;
XXunsigned short	def_sechd   = DEF_SECHD;
XXunsigned short	def_blksize = DEF_BLKSIZE;
XXunsigned short	def_step    = DEF_STEP;
XXunsigned short	def_maxfer  = DEF_MAXFER;
XX
XXchar	*progname, *drivename, *getstr(), *makelower(), *makeupper();
XXchar	localname[32];
XX
XXmain(argc,argv)
XXint	argc;
XXchar	*argv[];
XX{
XXregister int	partchange;
XX
XX	init(argc,argv);
XXrepeat:
XX	curpos(X_POS,Y_PROMPT);
XX	clreop();
XX	while (!prompt("Are these drive parameters acceptable?",0,0))
XX	{
XX		curpos(X_POS,Y_PARM);
XX		clreop();
XX		parmnew();
XX		curpos(X_POS,Y_PARM);
XX		clreop();
XX		parmdump();
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XX	}
XX	parminit();
XX	curpos(X_POS,Y_PROMPT);
XX	clreop();
XX	partchange = 0;
XX	while (!prompt("Are these drive PARTITIONS acceptable?",0,0))
XX	{
XX		register int	part;
XX
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XXprintf("Enter partition # to change or 0 to quit (1 to %d) [0] : ",NPART);
XX		while (part = getnum(0,4,0,0))
XX		{
XX			partchange = 1;
XX			part--;
XX			partnew(part);
XX			curpos(X_POS,Y_PART);
XX			clreop();
XX			partdump();
XX			curpos(X_POS,Y_PROMPT);
XX			clreop();
XXprintf("Enter partition # to change or 0 to quit (1 to %d) [0] : ",NPART);
XX		}
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XX	}
XX	if (partchange)
XX	{
XX		curpos(X_POS,Y_PARM);
XX		parmdump();
XX	}
XX	curpos(X_POS,Y_PROMPT);
XX	clreop();
XX	if (!prompt("Are you done with both parameters and partitions?",0,0))
XX		goto repeat;
XX	curpos(X_POS,Y_PROMPT);
XX	clreop();
XX	partchange = 0;
XX	while (prompt("Do you want to change active boot partition?",0,0))
XX	{
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XX		if (partactive())
XX		{
XX			partchange = 1;
XX			curpos(X_POS,Y_PART);
XX			clreop();
XX			partdump();
XX		}
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XX	}
XX	if (partchange)
XX	{
XX		curpos(X_POS,Y_PARM);
XX		parmdump();
XX	}
XX	curpos(X_POS,Y_PROMPT);
XX	clreop();
XX	if (prompt("Are you sure that you want to update the disk drive?",0,0))
XX	{
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XX		printf("Start updating disk drive: %s",drivename);
XX		if (lseek(drv_fd, 0L, 0) != 0)
XX		{
XX			fprintf(stderr,"ERROR: %s: ",drivename);
XX			perror("lseek block device");
XX			fatal("Cannot lseek to disk block zero.\n");
XX		}
XX		if (write(drv_fd, &zeroblk, sizeof(blkzero_t)) !=
XX			sizeof(blkzero_t))
XX		{
XX			fprintf(stderr,"ERROR: %s: ",drivename);
XX			perror("write block device");
XX			fatal("Cannot write disk block zero.\n");
XX		}
XX		curpos(X_POS,Y_QUIT);
XX		clreop();
XX		printf("Disk drive '%s' was updated!\n",drivename);
XX	}
XX	else
XX	{
XX		curpos(X_POS,Y_PROMPT);
XX		clreop();
XXif (prompt("Do you want instead to save this information to a file?",0,0))
XX		{
XX			curpos(X_POS,Y_PROMPT);
XX			clreop();
XX			sprintf(localname,"%s.%d",progname,getpid());
XX			printf("Enter file name (up to 14 characters) [%s] : ",
XX				makelower(localname));
XX			strcpy(localname,getstr(1,14,localname,0));
XX			close(drv_fd);
XX			if ((drv_fd = creat(localname,0644)) < 0)
XX			{
XX				fprintf(stderr,"ERROR: %s: ",localname);
XX				perror("create local file");
XX				fatal("Cannot create local file.\n");
XX			}
XX			if (write(drv_fd, &zeroblk, sizeof(blkzero_t)) !=
XX				sizeof(blkzero_t))
XX			{
XX				fprintf(stderr,"ERROR: %s: ",localname);
XX				perror("write local file");
XX				fatal("Cannot write to local file.\n");
XX			}
XX			curpos(X_POS,Y_QUIT);
XX			clreop();
XX	printf("Drive information saved to file '%s' in current directory!\n",
XX			localname);
XX		}
XX		else
XX		{
XX			curpos(X_POS,Y_PROMPT);
XX			clreop();
XX			curpos(X_POS,Y_QUIT);
XX			clreop();
XX			printf("Disk drive '%s' was NOT updated!\n",drivename);
XX		}
XX	}
XX	close(drv_fd);
XX	exit (0);
XX}
XX
XXinit(argc,argv)
XXint	argc;
XXchar	*argv[];
XX{
XX	if (argc != 2)
XX		exit(usage(argv[0]));
XX	setbuf(stdin,NULL);
XX	setbuf(stdout,NULL);
XX	setbuf(stderr,NULL);
XX	progname  = argv[0];
XX	drivename = argv[1];
XX	if ((drv_fd = open(drivename,2)) < 0)
XX	{
XX		fprintf(stderr,"ERROR: %s: ",drivename);
XX		perror("open block device");
XX		fatal("Error in accessing winchester.\n");
XX	}
XX	if (read(drv_fd, &zeroblk, sizeof(blkzero_t)) != sizeof(blkzero_t))
XX	{
XX		fprintf(stderr,"ERROR: %s: ",drivename);
XX		perror("read block device");
XX		fatal("Cannot read disk block zero.\n");
XX	}
XX	partinit();
XX	parminit();
XX	chome();
XX	clreop();
XX	anorm();
XX	curpos(X_POS,Y_BANNER);
XX	banner();
XX	curpos(X_POS,Y_PART);
XX	partdump();
XX	curpos(X_POS,Y_PARM);
XX	parmdump();
XX	if (strncmp(progname,DDISK,5) == 0)
XX		exit (0);
XX	return (0);
XX}
XX
XXusage(s)
XXregister char	*s;
XX{
XX	fprintf(stderr,"usage: %s device/file\n",s);
XX	return (1);
XX}
XX
XXfatal(f,s1,s2)
XXregister char	*f, *s1, *s2;
XX{
XX	fprintf(stderr,"%sFATAL ERROR: %s",hlon,hloff);
XX	fprintf(stderr,f,s1,s2);
XX	exit (-1);
XX}
XX
XXpartinit()
XX{
XXregister int	i, j;
XXunsigned char	sys;
XX
XX	blk0 = (blk0_t *) &zeroblk.blk0_data[BLK0_START];
XX	def_start   = 0;
XX	def_end     = DEF_NCYLS - 1;
XX	def_ndrv    = DEF_NDRV;
XX	def_npart   = DEF_NPART;
XX	def_nunit   = DEF_NUNIT;
XX	def_nhead   = DEF_NHEAD;
XX	def_ncyls   = DEF_NCYLS;
XX	def_sechd   = DEF_SECHD;
XX	def_blksize = DEF_BLKSIZE;
XX	def_step    = DEF_STEP;
XX	def_maxfer  = DEF_MAXFER;
XX	if (zeroblk.blk0_sig != BLK0_SIG)
XX	{
XX		for (i = 0; i < NPART; i++)
XX		{
XX			cyl_start[i] = def_start;
XX			cyl_end[i]   = def_end;
XX			if (i)
XX				act_part[i]  = BLK0_NULL;
XX			else
XX				act_part[i]  = BLK0_BOOT;
XXblk0->blk0_tab[i].blk0_boot  = act_part[i];
XXblk0->blk0_tab[i].blk0_s_h   = 0;
XXblk0->blk0_tab[i].blk0_s_s   = 2 | ((def_start >> 2) & 0x00C0);
XXblk0->blk0_tab[i].blk0_s_c   = def_start;
XXblk0->blk0_tab[i].blk0_sys   = BLK0_UNUSED;
XXblk0->blk0_tab[i].blk0_e_h   = def_nhead - 1;
XXblk0->blk0_tab[i].blk0_e_s   = def_sechd | ((def_end >> 2) & 0x00C0);
XXblk0->blk0_tab[i].blk0_e_c   = def_end;
XXblk0->blk0_tab[i].blk0_start = 1;	/* block 0 is reserved	*/
XXblk0->blk0_tab[i].blk0_size  = (def_ncyls * def_nhead * def_sechd) - 1;
XX		}
XX		zeroblk.blk0_sig = BLK0_SIG;
XX		def_end          = MAX_NCYLS;
XX		return (0);
XX	}
XX	for (i = 0; i < NPART; i++)
XX	{
XX		cyl_start[i] = (int) blk0->blk0_tab[i].blk0_s_c |
XX				((blk0->blk0_tab[i].blk0_s_s & 0x00C0) << 2);
XX		cyl_end[i]   = (int) blk0->blk0_tab[i].blk0_e_c |
XX				((blk0->blk0_tab[i].blk0_e_s & 0x00C0) << 2);
XX		act_part[i]  = blk0->blk0_tab[i].blk0_boot;
XX		sys = blk0->blk0_tab[i].blk0_sys;
XX		for (j = 0; j < MAX_TYPE; j++)
XX		{
XX			if (sys == part_type[j].type)
XX				break;
XX			if (part_type[j].type == LAST_TYPE)
XX			{
XX				part_type[j].type = sys;
XX				strcpy(part_type[j].name,PRIVATE_TYPE);
XX				part_type[j+1].type = LAST_TYPE;
XX				strcpy(part_type[j+1].name,UNKNOWN_TYPE);
XX				break;
XX			}
XX		}
XX	}
XX	def_end = MAX_NCYLS;
XX	return (0);
XX}
XX
XX/*
XX1
XX2
XX3              Boot     Partition       Cyl    Cyl     Cyl     Block     Block
XX4 Partition   Status       Type       Start    End    Size      Size    Offset
XX5 ----------------------------------------------------------------------------
XX6     1         x     xxxxxxxxxxxxxx  xxxxx  xxxxx   xxxxx  xxxxxxxx  xxxxxxxx
XX7     2         x     xxxxxxxxxxxxxx  xxxxx  xxxxx   xxxxx  xxxxxxxx  xxxxxxxx
XX8     3         x     xxxxxxxxxxxxxx  xxxxx  xxxxx   xxxxx  xxxxxxxx  xxxxxxxx
XX9     4         x     xxxxxxxxxxxxxx  xxxxx  xxxxx   xxxxx  xxxxxxxx  xxxxxxxx
XX0
XX*/
XXpartdump()
XX{
XXregister int	i, scyl, ecyl;
XX
XX	printf("               Boot     Partition       Cyl    ");
XX	printf("Cyl     Cyl     Block     Block\n");
XX	printf("  Partition   Status       Type       Start    ");
XX	printf("End    Size      Size    Offset\n");
XX	printf("  ---------------------------------------------");
XX	printf("-------------------------------\n");
XX	for (i = 0; i < NPART; i++ )
XX	{
XX		printf("      %d         %c     ",
XX			i + 1,
XX			(blk0->blk0_tab[i].blk0_boot == BLK0_BOOT ? 'A' : ' '));
XX		switch (blk0->blk0_tab[i].blk0_sys)
XX		{
XX			case BLK0_DOS_1:
XX				printf(DOS2_TYPE);
XX				break;
XX
XX			case BLK0_DOS_4:
XX				printf(DOS3_TYPE);
XX				break;
XX
XX			case BLK0_SYS_0:
XX				printf(ROOT_TYPE);
XX				break;
XX
XX			case BLK0_TMP_0:
XX				printf(TEMP_TYPE);
XX				break;
XX
XX			case BLK0_USR_0:
XX				printf(USER_TYPE);
XX				break;
XX
XX			case BLK0_UNUSED:
XX				printf(UNUSED_TYPE);
XX				break;
XX
XX			default:
XX				printf(UNKNOWN_TYPE);
XX		}
XX		scyl = blk0->blk0_tab[i].blk0_s_c +
XX			((blk0->blk0_tab[i].blk0_s_s & 0x00C0) << 2);
XX		ecyl = blk0->blk0_tab[i].blk0_e_c +
XX			((blk0->blk0_tab[i].blk0_e_s & 0x00C0) << 2);
XX		printf("  %5u ",scyl);
XX		printf(" %5u ",ecyl);
XX		if (blk0->blk0_tab[i].blk0_size)
XX			printf("  %5u ",(ecyl - scyl + 1));
XX		else
XX			printf("  %5u ",0);
XX		printf(" %8u ",blk0->blk0_tab[i].blk0_size);
XX		printf(" %8u\n",blk0->blk0_tab[i].blk0_start);
XX	}
XX	return (0);
XX}
XX
XXpartnew(part)
XXregister int	part;
XX{
XXregister int	i, opt, type, fstcyl, cylsize, partdef;
XXregister char	*name;
XX
XX	curpos(X_POS,Y_PARM);
XX	clreop();
XX	type = blk0->blk0_tab[part].blk0_sys;
XX	name = UNKNOWN_TYPE;
XX	for (i = 0; i < MAX_TYPE; i++)
XX	{
XX		if (part_type[i].type == LAST_TYPE)
XX			break;
XX		if (part_type[i].type == type)
XX		{
XX			name = part_type[i].name;
XX			break;
XX		}
XX	}
XX	printf("( 0)  0x%02x - \"%s\" <= Use this default type\n",
XX		type,name);
XX	printf("( 1)  Enter partition type manually (in decimal)\n");
XX	for (i = 0; i < MAX_TYPE; i++)
XX	{
XX		if (part_type[i].type == LAST_TYPE)
XX			break;
XX		if (part_type[i].type == type)
XX			name = part_type[i].name;
XX		printf("(%2d)  0x%02x - \"%s\"\n",
XX			i+2,part_type[i].type,part_type[i].name);
XX	}
XX	i++;
XX	curpos(X_POS,Y_PROMPT);
XX	clreop();
XX	printf("Select partition type using above menu (0 to %d) [0] : ",i);
XX	opt = getnum(0,i,0,0);
XX	switch (opt)
XX	{
XX		case  0:
XX			break;
XX
XX		case  1:
XX			curpos(X_POS,Y_PROMPT);
XX			clreop();
XX	printf("Enter partition type in decimal (0 to 255) [0x%02x] : ",type);
XX			type = getnum(0,255,type,0);
XX			name = PRIVATE_TYPE;
XX			break;
XX
XX		default:
XX			opt -= 2;
XX			type = part_type[opt].type;
XX			name = part_type[opt].name;
XX	}
XX	curpos(X_POS,Y_PARM);
XX	clreop();
XX	printf("Partition %d type: 0x%02x - \"%s\"\n",part+1,type,name);
XX	partdef = (part ? (cyl_end[part - 1] + 1) : cyl_start[part]);
XX	printf("Partition %d START cylinder number (%d to %d) [%d] : ",
XX		part+1,def_start,def_end,partdef);
XX	cyl_start[part] = getnum(def_start,def_end,partdef,1);
XX	/*
XX	**	Physical block/sector 0 of the disk is reserved for the
XX	**	boot block.  Account for it when calculating cylinder
XX	**	size for 1st physical partition.
XX	*/
XX	if (cyl_start[part] == 0)
XX		fstcyl = 1;
XX	else
XX		fstcyl = 0;
XX	partdef = ((cyl_start[(part + 1) % NPART] > cyl_start[part]) ?
XX			(cyl_start[(part + 1) % NPART] - 1) : cyl_end[part]);
XX	printf("Partition %d END   cylinder number (%d to %d) [%d] : ",
XX		part+1,cyl_start[part],def_end,partdef);
XX	cyl_end[part] = getnum(cyl_start[part],def_end,partdef,1);
XX	cylsize       = cyl_end[part] - cyl_start[part] + 1;
XX	blk0->blk0_tab[part].blk0_boot  =
XX		act_part[part];
XX	blk0->blk0_tab[part].blk0_s_h   =
XX		0;
XX	blk0->blk0_tab[part].blk0_s_s   =
XX		(1 + fstcyl) | ((cyl_start[part] >> 2) & 0x00C0);
XX	blk0->blk0_tab[part].blk0_s_c   =
XX		cyl_start[part];
XX	blk0->blk0_tab[part].blk0_sys   =
XX		type;
XX	blk0->blk0_tab[part].blk0_e_h   =
XX		info->info_nhead - 1;
XX	blk0->blk0_tab[part].blk0_e_s   =
XX		info->info_sechd | ((cyl_end[part] >> 2) & 0x00C0);
XX	blk0->blk0_tab[part].blk0_e_c   =
XX		cyl_end[part];
XX	blk0->blk0_tab[part].blk0_start =
XX		(cyl_start[part] * info->info_blkscyl) + fstcyl;
XX	blk0->blk0_tab[part].blk0_size  =
XX		cylsize * info->info_blkscyl - fstcyl;
XX	return (0);
XX}
XX
XXpartactive()
XX{
XXregister int	i, j, k;
XX
XX	for (i = 0, j = 0; i < NPART; i++)
XX	{
XX		if (blk0->blk0_tab[i].blk0_boot == BLK0_BOOT)
XX			j = i + 1;
XX		blk0->blk0_tab[i].blk0_boot = BLK0_NULL;
XX		
XX	}
XX	printf("Enter new active boot partition (%d to %d) [%d] : ",0,NPART,j);
XX	k = getnum(0,NPART,j,0);
XX	if (k)
XX		blk0->blk0_tab[k-1].blk0_boot = BLK0_BOOT;
XX	else
XX		if (j)
XX			blk0->blk0_tab[j-1].blk0_boot = BLK0_BOOT;
XX	if ((k == j) || (k == 0))
XX		return (0);
XX	return (1);
XX}
XX
XXparminit()
XX{
XX	/*
XX	**	The defaults are for 10MB 4 head 305 cylinder disk.
XX	*/
XX	info = (info_t *) &zeroblk.blk0_data[INFO_START];
XX	if ((info->info_sig1 != INFO_SIG1) || (info->info_sig2 != INFO_SIG2))
XX	{
XX		strcpy(info->info_name,"Drive 0");
XX		info->info_sig1    = INFO_SIG1;
XX		info->info_ndrv    = def_ndrv;
XX		info->info_npart   = def_npart;
XX		info->info_nunit   = def_nunit;
XX		info->info_nhead   = def_nhead;
XX		info->info_ncyls   = def_ncyls;
XX		info->info_sechd   = def_sechd;
XX		info->info_ntrack  = def_nhead * def_ncyls;
XX		info->info_blkscyl = def_nhead * def_sechd;
XX		info->info_blksize = def_blksize;
XX		info->info_step    = def_step;
XX		info->info_maxfer  = def_maxfer;
XX		info->info_sig2    = INFO_SIG2;
XX		return (0);
XX	}
XX	def_ndrv     = info->info_ndrv;
XX	def_npart    = info->info_npart;
XX	def_nunit    = info->info_nunit;
XX	def_nhead    = info->info_nhead;
XX	def_ncyls    = info->info_ncyls;
XX	def_sechd    = info->info_sechd;
XX	def_blksize  = info->info_blksize;
XX	def_step     = info->info_step;
XX	def_maxfer   = info->info_maxfer;
XX	def_end      = def_ncyls - 1;		/* override with real end */
XX	return (0);
XX}
XX
XXparmdump()
XX{
XX	printf("Drive   Number        : %8u\n",info->info_ndrv);
XX	printf("Drive   Name          : %8s\n",info->info_name);
XX	printf("Number  of Partitions : %8u\n",info->info_npart);
XX	printf("Number  of Units      : %8u\n",info->info_nunit);
XX	printf("Number  of Heads      : %8u\n",info->info_nhead);
XX	printf("Number  of Cylinders  : %8u\n",info->info_ncyls);
XX	printf("Sectors per Head      : %8u\n",info->info_sechd);
XX	printf("Tracks  per Drive     : %8u %s*%s\n",
XX		info->info_ntrack,hlon,hloff);
XX	printf("Blocks  per Cylinder  : %8u %s*%s\n",
XX		info->info_blkscyl,hlon,hloff);
XX	printf("Block   Size          : %8u %s*%s\n",
XX		info->info_blksize,hlon,hloff);
XX	printf("Maximum DMA Transfer  : %8u\n",info->info_maxfer);
XX	printf("Head Step Speed Code  : %8u\n",info->info_step);
XX	printf("%s* generated automatically%s\n",hlon,hloff);
XX	return (0);
XX}
XX
XXparmnew()
XX{
XX	printf("Drive Number         (0 to 4)   [%d] : ",
XX		info->info_ndrv);
XX	info->info_ndrv = getnum(0,4,info->info_ndrv,1);
XX	printf("Drive Name                      [%s] : ",
XX		info->info_name);
XX	strcpy(info->info_name,getstr(1,7,info->info_name,1));
XX	printf("Number of Partitions (%d to %d) [%d] : ",
XX		1,NPART,info->info_npart);
XX	info->info_npart = getnum(1,NPART,info->info_npart,1);
XX	printf("Number of Units      (%d to %d) [%d] : ",
XX		1,8,info->info_nunit);
XX	info->info_nunit = getnum(1,8,info->info_nunit,1);
XX	printf("Number of Heads      (%d to %d) [%d] : ",
XX		2,16,info->info_nhead);
XX	info->info_nhead = getnum(2,16,info->info_nhead,1);
XX	printf("Number of Cylinders  (%d to %d) [%d] : ",
XX		0,MAX_NCYLS,info->info_ncyls);
XX	info->info_ncyls = getnum(0,MAX_NCYLS,info->info_ncyls,1);
XX	printf("Sectors per Head     (%d to %d) [%d] : ",
XX		0,99,info->info_sechd);
XX	info->info_sechd = getnum(0,99,info->info_sechd,1);
XX	printf("Tracks per Drive                [%d] : %s%d%s\n",
XX		info->info_ntrack,rvon,
XX		info->info_nhead * info->info_ncyls,rvoff);
XX	info->info_ntrack = info->info_nhead * info->info_ncyls;
XX	printf("Blocks per Cylinder             [%d] : %s%d%s\n",
XX		info->info_blkscyl,rvon,
XX		info->info_nhead * info->info_sechd,rvoff);
XX	info->info_blkscyl = info->info_nhead * info->info_sechd;
XX	printf("Block Size is Bytes per Sector  [%d] : %s%d%s\n",
XX		info->info_blksize,rvon,info->info_blksize,rvoff);
XX	printf("Maximum DMA Transfer (%d to %d) [%d] : ",
XX		0,MAX_MAXFER,info->info_maxfer);
XX	info->info_maxfer = getnum(0,MAX_MAXFER,info->info_maxfer,1);
XX	printf("Head Step Speed Code (%d to %d) [%d] : ",
XX		0,9,info->info_step);
XX	info->info_step = getnum(0,9,info->info_step,1);
XX	return (0);
XX}
XX
XXbanner()
XX{
XX	printf("\t%s %s %s %s",rvon,makeupper(progname),_message,rvoff);
XX	makelower(progname);
XX	return (0);
XX}
XX
XX#define toupper(c)	((c)-'a'+'A')
XX#define tolower(c)	((c)-'A'+'a')
XX#define toascii(c)	((c)&0177)
XX
XXchar *
XXmakelower(s)
XXregister char	*s;
XX{
XXregister char	*p = s;
XX
XX	while (*s)
XX	{
XX		if ((*s >= 'A') && (*s <= 'Z'))
XX			*s = tolower(*s);
XX		s++;
XX	}
XX	return (p);
XX}
XX
XXchar *
XXmakeupper(s)
XXregister char	*s;
XX{
XXregister char	*p = s;
XX
XX	while (*s)
XX	{
XX		if ((*s >= 'a') && (*s <= 'z'))
XX			*s = toupper(*s);
XX		s++;
XX	}
XX	return (p);
XX}
SHAR_EOF
if test 19770 -ne "`wc -c fdisk.c`"
then
echo shar: error transmitting fdisk.c '(should have been 19770 characters)'
fi
echo shar: extracting input.c '(4617 characters)'
sed 's/^XX//' << \SHAR_EOF > input.c
XX/*
XX**	@(#) input.c: version 1.5 created on 6/29/87 at 13:00:43
XX*/
XXstatic	char	_sccs_C_id_[] =
XX	"@(#) input.c: version 1.5 created on 6/29/87 at 13:00:43";
XX
XX#include	<stdio.h>
XX#include	<sgtty.h>
XX
XX#define DEL	(0177)		/* delete    key - ^? -	0x7f	*/
XX#define BSP	(010)		/* backspace key - ^H - 0x08	*/
XX
XX/*
XX**	The following are defined in screen.c and are terminal dependent.
XX*/
XXextern	char	clear[];	/* clear and home cursor	*/
XXextern	char	rvon[];		/* reverse video on		*/
XXextern	char	rvoff[];	/* reverse video off		*/
XXextern	char	hlon[];		/* highlight on			*/
XXextern	char	hloff[];	/* highlight off		*/
XXextern	char	ulon[];		/* underline on			*/
XXextern	char	uloff[];	/* underline off		*/
XXextern	char	blon[];		/* blink on			*/
XXextern	char	bloff[];	/* blink off			*/
XXextern	char	alloff[];	/* all attributes off		*/
XX
XXstruct	sgttyb sgbuf;
XX
XXprompt(string,high,ret)
XXregister char	*string;
XXregister int	high, ret;
XX{
XX	/*
XX	**	prompt overhead is 10 character positions.
XX	*/
XX	printf("%s%s%s (%sy%s or %sn%s) ",
XX		high ? hlon : "", string, high ? hloff : "",
XX		hlon,hloff,hlon,hloff);
XX	while (1)
XX	{
XX		switch (xgetchar())
XX		{
XX			case 'y':
XX			case 'Y':
XX				printf("%sYes%s",rvon,rvoff);
XX				if (ret)
XX					printf("\r\n");
XX				return (1);
XX
XX			case 'n':
XX			case 'N':
XX				printf("%sNo%s",rvon,rvoff);
XX				if (ret)
XX					printf("\r\n");
XX				return (0);
XX
XX			default:
XX				printf("\007");
XX		}
XX	}
XX}
XX	
XXchar *
XXgetstr(min,max,defstr,ret)
XXregister int	min, max, ret;
XXregister char	*defstr;
XX{
XXregister char *cp;
XXchar	 c, cbuf[64];
XXint	 flags;
XX
XX	ioctl(0,TIOCGETP,&sgbuf);
XX	flags = sgbuf.sg_flags;
XX	sgbuf.sg_flags = RAW;
XX	ioctl(0,TIOCSETP,&sgbuf);
XX	while (1)
XX	{
XX		printf("%s",rvon);
XX		for (cp = cbuf; cp < cbuf + max;)
XX		{
XX			read(0,&c,1);           
XX			if ((c == '\r' || c == '\n') && (cp > cbuf))
XX			{
XX				break;
XX			}
XX			else
XX			{
XX				if ((c == DEL) || (c == BSP))
XX				{
XX					if (cp > cbuf)
XX					{
XX						printf("%s\b \b%s",
XX							rvoff,rvon);
XX						--cp;
XX					}
XX					else
XX					{
XX						printf("\007");
XX					}
XX				}
XX				else 
XX				{
XX					/* use the default */
XX					if ((c == '\r' || c == '\n') &&
XX						(cp == cbuf))
XX					{
XX						printf("%s",(cp = defstr));
XX						goto strout;
XX					}
XX					else    /* record character */
XX					{ 
XX						*cp++ = c;
XX						printf("%c",c);
XX					}
XX				}
XX			}
XX		}
XX		*cp = 0;
XX		cp = cbuf;
XXstrout:
XX		printf("%s",rvoff);
XX		/*
XX		 * check that string length is bewteen bounds, 
XX		 */
XX		if (min <= strlen(cp) && strlen(cp) <= max)
XX		{
XX			if (ret)
XX				printf("\r\n");
XX			sgbuf.sg_flags = flags;
XX			ioctl(0,TIOCSETP,&sgbuf);
XX			return (cp);
XX		}
XX		printf("\r%sInvalid string%s: please re-enter [%s] : ",
XX			hlon,hloff,defstr);
XX		clreol();
XX	}
XX}
XX
XXcheckrange(min,max,def)
XXregister int	*min, *max, *def;
XX{
XX	if (*min > *max)
XX		*min = *max;
XX	if (*def > *max)
XX		*def = *max;
XX	else
XX		if (*def < *min)
XX			*def = *min;
XX	return (0);
XX}
XX
XXgetnum(min,max,def,ret)
XXint	min, max, def, ret;
XX{
XXregister char *cp;
XXchar	 c, cbuf[10];
XXint	 r, flags;
XX
XX	checkrange(&min,&max,&def);
XX	ioctl(0,TIOCGETP,&sgbuf);
XX	flags = sgbuf.sg_flags;
XX	sgbuf.sg_flags = RAW;
XX	ioctl(0,TIOCSETP,&sgbuf);
XX	while (1)
XX	{
XX		printf("%s",rvon);
XX		for (cp = cbuf; cp < cbuf + 10;)
XX		{
XX			read(0,&c,1);           
XX			if      (((c >= '0') && (c <= '9')) || 
XX				 (
XX				  (cp == cbuf) &&       /* first digit? */
XX				  (
XX				   (c == '+' && max >= 0) ||    /* '+' okay? */
XX				   (c == '-' && min < 0)        /* '-' okay? */
XX				  )
XX				 )
XX				)
XX			{ 
XX				*cp++ = c;
XX				printf("%c",c);
XX			}
XX			else
XX			{
XX				if ((c == '\r' || c == '\n') && (cp > cbuf))
XX				{
XX					break;
XX				}
XX				else
XX				{
XX					if (c == DEL)
XX					{
XX						if (cp > cbuf)
XX						{
XX							printf("%s\b \b%s",
XX								rvoff,rvon);
XX							--cp;
XX						}
XX						else
XX						{
XX							printf("\007");
XX						}
XX					}
XX					else 
XX					{
XX						/* use the default */
XX						if (    (c == '\r' ||
XX							c == '\n') &&
XX							(cp == cbuf)
XX						   )
XX						{
XX							printf("%d",
XX								(r = def));
XX							goto numout;
XX						}
XX						else
XX						{
XX							printf("\007");
XX						}
XX					}
XX				}
XX			}
XX		}
XX		*cp = 0;
XX		r = atoi(cbuf);
XXnumout:
XX		printf("%s",rvoff);
XX		/*
XX		 * check number bewteen bounds, 
XX		 * allowing also for unsigned values
XX		 */
XX		if (min <= r && r <= max)
XX		{
XX			if (ret)
XX				printf("\r\n");
XX			sgbuf.sg_flags = flags;
XX			ioctl(0,TIOCSETP,&sgbuf);
XX			return (r);
XX		}
XX	printf("\r%sInvalid number%s: please re-enter (%d to %d) [%d] : ",
XX			hlon,hloff,min,max,def);
XX		clreol();
XX	}
XX}
XX
XXxgetchar()
XX{
XXregister int	flags;
XXchar	c;
XX
XX	ioctl(0,TIOCGETP,&sgbuf);
XX	flags = sgbuf.sg_flags;
XX	sgbuf.sg_flags = RAW;
XX	ioctl(0,TIOCSETP,&sgbuf);
XX	read(0, &c, 1);
XX	sgbuf.sg_flags = flags;
XX	ioctl(0,TIOCSETP,&sgbuf);
XX	return (c == '\r' ? '\n' : c);
XX}
SHAR_EOF
if test 4617 -ne "`wc -c input.c`"
then
echo shar: error transmitting input.c '(should have been 4617 characters)'
fi
echo shar: extracting screen.c '(4478 characters)'
sed 's/^XX//' << \SHAR_EOF > screen.c
XX/*
XX**	@(#) screen.c: version 1.5 created on 6/29/87 at 13:00:49
XX*/
XXstatic	char	_sccs_C_id_[] =
XX	"@(#) screen.c: version 1.5 created on 6/29/87 at 13:00:49";
XX
XX#include	<stdio.h>
XX
XX#ifdef	VENIX
XX#define	INTRODUCER	'\033'		/* good old ESCAPE - ^[		*/
XXchar	clear[]  = "\033H\033J";	/* clear and home cursor	*/
XXchar	rvon[]   = "\033\010";		/* reverse video on		*/
XXchar	rvoff[]  = "\033\007";		/* reverse video off		*/
XXchar	hlon[]   = "\033\006";		/* highlight on			*/
XXchar	hloff[]  = "\033\005";		/* highlight off		*/
XXchar	ulon[]   = "\033\004";		/* underline on			*/
XXchar	uloff[]  = "\033\003";		/* underline off		*/
XXchar	blon[]   = "\033\002";		/* blink on			*/
XXchar	bloff[]  = "\033\001";		/* blink off			*/
XXchar	alloff[] = "\033\016";		/* all attributes off		*/
XX#endif	/* VENIX */
XX
XX#ifdef	MINIX
XX#define	INTRODUCER	'\033'		/* good old ESCAPE - ^[		*/
XXchar	clear[]  = "\033[H\033[J";	/* clear and home cursor	*/
XXchar	rvon[]   = "\033[7m";		/* reverse video on		*/
XXchar	rvoff[]  = "\033[0m";		/* reverse video off		*/
XXchar	hlon[]   = "\033[1m";		/* highlight on			*/
XXchar	hloff[]  = "\033[0m";		/* highlight off		*/
XXchar	ulon[]   = "\033[4m";		/* underline on			*/
XXchar	uloff[]  = "\033[0m";		/* underline off		*/
XXchar	blon[]   = "\033[5m";		/* blink on			*/
XXchar	bloff[]  = "\033[0m";		/* blink off			*/
XXchar	alloff[] = "\033[0m";		/* all attributes off		*/
XX#endif	/* MINIX */
XX
XX#ifdef	VT100
XX#define	INTRODUCER	'\033'		/* good old ESCAPE - ^[		*/
XXchar	clear[]  = "\033[H\033[J";	/* clear and home cursor	*/
XXchar	rvon[]   = "\033[7m";		/* reverse video on		*/
XXchar	rvoff[]  = "\033[0m";		/* reverse video off		*/
XXchar	hlon[]   = "\033[1m";		/* highlight on			*/
XXchar	hloff[]  = "\033[0m";		/* highlight off		*/
XXchar	ulon[]   = "\033[4m";		/* underline on			*/
XXchar	uloff[]  = "\033[0m";		/* underline off		*/
XXchar	blon[]   = "\033[5m";		/* blink on			*/
XXchar	bloff[]  = "\033[0m";		/* blink off			*/
XXchar	alloff[] = "\033[0m";		/* all attributes off		*/
XX#endif	/* VT100 */
XX
XX/*
XX**	Position cursor.
XX*/
XXcurpos(col,row)
XXregister int	col, row;
XX{
XXchar	cmd[16];
XX
XX#ifdef	VENIX
XX	sprintf(cmd,"%cY%c%c",INTRODUCER,(040 + (row - 1)),(040 + (col - 1)));
XX#endif	/* VENIX */
XX
XX#ifdef	MINIX
XX	sprintf(cmd,"%c[%d;%dH",INTRODUCER,row,col);
XX#endif	/* MINIX */
XX
XX#ifdef	VT100
XX	sprintf(cmd,"%c[%d;%dH",INTRODUCER,row,col);
XX#endif	/* VT100 */
XX
XX	write(1,cmd,strlen(cmd));
XX}
XX
XX/*
XX**	Cursor Home.
XX*/
XXchome()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('H');
XX}
XX
XX/*
XX**	Cursor Up.
XX*/
XXcup()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('A');
XX}
XX
XX/*
XX**	Cursor Down.
XX*/
XXcdown()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('B');
XX}
XX
XX/*
XX**	Cursor Right.
XX*/
XXcright()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('C');
XX}
XX
XX/*
XX**	Cursor Left.
XX*/
XXcleft()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('D');
XX}
XX
XX/*
XX**	Reverse Scroll.
XX*/
XXrscroll()
XX{
XX#ifdef	VENIX
XX	putchar(INTRODUCER);
XX	putchar('I');
XX#endif	/* VENIX */
XX}
XX
XX/*
XX**	Clear to End Of Line.
XX*/
XXclreol()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('K');
XX}
XX
XX/*
XX**	Clear to End Of Page/Screen.
XX*/
XXclreop()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('J');
XX}
XX
XX/*
XX**	Insert Line at Cursor.
XX*/
XXinsline()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('L');
XX}
XX
XX/*
XX**	Delete Line at Cursor.
XX*/
XXdelline()
XX{
XX	putchar(INTRODUCER);
XX#ifdef	MINIX
XX	putchar('[');
XX#endif	/* MINIX */
XX#ifdef	VT100
XX	putchar('[');
XX#endif	/* VT100 */
XX	putchar('M');
XX}
XX
XX/*
XX**	Normal Attribute.
XX*/
XXanorm()
XX{
XX	puts(alloff);
XX}
XX
XX/*
XX**	Blink Attribute.
XX*/
XXablink(on)
XXregister int	on;
XX{
XX	if (on)
XX		puts(blon);
XX	else
XX		puts(bloff);
XX}
XX
XX/*
XX**	High Intensity Attribute.
XX*/
XXahigh(on)
XXregister int	on;
XX{
XX	if (on)
XX		puts(hlon);
XX	else
XX		puts(hloff);
XX}
XX
XX/*
XX**	Reverse Video Attribute.
XX*/
XXarev(on)
XXregister int	on;
XX{
XX	if (on)
XX		puts(rvon);
XX	else
XX		puts(rvoff);
XX}
XX
XX/*
XX**	Underline attribute.
XX*/
XXauline(on)
XXregister int	on;
XX{
XX	if (on)
XX		puts(ulon);
XX	else
XX		puts(uloff);
XX}
SHAR_EOF
if test 4478 -ne "`wc -c screen.c`"
then
echo shar: error transmitting screen.c '(should have been 4478 characters)'
fi
echo shar: extracting test.uu '(733 characters)'
sed 's/^XX//' << \SHAR_EOF > test.uu
XXbegin 440 test.dat
XXM!P$``%06``!,#````````+0#````````B!$`````````#-VL"-VL!/L"[Y\$
XXM``#=&-T!^P+OYO____L`[]_____=`-T`W^]I%P``^P/OSO___]50$@,QB`#[
XXM`.]^#P``W1C=`?L"[[7____[`.^N____W0#=`-_O7Q<``/L#[YW____54!(#
XXM,8P`U5L3$MT+W0'[`N^'____^P#ONA```-T8W0'[`N]U____^P#O;O___]T`
XXMW0#?[[H7``#[`^]=____U5`2`S%E_]T8W0'[`N]+____^P#O1/___]1;,?D`
XXMW0O=`?L"[S3____[`.\M____^P#OP!$``-T+W0'[`N\;____^P#O%/____L`
XXM[T<0```Q&?_=&-T!^P+O__[___L`[_C^___46]T$W^_0%@``^P+OY_[__]T`
XXMW0#=!-T`^P3OV/[__]!06A(#,1#_T`%;UUK=6OM;[QX*``#=`]T!^P+OM_[_
XXM__L`[[#^___[`.\/"```W1C=`?L"[Y[^___[`.^7_O__W03?[ZL6```1G]`!
XXM6]T8W5O[`J6E``!$<FEV92`P``0`"`#$!`0`$0`Q`40```(%`/__6EH```(`
XXM!`,19`$```#3&@``@``!91`#$<C4&@``D!H``````<D@`Q'<9#4``%`%````
XX1``'=0`-1,+0Z``!0%@``5:H#
XX`
XXend
SHAR_EOF
if test 733 -ne "`wc -c test.uu`"
then
echo shar: error transmitting test.uu '(should have been 733 characters)'
fi
#	End of shell archive
exit 0