Blame misc.c

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