Blame misc.c

Packit 6f02de
/*
Packit 6f02de
 * misc.c - common miscellaneous functions for lsof
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Copyright 1994 Purdue Research Foundation, West Lafayette, Indiana
Packit 6f02de
 * 47907.  All rights reserved.
Packit 6f02de
 *
Packit 6f02de
 * Written by Victor A. Abell
Packit 6f02de
 *
Packit 6f02de
 * This software is not subject to any license of the American Telephone
Packit 6f02de
 * and Telegraph Company or the Regents of the University of California.
Packit 6f02de
 *
Packit 6f02de
 * Permission is granted to anyone to use this software for any purpose on
Packit 6f02de
 * any computer system, and to alter it and redistribute it freely, subject
Packit 6f02de
 * to the following restrictions:
Packit 6f02de
 *
Packit 6f02de
 * 1. Neither the authors nor Purdue University are responsible for any
Packit 6f02de
 *    consequences of the use of this software.
Packit 6f02de
 *
Packit 6f02de
 * 2. The origin of this software must not be misrepresented, either by
Packit 6f02de
 *    explicit claim or by omission.  Credit to the authors and Purdue
Packit 6f02de
 *    University must appear in documentation and sources.
Packit 6f02de
 *
Packit 6f02de
 * 3. Altered versions must be plainly marked as such, and must not be
Packit 6f02de
 *    misrepresented as being the original software.
Packit 6f02de
 *
Packit 6f02de
 * 4. This notice may not be removed or altered.
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
#ifndef lint
Packit 6f02de
static char copyright[] =
Packit 6f02de
"@(#) Copyright 1994 Purdue Research Foundation.\nAll rights reserved.\n";
Packit 6f02de
static char *rcsid = "$Id: misc.c,v 1.29 2018/02/14 14:20:14 abe Exp $";
Packit 6f02de
#endif
Packit 6f02de
Packit 6f02de
Packit 6f02de
#include "lsof.h"
Packit 6f02de
Packit 6f02de
#if	defined(HASWIDECHAR)
Packit 6f02de
# if	defined(WIDECHARINCL)
Packit 6f02de
#include WIDECHARINCL
Packit 6f02de
# endif	/* defined(WIDECHARINCL) */
Packit 6f02de
# if	defined(HASWCTYPE_H)
Packit 6f02de
#include <wctype.h>
Packit 6f02de
# endif	/* defined(HASWCTYPE_H) */
Packit 6f02de
#endif	/* defined(HASWIDECHAR) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Local definitions
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
#if	!defined(MAXSYMLINKS)
Packit 6f02de
#define	MAXSYMLINKS	32
Packit 6f02de
#endif	/* !defined(MAXSYMLINKS) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Local function prototypes
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
_PROTOTYPE(static void closePipes,(void));
Packit 6f02de
_PROTOTYPE(static int dolstat,(char *path, char *buf, int len));
Packit 6f02de
_PROTOTYPE(static int dostat,(char *path, char *buf, int len));
Packit 6f02de
_PROTOTYPE(static int doreadlink,(char *path, char *buf, int len));
Packit 6f02de
_PROTOTYPE(static int doinchild,(int (*fn)(), char *fp, char *rbuf, int rbln));
Packit 6f02de
Packit 6f02de
#if	defined(HASINTSIGNAL)
Packit 6f02de
_PROTOTYPE(static int handleint,(int sig));
Packit 6f02de
#else	/* !defined(HASINTSIGNAL) */
Packit 6f02de
_PROTOTYPE(static void handleint,(int sig));
Packit 6f02de
#endif	/* defined(HASINTSIGNAL) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Local variables
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static pid_t Cpid = 0;			/* child PID */
Packit 6f02de
static jmp_buf Jmp_buf;			/* jump buffer */
Packit 6f02de
static int Pipes[] =			/* pipes for child process */
Packit 6f02de
	{ -1, -1, -1, -1 };
Packit 6f02de
static int CtSigs[] = { 0, SIGINT, SIGKILL };
Packit 6f02de
					/* child termination signals (in order
Packit 6f02de
					 * of application) -- the first is a
Packit 6f02de
					 * dummy to allow pipe closure to
Packit 6f02de
					 * cause the child to exit */
Packit 6f02de
#define	NCTSIGS	(sizeof(CtSigs) / sizeof(int))
Packit 6f02de
Packit 6f02de
Packit 6f02de
#if	defined(HASNLIST)
Packit 6f02de
/*
Packit 6f02de
 * build-Nl() - build kernel name list table
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static struct drive_Nl *Build_Nl = (struct drive_Nl *)NULL;
Packit 6f02de
					/* the default Drive_Nl address */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
build_Nl(d)
Packit 6f02de
	struct drive_Nl *d;		/* data to drive the construction */
