1 /*
2  * Copyright (c) 1995
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 /*
9  * Auxillary functions to aid portability to other systems.
10  * These are 4.4BSD routines that are often not found on other systems.
11  *
12  * !!!USE THIS FILE ONLY IF YOU ARE NOT RUNNING 4.4BSD!!!
13  */
14 
15 #if __STDC__
16 #include <stdarg.h>
17 #else
18 #include <varargs.h>
19 #endif
20 
21 #ifdef NO_SNPRINTF
22 #if __STDC__
23 snprintf(char *str, size_t n, const char *fmt, ...)
24 #else
25 snprintf(str, n, fmt, va_alist)
26 	char *str;
27 	size_t n;
28 	char *fmt;
29 	va_dcl
30 #endif
31 {
32 	int ret;
33 	va_list ap;
34 
35 #if __STDC__
36 	va_start(ap, fmt);
37 #else
38 	va_start(ap);
39 #endif
40 	ret = vsprintf(str, fmt, ap);
41 	va_end(ap);
42 	if (strlen(str) > n)
43 		fatal("memory corrupted");
44 	return (ret);
45 }
46 
47 vsnprintf(str, n, fmt, ap)
48 	char *str;
49 	size_t n;
50 	char *fmt;
51 	va_list ap;
52 {
53 	int ret;
54 
55 	ret = vsprintf(str, fmt, ap);
56 	if (strlen(str) > n)
57 		fatal("memory corrupted");
58 	return (ret);
59 }
60 #endif
61 
62 #ifdef NO_STRERROR
63 char *
64 strerror(num)
65 	int num;
66 {
67 	extern int sys_nerr;
68 	extern char *sys_errlist[];
69 #define	UPREFIX	"Unknown error: "
70 	static char ebuf[40] = UPREFIX;		/* 64-bit number + slop */
71 	register unsigned int errnum;
72 	register char *p, *t;
73 	char tmp[40];
74 
75 	errnum = num;				/* convert to unsigned */
76 	if (errnum < sys_nerr)
77 		return(sys_errlist[errnum]);
78 
79 	/* Do this by hand, so we don't include stdio(3). */
80 	t = tmp;
81 	do {
82 		*t++ = "0123456789"[errnum % 10];
83 	} while (errnum /= 10);
84 	for (p = ebuf + sizeof(UPREFIX) - 1;;) {
85 		*p++ = *--t;
86 		if (t <= tmp)
87 			break;
88 	}
89 	return(ebuf);
90 }
91 #endif
92 
93 #ifdef NO_STRDUP
94 char *
95 strdup(str)
96 	char *str;
97 {
98 	int n;
99 	char *sp;
100 
101 	n = strlen(str) + 1;
102 	if (sp = (char *) malloc(n))
103 		memcpy(sp, str, n);
104 	return (sp);
105 }
106 #endif
107 
108 #ifdef NO_DAEMON
109 #include <fcntl.h>
110 #include <paths.h>
111 #include <unistd.h>
112 #include <sgtty.h>
113 #define STDIN_FILENO	0
114 #define STDOUT_FILENO	1
115 #define STDERR_FILENO	2
116 
117 int
118 daemon(nochdir, noclose)
119 	int nochdir, noclose;
120 {
121 	int fd;
122 
123 	switch (fork()) {
124 	case -1:
125 		return (-1);
126 	case 0:
127 		break;
128 	default:
129 		_exit(0);
130 	}
131 
132 	if (setsid() == -1)
133 		return (-1);
134 
135 	if (!nochdir)
136 		(void)chdir("/");
137 
138 	if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
139 		(void)dup2(fd, STDIN_FILENO);
140 		(void)dup2(fd, STDOUT_FILENO);
141 		(void)dup2(fd, STDERR_FILENO);
142 		if (fd > 2)
143 			(void)close (fd);
144 	}
145 	return (0);
146 }
147 #endif
148 
149 
150 #ifdef NO_SETSID
151 int
152 setsid()
153 {
154 	int f;
155 
156 	f = open("/dev/tty", O_RDWR);
157 	if (f > 0) {
158 		ioctl(f, TIOCNOTTY, 0);
159 		(void) close(f);
160 	}
161 	return f;
162 }
163 #endif
164 
165 
166 #ifdef NO_VSYSLOG
167 #include <stdio.h>
168 #include <errno.h>
169 #if __STDC__
170 #include <stdarg.h>
171 #else
172 #include <varargs.h>
173 #endif
174 
175 vsyslog(pri, fmt, ap)
176 	int pri;
177 	const char *fmt;
178 	va_list ap;
179 {
180 	char buf[2048], fmt_cpy[1024];
181 
182 	/* substitute error message for %m */
183 	{
184 		register char ch, *t1, *t2;
185 		char *strerror();
186 
187 		for (t1 = fmt_cpy; ch = *fmt; ++fmt)
188 			if (ch == '%' && fmt[1] == 'm') {
189 				++fmt;
190 				for (t2 = strerror(errno);
191 				    *t1 = *t2++; ++t1);
192 			}
193 			else
194 				*t1++ = ch;
195 		*t1 = '\0';
196 	}
197 	vsprintf(buf, fmt_cpy, ap);
198 	syslog(pri, "%s", buf);
199 }
200 #endif
201 
202 
203 #ifdef NO_IVALIDUSER
204 #include <stdio.h>
205 #include <ctype.h>
206 #include <netdb.h>
207 #include <netinet/in.h>
208 #include <sys/types.h>
209 #include <sys/param.h>
210 #include "pathnames.h"
211 
212 /*
213  * Returns 0 if ok, -1 if not ok.
214  */
215 int
216 __ivaliduser(hostf, raddr, luser, ruser)
217 	FILE *hostf;
218 	struct in_addr raddr;
219 	const char *luser, *ruser;
220 {
221 	register char *user, *p;
222 	int ch;
223 	char buf[MAXHOSTNAMELEN + 128];		/* host + login */
224 
225 	while (fgets(buf, sizeof(buf), hostf)) {
226 		p = buf;
227 		/* Skip lines that are too long. */
228 		if (strchr(p, '\n') == NULL) {
229 			while ((ch = getc(hostf)) != '\n' && ch != EOF);
230 			continue;
231 		}
232 		while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
233 			*p = isupper(*p) ? tolower(*p) : *p;
234 			p++;
235 		}
236 		if (*p == ' ' || *p == '\t') {
237 			*p++ = '\0';
238 			while (*p == ' ' || *p == '\t')
239 				p++;
240 			user = p;
241 			while (*p != '\n' && *p != ' ' &&
242 			    *p != '\t' && *p != '\0')
243 				p++;
244 		} else
245 			user = p;
246 		*p = '\0';
247 		if (__icheckhost(raddr, buf) &&
248 		    strcmp(ruser, *user ? user : luser) == 0) {
249 			return (0);
250 		}
251 	}
252 	return (-1);
253 }
254 
255 /*
256  * Returns "true" if match, 0 if no match.
257  */
258 __icheckhost(raddr, lhost)
259 	struct in_addr raddr;
260 	register char *lhost;
261 {
262 	register struct hostent *hp;
263 	struct in_addr laddr;
264 	register char **pp;
265 
266 	/* Try for raw ip address first. */
267 	if (isdigit(*lhost) && (laddr.s_addr = inet_addr(lhost)) != INADDR_NONE)
268 		return (raddr.s_addr == laddr.s_addr);
269 
270 	/* Better be a hostname. */
271 	if ((hp = gethostbyname(lhost)) == NULL)
272 		return (0);
273 
274 	/* Spin through ip addresses. */
275 	for (pp = hp->h_addr_list; *pp; ++pp)
276 		if (!bcmp(&raddr, *pp, sizeof(struct in_addr)))
277 			return (1);
278 
279 	/* No match. */
280 	return (0);
281 }
282 #endif /* NO_IVALIDUSER */
283 
284 
285 #ifdef	NO_STATFS
286 #include <sys/types.h>
287 #include <sys/file.h>
288 #include <sys/stat.h>
289 #include <sys/dir.h>
290 #include <sys/param.h>
291 #include <ufs/fs.h>
292 
293 /*
294  * Check to see if there is enough space on the disk for size bytes.
295  * 1 == OK, 0 == Not OK.
296  */
297 static int
298 chksize(size)
299 	int size;
300 {
301 	struct stat stb;
302 	int spacefree;
303 	struct fs fs;
304 	static int dfd;
305 	static char *find_dev();
306 
307 #ifndef SBOFF
308 #define SBOFF ((off_t)(BBSIZE))
309 #endif
310 	if (dfd <= 0) {
311 		char *ddev;
312 
313 		if (stat(".", &stb) < 0) {
314 			syslog(LOG_ERR, "%s: %m", "statfs(\".\")");
315 			return (1);
316 		}
317 		ddev = find_dev(stb.st_dev, S_IFBLK);
318 		if ((dfd = open(ddev, O_RDONLY)) < 0) {
319 			syslog(LOG_WARNING, "%s: %s: %m", printer, ddev);
320 			return (1);
321 		}
322 	}
323 	if (lseek(dfd, (off_t)(SBOFF), 0) < 0)
324 		return(1);
325 	if (read(dfd, (char *)&fs, sizeof fs) != sizeof fs
326 	    || fs.fs_magic != FS_MAGIC) {
327 		syslog(LOG_ERR, "Can't calculate free space on spool device");
328 		return(1);
329 	}
330 	spacefree = freespace(&fs, fs.fs_minfree) * fs.fs_fsize / 512;
331 	size = (size + 511) / 512;
332 	if (minfree + size > spacefree)
333 		return(0);
334 	return(1);
335 }
336 
337 static char *
338 find_dev(dev, type)
339 	register dev_t dev;
340 	register int type;
341 {
342 	register DIR *dfd;
343 	struct direct *dir;
344 	struct stat stb;
345 	char devname[MAXNAMLEN+6];
346 	char *dp;
347 	int n;
348 
349 	strcpy(devname, "/dev/dsk");
350 	if ((dfd = opendir(devname)) == NULL) {
351 		strcpy(devname, "/dev");
352 		dfd = opendir(devname);
353 	}
354 	strcat(devname, "/");
355 	n = strlen(devname);
356 
357 	while ((dir = readdir(dfd))) {
358 		strcpy(devname + n, dir->d_name);
359 		if (stat(devname, &stb))
360 			continue;
361 		if ((stb.st_mode & S_IFMT) != type)
362 			continue;
363 		if (dev == stb.st_rdev) {
364 			closedir(dfd);
365 			dp = (char *)malloc(strlen(devname)+1);
366 			strcpy(dp, devname);
367 			return(dp);
368 		}
369 	}
370 	closedir(dfd);
371 	frecverr("cannot find device %d, %d", major(dev), minor(dev));
372 	/*NOTREACHED*/
373 }
374 #endif	/* NOSTATFS */
375