Subject: Disklabels arrive for 2.11BSD (#257 part 8 of 18)
Index:	sys,bin,usr.lib,(many more)/<many> 2.11BSD

Description:
	The moving the partitions tables out of the disk drivers and to
	a disklabel residing on the media has been on the wish list for
	many many years.

	Disklabels have finally arrived for 2.11BSD!

Repeat-By:
	Observation.  Also a reading of the setup and installation
	documentation for previous 2BSD releases (2.9, 2.10, 2.11)
	all have a paragraph similar to this present:

"It is possible to change the partitions by changing the code for the
table in the disk driver.  Since it's desirable to do this, these tables
really should be read off each pack...."

Fix:
	This is part 8 of 18.  Gather all parts before doing anything
	except reading the instructions which are in #250 (part 1).

	Updated by this part are:

/usr/src/lib/libc/gen/disklabel.c
/usr/src/lib/libc/gen/Makefile
/usr/src/lib/libc/pdp/gen/disktab.c
/usr/src/lib/libc/pdp/gen/Makefile

	'disklabel.c' is new and added to the system by unpacking the
	included shar archive.

	'disktab.c' is removed from the system.  It has been replaced
	by the 'disklabel.c' module.

	NOTE:  The /etc/disktab format has changed.  There will be a
	       reminder of this in the part which replaces the disktab
	       file.

	Cut where indicated and save to a file (/tmp/257).  Then:

		cd /tmp
		sh 257
		sh lib.shar
		sh lib.sh
		patch -p0 < lib.patch
		rm lib.shar lib.sh lib.patch

-------------------------cut here-----------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	lib.sh
#	lib.patch
#	lib.shar
# This archive created: Tue Jun 27 22:20:38 1995
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'lib.sh'
then
	echo shar: "will not over-write existing file 'lib.sh'"
else
sed 's/^Y//' << \SHAR_EOF > 'lib.sh'
Y#!/bin/sh
Ymv /usr/src/lib/libc/pdp/gen/disktab.c /usr/src/lib/libc/pdp/gen/disktab.c~
SHAR_EOF
fi
if test -f 'lib.patch'
then
	echo shar: "will not over-write existing file 'lib.patch'"
else
sed 's/^Y//' << \SHAR_EOF > 'lib.patch'
Y*** /usr/src/lib/libc/gen/Makefile.old	Sat Apr  1 23:16:43 1995
Y--- /usr/src/lib/libc/gen/Makefile	Thu Apr 13 22:08:34 1995
Y***************
Y*** 3,9 ****
Y  # All rights reserved.  The Berkeley software License Agreement
Y  # specifies the terms and conditions for redistribution.
Y  #
Y! #	@(#)Makefile	5.7.3 (2.11BSD) 1995/04/01
Y  #
Y  # Several routines have been rewritten in assembly language for the VAX and
Y  # the PDP. If you are not running on a VAX or PDP, you should use the
Y--- 3,9 ----
Y  # All rights reserved.  The Berkeley software License Agreement
Y  # specifies the terms and conditions for redistribution.
Y  #
Y! #	@(#)Makefile	5.7.4 (2.11BSD) 1995/04/13
Y  #
Y  # Several routines have been rewritten in assembly language for the VAX and
Y  # the PDP. If you are not running on a VAX or PDP, you should use the
Y***************
Y*** 14,20 ****
Y  
Y  CFLAGS=	-O ${DEFS}
Y  STDSRC=	abort.c alarm.c atoi.c atol.c calloc.c closedir.c crypt.c \
Y! 	ctime.c ctype_.c daemon.c devname.c err.c errlst.c execvp.c fakcu.c \
Y  	fstab.c gcvt.c getenv.c getgrent.c getgrgid.c getgrnam.c getlogin.c \
Y  	getpass.c getpwent.c getloadavg.c \
Y  	getttyent.c getttynam.c getusershell.c getwd.c \
Y--- 14,21 ----
Y  
Y  CFLAGS=	-O ${DEFS}
Y  STDSRC=	abort.c alarm.c atoi.c atol.c calloc.c closedir.c crypt.c \
Y! 	ctime.c ctype_.c daemon.c devname.c disklabel.c err.c errlst.c \
Y! 	execvp.c fakcu.c \
Y  	fstab.c gcvt.c getenv.c getgrent.c getgrgid.c getgrnam.c getlogin.c \
Y  	getpass.c getpwent.c getloadavg.c \
Y  	getttyent.c getttynam.c getusershell.c getwd.c \
Y***************
Y*** 26,32 ****
Y  	telldir.c time.c timezone.c ttyname.c ttyslot.c ualarm.c usleep.c \
Y  	valloc.c strdup.c strsep.c uname.c wait.c wait3.c waitpid.c
Y  STDOBJ=	abort.o alarm.o atoi.o atol.o calloc.o closedir.o crypt.o \
Y! 	ctime.o ctype_.o daemon.o devname.o err.o errlst.o execvp.o fakcu.o \
Y  	fstab.o gcvt.o getenv.o getgrent.o getgrgid.o getgrnam.o getlogin.o \
Y  	getpass.o getpwent.o getloadavg.o \
Y  	getttyent.o getttynam.o getusershell.o getwd.o \
Y--- 27,34 ----
Y  	telldir.c time.c timezone.c ttyname.c ttyslot.c ualarm.c usleep.c \
Y  	valloc.c strdup.c strsep.c uname.c wait.c wait3.c waitpid.c
Y  STDOBJ=	abort.o alarm.o atoi.o atol.o calloc.o closedir.o crypt.o \
Y! 	ctime.o ctype_.o daemon.o devname.o disklabel.o err.o errlst.o \
Y! 	execvp.o fakcu.o \
Y  	fstab.o gcvt.o getenv.o getgrent.o getgrgid.o getgrnam.o getlogin.o \
Y  	getpass.o getpwent.o getloadavg.o \
Y  	getttyent.o getttynam.o getusershell.o getwd.o \
Y*** /usr/src/lib/libc/pdp/gen/Makefile.old	Sat Apr  9 00:56:31 1994
Y--- /usr/src/lib/libc/pdp/gen/Makefile	Thu Apr 13 22:10:18 1995
Y***************
Y*** 3,15 ****
Y  # All rights reserved.  The Berkeley software License Agreement
Y  # specifies the terms and conditions for redistribution.
Y  #
Y! #	@(#)Makefile	5.6.2 (2.11BSD GTE) 4/9/94
Y  #
Y! SRCS=	_setjmp.s abs.s alloca.s atof.c bcmp.s bcopy.s bzero.s disktab.c \
Y  	ecvt.c fabs.s ffs.s frexp.s index.s insque.s ldexp.s ldfps.s \
Y  	modf.s nsym.c remque.s rindex.s rollback.s setjmp.s setjmperr.c \
Y  	strcat.s strcmp.s strcpy.s strlen.s strncat.s strncmp.s strncpy.s
Y! OBJS=	_setjmp.o abs.o alloca.o atof.o bcmp.o bcopy.o bzero.o disktab.o \
Y  	ecvt.o fabs.o ffs.o frexp.o index.o insque.o ldexp.o ldfps.o \
Y  	modf.o nsym.o remque.o rindex.o rollback.o setjmp.o setjmperr.o \
Y  	strcat.o strcmp.o strcpy.o strlen.o strncat.o strncmp.o strncpy.o
Y--- 3,15 ----
Y  # All rights reserved.  The Berkeley software License Agreement
Y  # specifies the terms and conditions for redistribution.
Y  #
Y! #	@(#)Makefile	5.6.3 (2.11BSD GTE) 1995/04/13
Y  #
Y! SRCS=	_setjmp.s abs.s alloca.s atof.c bcmp.s bcopy.s bzero.s \
Y  	ecvt.c fabs.s ffs.s frexp.s index.s insque.s ldexp.s ldfps.s \
Y  	modf.s nsym.c remque.s rindex.s rollback.s setjmp.s setjmperr.c \
Y  	strcat.s strcmp.s strcpy.s strlen.s strncat.s strncmp.s strncpy.s
Y! OBJS=	_setjmp.o abs.o alloca.o atof.o bcmp.o bcopy.o bzero.o \
Y  	ecvt.o fabs.o ffs.o frexp.o index.o insque.o ldexp.o ldfps.o \
Y  	modf.o nsym.o remque.o rindex.o rollback.o setjmp.o setjmperr.o \
Y  	strcat.o strcmp.o strcpy.o strlen.o strncat.o strncmp.o strncpy.o
Y***************
Y*** 41,47 ****
Y  
Y  tags:
Y  	cwd=`pwd`; \
Y! 	for i in atof.c disktab.c ecvt.c; do \
Y  		ctags -a -f ${TAGSFILE} $$cwd/$$i; \
Y  	done
Y  
Y--- 41,47 ----
Y  
Y  tags:
Y  	cwd=`pwd`; \
Y! 	for i in atof.c ecvt.c; do \
Y  		ctags -a -f ${TAGSFILE} $$cwd/$$i; \
Y  	done
Y  
Y***************
Y*** 75,82 ****
Y  bcmp.o: bcmp.s ./DEFS.h
Y  bcopy.o: bcopy.s ./DEFS.h
Y  bzero.o: bzero.s ./DEFS.h
Y- disktab.o: disktab.c /usr/include/disktab.h /usr/include/stdio.h
Y- disktab.o: /usr/include/ctype.h
Y  ecvt.o: ecvt.c
Y  fabs.o: fabs.s ./DEFS.h
Y  ffs.o: ffs.s ./DEFS.h
Y--- 75,80 ----
SHAR_EOF
fi
if test -f 'lib.shar'
then
	echo shar: "will not over-write existing file 'lib.shar'"
else
sed 's/^Y//' << \SHAR_EOF > 'lib.shar'
Y#! /bin/sh
Y# This is a shell archive, meaning:
Y# 1. Remove everything above the #! /bin/sh line.
Y# 2. Save the resulting text in a file.
Y# 3. Execute the file with /bin/sh (not csh) to create:
Y#	/usr/src/lib/libc/gen/disklabel.c
Y# This archive created: Mon Jun 19 20:23:34 1995
Yexport PATH; PATH=/bin:/usr/bin:$PATH
Yif test -f '/usr/src/lib/libc/gen/disklabel.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/lib/libc/gen/disklabel.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/lib/libc/gen/disklabel.c'
YX/*
YX * Copyright (c) 1983, 1987 Regents of the University of California.
YX * All rights reserved.
YX *
YX * Redistribution and use in source and binary forms, with or without
YX * modification, are permitted provided that the following conditions
YX * are met:
YX * 1. Redistributions of source code must retain the above copyright
YX *    notice, this list of conditions and the following disclaimer.
YX * 2. Redistributions in binary form must reproduce the above copyright
YX *    notice, this list of conditions and the following disclaimer in the
YX *    documentation and/or other materials provided with the distribution.
YX * 3. All advertising materials mentioning features or use of this software
YX *    must display the following acknowledgement:
YX *	This product includes software developed by the University of
YX *	California, Berkeley and its contributors.
YX * 4. Neither the name of the University nor the names of its contributors
YX *    may be used to endorse or promote products derived from this software
YX *    without specific prior written permission.
YX *
YX * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
YX * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
YX * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
YX * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
YX * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
YX * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
YX * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
YX * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
YX * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
YX * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
YX * SUCH DAMAGE.
YX */
YX
YX#if defined(LIBC_SCCS) && !defined(lint)
YXstatic char sccsid[] = "@(#)disklabel.c	5.17.1 (2.11BSD) 4/10/95";
YX#endif /* LIBC_SCCS and not lint */
YX
YX#include <sys/param.h>
YX#include <sys/errno.h>
YX#include <sys/fs.h>
YX#include <sys/file.h>
YX#include <sys/uio.h>
YX
YX#define DKTYPENAMES
YX#include <sys/disklabel.h>
YX#include <stdio.h>
YX#include <string.h>
YX
YXextern	int	errno;
YX
YXstatic	char *dgetstr();
YXstatic	dgetent();
YXstatic	dnamatch();
YXstatic	long dgetnum(), _gtnumdflt();
YXstatic	dgetflag();
YXstatic	gettype();
YXstatic	error();
YX
YX#define getnumdflt(field, dname, dflt) field=_gtnumdflt(dname,(long)dflt)
YX
YXstruct disklabel *
YXgetdiskbyname(name)
YX	char *name;
YX{
YX	static struct	disklabel disk;
YX	static char 	boot[MAXPATHLEN];
YX	char	localbuf[256];	/* BUFSIZ reduced to save stack space */
YX	char	buf[BUFSIZ];
YX	char	*cp, *cq;	/* can't be register */
YX	register struct	disklabel *dp = &disk;
YX	register struct partition *pp;
YX	char	p, max, psize[3], pbsize[3],
YX		pfsize[3], poffset[3], ptype[3];
YX	u_long	*dx;
YX
YX	if (dgetent(buf, name) <= 0)
YX		return ((struct disklabel *)0);
YX	bzero((char *)&disk, sizeof(disk));
YX	/*
YX	 * typename
YX	 */
YX	cq = dp->d_typename;
YX	cp = buf;
YX	while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 &&
YX	    (*cq = *cp) && *cq != '|' && *cq != ':')
YX		cq++, cp++;
YX	*cq = '\0';
YX	/*
YX	 * boot name (optional)  xxboot
YX	 */
YX	cp = boot;
YX	dp->d_boot0 = dgetstr("b0", &cp);
YX	cp = localbuf;
YX	cq = dgetstr("ty", &cp);
YX	if (cq && strcmp(cq, "removable") == 0)
YX		dp->d_flags |= D_REMOVABLE;
YX	else  if (cq && strcmp(cq, "simulated") == 0)
YX		dp->d_flags |= D_RAMDISK;
YX	if (dgetflag("sf"))
YX		dp->d_flags |= D_BADSECT;
YX
YX/*
YX *	Have to do this because anything except 512 will cause chaos in
YX *	disklabel(8).  disklabel(8) tries to protect itself against this
YX *	but the safest thing is to fix the sector size here.  The only thing
YX *	which ever used a value other than 512 was the RL02 and RL01
YX *	disktab entries and they have been fixed.
YX*/
YX	
YX#ifdef	corrupt_filesystems
YX	getnumdflt(dp->d_secsize, "se", 512);
YX#endif
YX	dp->d_secsize = 512;
YX
YX	dp->d_ntracks = dgetnum("nt");
YX	dp->d_nsectors = dgetnum("ns");
YX	dp->d_ncylinders = dgetnum("nc");
YX	cq = dgetstr("dt", &cp);
YX	if (cq)
YX		dp->d_type = gettype(cq, dktypenames);
YX	else
YX		getnumdflt(dp->d_type, "dt", 0);
YX	getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
YX	getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
YX	getnumdflt(dp->d_sparespertrack, "rt", 0);
YX	getnumdflt(dp->d_sparespercyl, "rc", 0);
YX	getnumdflt(dp->d_acylinders, "ac", 0);
YX	getnumdflt(dp->d_rpm, "rm", 3600);
YX	getnumdflt(dp->d_interleave, "il", 1);
YX	getnumdflt(dp->d_trackskew, "sk", 0);
YX	getnumdflt(dp->d_cylskew, "cs", 0);
YX	getnumdflt(dp->d_headswitch, "hs", 0);
YX	getnumdflt(dp->d_trkseek, "ts", 0);
YX
YX/*
YX * See the comments in src/bin/disklabel.c for a more detailed explaination
YX * which the 'bbsize' is set to 512.  The simple explanation is that the
YX * designers of disklabeling confused 'sectors' and 'filesystem blocks'. 
YX * BBSIZE is set to 1024 even though the real boot area (what the boot roms
YX * will read) is 512.
YX*/
YX#ifdef	boot_area_really_is_1k
YX	getnumdflt(dp->d_bbsize, "bs", BBSIZE);
YX#endif
YX	dp->d_bbsize = 512;
YX
YX	getnumdflt(dp->d_sbsize, "sb", SBSIZE);
YX	strcpy(psize, "px");
YX	strcpy(pbsize, "bx");
YX	strcpy(pfsize, "fx");
YX	strcpy(poffset, "ox");
YX	strcpy(ptype, "tx");
YX	max = 'a' - 1;
YX	pp = &dp->d_partitions[0];
YX	for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) {
YX		psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p;
YX		pp->p_size = dgetnum(psize);
YX		if (pp->p_size == -1L)
YX			pp->p_size = 0L;
YX		else {
YX			pp->p_offset = dgetnum(poffset);
YX			getnumdflt(pp->p_fsize, pfsize, 0);
YX			if (pp->p_fsize)
YX				pp->p_frag = dgetnum(pbsize) / pp->p_fsize;
YX			getnumdflt(pp->p_fstype, ptype, 0);
YX			if (pp->p_fstype == 0 && (cq = dgetstr(ptype, &cp)))
YX				pp->p_fstype = gettype(cq, fstypenames);
YX			max = p;
YX		}
YX	}
YX	dp->d_npartitions = max + 1 - 'a';
YX	(void)strcpy(psize, "dx");
YX	dx = dp->d_drivedata;
YX	for (p = '0'; p < '0' + NDDATA; p++, dx++) {
YX		psize[1] = p;
YX		getnumdflt(*dx, psize, 0);
YX	}
YX	dp->d_magic = DISKMAGIC;
YX	dp->d_magic2 = DISKMAGIC;
YX	return (dp);
YX}
YX
YX#include <ctype.h>
YX
YXstatic	char *tbuf;
YXstatic	char *dskip();
YXstatic	char *ddecode();
YX
YX/*
YX * Get an entry for disk name in buffer bp,
YX * from the diskcap file.  Parse is very rudimentary;
YX * we just notice escaped newlines.
YX */
YXstatic
YXdgetent(bp, name)
YX	char *bp, *name;
YX{
YX	register char *cp;
YX	register int c;
YX	register int i = 0, cnt = 0;
YX	char ibuf[512];		/* BUFSIZE - reduced to conserve stack space */
YX	int tf;
YX
YX	tbuf = bp;
YX	tf = open(_PATH_DISKTAB, 0);
YX	if (tf < 0) {
YX		error(errno);
YX		return (-1);
YX	}
YX	for (;;) {
YX		cp = bp;
YX		for (;;) {
YX			if (i == cnt) {
YX				cnt = read(tf, ibuf, sizeof (ibuf));
YX				if (cnt <= 0) {
YX					error(errno);
YX					close(tf);
YX					return (0);
YX				}
YX				i = 0;
YX			}
YX			c = ibuf[i++];
YX			if (c == '\n') {
YX				if (cp > bp && cp[-1] == '\\'){
YX					cp--;
YX					continue;
YX				}
YX				break;
YX			}
YX			if (cp >= bp+BUFSIZ) {
YX				error(EFTYPE);
YX				break;
YX			} else
YX				*cp++ = c;
YX		}
YX		*cp = 0;
YX
YX		/*
YX		 * The real work for the match.
YX		 */
YX		if (dnamatch(name)) {
YX			close(tf);
YX			return (1);
YX		}
YX	}
YX}
YX
YX/*
YX * Dnamatch deals with name matching.  The first field of the disktab
YX * entry is a sequence of names separated by |'s, so we compare
YX * against each such name.  The normal : terminator after the last
YX * name (before the first field) stops us.
YX */
YXstatic
YXdnamatch(np)
YX	char *np;
YX{
YX	register char *Np, *Bp;
YX
YX	Bp = tbuf;
YX	if (*Bp == '#')
YX		return (0);
YX	for (;;) {
YX		for (Np = np; *Np && *Bp == *Np; Bp++, Np++)
YX			continue;
YX		if (*Np == 0 && (*Bp == '|' || *Bp == ':' || *Bp == 0))
YX			return (1);
YX		while (*Bp && *Bp != ':' && *Bp != '|')
YX			Bp++;
YX		if (*Bp == 0 || *Bp == ':')
YX			return (0);
YX		Bp++;
YX	}
YX}
YX
YX/*
YX * Skip to the next field.  Notice that this is very dumb, not
YX * knowing about \: escapes or any such.  If necessary, :'s can be put
YX * into the diskcap file in octal.
YX */
YXstatic char *
YXdskip(bp)
YX	register char *bp;
YX{
YX
YX	while (*bp && *bp != ':')
YX		bp++;
YX	while (*bp == ':')
YX		bp++;
YX	return (bp);
YX}
YX
YX/*
YX * Return the (numeric) option id.
YX * Numeric options look like
YX *	li#80
YX * i.e. the option string is separated from the numeric value by
YX * a # character.  If the option is not found we return -1.
YX * Note that we handle octal numbers beginning with 0.
YX */
YXstatic long
YXdgetnum(id)
YX	char *id;
YX{
YX	register int base;
YX	long i;
YX	register char *bp = tbuf;
YX
YX	for (;;) {
YX		bp = dskip(bp);
YX		if (*bp == 0)
YX			return (-1);
YX		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
YX			continue;
YX		if (*bp == '@')
YX			return (-1);
YX		if (*bp != '#')
YX			continue;
YX		bp++;
YX		base = 10;
YX		if (*bp == '0')
YX			base = 8;
YX		i = 0;
YX		while (isdigit(*bp))
YX			i *= base, i += *bp++ - '0';
YX		return (i);
YX	}
YX}
YX
YX/*
YX * Handle a flag option.
YX * Flag options are given "naked", i.e. followed by a : or the end
YX * of the buffer.  Return 1 if we find the option, or 0 if it is
YX * not given.
YX */
YXstatic
YXdgetflag(id)
YX	char *id;
YX{
YX	register char *bp = tbuf;
YX
YX	for (;;) {
YX		bp = dskip(bp);
YX		if (!*bp)
YX			return (0);
YX		if (*bp++ == id[0] && *bp != 0 && *bp++ == id[1]) {
YX			if (!*bp || *bp == ':')
YX				return (1);
YX			else if (*bp == '@')
YX				return (0);
YX		}
YX	}
YX}
YX
YX/*
YX * Get a string valued option.
YX * These are given as
YX *	cl=^Z
YX * Much decoding is done on the strings, and the strings are
YX * placed in area, which is a ref parameter which is updated.
YX * No checking on area overflow.
YX */
YXstatic char *
YXdgetstr(id, area)
YX	char *id, **area;
YX{
YX	register char *bp = tbuf;
YX
YX	for (;;) {
YX		bp = dskip(bp);
YX		if (!*bp)
YX			return (0);
YX		if (*bp++ != id[0] || *bp == 0 || *bp++ != id[1])
YX			continue;
YX		if (*bp == '@')
YX			return (0);
YX		if (*bp != '=')
YX			continue;
YX		bp++;
YX		return (ddecode(bp, area));
YX	}
YX}
YX
YX/*
YX * Tdecode does the grung work to decode the
YX * string capability escapes.
YX */
YXstatic char *
YXddecode(str, area)
YX	register char *str;
YX	char **area;
YX{
YX	register char *cp;
YX	register int c;
YX	register char *dp;
YX	int i;
YX
YX	cp = *area;
YX	while ((c = *str++) && c != ':') {
YX		switch (c) {
YX
YX		case '^':
YX			c = *str++ & 037;
YX			break;
YX
YX		case '\\':
YX			dp = "E\033^^\\\\::n\nr\rt\tb\bf\f";
YX			c = *str++;
YXnextc:
YX			if (*dp++ == c) {
YX				c = *dp++;
YX				break;
YX			}
YX			dp++;
YX			if (*dp)
YX				goto nextc;
YX			if (isdigit(c)) {
YX				c -= '0', i = 2;
YX				do
YX					c <<= 3, c |= *str++ - '0';
YX				while (--i && isdigit(*str));
YX			}
YX			break;
YX		}
YX		*cp++ = c;
YX	}
YX	*cp++ = 0;
YX	str = *area;
YX	*area = cp;
YX	return (str);
YX}
YX
YXstatic
YXgettype(t, names)
YX	char *t;
YX	char **names;
YX{
YX	register char **nm;
YX
YX	for (nm = names; *nm; nm++)
YX		if (strcasecmp(t, *nm) == 0)
YX			return (nm - names);
YX	if (isdigit(*t))
YX		return (atoi(t));
YX	return (0);
YX}
YX
YXstatic
YXerror(err)
YX	int err;
YX{
YX	struct iovec iov[4];
YX
YX	iov[0].iov_base = "disktab: ";
YX	iov[0].iov_len = 9;
YX	iov[1].iov_base = _PATH_DISKTAB;
YX	iov[1].iov_len = sizeof (_PATH_DISKTAB) -  1;
YX	iov[2].iov_base = strerror(err);
YX	iov[2].iov_len = strlen(iov[2].iov_base);
YX	iov[3].iov_base = "\n";
YX	iov[3].iov_len = 1;
YX	(void)writev(fileno(stderr), &iov, 4);
YX}
YX
YXstatic long
YX_gtnumdflt(dname, dflt)
YX	char *dname;
YX	long dflt;
YX	{
YX	long f;
YX
YX	f = dgetnum(dname);
YX	if	(f == -1L)
YX		f = dflt;
YX	return(f);
YX	}
YSHAR_EOF
Yfi
Yexit 0
Y#	End of shell archive
SHAR_EOF
fi
exit 0
#	End of shell archive