Packit 6f02de
{
Packit 6f02de
	struct drive_Nl *dp;
Packit 6f02de
	int i, n;
Packit 6f02de
Packit 6f02de
	for (dp = d, n = 0; dp->nn; dp++, n++)
Packit 6f02de
	    ;
Packit 6f02de
	if (n < 1) {
Packit 6f02de
	    (void) fprintf(stderr,
Packit 6f02de
		"%s: can't calculate kernel name list length\n", Pn);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	if (!(Nl = (struct NLIST_TYPE *)calloc((n + 1),
Packit 6f02de
					       sizeof(struct NLIST_TYPE))))
Packit 6f02de
	{
Packit 6f02de
	    (void) fprintf(stderr,
Packit 6f02de
		"%s: can't allocate %d bytes to kernel name list structure\n",
Packit 6f02de
		Pn, (int)((n + 1) * sizeof(struct NLIST_TYPE)));
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	for (dp = d, i = 0; i < n; dp++, i++) {
Packit 6f02de
	    Nl[i].NL_NAME = dp->knm;
Packit 6f02de
	}
Packit 6f02de
	Nll = (int)((n + 1) * sizeof(struct NLIST_TYPE));
Packit 6f02de
	Build_Nl = d;
Packit 6f02de
}
Packit 6f02de
#endif	/* defined(HASNLIST) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * childx() - make child process exit (if possible)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
childx()
Packit 6f02de
{
Packit 6f02de
	static int at, sx;
Packit 6f02de
	pid_t wpid;
Packit 6f02de
Packit 6f02de
	if (Cpid > 1) {
Packit 6f02de
Packit 6f02de
	/*
Packit 6f02de
	 * First close the pipes to and from the child.  That should cause the
Packit 6f02de
	 * child to exit.  Compute alarm time shares.
Packit 6f02de
	 */
Packit 6f02de
	    (void) closePipes();
Packit 6f02de
	    if ((at = TmLimit / NCTSIGS) < TMLIMMIN)
Packit 6f02de
		at = TMLIMMIN;
Packit 6f02de
	/*
Packit 6f02de
	 * Loop, waiting for the child to exit.  After the first pass, help
Packit 6f02de
	 * the child exit by sending it signals.
Packit 6f02de
	 */
Packit 6f02de
	    for (sx = 0; sx < NCTSIGS; sx++) {
Packit 6f02de
		if (setjmp(Jmp_buf)) {
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * An alarm has rung.  Disable further alarms.
Packit 6f02de
		 *
Packit 6f02de
		 * If there are more signals to send, continue the signal loop.
Packit 6f02de
		 *
Packit 6f02de
		 * If the last signal has been sent, issue a warning (unless
Packit 6f02de
		 * warninge have been suppressed) and exit the signal loop.
Packit 6f02de
		 */
Packit 6f02de
		    (void) alarm(0);
Packit 6f02de
		    (void) signal(SIGALRM, SIG_DFL);
Packit 6f02de
		    if (sx < (NCTSIGS - 1))
Packit 6f02de
			continue;
Packit 6f02de
		    if (!Fwarn)
Packit 6f02de
			(void) fprintf(stderr,
Packit 6f02de
			    "%s: WARNING -- child process %d may be hung.\n",
Packit 6f02de
			    Pn, (int)Cpid);
Packit 6f02de
		    break;
Packit 6f02de
	        }
Packit 6f02de
	    /*
Packit 6f02de
	     * Send the next signal to the child process, after the first pass
Packit 6f02de
	     * through the loop.
Packit 6f02de
	     *
Packit 6f02de
	     * Wrap the wait() with an alarm.
Packit 6f02de
	     */
Packit 6f02de
		if (sx)
Packit 6f02de
		    (void) kill(Cpid, CtSigs[sx]);
Packit 6f02de
		(void) signal(SIGALRM, handleint);
Packit 6f02de
		(void) alarm(at);
Packit 6f02de
		wpid = (pid_t) wait(NULL);
Packit 6f02de
		(void) alarm(0);
Packit 6f02de
		(void) signal(SIGALRM, SIG_DFL);
Packit 6f02de
		if (wpid == Cpid)
Packit 6f02de
		    break;
Packit 6f02de
	    }
Packit 6f02de
	    Cpid = 0;
Packit 6f02de
	}
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * closePipes() - close open pipe file descriptors
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static void
Packit 6f02de
closePipes()
Packit 6f02de
{
Packit 6f02de
	int i;
Packit 6f02de
Packit 6f02de
	for (i = 0; i < 4; i++) {
Packit 6f02de
	    if (Pipes[i] >= 0) {
Packit 6f02de
		(void) close(Pipes[i]);
Packit 6f02de
		Pipes[i] = -1;
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * compdev() - compare Devtp[] entries
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
compdev(a1, a2)
Packit 6f02de
	COMP_P *a1, *a2;
Packit 6f02de
{
Packit 6f02de
	struct l_dev **p1 = (struct l_dev **)a1;
Packit 6f02de
	struct l_dev **p2 = (struct l_dev **)a2;
Packit 6f02de
Packit 6f02de
	if ((dev_t)((*p1)->rdev) < (dev_t)((*p2)->rdev))
Packit 6f02de
	    return(-1);
Packit 6f02de
	if ((dev_t)((*p1)->rdev) > (dev_t)((*p2)->rdev))
Packit 6f02de
	    return(1);
Packit 6f02de
	if ((INODETYPE)((*p1)->inode) < (INODETYPE)((*p2)->inode))
Packit 6f02de
	    return(-1);
Packit 6f02de
	if ((INODETYPE)((*p1)->inode) > (INODETYPE)((*p2)->inode))
Packit 6f02de
	    return(1);
Packit 6f02de
	return(strcmp((*p1)->name, (*p2)->name));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * doinchild() -- do a function in a child process
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static int
Packit 6f02de
doinchild(fn, fp, rbuf, rbln)
Packit 6f02de
	int (*fn)();			/* function to perform */
Packit 6f02de
	char *fp;			/* function parameter */
Packit 6f02de
	char *rbuf;			/* response buffer */
Packit 6f02de
	int rbln;			/* response buffer length */
Packit 6f02de
{
Packit 6f02de
	int en, rv;
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Check reply buffer size.
Packit 6f02de
 */
Packit 6f02de
	if (!Fovhd && rbln > MAXPATHLEN) {
Packit 6f02de
	    (void) fprintf(stderr,
Packit 6f02de
		"%s: doinchild error; response buffer too large: %d\n",
Packit 6f02de
		Pn, rbln);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Set up to handle an alarm signal; handle an alarm signal; build
Packit 6f02de
 * pipes for exchanging information with a child process; start the
Packit 6f02de
 * child process; and perform functions in the child process.
Packit 6f02de
 */
Packit 6f02de
	if (!Fovhd) {
Packit 6f02de
	    if (setjmp(Jmp_buf)) {
Packit 6f02de
Packit 6f02de
	    /*
Packit 6f02de
	     * Process an alarm that has rung.
Packit 6f02de
	     */
Packit 6f02de
		(void) alarm(0);
Packit 6f02de
		(void) signal(SIGALRM, SIG_DFL);
Packit 6f02de
		(void) childx();
Packit 6f02de
		errno = ETIMEDOUT;
Packit 6f02de
		return(1);
Packit 6f02de
	    } else if (!Cpid) {
Packit 6f02de
Packit 6f02de
	    /*
Packit 6f02de
	     * Create pipes to exchange function information with a child
Packit 6f02de
	     * process.
Packit 6f02de
	     */
Packit 6f02de
		if (pipe(Pipes) < 0 || pipe(&Pipes[2]) < 0) {
Packit 6f02de
		    (void) fprintf(stderr, "%s: can't open pipes: %s\n",
Packit 6f02de
			Pn, strerror(errno));
Packit 6f02de
		    Exit(1);
Packit 6f02de
		}
Packit 6f02de
	    /*
Packit 6f02de
	     * Fork a child to execute functions.
Packit 6f02de
	     */
Packit 6f02de
		if ((Cpid = fork()) == 0) {
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * Begin the child process.
Packit 6f02de
		 */
Packit 6f02de
Packit 6f02de
		    int r_al, r_rbln;
Packit 6f02de
		    char r_arg[MAXPATHLEN+1], r_rbuf[MAXPATHLEN+1];
Packit 6f02de
		    int (*r_fn)();
Packit 6f02de
		/*
Packit 6f02de
		 * Close sufficient open file descriptors except Pipes[0] and
Packit 6f02de
		 * Pipes[3].
Packit 6f02de
		 */
Packit 6f02de
Packit 6f02de
#if	defined(HAS_DUP2) && defined(HAS_CLOSEFROM)
Packit 6f02de
		    int rc;
Packit 6f02de
Packit 6f02de
		    rc = dup2(Pipes[0], 0);
Packit 6f02de
		    if (rc < 0) {
Packit 6f02de
			(void) fprintf(stderr,
Packit 6f02de
			    "%s: can't dup Pipes[0] to fd 0: %s\n",
Packit 6f02de
			    Pn, strerror(errno));
Packit 6f02de
			Exit(1);
Packit 6f02de
		    }
Packit 6f02de
		    Pipes[0] = 0;
Packit 6f02de
		    rc = dup2(Pipes[3], 1);
Packit 6f02de
		    if (rc < 0) {
Packit 6f02de
			(void) fprintf(stderr,
Packit 6f02de
			    "%s: can't dup Pipes.[3] to fd 1: %s\n",
Packit 6f02de
			    Pn, strerror(errno));
Packit 6f02de
			Exit(1);
Packit 6f02de
		    }
Packit 6f02de
		    Pipes[3] = 1;
Packit 6f02de
		    (void) closefrom(2);
Packit 6f02de
		    Pipes[1] = -1;
Packit 6f02de
		    Pipes[2] = -1;
Packit 6f02de
Packit 6f02de
#else	/* !defined(HAS_DUP2) && !defined(HAS_CLOSEFROM) */
Packit 6f02de
		    int fd;
Packit 6f02de
Packit 6f02de
		    for (fd = 0; fd < MaxFd; fd++) {
Packit 6f02de
			if (fd == Pipes[0] || fd == Pipes[3])
Packit 6f02de
			    continue;
Packit 6f02de
			(void) close(fd);
Packit 6f02de
			if (fd == Pipes[1])
Packit 6f02de
			    Pipes[1] = -1;
Packit 6f02de
			else if (fd == Pipes[2])
Packit 6f02de
			    Pipes[2] = -1;
Packit 6f02de
		    }
Packit 6f02de
		    if (Pipes[1] >= 0) {
Packit 6f02de
			(void) close(Pipes[1]);
Packit 6f02de
			Pipes[1] = -1;
Packit 6f02de
		    }
Packit 6f02de
		    if (Pipes[2] >= 0) {
Packit 6f02de
			(void) close(Pipes[2]);
Packit 6f02de
			Pipes[2] = -1;
Packit 6f02de
		    }
Packit 6f02de
#endif	/* defined(HAS_DUP2) && defined(HAS_CLOSEFROM) */
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * Read function requests, process them, and return replies.
Packit 6f02de
		 */
Packit 6f02de
		    for (;;) {
Packit 6f02de
			if (read(Pipes[0], (char *)&r_fn, sizeof(r_fn))
Packit 6f02de
			    != (int)sizeof(r_fn)
Packit 6f02de
			||  read(Pipes[0], (char *)&r_al, sizeof(int))
Packit 6f02de
			    != (int)sizeof(int)
Packit 6f02de
			||  r_al < 1
Packit 6f02de
			||  r_al > (int)sizeof(r_arg)
Packit 6f02de
			||  read(Pipes[0], r_arg, r_al) != r_al
Packit 6f02de
			||  read(Pipes[0], (char *)&r_rbln, sizeof(r_rbln))
Packit 6f02de
			    != (int)sizeof(r_rbln)
Packit 6f02de
			||  r_rbln < 1 || r_rbln > (int)sizeof(r_rbuf))
Packit 6f02de
			    break;
Packit 6f02de
			rv = r_fn(r_arg, r_rbuf, r_rbln);
Packit 6f02de
			en = errno;
Packit 6f02de
			if (write(Pipes[3], (char *)&rv, sizeof(rv))
Packit 6f02de
			    != sizeof(rv)
Packit 6f02de
			||  write(Pipes[3], (char *)&en, sizeof(en))
Packit 6f02de
			    != sizeof(en)
Packit 6f02de
			||  write(Pipes[3], r_rbuf, r_rbln) != r_rbln)
Packit 6f02de
			    break;
Packit 6f02de
		    }
Packit 6f02de
		    (void) _exit(0);
Packit 6f02de
		}
Packit 6f02de
	    /*
Packit 6f02de
	     * Continue in the parent process to finish the setup.
Packit 6f02de
	     */
Packit 6f02de
		if (Cpid < 0) {
Packit 6f02de
		    (void) fprintf(stderr, "%s: can't fork: %s\n",
Packit 6f02de
			Pn, strerror(errno));
Packit 6f02de
		    Exit(1);
Packit 6f02de
		}
Packit 6f02de
		(void) close(Pipes[0]);
Packit 6f02de
		(void) close(Pipes[3]);
Packit 6f02de
		Pipes[0] = Pipes[3] = -1;
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	if (!Fovhd) {
Packit 6f02de
	    int len;
Packit 6f02de
Packit 6f02de
	/*
Packit 6f02de
	 * Send a function to the child and wait for the response.
Packit 6f02de
	 */
Packit 6f02de
	    len  = strlen(fp) + 1;
Packit 6f02de
	    (void) signal(SIGALRM, handleint);
Packit 6f02de
	    (void) alarm(TmLimit);
Packit 6f02de
	    if (write(Pipes[1], (char *)&fn, sizeof(fn)) != sizeof(fn)
Packit 6f02de
	    ||  write(Pipes[1], (char *)&len, sizeof(len)) != sizeof(len)
Packit 6f02de
	    ||  write(Pipes[1], fp, len) != len
Packit 6f02de
	    ||  write(Pipes[1], (char *)&rbln, sizeof(rbln)) != sizeof(rbln)
Packit 6f02de
	    ||  read(Pipes[2], (char *)&rv, sizeof(rv)) != sizeof(rv)
Packit 6f02de
	    ||  read(Pipes[2], (char *)&en, sizeof(en)) != sizeof(en)
Packit 6f02de
	    ||  read(Pipes[2], rbuf, rbln) != rbln) {
Packit 6f02de
		(void) alarm(0);
Packit 6f02de
		(void) signal(SIGALRM, SIG_DFL);
Packit 6f02de
		(void) childx();
Packit 6f02de
		errno = ECHILD;
Packit 6f02de
		return(-1);
Packit 6f02de
	    }
Packit 6f02de
	} else {
Packit 6f02de
Packit 6f02de
	/*
Packit 6f02de
	 * Do the operation directly -- not in a child.
Packit 6f02de
	 */
Packit 6f02de
	    (void) signal(SIGALRM, handleint);
Packit 6f02de
	    (void) alarm(TmLimit);
Packit 6f02de
	    rv = fn(fp, rbuf, rbln);
Packit 6f02de
	    en = errno;
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Function completed, response collected -- complete the operation.
Packit 6f02de
 */
Packit 6f02de
	(void) alarm(0);
Packit 6f02de
	(void) signal(SIGALRM, SIG_DFL);
Packit 6f02de
	errno = en;
Packit 6f02de
	return(rv);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * dolstat() - do an lstat() function
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static int
Packit 6f02de
dolstat(path, rbuf, rbln)
Packit 6f02de
	char *path;			/* path */
Packit 6f02de
	char *rbuf;			/* response buffer */
Packit 6f02de
	int rbln;			/* response buffer length */
Packit 6f02de
Packit 6f02de
/* ARGSUSED */
Packit 6f02de
Packit 6f02de
{
Packit 6f02de
	return(lstat(path, (struct stat *)rbuf));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * doreadlink() -- do a readlink() function
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static int
Packit 6f02de
doreadlink(path, rbuf, rbln)
Packit 6f02de
	char *path;			/* path */
Packit 6f02de
	char *rbuf;			/* response buffer */
Packit 6f02de
	int rbln;			/* response buffer length */
Packit 6f02de
{
Packit 6f02de
	return(readlink(path, rbuf, rbln));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * dostat() - do a stat() function
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
static int
Packit 6f02de
dostat(path, rbuf, rbln)
Packit 6f02de
	char *path;			/* path */
Packit 6f02de
	char *rbuf;			/* response buffer */
Packit 6f02de
	int rbln;			/* response buffer length */
Packit 6f02de
Packit 6f02de
/* ARGSUSED */
Packit 6f02de
Packit 6f02de
{
Packit 6f02de
	return(stat(path, (struct stat *)rbuf));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
#if	defined(WILLDROPGID)
Packit 6f02de
/*
Packit 6f02de
 * dropgid() - drop setgid permission
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
dropgid()
Packit 6f02de
{
Packit 6f02de
	if (!Setuidroot && Setgid) {
Packit 6f02de
	    if (setgid(Mygid) < 0) {
Packit 6f02de
		(void) fprintf(stderr, "%s: can't setgid(%d): %s\n",
Packit 6f02de
		    Pn, (int)Mygid, strerror(errno));
Packit 6f02de
		Exit(1);
Packit 6f02de
	    }
Packit 6f02de
	    Setgid = 0;
Packit 6f02de
	}
Packit 6f02de
}
Packit 6f02de
#endif	/* defined(WILLDROPGID) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * enter_dev_ch() - enter device characters in file structure
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
enter_dev_ch(m)
Packit 6f02de
	char *m;
Packit 6f02de
{
Packit 6f02de
	char *mp;
Packit 6f02de
Packit 6f02de
	if (!m || *m == '\0')
Packit 6f02de
	    return;
Packit 6f02de
	if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
Packit 6f02de
	    (void) fprintf(stderr, "%s: no more dev_ch space at PID %d: \n",
Packit 6f02de
		Pn, Lp->pid);
Packit 6f02de
	    safestrprt(m, stderr, 1);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	if (Lf->dev_ch)
Packit 6f02de
	   (void) free((FREE_P *)Lf->dev_ch);
Packit 6f02de
	Lf->dev_ch = mp;
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * enter_IPstate() -- enter a TCP or UDP state
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
enter_IPstate(ty, nm, nr)
Packit 6f02de
	char *ty;			/* type -- TCP or UDP */
Packit 6f02de
	char *nm;			/* state name (may be NULL) */
Packit 6f02de
	int nr;				/* state number */
Packit 6f02de
{
Packit 6f02de
Packit 6f02de
#if	defined(USE_LIB_PRINT_TCPTPI)
Packit 6f02de
	TcpNstates = nr;
Packit 6f02de
#else	/* !defined(USE_LIB_PRINT_TCPTPI) */
Packit 6f02de
Packit 6f02de
	int al, i, j, oc, nn, ns, off, tx;
Packit 6f02de
	char *cp;
Packit 6f02de
	MALLOC_S len;
Packit 6f02de
/*
Packit 6f02de
 * Check the type name and set the type index.
Packit 6f02de
 */
Packit 6f02de
	if (!ty) {
Packit 6f02de
	    (void) fprintf(stderr,
Packit 6f02de
		"%s: no type specified to enter_IPstate()\n", Pn);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	if (!strcmp(ty, "TCP"))
Packit 6f02de
	    tx = 0;
Packit 6f02de
	else if (!strcmp(ty, "UDP"))
Packit 6f02de
	    tx = 1;
Packit 6f02de
	else {
Packit 6f02de
	    (void) fprintf(stderr, "%s: unknown type for enter_IPstate: %s\n",
Packit 6f02de
		Pn, ty);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * If the name argument is NULL, reduce the allocated table to its minimum
Packit 6f02de
 * size.
Packit 6f02de
 */
Packit 6f02de
	if (!nm) {
Packit 6f02de
	    if (tx) {
Packit 6f02de
		if (UdpSt) {
Packit 6f02de
		    if (!UdpNstates) {
Packit 6f02de
			(void) free((MALLOC_P *)UdpSt);
Packit 6f02de
			UdpSt = (char **)NULL;
Packit 6f02de
		    }
Packit 6f02de
		    if (UdpNstates < UdpStAlloc) {
Packit 6f02de
			len = (MALLOC_S)(UdpNstates * sizeof(char *));
Packit 6f02de
			if (!(UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len)))
Packit 6f02de
			{
Packit 6f02de
			    (void) fprintf(stderr,
Packit 6f02de
				"%s: can't reduce UdpSt[]\n", Pn);
Packit 6f02de
			    Exit(1);
Packit 6f02de
			}
Packit 6f02de
		    }
Packit 6f02de
		    UdpStAlloc = UdpNstates;
Packit 6f02de
		}
Packit 6f02de
	    } else {
Packit 6f02de
		if (TcpSt) {
Packit 6f02de
		    if (!TcpNstates) {
Packit 6f02de
			(void) free((MALLOC_P *)TcpSt);
Packit 6f02de
			TcpSt = (char **)NULL;
Packit 6f02de
		    }
Packit 6f02de
		    if (TcpNstates < TcpStAlloc) {
Packit 6f02de
			len = (MALLOC_S)(TcpNstates * sizeof(char *));
Packit 6f02de
			if (!(TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len)))
Packit 6f02de
			{
Packit 6f02de
			    (void) fprintf(stderr,
Packit 6f02de
				"%s: can't reduce TcpSt[]\n", Pn);
Packit 6f02de
			    Exit(1);
Packit 6f02de
			}
Packit 6f02de
		    }
Packit 6f02de
		    TcpStAlloc = TcpNstates;
Packit 6f02de
		}
Packit 6f02de
	    }
Packit 6f02de
	    return;
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Check the name and number.
Packit 6f02de
 */
Packit 6f02de
	if ((len = (size_t)strlen(nm)) < 1) {
Packit 6f02de
	    (void) fprintf(stderr,
Packit 6f02de
		"%s: bad %s name (\"%s\"), number=%d\n", Pn, ty, nm, nr);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Make a copy of the name.
Packit 6f02de
 */
Packit 6f02de
	if (!(cp = mkstrcpy(nm, (MALLOC_S *)NULL))) {
Packit 6f02de
	    (void) fprintf(stderr,
Packit 6f02de
		"%s: enter_IPstate(): no %s space for %s\n",
Packit 6f02de
		Pn, ty, nm);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Set the necessary offset for using nr as an index.  If it is
Packit 6f02de
 * a new offset, adjust previous entries.
Packit 6f02de
 */
Packit 6f02de
	if ((nr < 0) && ((off = -nr) > (tx ? UdpStOff : TcpStOff))) {
Packit 6f02de
	    if (tx ? UdpSt : TcpSt) {
Packit 6f02de
Packit 6f02de
	    /*
Packit 6f02de
	     * A new, larger offset (smaller negative state number) could mean
Packit 6f02de
	     * a previously allocated state table must be enlarged and its
Packit 6f02de
	     * previous entries moved.
Packit 6f02de
	     */
Packit 6f02de
		oc = off - (tx ? UdpStOff : TcpStOff);
Packit 6f02de
		al = tx ? UdpStAlloc : TcpStAlloc;
Packit 6f02de
		ns = tx ? UdpNstates : TcpNstates;
Packit 6f02de
		if ((nn = ns + oc) >= al) {
Packit 6f02de
		    while ((nn + 5) > al) {
Packit 6f02de
			al += TCPUDPALLOC;
Packit 6f02de
		    }
Packit 6f02de
		    len = (MALLOC_S)(al * sizeof(char *));
Packit 6f02de
		    if (tx) {
Packit 6f02de
			if (!(UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len)))
Packit 6f02de
			    goto no_IP_space;
Packit 6f02de
			UdpStAlloc = al;
Packit 6f02de
		    } else {
Packit 6f02de
			if (!(TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len)))
Packit 6f02de
			    goto no_IP_space;
Packit 6f02de
			TcpStAlloc = al;
Packit 6f02de
		    }
Packit 6f02de
		    for (i = 0, j = oc; i < oc; i++, j++) {
Packit 6f02de
			if (tx) {
Packit 6f02de
			    if (i < UdpNstates)
Packit 6f02de
				UdpSt[j] = UdpSt[i];
Packit 6f02de
			    UdpSt[i] = (char *)NULL;
Packit 6f02de
			} else {
Packit 6f02de
			    if (i < TcpNstates)
Packit 6f02de
				TcpSt[j] = TcpSt[i];
Packit 6f02de
			    TcpSt[i] = (char *)NULL;
Packit 6f02de
			}
Packit 6f02de
		    }
Packit 6f02de
		    if (tx)
Packit 6f02de
			UdpNstates += oc;
Packit 6f02de
		    else
Packit 6f02de
			TcpNstates += oc;
Packit 6f02de
		}
Packit 6f02de
	    }
Packit 6f02de
	    if (tx)
Packit 6f02de
		UdpStOff = off;
Packit 6f02de
	    else
Packit 6f02de
		TcpStOff = off;
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Enter name as {Tc|Ud}pSt[nr + {Tc|Ud}pStOff].
Packit 6f02de
 *
Packit 6f02de
 * Allocate space, as required.
Packit 6f02de
 */
Packit 6f02de
	al = tx ? UdpStAlloc : TcpStAlloc;
Packit 6f02de
	off = tx ? UdpStOff : TcpStOff;
Packit 6f02de
	nn = nr + off + 1;
Packit 6f02de
	if (nn > al) {
Packit 6f02de
	    i = tx ? UdpNstates : TcpNstates;
Packit 6f02de
	    while ((nn + 5) > al) {
Packit 6f02de
		al += TCPUDPALLOC;
Packit 6f02de
	    }
Packit 6f02de
	    len = (MALLOC_S)(al * sizeof(char *));
Packit 6f02de
	    if (tx) {
Packit 6f02de
		if (UdpSt)
Packit 6f02de
		    UdpSt = (char **)realloc((MALLOC_P *)UdpSt, len);
Packit 6f02de
		else
Packit 6f02de
		    UdpSt = (char **)malloc(len);
Packit 6f02de
		if (!UdpSt) {
Packit 6f02de
Packit 6f02de
no_IP_space:
Packit 6f02de
Packit 6f02de
		    (void) fprintf(stderr, "%s: no %s state space\n", Pn, ty);
Packit 6f02de
		    Exit(1);
Packit 6f02de
		}
Packit 6f02de
		UdpNstates = nn;
Packit 6f02de
		UdpStAlloc = al;
Packit 6f02de
	    } else {
Packit 6f02de
		if (TcpSt)
Packit 6f02de
		    TcpSt = (char **)realloc((MALLOC_P *)TcpSt, len);
Packit 6f02de
		else
Packit 6f02de
		    TcpSt = (char **)malloc(len);
Packit 6f02de
		if (!TcpSt)
Packit 6f02de
		    goto no_IP_space;
Packit 6f02de
		TcpNstates = nn;
Packit 6f02de
		TcpStAlloc = al;
Packit 6f02de
	    }
Packit 6f02de
	    while (i < al) {
Packit 6f02de
		if (tx)
Packit 6f02de
		    UdpSt[i] = (char *)NULL;
Packit 6f02de
		else
Packit 6f02de
		    TcpSt[i] = (char *)NULL;
Packit 6f02de
		i++;
Packit 6f02de
	    }
Packit 6f02de
	} else {
Packit 6f02de
	    if (tx) {
Packit 6f02de
		if (nn > UdpNstates)
Packit 6f02de
		    UdpNstates = nn;
Packit 6f02de
	    } else {
Packit 6f02de
		if (nn > TcpNstates)
Packit 6f02de
		    TcpNstates = nn;
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	if (tx) {
Packit 6f02de
	    if (UdpSt[nr + UdpStOff]) {
Packit 6f02de
Packit 6f02de
dup_IP_state:
Packit 6f02de
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: duplicate %s state %d (already %s): %s\n",
Packit 6f02de
		    Pn, ty, nr,
Packit 6f02de
		    tx ? UdpSt[nr + UdpStOff] : TcpSt[nr + TcpStOff],
Packit 6f02de
		    nm);
Packit 6f02de
	 	Exit(1);
Packit 6f02de
	    }
Packit 6f02de
	    UdpSt[nr + UdpStOff] = cp;
Packit 6f02de
	} else {
Packit 6f02de
	    if (TcpSt[nr + TcpStOff])
Packit 6f02de
		goto dup_IP_state;
Packit 6f02de
	    TcpSt[nr + TcpStOff] = cp;
Packit 6f02de
	}
Packit 6f02de
#endif	/* defined(USE_LIB_PRINT_TCPTPI) */
Packit 6f02de
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * enter_nm() - enter name in local file structure
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
enter_nm(m)
Packit 6f02de
	char *m;
Packit 6f02de
{
Packit 6f02de
	char *mp;
Packit 6f02de
Packit 6f02de
	if (!m || *m == '\0')
Packit 6f02de
	    return;
Packit 6f02de
	if (!(mp = mkstrcpy(m, (MALLOC_S *)NULL))) {
Packit 6f02de
	    (void) fprintf(stderr, "%s: no more nm space at PID %d for: ",
Packit 6f02de
		Pn, Lp->pid);
Packit 6f02de
	    safestrprt(m, stderr, 1);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	if (Lf->nm)
Packit 6f02de
	    (void) free((FREE_P *)Lf->nm);
Packit 6f02de
	Lf->nm = mp;
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Exit() - do a clean exit()
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
Exit(xv)
Packit 6f02de
	int xv;				/* exit() value */
Packit 6f02de
{
Packit 6f02de
	(void) childx();
Packit 6f02de
Packit 6f02de
#if	defined(HASDCACHE)
Packit 6f02de
	if (DCrebuilt && !Fwarn)
Packit 6f02de
	    (void) fprintf(stderr, "%s: WARNING: %s was updated.\n",
Packit 6f02de
		Pn, DCpath[DCpathX]);
Packit 6f02de
#endif	/* defined(HASDCACHE) */
Packit 6f02de
Packit 6f02de
	exit(xv);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
#if	defined(HASNLIST)
Packit 6f02de
/*
Packit 6f02de
 * get_Nl_value() - get Nl value for nickname
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
get_Nl_value(nn, d, v)
Packit 6f02de
	char *nn;			/* nickname of requested entry */
Packit 6f02de
	struct drive_Nl *d;		/* drive_Nl table that built Nl
Packit 6f02de
					 * (if NULL, use Build_Nl) */
Packit 6f02de
	KA_T *v;			/* returned value (if NULL,
Packit 6f02de
					 * return nothing) */
Packit 6f02de
{
Packit 6f02de
	int i;
Packit 6f02de
Packit 6f02de
	if (!Nl || !Nll)
Packit 6f02de
	    return(-1);
Packit 6f02de
	if (!d)
Packit 6f02de
	    d = Build_Nl;
Packit 6f02de
	for (i = 0; d->nn; d++, i++) {
Packit 6f02de
	    if (strcmp(d->nn, nn) == 0) {
Packit 6f02de
		if (v)
Packit 6f02de
		    *v = (KA_T)Nl[i].n_value;
Packit 6f02de
		return(i);
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	return(-1);
Packit 6f02de
}
Packit 6f02de
#endif	/* defined(HASNLIST) */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * handleint() - handle an interrupt
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
#if	defined(HASINTSIGNAL)
Packit 6f02de
static int
Packit 6f02de
#else
Packit 6f02de
static void
Packit 6f02de
#endif
Packit 6f02de
Packit 6f02de
/* ARGSUSED */
Packit 6f02de
Packit 6f02de
handleint(sig)
Packit 6f02de
	int sig;
Packit 6f02de
{
Packit 6f02de
	longjmp(Jmp_buf, 1);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * hashbyname() - hash by name
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
hashbyname(nm, mod)
Packit 6f02de
	char *nm;			/* pointer to NUL-terminated name */
Packit 6f02de
	int mod;			/* hash modulus */
Packit 6f02de
{
Packit 6f02de
	int i, j;
Packit 6f02de
Packit 6f02de
	for (i = j = 0; *nm; nm++) {
Packit 6f02de
	    i ^= (int)*nm << j;
Packit 6f02de
	    if (++j > 7)
Packit 6f02de
		j = 0;
Packit 6f02de
	}
Packit 6f02de
	return(((int)(i * 31415)) & (mod - 1));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * is_nw_addr() - is this network address selected?
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
is_nw_addr(ia, p, af)
Packit 6f02de
	unsigned char *ia;		/* Internet address */
Packit 6f02de
	int p;				/* port */
Packit 6f02de
	int af;				/* address family -- e.g., AF_INET,
Packit 6f02de
					 * AF_INET6 */
Packit 6f02de
{
Packit 6f02de
	struct nwad *n;
Packit 6f02de
Packit 6f02de
	if (!(n = Nwad))
Packit 6f02de
	    return(0);
Packit 6f02de
	for (; n; n = n->next) {
Packit 6f02de
	    if (n->proto) {
Packit 6f02de
		if (strcasecmp(n->proto, Lf->iproto) != 0)
Packit 6f02de
		    continue;
Packit 6f02de
	    }
Packit 6f02de
	    if (af && n->af && af != n->af)
Packit 6f02de
		continue;
Packit 6f02de
Packit 6f02de
#if	defined(HASIPv6)
Packit 6f02de
	    if (af == AF_INET6) {
Packit 6f02de
		if (n->a[15] || n->a[14] || n->a[13] || n->a[12]
Packit 6f02de
		||  n->a[11] || n->a[10] || n->a[9]  || n->a[8]
Packit 6f02de
		||  n->a[7]  || n->a[6]  || n->a[5]  || n->a[4]
Packit 6f02de
		||  n->a[3]  || n->a[2]  || n->a[1]  || n->a[0]) {
Packit 6f02de
		    if (ia[15] != n->a[15] || ia[14] != n->a[14]
Packit 6f02de
		    ||  ia[13] != n->a[13] || ia[12] != n->a[12]
Packit 6f02de
		    ||  ia[11] != n->a[11] || ia[10] != n->a[10]
Packit 6f02de
		    ||  ia[9]  != n->a[9]  || ia[8]  != n->a[8]
Packit 6f02de
		    ||  ia[7]  != n->a[7]  || ia[6]  != n->a[6]
Packit 6f02de
		    ||  ia[5]  != n->a[5]  || ia[4]  != n->a[4]
Packit 6f02de
		    ||  ia[3]  != n->a[3]  || ia[2]  != n->a[2]
Packit 6f02de
		    ||  ia[1]  != n->a[1]  || ia[0]  != n->a[0])
Packit 6f02de
			continue;
Packit 6f02de
		}
Packit 6f02de
	    } else if (af == AF_INET)
Packit 6f02de
#endif	/* defined(HASIPv6) */
Packit 6f02de
Packit 6f02de
	    {
Packit 6f02de
		if (n->a[3] || n->a[2] || n->a[1] || n->a[0]) {
Packit 6f02de
		    if (ia[3] != n->a[3] || ia[2] != n->a[2]
Packit 6f02de
		    ||  ia[1] != n->a[1] || ia[0] != n->a[0])
Packit 6f02de
			continue;
Packit 6f02de
		}
Packit 6f02de
	    }
Packit 6f02de
Packit 6f02de
#if	defined(HASIPv6)
Packit 6f02de
	    else
Packit 6f02de
		continue;
Packit 6f02de
#endif	/* defined(HASIPv6) */
Packit 6f02de
Packit 6f02de
	    if (n->sport == -1 || (p >= n->sport && p <= n->eport)) {
Packit 6f02de
		n->f = 1;
Packit 6f02de
		return(1);
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	return(0);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * mkstrcpy() - make a string copy in malloc()'d space
Packit 6f02de
 *
Packit 6f02de
 * return: copy pointer
Packit 6f02de
 *	   copy length (optional)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
char *
Packit 6f02de
mkstrcpy(src, rlp)
Packit 6f02de
	char *src;			/* source */
Packit 6f02de
	MALLOC_S *rlp;			/* returned length pointer (optional)
Packit 6f02de
					 * The returned length is an strlen()
Packit 6f02de
					 * equivalent */
Packit 6f02de
{
Packit 6f02de
	MALLOC_S len;
Packit 6f02de
	char *ns;
Packit 6f02de
Packit 6f02de
	len = (MALLOC_S)(src ? strlen(src) : 0);
Packit 6f02de
	ns = (char *)malloc(len + 1);
Packit 6f02de
	if (ns) {
Packit 6f02de
	    if (src)
Packit 6f02de
		(void) snpf(ns, len + 1, "%s", src);
Packit 6f02de
	    else
Packit 6f02de
		*ns = '\0';
Packit 6f02de
	}
Packit 6f02de
	if (rlp)
Packit 6f02de
	    *rlp = len;
Packit 6f02de
	return(ns);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * mkstrcat() - make a catenated copy of up to three strings under optional
Packit 6f02de
 *		string-by-string count control
Packit 6f02de
 *
Packit 6f02de
 * return: copy pointer
Packit 6f02de
 *	   copy string length (optional)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
char *
Packit 6f02de
mkstrcat(s1, l1, s2, l2, s3, l3, clp)
Packit 6f02de
	char *s1;			/* source string 1 */
Packit 6f02de
	int l1;				/* length of string 1 (-1 if none) */
Packit 6f02de
	char *s2;			/* source string 2 */
Packit 6f02de
	int l2;				/* length of string 2 (-1 if none) */
Packit 6f02de
	char *s3;			/* source string 3 (optional) */
Packit 6f02de
	int l3	;			/* length of string 3 (-1 if none) */
Packit 6f02de
	MALLOC_S *clp;			/* pointer to return of copy length
Packit 6f02de
					 * (optional) */
Packit 6f02de
{
Packit 6f02de
	MALLOC_S cl, len1, len2, len3;
Packit 6f02de
	char *cp;
Packit 6f02de
Packit 6f02de
	if (s1)
Packit 6f02de
	    len1 = (MALLOC_S)((l1 >= 0) ? l1 : strlen(s1));
Packit 6f02de
	else
Packit 6f02de
	    len1 = (MALLOC_S)0;
Packit 6f02de
	if (s2)
Packit 6f02de
	    len2 = (MALLOC_S)((l2 >= 0) ? l2 : strlen(s2));
Packit 6f02de
	else
Packit 6f02de
	    len2 = (MALLOC_S)0;
Packit 6f02de
	if (s3)
Packit 6f02de
	    len3 = (MALLOC_S)((l3 >= 0) ? l3 : strlen(s3));
Packit 6f02de
	else
Packit 6f02de
	    len3 = (MALLOC_S)0;
Packit 6f02de
	cl = len1 + len2 + len3;
Packit 6f02de
	if ((cp = (char *)malloc(cl + 1))) {
Packit 6f02de
	    char *tp = cp;
Packit 6f02de
Packit 6f02de
	    if (s1 && len1) {
Packit 6f02de
		(void) strncpy(tp, s1, len1);
Packit 6f02de
		tp += len1;
Packit 6f02de
	    }
Packit 6f02de
	    if (s2 && len2) {
Packit 6f02de
		(void) strncpy(tp, s2, len2);
Packit 6f02de
		tp += len2;
Packit 6f02de
	    }
Packit 6f02de
	    if (s3 && len3) {
Packit 6f02de
		(void) strncpy(tp, s3, len3);
Packit 6f02de
		tp += len3;
Packit 6f02de
	    }
Packit 6f02de
	    *tp = '\0';
Packit 6f02de
	}
Packit 6f02de
	if (clp)
Packit 6f02de
	    *clp = cl;
Packit 6f02de
	return(cp);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * is_readable() -- is file readable
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
is_readable(path, msg)
Packit 6f02de
	char *path;			/* file path */
Packit 6f02de
	int msg;			/* issue warning message if 1 */
Packit 6f02de
{
Packit 6f02de
	if (access(path, R_OK) < 0) {
Packit 6f02de
	    if (!Fwarn && msg == 1)
Packit 6f02de
		(void) fprintf(stderr, ACCESSERRFMT, Pn, path, strerror(errno));
Packit 6f02de
	    return(0);
Packit 6f02de
	}
Packit 6f02de
	return(1);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * lstatsafely() - lstat path safely (i. e., with timeout)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
lstatsafely(path, buf)
Packit 6f02de
	char *path;			/* file path */
Packit 6f02de
	struct stat *buf;		/* stat buffer address */
Packit 6f02de
{
Packit 6f02de
	if (Fblock) {
Packit 6f02de
	    if (!Fwarn) 
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: avoiding stat(%s): -b was specified.\n",
Packit 6f02de
		    Pn, path);
Packit 6f02de
	    errno = EWOULDBLOCK;
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	return(doinchild(dolstat, path, (char *)buf, sizeof(struct stat)));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Readlink() - read and interpret file system symbolic links
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
char *
Packit 6f02de
Readlink(arg)
Packit 6f02de
	char *arg;			/* argument to be interpreted */
Packit 6f02de
{
Packit 6f02de
	char abuf[MAXPATHLEN+1];
Packit 6f02de
	int alen;
Packit 6f02de
	char *ap;
Packit 6f02de
	char *argp1, *argp2;
Packit 6f02de
	int i, len, llen, slen;
Packit 6f02de
	char lbuf[MAXPATHLEN+1];
Packit 6f02de
	static char *op = (char *)NULL;
Packit 6f02de
	static int ss = 0;
Packit 6f02de
	char *s1;
Packit 6f02de
	static char **stk = (char **)NULL;
Packit 6f02de
	static int sx = 0;
Packit 6f02de
	char tbuf[MAXPATHLEN+1];
Packit 6f02de
/*
Packit 6f02de
 * See if avoiding kernel blocks.
Packit 6f02de
 */
Packit 6f02de
	if (Fblock) {
Packit 6f02de
	    if (!Fwarn) {
Packit 6f02de
		(void) fprintf(stderr, "%s: avoiding readlink(", Pn);
Packit 6f02de
		safestrprt(arg, stderr, 0);
Packit 6f02de
		(void) fprintf(stderr, "): -b was specified.\n");
Packit 6f02de
	    }
Packit 6f02de
	    op = (char *)NULL;
Packit 6f02de
	    return(arg);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Save the original path.
Packit 6f02de
 */
Packit 6f02de
	if (!op)
Packit 6f02de
	    op = arg;
Packit 6f02de
/*
Packit 6f02de
 * Evaluate each component of the argument for a symbolic link.
Packit 6f02de
 */
Packit 6f02de
	for (alen = 0, ap = abuf, argp1 = argp2 = arg; *argp2; argp1 = argp2 ) {
Packit 6f02de
	    for (argp2 = argp1 + 1; *argp2 && *argp2 != '/'; argp2++)
Packit 6f02de
		;
Packit 6f02de
	    if ((len = argp2 - arg) >= (int)sizeof(tbuf)) {
Packit 6f02de
Packit 6f02de
path_too_long:
Packit 6f02de
		if (!Fwarn) {
Packit 6f02de
		    (void) fprintf(stderr,
Packit 6f02de
			"%s: readlink() path too long: ", Pn);
Packit 6f02de
		    safestrprt(op ? op : arg, stderr, 1);
Packit 6f02de
		}
Packit 6f02de
		op = (char *)NULL;
Packit 6f02de
		return((char *)NULL);
Packit 6f02de
	    }
Packit 6f02de
	    (void) strncpy(tbuf, arg, len);
Packit 6f02de
	    tbuf[len] = '\0';
Packit 6f02de
	/*
Packit 6f02de
	 * Dereference a symbolic link.
Packit 6f02de
	 */
Packit 6f02de
	    if ((llen=doinchild(doreadlink,tbuf,lbuf,sizeof(lbuf) - 1)) >= 0) {
Packit 6f02de
Packit 6f02de
	    /*
Packit 6f02de
	     * If the link is a new absolute path, replace
Packit 6f02de
	     * the previous assembly with it.
Packit 6f02de
	     */
Packit 6f02de
		if (lbuf[0] == '/') {
Packit 6f02de
		    (void) strncpy(abuf, lbuf, llen);
Packit 6f02de
		    ap = &abuf[llen];
Packit 6f02de
		    *ap = '\0';
Packit 6f02de
		    alen = llen;
Packit 6f02de
		    continue;
Packit 6f02de
		}
Packit 6f02de
		lbuf[llen] = '\0';
Packit 6f02de
		s1 = lbuf;
Packit 6f02de
	    } else {
Packit 6f02de
		llen = argp2 - argp1;
Packit 6f02de
		s1 = argp1;
Packit 6f02de
	    }
Packit 6f02de
	/*
Packit 6f02de
	 * Make sure two components are separated by a `/'.
Packit 6f02de
	 *
Packit 6f02de
	 * If the first component is not a link, don't force
Packit 6f02de
	 * a leading '/'.
Packit 6f02de
	 *
Packit 6f02de
	 * If the first component is a link and the source of
Packit 6f02de
	 * the link has a leading '/', force a leading '/'.
Packit 6f02de
	 */
Packit 6f02de
	    if (*s1 == '/')
Packit 6f02de
		slen = 1;
Packit 6f02de
	    else {
Packit 6f02de
		if (alen > 0) {
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * This is not the first component.
Packit 6f02de
		 */
Packit 6f02de
		    if (abuf[alen - 1] == '/')
Packit 6f02de
			slen = 1;
Packit 6f02de
		    else
Packit 6f02de
			slen = 2;
Packit 6f02de
		} else {
Packit 6f02de
Packit 6f02de
		/*
Packit 6f02de
		 * This is the first component.
Packit 6f02de
		 */
Packit 6f02de
		    if (s1 == lbuf && tbuf[0] == '/')
Packit 6f02de
			slen = 2;
Packit 6f02de
		    else
Packit 6f02de
			slen = 1;
Packit 6f02de
		}
Packit 6f02de
	    }
Packit 6f02de
	/*
Packit 6f02de
	 * Add to the path assembly.
Packit 6f02de
	 */
Packit 6f02de
	    if ((alen + llen + slen) >= (int)sizeof(abuf))
Packit 6f02de
		goto path_too_long;
Packit 6f02de
	    if (slen == 2)
Packit 6f02de
		*ap++ = '/';
Packit 6f02de
	    (void) strncpy(ap, s1, llen);
Packit 6f02de
	    ap += llen;
Packit 6f02de
	    *ap = '\0';
Packit 6f02de
	    alen += (llen + slen - 1);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * If the assembled path and argument are the same, free all but the
Packit 6f02de
 * last string in the stack, and return the argument.
Packit 6f02de
 */
Packit 6f02de
	if (strcmp(arg, abuf) == 0) {
Packit 6f02de
	    for (i = 0; i < sx; i++) {
Packit 6f02de
		if (i < (sx - 1))
Packit 6f02de
		    (void) free((FREE_P *)stk[i]);
Packit 6f02de
		stk[i] = (char *)NULL;
Packit 6f02de
	    }
Packit 6f02de
	    sx = 0;
Packit 6f02de
	    op = (char *)NULL;
Packit 6f02de
	    return(arg);
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * If the assembled path and argument are different, add it to the
Packit 6f02de
 * string stack, then Readlink() it.
Packit 6f02de
 */
Packit 6f02de
	if (!(s1 = mkstrcpy(abuf, (MALLOC_S *)NULL))) {
Packit 6f02de
Packit 6f02de
no_readlink_space:
Packit 6f02de
Packit 6f02de
	    (void) fprintf(stderr, "%s: no Readlink string space for ", Pn);
Packit 6f02de
	    safestrprt(abuf, stderr, 1);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	if (sx >= MAXSYMLINKS) {
Packit 6f02de
Packit 6f02de
	/*
Packit 6f02de
	 * If there are too many symbolic links, report an error, clear
Packit 6f02de
	 * the stack, and return no path.
Packit 6f02de
	 */
Packit 6f02de
	    if (!Fwarn) {
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: too many (> %d) symbolic links in readlink() path: ",
Packit 6f02de
			Pn, MAXSYMLINKS);
Packit 6f02de
		safestrprt(op ? op : arg, stderr, 1);
Packit 6f02de
	    }
Packit 6f02de
	    for (i = 0; i < sx; i++) {
Packit 6f02de
		(void) free((FREE_P *)stk[i]);
Packit 6f02de
		stk[i] = (char *)NULL;
Packit 6f02de
	    }
Packit 6f02de
	    (void) free((FREE_P *)stk);
Packit 6f02de
	    (void) free((FREE_P *)s1);
Packit 6f02de
	    stk = (char **)NULL;
Packit 6f02de
	    ss = sx = 0;
Packit 6f02de
	    s1 = (char *)NULL;
Packit 6f02de
	    op = (char *)NULL;
Packit 6f02de
	    return((char *)NULL);
Packit 6f02de
	}
Packit 6f02de
	if (++sx > ss) {
Packit 6f02de
	    if (!stk)
Packit 6f02de
		stk = (char **)malloc((MALLOC_S)(sizeof(char *) * sx));
Packit 6f02de
	    else
Packit 6f02de
		stk = (char **)realloc((MALLOC_P *)stk,
Packit 6f02de
					(MALLOC_S)(sizeof(char *) * sx));
Packit 6f02de
	    if (!stk)
Packit 6f02de
		goto no_readlink_space;
Packit 6f02de
	    ss = sx;
Packit 6f02de
	}
Packit 6f02de
	stk[sx - 1] = s1;
Packit 6f02de
	return(Readlink(s1));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
#if	defined(HASSTREAMS)
Packit 6f02de
/*
Packit 6f02de
 * readstdata() - read stream's stdata structure
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
readstdata(addr, buf)
Packit 6f02de
	KA_T addr;			/* stdata address in kernel*/
Packit 6f02de
	struct stdata *buf;		/* buffer addess */
Packit 6f02de
{
Packit 6f02de
	if (!addr
Packit 6f02de
	||  kread(addr, (char *)buf, sizeof(struct stdata))) {
Packit 6f02de
	    (void) snpf(Namech, Namechl, "no stream data in %s",
Packit 6f02de
		print_kptr(addr, (char *)NULL, 0));
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	return(0);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * readsthead() - read stream head
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
readsthead(addr, buf)
Packit 6f02de
	KA_T addr;			/* starting queue pointer in kernel */
Packit 6f02de
	struct queue *buf;		/* buffer for queue head */
Packit 6f02de
{
Packit 6f02de
	KA_T qp;
Packit 6f02de
Packit 6f02de
	if (!addr) {
Packit 6f02de
	    (void) snpf(Namech, Namechl, "no stream queue head");
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	for (qp = addr; qp; qp = (KA_T)buf->q_next) {
Packit 6f02de
	    if (kread(qp, (char *)buf, sizeof(struct queue))) {
Packit 6f02de
		(void) snpf(Namech, Namechl, "bad stream queue link at %s",
Packit 6f02de
		    print_kptr(qp, (char *)NULL, 0));
Packit 6f02de
		return(1);
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	return(0);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * readstidnm() - read stream module ID name
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
readstidnm(addr, buf, len)
Packit 6f02de
	KA_T addr;			/* module ID name address in kernel */
Packit 6f02de
	char *buf;			/* receiving buffer address */
Packit 6f02de
	READLEN_T len;			/* buffer length */
Packit 6f02de
{
Packit 6f02de
	if (!addr || kread(addr, buf, len)) {
Packit 6f02de
	    (void) snpf(Namech, Namechl, "can't read module ID name from %s",
Packit 6f02de
		print_kptr(addr, (char *)NULL, 0));
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	return(0);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * readstmin() - read stream's module info
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
readstmin(addr, buf)
Packit 6f02de
	KA_T addr;			/* module info address in kernel */
Packit 6f02de
	struct module_info *buf;	/* receiving buffer address */
Packit 6f02de
{
Packit 6f02de
	if (!addr || kread(addr, (char *)buf, sizeof(struct module_info))) {
Packit 6f02de
	    (void) snpf(Namech, Namechl, "can't read module info from %s",
Packit 6f02de
		print_kptr(addr, (char *)NULL, 0));
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	return(0);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * readstqinit() - read stream's queue information structure
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
readstqinit(addr, buf)
Packit 6f02de
	KA_T addr;			/* queue info address in kernel */
Packit 6f02de
	struct qinit *buf;		/* receiving buffer address */
Packit 6f02de
{
Packit 6f02de
	if (!addr || kread(addr, (char *)buf, sizeof(struct qinit))) {
Packit 6f02de
	    (void) snpf(Namech, Namechl, "can't read queue info from %s",
Packit 6f02de
		print_kptr(addr, (char *)NULL, 0));
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	return(0);
Packit 6f02de
}
Packit 6f02de
#endif	/* HASSTREAMS */
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * safepup() - safely print an unprintable character -- i.e., print it in a
Packit 6f02de
 *	       printable form
Packit 6f02de
 *
Packit 6f02de
 * return: char * to printable equivalent
Packit 6f02de
 *	   cl = strlen(printable equivalent)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
char *
Packit 6f02de
safepup(c, cl)
Packit 6f02de
	unsigned int c;			/* unprintable (i.e., !isprint())
Packit 6f02de
					 * character  and '\\' */
Packit 6f02de
	int *cl;			/* returned printable strlen -- NULL if
Packit 6f02de
					 * no return needed */
Packit 6f02de
{
Packit 6f02de
	int len;
Packit 6f02de
	char *rp;
Packit 6f02de
	static char up[8];
Packit 6f02de
Packit 6f02de
	if (c < 0x20) {
Packit 6f02de
	    switch (c) {
Packit 6f02de
	    case '\b':
Packit 6f02de
		rp = "\\b";
Packit 6f02de
		break;
Packit 6f02de
	    case '\f':
Packit 6f02de
		rp = "\\f";
Packit 6f02de
		break;
Packit 6f02de
	    case '\n':
Packit 6f02de
		rp = "\\n";
Packit 6f02de
		break;
Packit 6f02de
	    case '\r':
Packit 6f02de
		rp = "\\r";
Packit 6f02de
		break;
Packit 6f02de
	    case '\t':
Packit 6f02de
		rp = "\\t";
Packit 6f02de
		break;
Packit 6f02de
	    default:
Packit 6f02de
		(void) snpf(up, sizeof(up), "^%c", c + 0x40);
Packit 6f02de
		rp = up;
Packit 6f02de
	    }
Packit 6f02de
	    len = 2;
Packit 6f02de
	} else if (c == 0xff) {
Packit 6f02de
	    rp = "^?";
Packit 6f02de
	    len = 2;
Packit 6f02de
	} else if (c == '\\') {
Packit 6f02de
	    rp = "\\\\";
Packit 6f02de
	    len = 2;
Packit 6f02de
	} else {
Packit 6f02de
	    (void) snpf(up, sizeof(up), "\\x%02x", (int)(c & 0xff));
Packit 6f02de
	    rp = up;
Packit 6f02de
	    len = 4;
Packit 6f02de
	}
Packit 6f02de
	if (cl)
Packit 6f02de
	    *cl = len;
Packit 6f02de
	return(rp);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * safestrlen() - calculate a "safe" string length -- i.e., compute space for
Packit 6f02de
 *		  non-printable characters when printed in a printable form
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
safestrlen(sp, flags)
Packit 6f02de
	char *sp;			/* string pointer */
Packit 6f02de
	int flags;			/* flags:
Packit 6f02de
					 *   bit 0: 0 (0) = no NL
Packit 6f02de
					 *	    1 (1) = add trailing NL
Packit 6f02de
					 *	 1: 0 (0) = ' ' printable
Packit 6f02de
					 *	    1 (2) = ' ' not printable
Packit 6f02de
					 */
Packit 6f02de
{
Packit 6f02de
	char c;
Packit 6f02de
	int len = 0;
Packit 6f02de
Packit 6f02de
	c = (flags & 2) ? ' ' : '\0';
Packit 6f02de
	if (sp) {
Packit 6f02de
	    for (; *sp; sp++) {
Packit 6f02de
		if (!isprint((unsigned char)*sp)
Packit 6f02de
		||  (*sp == '\\') || (*sp == c))
Packit 6f02de
		{
Packit 6f02de
		    if ((*sp < 0x20) || ((unsigned char)*sp == 0xff)
Packit 6f02de
		    ||  (*sp == '\\'))
Packit 6f02de
			len += 2;		/* length of \. or ^. form */
Packit 6f02de
		    else
Packit 6f02de
			len += 4;		/* length of "\x%02x" printf */
Packit 6f02de
		} else
Packit 6f02de
		    len++;
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	return(len);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * safestrprt() - print a string "safely" to the indicated stream -- i.e.,
Packit 6f02de
 *		  print unprintable characters in a printable form
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
safestrprt(sp, fs, flags)
Packit 6f02de
	char *sp;			/* string to print pointer pointer */
Packit 6f02de
	FILE *fs;			/* destination stream -- e.g., stderr
Packit 6f02de
					 * or stdout */
Packit 6f02de
	int flags;			/* flags:
Packit 6f02de
					 *   bit 0: 0 (0) = no NL
Packit 6f02de
					 *	    1 (1) = add trailing NL
Packit 6f02de
					 *	 1: 0 (0) = ' ' printable
Packit 6f02de
					 *	    1 (2) = ' ' not printable
Packit 6f02de
					 *	 2: 0 (0) = print string as is
Packit 6f02de
					 *	    1 (4) = surround string
Packit 6f02de
					 *		    with '"'
Packit 6f02de
					 *	 4: 0 (0) = print ending '\n'
Packit 6f02de
					 *	    1 (8) = don't print ending
Packit 6f02de
					 *		    '\n'
Packit 6f02de
					 */
Packit 6f02de
{
Packit 6f02de
	char c;
Packit 6f02de
	int lnc, lnt, sl;
Packit 6f02de
Packit 6f02de
#if	defined(HASWIDECHAR)
Packit 6f02de
	wchar_t w;
Packit 6f02de
	int wcmx = MB_CUR_MAX;
Packit 6f02de
#else	/* !defined(HASWIDECHAR) */
Packit 6f02de
	static int wcmx = 1;
Packit 6f02de
#endif	/* defined(HASWIDECHAR) */
Packit 6f02de
Packit 6f02de
	c = (flags & 2) ? ' ' : '\0';
Packit 6f02de
	if (flags & 4)
Packit 6f02de
	    putc('"', fs);
Packit 6f02de
	if (sp) {
Packit 6f02de
	    for (sl = strlen(sp); *sp; sl -= lnc, sp += lnc) {
Packit 6f02de
Packit 6f02de
#if	defined(HASWIDECHAR)
Packit 6f02de
		if (wcmx > 1) {
Packit 6f02de
		    lnc = mblen(sp, sl);
Packit 6f02de
		    if (lnc > 1) {
Packit 6f02de
			if ((mbtowc(&w, sp, sl) == lnc) && iswprint(w)) {
Packit 6f02de
			    for (lnt = 0; lnt < lnc; lnt++) {
Packit 6f02de
				putc((int)*(sp + lnt), fs);
Packit 6f02de
			    }
Packit 6f02de
			} else {
Packit 6f02de
			    for (lnt = 0; lnt < lnc; lnt++) {
Packit 6f02de
			        fputs(safepup((unsigned int)*(sp + lnt),
Packit 6f02de
					      (int *)NULL), fs);
Packit 6f02de
			    }
Packit 6f02de
			}
Packit 6f02de
			continue;
Packit 6f02de
		    } else
Packit 6f02de
			lnc = 1;
Packit 6f02de
		} else
Packit 6f02de
		    lnc = 1;
Packit 6f02de
#else	/* !defined(HASWIDECHAR) */
Packit 6f02de
		lnc = 1;
Packit 6f02de
#endif	/* defined(HASWIDECHAR) */
Packit 6f02de
Packit 6f02de
		if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c)
Packit 6f02de
		    putc((int)(*sp & 0xff), fs);
Packit 6f02de
		else {
Packit 6f02de
		    if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
Packit 6f02de
			break;
Packit 6f02de
		    fputs(safepup((unsigned int)*sp, (int *)NULL), fs);
Packit 6f02de
		}
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	if (flags & 4)
Packit 6f02de
	    putc('"', fs);
Packit 6f02de
	if (flags & 1)
Packit 6f02de
	    putc('\n', fs);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * safestrprtn() - print a specified number of characters from a string
Packit 6f02de
 *		   "safely" to the indicated stream
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
safestrprtn(sp, len, fs, flags)
Packit 6f02de
	char *sp;			/* string to print pointer pointer */
Packit 6f02de
	int len;			/* safe number of characters to
Packit 6f02de
					 * print */
Packit 6f02de
	FILE *fs;			/* destination stream -- e.g., stderr
Packit 6f02de
					 * or stdout */
Packit 6f02de
	int flags;			/* flags:
Packit 6f02de
					 *   bit 0: 0 (0) = no NL
Packit 6f02de
					 *	    1 (1) = add trailing NL
Packit 6f02de
					 *	 1: 0 (0) = ' ' printable
Packit 6f02de
					 *	    1 (2) = ' ' not printable
Packit 6f02de
					 *	 2: 0 (0) = print string as is
Packit 6f02de
					 *	    1 (4) = surround string
Packit 6f02de
					 *		    with '"'
Packit 6f02de
					 *	 4: 0 (0) = print ending '\n'
Packit 6f02de
					 *	    1 (8) = don't print ending
Packit 6f02de
					 *		    '\n'
Packit 6f02de
					 */
Packit 6f02de
{
Packit 6f02de
	char c, *up;
Packit 6f02de
	int cl, i;
Packit 6f02de
Packit 6f02de
	if (flags & 4)
Packit 6f02de
	    putc('"', fs);
Packit 6f02de
	if (sp) {
Packit 6f02de
	    c = (flags & 2) ? ' ' : '\0';
Packit 6f02de
	    for (i = 0; i < len && *sp; sp++) {
Packit 6f02de
		if ((*sp != '\\') && isprint((unsigned char)*sp) && *sp != c) {
Packit 6f02de
		    putc((int)(*sp & 0xff), fs);
Packit 6f02de
		    i++;
Packit 6f02de
		} else {
Packit 6f02de
		    if ((flags & 8) && (*sp == '\n') && !*(sp + 1))
Packit 6f02de
			break;
Packit 6f02de
		    up = safepup((unsigned int)*sp, &cl);
Packit 6f02de
		    if ((i + cl) > len)
Packit 6f02de
			break;
Packit 6f02de
		    fputs(up, fs);
Packit 6f02de
		    i += cl;
Packit 6f02de
		}
Packit 6f02de
	    }
Packit 6f02de
	} else
Packit 6f02de
	    i = 0;
Packit 6f02de
	for (; i < len; i++)
Packit 6f02de
	    putc(' ', fs);
Packit 6f02de
	if (flags & 4)
Packit 6f02de
	    putc('"', fs);
Packit 6f02de
	if (flags & 1)
Packit 6f02de
	    putc('\n', fs);
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * statsafely() - stat path safely (i. e., with timeout)
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
int
Packit 6f02de
statsafely(path, buf)
Packit 6f02de
	char *path;			/* file path */
Packit 6f02de
	struct stat *buf;		/* stat buffer address */
Packit 6f02de
{
Packit 6f02de
	if (Fblock) {
Packit 6f02de
	    if (!Fwarn) 
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: avoiding stat(%s): -b was specified.\n",
Packit 6f02de
		    Pn, path);
Packit 6f02de
	    errno = EWOULDBLOCK;
Packit 6f02de
	    return(1);
Packit 6f02de
	}
Packit 6f02de
	return(doinchild(dostat, path, (char *)buf, sizeof(struct stat)));
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * stkdir() - stack directory name
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
void
Packit 6f02de
stkdir(p)
Packit 6f02de
	char *p;		/* directory path */
Packit 6f02de
{
Packit 6f02de
	MALLOC_S len;
Packit 6f02de
/*
Packit 6f02de
 * Provide adequate space for directory stack pointers.
Packit 6f02de
 */
Packit 6f02de
	if (Dstkx >= Dstkn) {
Packit 6f02de
	    Dstkn += 128;
Packit 6f02de
	    len = (MALLOC_S)(Dstkn * sizeof(char *));
Packit 6f02de
	    if (!Dstk)
Packit 6f02de
		Dstk = (char **)malloc(len);
Packit 6f02de
	    else
Packit 6f02de
		Dstk = (char **)realloc((MALLOC_P *)Dstk, len);
Packit 6f02de
	    if (!Dstk) {
Packit 6f02de
		(void) fprintf(stderr,
Packit 6f02de
		    "%s: no space for directory stack at: ", Pn);
Packit 6f02de
		safestrprt(p, stderr, 1);
Packit 6f02de
		Exit(1);
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Allocate space for the name, copy it there and put its pointer on the stack.
Packit 6f02de
 */
Packit 6f02de
	if (!(Dstk[Dstkx] = mkstrcpy(p, (MALLOC_S *)NULL))) {
Packit 6f02de
	    (void) fprintf(stderr, "%s: no space for: ", Pn);
Packit 6f02de
	    safestrprt(p, stderr, 1);
Packit 6f02de
	    Exit(1);
Packit 6f02de
	}
Packit 6f02de
	Dstkx++;
Packit 6f02de
}
Packit 6f02de
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * x2dev() - convert hexadecimal ASCII string to device number
Packit 6f02de
 */
Packit 6f02de
Packit 6f02de
char *
Packit 6f02de
x2dev(s, d)
Packit 6f02de
	char *s;			/* ASCII string */
Packit 6f02de
	dev_t *d;			/* device receptacle */
Packit 6f02de
{
Packit 6f02de
	char *cp, *cp1;
Packit 6f02de
	int n;
Packit 6f02de
	dev_t r;
Packit 6f02de
Packit 6f02de
/*
Packit 6f02de
 * Skip an optional leading 0x.  Count the number of hex digits up to the end
Packit 6f02de
 * of the string, or to a space, or to a comma.  Return an error if an unknown
Packit 6f02de
 * character is encountered.  If the count is larger than (2 * sizeof(dev_t))
Packit 6f02de
 * -- e.g., because of sign extension -- ignore excess leading hex 0xf digits,
Packit 6f02de
 * but return an error if an excess leading digit isn't 0xf.
Packit 6f02de
 */
Packit 6f02de
	if  (strncasecmp(s, "0x", 2) == 0)
Packit 6f02de
		s += 2;
Packit 6f02de
	for (cp = s, n = 0; *cp; cp++, n++) {
Packit 6f02de
	    if (isdigit((unsigned char)*cp))
Packit 6f02de
		continue;
Packit 6f02de
	    if ((unsigned char)*cp >= 'a' && (unsigned char)*cp <= 'f')
Packit 6f02de
		continue;
Packit 6f02de
	    if ((unsigned char)*cp >= 'A' && (unsigned char)*cp <= 'F')
Packit 6f02de
		continue;
Packit 6f02de
	    if (*cp == ' ' || *cp == ',')
Packit 6f02de
		break;
Packit 6f02de
	    return((char *)NULL);
Packit 6f02de
	}
Packit 6f02de
	if (!n)
Packit 6f02de
	    return((char *)NULL);
Packit 6f02de
	if (n > (2 * (int)sizeof(dev_t))) {
Packit 6f02de
	    cp1 = s;
Packit 6f02de
	    s += (n - (2 * sizeof(dev_t)));
Packit 6f02de
	    while (cp1 < s) {
Packit 6f02de
		if (*cp1 != 'f' && *cp1 != 'F')
Packit 6f02de
		    return((char *)NULL);
Packit 6f02de
		cp1++;
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
/*
Packit 6f02de
 * Assemble the validated hex digits of the device number, starting at a point
Packit 6f02de
 * in the string relevant to sizeof(dev_t).
Packit 6f02de
 */
Packit 6f02de
	for (r = 0; s < cp; s++) {
Packit 6f02de
	    r = r << 4;
Packit 6f02de
	    if (isdigit((unsigned char)*s))
Packit 6f02de
		r |= (unsigned char)(*s - '0') & 0xf;
Packit 6f02de
	    else {
Packit 6f02de
		if (isupper((unsigned char)*s))
Packit 6f02de
		    r |= ((unsigned char)(*s - 'A') + 10) & 0xf;
Packit 6f02de
		else
Packit 6f02de
		    r |= ((unsigned char)(*s - 'a') + 10) & 0xf;
Packit 6f02de
	    }
Packit 6f02de
	}
Packit 6f02de
	*d = r;
Packit 6f02de
	return(s);
Packit 6f02de
}