169070Stef /*
2*69076Stef  * Copyright (c) 1995
3*69076Stef  *	The Regents of the University of California.  All rights reserved.
469070Stef  *
5*69076Stef  * %sccs.include.redist.c%
669070Stef  */
769070Stef 
8*69076Stef /*
9*69076Stef  * Auxillary functions to aid portability to other systems.
10*69076Stef  * These are 4.4BSD routines that are often not found on other systems.
1169070Stef  *
12*69076Stef  * !!!USE THIS FILE ONLY IF YOU ARE NOT RUNNING 4.4BSD!!!
1369070Stef  */
1469070Stef 
15*69076Stef #if __STDC__
16*69076Stef #include <stdarg.h>
17*69076Stef #else
18*69076Stef #include <varargs.h>
19*69076Stef #endif
20*69076Stef 
2169070Stef #ifdef NO_SNPRINTF
2269070Stef #if __STDC__
snprintf(char * str,size_t n,const char * fmt,...)2369070Stef snprintf(char *str, size_t n, const char *fmt, ...)
2469070Stef #else
2569070Stef snprintf(str, n, fmt, va_alist)
2669070Stef 	char *str;
2769070Stef 	size_t n;
2869070Stef 	char *fmt;
2969070Stef 	va_dcl
3069070Stef #endif
3169070Stef {
3269070Stef 	int ret;
3369070Stef 	va_list ap;
3469070Stef 
3569070Stef #if __STDC__
3669070Stef 	va_start(ap, fmt);
3769070Stef #else
3869070Stef 	va_start(ap);
3969070Stef #endif
4069070Stef 	ret = vsprintf(str, fmt, ap);
4169070Stef 	va_end(ap);
4269070Stef 	if (strlen(str) > n)
4369070Stef 		fatal("memory corrupted");
4469070Stef 	return (ret);
4569070Stef }
4669070Stef 
vsnprintf(str,n,fmt,ap)4769070Stef vsnprintf(str, n, fmt, ap)
4869070Stef 	char *str;
4969070Stef 	size_t n;
5069070Stef 	char *fmt;
5169070Stef 	va_list ap;
5269070Stef {
5369070Stef 	int ret;
5469070Stef 
5569070Stef 	ret = vsprintf(str, fmt, ap);
5669070Stef 	if (strlen(str) > n)
5769070Stef 		fatal("memory corrupted");
5869070Stef 	return (ret);
5969070Stef }
6069070Stef #endif
6169070Stef 
6269070Stef #ifdef NO_STRERROR
6369070Stef char *
strerror(num)6469070Stef strerror(num)
6569070Stef 	int num;
6669070Stef {
6769070Stef 	extern int sys_nerr;
6869070Stef 	extern char *sys_errlist[];
6969070Stef #define	UPREFIX	"Unknown error: "
7069070Stef 	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */
7169070Stef 	register unsigned int errnum;
7269070Stef 	register char *p, *t;
7369070Stef 	char tmp[40];
7469070Stef 
7569070Stef 	errnum = num;				/* convert to unsigned */
7669070Stef 	if (errnum < sys_nerr)
7769070Stef 		return(sys_errlist[errnum]);
7869070Stef 
7969070Stef 	/* Do this by hand, so we don't include stdio(3). */
8069070Stef 	t = tmp;
8169070Stef 	do {
8269070Stef 		*t++ = "0123456789"[errnum % 10];
8369070Stef 	} while (errnum /= 10);
8469070Stef 	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
8569070Stef 		*p++ = *--t;
8669070Stef 		if (t <= tmp)
8769070Stef 			break;
8869070Stef 	}
8969070Stef 	return(ebuf);
9069070Stef }
9169070Stef #endif
9269070Stef 
9369070Stef #ifdef NO_STRDUP
9469070Stef char *
strdup(str)9569070Stef strdup(str)
9669070Stef 	char *str;
9769070Stef {
9869070Stef 	int n;
9969070Stef 	char *sp;
10069070Stef 
10169070Stef 	n = strlen(str) + 1;
10269070Stef 	if (sp = (char *) malloc(n))
10369070Stef 		memcpy(sp, str, n);
10469070Stef 	return (sp);
10569070Stef }
10669070Stef #endif
10769070Stef 
10869070Stef #ifdef NO_DAEMON
10969070Stef #include <fcntl.h>
11069070Stef #include <paths.h>
11169070Stef #include <unistd.h>
11269070Stef #include <sgtty.h>
11369070Stef #define STDIN_FILENO	0
11469070Stef #define STDOUT_FILENO	1
11569070Stef #define STDERR_FILENO	2
11669070Stef 
11769070Stef int
daemon(nochdir,noclose)11869070Stef daemon(nochdir, noclose)
11969070Stef 	int nochdir, noclose;
12069070Stef {
12169070Stef 	int fd;
12269070Stef 
12369070Stef 	switch (fork()) {
12469070Stef 	case -1:
12569070Stef 		return (-1);
12669070Stef 	case 0:
12769070Stef 		break;
12869070Stef 	default:
12969070Stef 		_exit(0);
13069070Stef 	}
13169070Stef 
13269070Stef 	if (setsid() == -1)
13369070Stef 		return (-1);
13469070Stef 
13569070Stef 	if (!nochdir)
13669070Stef 		(void)chdir("/");
13769070Stef 
13869070Stef 	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
13969070Stef 		(void)dup2(fd, STDIN_FILENO);
14069070Stef 		(void)dup2(fd, STDOUT_FILENO);
14169070Stef 		(void)dup2(fd, STDERR_FILENO);
14269070Stef 		if (fd > 2)
14369070Stef 			(void)close (fd);
14469070Stef 	}
14569070Stef 	return (0);
14669070Stef }
14769070Stef #endif
14869070Stef 
14969070Stef 
15069070Stef #ifdef NO_SETSID
15169070Stef int
setsid()15269070Stef setsid()
15369070Stef {
15469070Stef 	int f;
15569070Stef 
15669070Stef 	f = open("/dev/tty", O_RDWR);
15769070Stef 	if (f > 0) {
15869070Stef 		ioctl(f, TIOCNOTTY, 0);
15969070Stef 		(void) close(f);
16069070Stef 	}
16169070Stef 	return f;
16269070Stef }
16369070Stef #endif
16469070Stef 
16569070Stef 
16669070Stef #ifdef NO_VSYSLOG
16769070Stef #include <stdio.h>
16869070Stef #include <errno.h>
16969070Stef #if __STDC__
17069070Stef #include <stdarg.h>
17169070Stef #else
17269070Stef #include <varargs.h>
17369070Stef #endif
17469070Stef 
vsyslog(pri,fmt,ap)17569070Stef vsyslog(pri, fmt, ap)
17669070Stef 	int pri;
17769070Stef 	const char *fmt;
17869070Stef 	va_list ap;
17969070Stef {
18069070Stef 	char buf[2048], fmt_cpy[1024];
18169070Stef 
18269070Stef 	/* substitute error message for %m */
18369070Stef 	{
18469070Stef 		register char ch, *t1, *t2;
18569070Stef 		char *strerror();
18669070Stef 
18769070Stef 		for (t1 = fmt_cpy; ch = *fmt; ++fmt)
18869070Stef 			if (ch == '%' && fmt[1] == 'm') {
18969070Stef 				++fmt;
19069070Stef 				for (t2 = strerror(errno);
19169070Stef 				    *t1 = *t2++; ++t1);
19269070Stef 			}
19369070Stef 			else
19469070Stef 				*t1++ = ch;
19569070Stef 		*t1 = '\0';
19669070Stef 	}
19769070Stef 	vsprintf(buf, fmt_cpy, ap);
19869070Stef 	syslog(pri, "%s", buf);
19969070Stef }
20069070Stef #endif
20169070Stef 
20269070Stef 
20369070Stef #ifdef NO_IVALIDUSER
20469070Stef #include <stdio.h>
20569070Stef #include <ctype.h>
20669070Stef #include <netdb.h>
20769070Stef #include <netinet/in.h>
20869070Stef #include <sys/types.h>
20969070Stef #include <sys/param.h>
21069070Stef #include "pathnames.h"
21169070Stef 
21269070Stef /*
21369070Stef  * Returns 0 if ok, -1 if not ok.
21469070Stef  */
21569070Stef int
__ivaliduser(hostf,raddr,luser,ruser)21669070Stef __ivaliduser(hostf, raddr, luser, ruser)
21769070Stef 	FILE *hostf;
21869070Stef 	struct in_addr raddr;
21969070Stef 	const char *luser, *ruser;
22069070Stef {
22169070Stef 	register char *user, *p;
22269070Stef 	int ch;
22369070Stef 	char buf[MAXHOSTNAMELEN + 128];		/* host + login */
22469070Stef 
22569070Stef 	while (fgets(buf, sizeof(buf), hostf)) {
22669070Stef 		p = buf;
22769070Stef 		/* Skip lines that are too long. */
22869070Stef 		if (strchr(p, '\n') == NULL) {
22969070Stef 			while ((ch = getc(hostf)) != '\n' && ch != EOF);
23069070Stef 			continue;
23169070Stef 		}
23269070Stef 		while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
23369070Stef 			*p = isupper(*p) ? tolower(*p) : *p;
23469070Stef 			p++;
23569070Stef 		}
23669070Stef 		if (*p == ' ' || *p == '\t') {
23769070Stef 			*p++ = '\0';
23869070Stef 			while (*p == ' ' || *p == '\t')
23969070Stef 				p++;
24069070Stef 			user = p;
24169070Stef 			while (*p != '\n' && *p != ' ' &&
24269070Stef 			    *p != '\t' && *p != '\0')
24369070Stef 				p++;
24469070Stef 		} else
24569070Stef 			user = p;
24669070Stef 		*p = '\0';
24769070Stef 		if (__icheckhost(raddr, buf) &&
24869070Stef 		    strcmp(ruser, *user ? user : luser) == 0) {
24969070Stef 			return (0);
25069070Stef 		}
25169070Stef 	}
25269070Stef 	return (-1);
25369070Stef }
25469070Stef 
25569070Stef /*
25669070Stef  * Returns "true" if match, 0 if no match.
25769070Stef  */
25869070Stef __icheckhost(raddr, lhost)
25969070Stef 	struct in_addr raddr;
26069070Stef 	register char *lhost;
26169070Stef {
26269070Stef 	register struct hostent *hp;
26369070Stef 	struct in_addr laddr;
26469070Stef 	register char **pp;
26569070Stef 
26669070Stef 	/* Try for raw ip address first. */
26769070Stef 	if (isdigit(*lhost) && (laddr.s_addr = inet_addr(lhost)) != INADDR_NONE)
26869070Stef 		return (raddr.s_addr == laddr.s_addr);
26969070Stef 
27069070Stef 	/* Better be a hostname. */
27169070Stef 	if ((hp = gethostbyname(lhost)) == NULL)
27269070Stef 		return (0);
27369070Stef 
27469070Stef 	/* Spin through ip addresses. */
27569070Stef 	for (pp = hp->h_addr_list; *pp; ++pp)
27669070Stef 		if (!bcmp(&raddr, *pp, sizeof(struct in_addr)))
27769070Stef 			return (1);
27869070Stef 
27969070Stef 	/* No match. */
28069070Stef 	return (0);
28169070Stef }
28269070Stef #endif /* NO_IVALIDUSER */
28369070Stef 
28469070Stef 
28569070Stef #ifdef	NO_STATFS
28669070Stef #include <sys/types.h>
28769070Stef #include <sys/file.h>
28869070Stef #include <sys/stat.h>
28969070Stef #include <sys/dir.h>
29069070Stef #include <sys/param.h>
29169070Stef #include <ufs/fs.h>
29269070Stef 
29369070Stef /*
29469070Stef  * Check to see if there is enough space on the disk for size bytes.
29569070Stef  * 1 == OK, 0 == Not OK.
29669070Stef  */
29769070Stef static int
chksize(size)29869070Stef chksize(size)
29969070Stef 	int size;
30069070Stef {
30169070Stef 	struct stat stb;
30269070Stef 	int spacefree;
30369070Stef 	struct fs fs;
30469070Stef 	static int dfd;
30569070Stef 	static char *find_dev();
30669070Stef 
30769070Stef #ifndef SBOFF
30869070Stef #define SBOFF ((off_t)(BBSIZE))
30969070Stef #endif
31069070Stef 	if (dfd <= 0) {
31169070Stef 		char *ddev;
31269070Stef 
31369070Stef 		if (stat(".", &stb) < 0) {
31469070Stef 			syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
31569070Stef 			return (1);
31669070Stef 		}
31769070Stef 		ddev = find_dev(stb.st_dev, S_IFBLK);
31869070Stef 		if ((dfd = open(ddev, O_RDONLY)) < 0) {
31969070Stef 			syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
32069070Stef 			return (1);
32169070Stef 		}
32269070Stef 	}
32369070Stef 	if (lseek(dfd, (off_t)(SBOFF), 0) < 0)
32469070Stef 		return(1);
32569070Stef 	if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs
32669070Stef 	    || fs.fs_magic != FS_MAGIC) {
32769070Stef 		syslog(LOG_ERR, "Can't calculate free space on spool device");
32869070Stef 		return(1);
32969070Stef 	}
33069070Stef 	spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 512;
33169070Stef 	size = (size + 511) / 512;
33269070Stef 	if (minfree + size > spacefree)
33369070Stef 		return(0);
33469070Stef 	return(1);
33569070Stef }
33669070Stef 
33769070Stef static char *
find_dev(dev,type)33869070Stef find_dev(dev, type)
33969070Stef 	register dev_t dev;
34069070Stef 	register int type;
34169070Stef {
34269070Stef 	register DIR *dfd;
34369070Stef 	struct direct *dir;
34469070Stef 	struct stat stb;
34569070Stef 	char devname[MAXNAMLEN+6];
34669070Stef 	char *dp;
34769070Stef 	int n;
34869070Stef 
34969070Stef 	strcpy(devname, "/dev/dsk");
35069070Stef 	if ((dfd = opendir(devname)) == NULL) {
35169070Stef 		strcpy(devname, "/dev");
35269070Stef 		dfd = opendir(devname);
35369070Stef 	}
35469070Stef 	strcat(devname, "/");
35569070Stef 	n = strlen(devname);
35669070Stef 
35769070Stef 	while ((dir = readdir(dfd))) {
35869070Stef 		strcpy(devname + n, dir->d_name);
35969070Stef 		if (stat(devname, &stb))
36069070Stef 			continue;
36169070Stef 		if ((stb.st_mode & S_IFMT) != type)
36269070Stef 			continue;
36369070Stef 		if (dev == stb.st_rdev) {
36469070Stef 			closedir(dfd);
36569070Stef 			dp = (char *)malloc(strlen(devname)+1);
36669070Stef 			strcpy(dp, devname);
36769070Stef 			return(dp);
36869070Stef 		}
36969070Stef 	}
37069070Stef 	closedir(dfd);
37169070Stef 	frecverr("cannot find device %d, %d", major(dev), minor(dev));
37269070Stef 	/*NOTREACHED*/
37369070Stef }
37469070Stef #endif	/* NOSTATFS */
375