xref: /dflybsd-src/usr.bin/dsynth/subs.c (revision a361ab312536a661d74caf5630c7ae20bcd8e3e4)
18e25f19bSMatthew Dillon /*
2f9d29536SMatthew Dillon  * Copyright (c) 2019-2020 The DragonFly Project.  All rights reserved.
38e25f19bSMatthew Dillon  *
48e25f19bSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
58e25f19bSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
68e25f19bSMatthew Dillon  *
78e25f19bSMatthew Dillon  * This code uses concepts and configuration based on 'synth', by
88e25f19bSMatthew Dillon  * John R. Marino <draco@marino.st>, which was written in ada.
98e25f19bSMatthew Dillon  *
108e25f19bSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
118e25f19bSMatthew Dillon  * modification, are permitted provided that the following conditions
128e25f19bSMatthew Dillon  * are met:
138e25f19bSMatthew Dillon  *
148e25f19bSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
158e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
168e25f19bSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
178e25f19bSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
188e25f19bSMatthew Dillon  *    the documentation and/or other materials provided with the
198e25f19bSMatthew Dillon  *    distribution.
208e25f19bSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
218e25f19bSMatthew Dillon  *    contributors may be used to endorse or promote products derived
228e25f19bSMatthew Dillon  *    from this software without specific, prior written permission.
238e25f19bSMatthew Dillon  *
248e25f19bSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
258e25f19bSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
268e25f19bSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
278e25f19bSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
288e25f19bSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
298e25f19bSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
308e25f19bSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
318e25f19bSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
328e25f19bSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
338e25f19bSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
348e25f19bSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
358e25f19bSMatthew Dillon  * SUCH DAMAGE.
368e25f19bSMatthew Dillon  */
378e25f19bSMatthew Dillon 
388e25f19bSMatthew Dillon #include "dsynth.h"
398e25f19bSMatthew Dillon 
40f9d29536SMatthew Dillon struct logerrinfo {
41f9d29536SMatthew Dillon 	struct logerrinfo *next;
42f9d29536SMatthew Dillon 	char	*logid;
43f9d29536SMatthew Dillon 	pid_t	pid;
44f9d29536SMatthew Dillon 	long	seq;
45f9d29536SMatthew Dillon 	int	exited;
46f9d29536SMatthew Dillon };
47f9d29536SMatthew Dillon 
488e25f19bSMatthew Dillon buildenv_t *BuildEnv;
498e25f19bSMatthew Dillon static buildenv_t **BuildEnvTail = &BuildEnv;
508e25f19bSMatthew Dillon 
516fd67931SMatthew Dillon extern char **environ;
526fd67931SMatthew Dillon 
53f9d29536SMatthew Dillon static void *dexec_logerr_thread(void *info);
54f9d29536SMatthew Dillon 
55f9d29536SMatthew Dillon #define EINFO_HSIZE	1024
56f9d29536SMatthew Dillon #define EINFO_HMASK	(EINFO_HSIZE - 1)
57f9d29536SMatthew Dillon 
58f9d29536SMatthew Dillon static struct logerrinfo *EInfo[EINFO_HSIZE];
59f9d29536SMatthew Dillon static pthread_t ETid;
60f9d29536SMatthew Dillon static int EFds[2];
61f9d29536SMatthew Dillon static pthread_cond_t ECond;
62f9d29536SMatthew Dillon 
63f9d29536SMatthew Dillon static __inline
64f9d29536SMatthew Dillon struct logerrinfo **
einfohash(pid_t pid)65f9d29536SMatthew Dillon einfohash(pid_t pid)
66f9d29536SMatthew Dillon {
67f9d29536SMatthew Dillon 	return(&EInfo[pid & EINFO_HMASK]);
68f9d29536SMatthew Dillon }
69f9d29536SMatthew Dillon 
708e25f19bSMatthew Dillon __dead2 void
_dfatal(const char * file __unused,int line __unused,const char * func,int do_errno,const char * ctl,...)718e25f19bSMatthew Dillon _dfatal(const char *file __unused, int line __unused, const char *func,
728e25f19bSMatthew Dillon 	int do_errno, const char *ctl, ...)
738e25f19bSMatthew Dillon {
748e25f19bSMatthew Dillon 	va_list va;
758e25f19bSMatthew Dillon 
768e25f19bSMatthew Dillon 	fprintf(stderr, "%s: ", func);
778e25f19bSMatthew Dillon 	va_start(va, ctl);
788e25f19bSMatthew Dillon 	vfprintf(stderr, ctl, va);
798e25f19bSMatthew Dillon 	va_end(va);
808e25f19bSMatthew Dillon 	if (do_errno & 1)
818e25f19bSMatthew Dillon 		fprintf(stderr, ": %s", strerror(errno));
828e25f19bSMatthew Dillon 	fprintf(stderr, "\n");
838e25f19bSMatthew Dillon 	fflush(stderr);
848e25f19bSMatthew Dillon 
858e25f19bSMatthew Dillon 	if (do_errno & 2)
868e25f19bSMatthew Dillon 		kill(getpid(), SIGQUIT);
878e25f19bSMatthew Dillon 	exit(1);
888e25f19bSMatthew Dillon }
898e25f19bSMatthew Dillon 
908e25f19bSMatthew Dillon void
_ddprintf(int tab,const char * ctl,...)918e25f19bSMatthew Dillon _ddprintf(int tab, const char *ctl, ...)
928e25f19bSMatthew Dillon {
938e25f19bSMatthew Dillon 	va_list va;
948e25f19bSMatthew Dillon 
958e25f19bSMatthew Dillon 	if (tab)
968e25f19bSMatthew Dillon 		printf("%*.*s", tab, tab, "");
978e25f19bSMatthew Dillon 	va_start(va, ctl);
988e25f19bSMatthew Dillon 	vfprintf(stdout, ctl, va);
998e25f19bSMatthew Dillon 	va_end(va);
1008e25f19bSMatthew Dillon }
1018e25f19bSMatthew Dillon 
1024ea2ee4dSMatthew Dillon char *
strdup_or_null(char * str)1034ea2ee4dSMatthew Dillon strdup_or_null(char *str)
1044ea2ee4dSMatthew Dillon {
1054ea2ee4dSMatthew Dillon 	if (str && str[0])
1064ea2ee4dSMatthew Dillon 		return(strdup(str));
1074ea2ee4dSMatthew Dillon 	return NULL;
1084ea2ee4dSMatthew Dillon }
1094ea2ee4dSMatthew Dillon 
1108e25f19bSMatthew Dillon static const char *DLogNames[] = {
1118e25f19bSMatthew Dillon 	"00_last_results.log",
1128e25f19bSMatthew Dillon 	"01_success_list.log",
1138e25f19bSMatthew Dillon 	"02_failure_list.log",
1148e25f19bSMatthew Dillon 	"03_ignored_list.log",
1158e25f19bSMatthew Dillon 	"04_skipped_list.log",
1168e25f19bSMatthew Dillon 	"05_abnormal_command_output.log",
117349e3a76SMatthew Dillon 	"06_obsolete_packages.log",
118349e3a76SMatthew Dillon 	"07_debug.log",
1198e25f19bSMatthew Dillon };
1208e25f19bSMatthew Dillon 
1213699ee09SMatthew Dillon static int DLogFd[DLOG_COUNT];
1223699ee09SMatthew Dillon static pthread_mutex_t DLogFdMutex;
1233699ee09SMatthew Dillon 
1248e25f19bSMatthew Dillon #define arysize(ary)	(sizeof((ary)) / sizeof((ary)[0]))
1258e25f19bSMatthew Dillon 
1263699ee09SMatthew Dillon static int
dlogfd(int which,int modes)1273699ee09SMatthew Dillon dlogfd(int which, int modes)
1283699ee09SMatthew Dillon {
1293699ee09SMatthew Dillon 	char *path;
1303699ee09SMatthew Dillon 	int fd;
1313699ee09SMatthew Dillon 
132a574cbf0SMatthew Dillon 	which &= DLOG_MASK;
1333699ee09SMatthew Dillon 	if ((fd = DLogFd[which]) > 0)
1343699ee09SMatthew Dillon 		return fd;
1353699ee09SMatthew Dillon 	pthread_mutex_lock(&DLogFdMutex);
1363699ee09SMatthew Dillon 	if ((fd = DLogFd[which]) <= 0) {
1373699ee09SMatthew Dillon 		asprintf(&path, "%s/%s", LogsPath, DLogNames[which]);
1383699ee09SMatthew Dillon 		fd = open(path, modes, 0666);
1393699ee09SMatthew Dillon 		DLogFd[which] = fd;
1403699ee09SMatthew Dillon 		free(path);
1413699ee09SMatthew Dillon 	}
1423699ee09SMatthew Dillon 	pthread_mutex_unlock(&DLogFdMutex);
1433699ee09SMatthew Dillon 
1443699ee09SMatthew Dillon 	return fd;
1453699ee09SMatthew Dillon }
1463699ee09SMatthew Dillon 
1473699ee09SMatthew Dillon 
1488e25f19bSMatthew Dillon void
dlogreset(void)1498e25f19bSMatthew Dillon dlogreset(void)
1508e25f19bSMatthew Dillon {
1518e25f19bSMatthew Dillon 	int i;
1528e25f19bSMatthew Dillon 
1538e25f19bSMatthew Dillon 	ddassert(DLOG_COUNT == arysize(DLogNames));
1548e25f19bSMatthew Dillon 	for (i = 0; i < DLOG_COUNT; ++i) {
1553699ee09SMatthew Dillon 		if (DLogFd[i] > 0) {
1563699ee09SMatthew Dillon 			close(DLogFd[i]);
1573699ee09SMatthew Dillon 			DLogFd[i] = -1;
1583699ee09SMatthew Dillon 		}
1593699ee09SMatthew Dillon 		(void)dlogfd(i, O_RDWR|O_CREAT|O_TRUNC|O_APPEND);
1608e25f19bSMatthew Dillon 	}
1618e25f19bSMatthew Dillon }
1628e25f19bSMatthew Dillon 
1638e25f19bSMatthew Dillon void
_dlog(int which,const char * ctl,...)1648e25f19bSMatthew Dillon _dlog(int which, const char *ctl, ...)
1658e25f19bSMatthew Dillon {
1668e25f19bSMatthew Dillon 	va_list va;
1678e25f19bSMatthew Dillon 	char *buf;
168a574cbf0SMatthew Dillon 	char *ptr;
1698e25f19bSMatthew Dillon 	size_t len;
1708e25f19bSMatthew Dillon 	int fd;
171a574cbf0SMatthew Dillon 	int filter;
172a574cbf0SMatthew Dillon 
173a574cbf0SMatthew Dillon 	filter = which;
174a574cbf0SMatthew Dillon 	which &= DLOG_MASK;
1758e25f19bSMatthew Dillon 
1768e25f19bSMatthew Dillon 	ddassert((uint)which < DLOG_COUNT);
1778e25f19bSMatthew Dillon 	va_start(va, ctl);
1788e25f19bSMatthew Dillon 	vasprintf(&buf, ctl, va);
1798e25f19bSMatthew Dillon 	va_end(va);
1808e25f19bSMatthew Dillon 	len = strlen(buf);
1818e25f19bSMatthew Dillon 
1827f0eca56SMatthew Dillon 	/*
183a574cbf0SMatthew Dillon 	 * The special sequence ## right-justfies the text after the ##.
184a574cbf0SMatthew Dillon 	 *
185a574cbf0SMatthew Dillon 	 * NOTE: Alignment test includes \n so use 80 instead of 79 to
186a574cbf0SMatthew Dillon 	 *	 leave one char unused on a 80-column terminal.
187a574cbf0SMatthew Dillon 	 */
188a574cbf0SMatthew Dillon 	if ((ptr = strstr(buf, "##")) != NULL) {
189a574cbf0SMatthew Dillon 		size_t l2;
190a574cbf0SMatthew Dillon 		size_t l1;
191a574cbf0SMatthew Dillon 		char *b2;
192a574cbf0SMatthew Dillon 		int spc;
193a574cbf0SMatthew Dillon 
194a574cbf0SMatthew Dillon 		l1 = (int)(ptr - buf);
195a574cbf0SMatthew Dillon 		l2 = len - l1 - 2;
196a574cbf0SMatthew Dillon 		if (l1 <= 80 - l2) {
197a574cbf0SMatthew Dillon 			spc = 80 - l1 - l2;
198a574cbf0SMatthew Dillon 			buf[l1] = 0;
199a574cbf0SMatthew Dillon 			asprintf(&b2, "%s%*.*s%s",
200a574cbf0SMatthew Dillon 				 buf, spc, spc, "", ptr + 2);
201a574cbf0SMatthew Dillon 		} else {
202a574cbf0SMatthew Dillon 			buf[l1] = 0;
203a574cbf0SMatthew Dillon 			asprintf(&b2, "%s%s", buf, ptr + 2);
204a574cbf0SMatthew Dillon 		}
205a574cbf0SMatthew Dillon 		len = strlen(b2);
206a574cbf0SMatthew Dillon 		free(buf);
207a574cbf0SMatthew Dillon 		buf = b2;
208a574cbf0SMatthew Dillon 	}
209a574cbf0SMatthew Dillon 
210a574cbf0SMatthew Dillon 	/*
2117f0eca56SMatthew Dillon 	 * All logs also go to log 00.
2127f0eca56SMatthew Dillon 	 */
2138e25f19bSMatthew Dillon 	if (which != DLOG_ALL) {
2143699ee09SMatthew Dillon 		fd = dlogfd(DLOG_ALL, O_RDWR|O_CREAT|O_APPEND);
2153699ee09SMatthew Dillon 		if (fd > 0)
2168e25f19bSMatthew Dillon 			write(fd, buf, len);
2178e25f19bSMatthew Dillon 	}
2187f0eca56SMatthew Dillon 
2197f0eca56SMatthew Dillon 	/*
2207f0eca56SMatthew Dillon 	 * Nominal log target
2217f0eca56SMatthew Dillon 	 */
2223699ee09SMatthew Dillon 	fd = dlogfd(which, O_RDWR|O_CREAT|O_APPEND);
2238e25f19bSMatthew Dillon 	write(fd, buf, len);
2247f0eca56SMatthew Dillon 
2257f0eca56SMatthew Dillon 	/*
2267f0eca56SMatthew Dillon 	 * If ncurses is not being used, all log output also goes
227a574cbf0SMatthew Dillon 	 * to stdout, unless filtered.
2287f0eca56SMatthew Dillon 	 */
22933170e2dSMatthew Dillon 	if ((UseNCurses == 0 || (filter & DLOG_STDOUT)) &&
23033170e2dSMatthew Dillon 	    (filter & DLOG_FILTER) == 0) {
231a574cbf0SMatthew Dillon 		if (ColorOpt) {
232a574cbf0SMatthew Dillon 			if (filter & DLOG_GRN)
23332811a0aSMatthew Dillon 				write(1, "\x1b[0;32m", 7);
234a574cbf0SMatthew Dillon 			if (filter & DLOG_RED)
23532811a0aSMatthew Dillon 				write(1, "\x1b[0;31m", 7);
2367f0eca56SMatthew Dillon 		}
237a574cbf0SMatthew Dillon 		write(1, buf, len);
238a574cbf0SMatthew Dillon 		if (ColorOpt && (filter & (DLOG_GRN|DLOG_RED))) {
239a574cbf0SMatthew Dillon 			write(1, "\x1b[0;39m", 7);
240a574cbf0SMatthew Dillon 		}
241a574cbf0SMatthew Dillon 	}
2423699ee09SMatthew Dillon 	free(buf);
2438e25f19bSMatthew Dillon }
2448e25f19bSMatthew Dillon 
24554f2fefcSMatthew Dillon int
dlog00_fd(void)24654f2fefcSMatthew Dillon dlog00_fd(void)
24754f2fefcSMatthew Dillon {
24854f2fefcSMatthew Dillon 	return(dlogfd(DLOG_ALL, O_RDWR|O_CREAT|O_APPEND));
24954f2fefcSMatthew Dillon }
25054f2fefcSMatthew Dillon 
251a67bf8dbSMatthew Dillon /*
252a67bf8dbSMatthew Dillon  * Bulk and Build environment control.  These routines are only called
253a67bf8dbSMatthew Dillon  * unthreaded or when dsynth threads are idle.
254a67bf8dbSMatthew Dillon  */
2558e25f19bSMatthew Dillon void
addbuildenv(const char * label,const char * data,int type)2566fd67931SMatthew Dillon addbuildenv(const char *label, const char *data, int type)
2578e25f19bSMatthew Dillon {
2588e25f19bSMatthew Dillon 	buildenv_t *env;
2598e25f19bSMatthew Dillon 
2608e25f19bSMatthew Dillon 	env = calloc(1, sizeof(*env));
26168dc2eeaSMatthew Dillon 	env->a1 = strdup(label);
26268dc2eeaSMatthew Dillon 	env->a2 = strdup(data);
26368dc2eeaSMatthew Dillon 	env->label = env->a1;
26468dc2eeaSMatthew Dillon 	env->data = env->a2;
2656fd67931SMatthew Dillon 	env->type = type;
2668e25f19bSMatthew Dillon 	*BuildEnvTail = env;
2678e25f19bSMatthew Dillon 	BuildEnvTail = &env->next;
2688e25f19bSMatthew Dillon }
2698e25f19bSMatthew Dillon 
2708e25f19bSMatthew Dillon void
delbuildenv(const char * label)271a67bf8dbSMatthew Dillon delbuildenv(const char *label)
272a67bf8dbSMatthew Dillon {
273a67bf8dbSMatthew Dillon 	buildenv_t **envp;
274a67bf8dbSMatthew Dillon 	buildenv_t *env;
275a67bf8dbSMatthew Dillon 
276a67bf8dbSMatthew Dillon 	envp = &BuildEnv;
277a67bf8dbSMatthew Dillon 	while ((env = *envp) != NULL) {
278a67bf8dbSMatthew Dillon 		if (strcmp(env->label, label) == 0) {
279a67bf8dbSMatthew Dillon 			*envp = env->next;
28068dc2eeaSMatthew Dillon 			if (env->a1)
28168dc2eeaSMatthew Dillon 				free(env->a1);
28268dc2eeaSMatthew Dillon 			if (env->a2)
28368dc2eeaSMatthew Dillon 				free(env->a2);
284a67bf8dbSMatthew Dillon 			free(env);
285a67bf8dbSMatthew Dillon 		} else {
286a67bf8dbSMatthew Dillon 			envp = &env->next;
287a67bf8dbSMatthew Dillon 		}
288a67bf8dbSMatthew Dillon 	}
289a67bf8dbSMatthew Dillon 	BuildEnvTail = envp;
290a67bf8dbSMatthew Dillon }
291a67bf8dbSMatthew Dillon 
292aeecca07SMatthew Dillon const char *
getbuildenv(const char * label)293aeecca07SMatthew Dillon getbuildenv(const char *label)
294aeecca07SMatthew Dillon {
295aeecca07SMatthew Dillon 	buildenv_t **envp;
296aeecca07SMatthew Dillon 	buildenv_t *env;
297aeecca07SMatthew Dillon 
298aeecca07SMatthew Dillon 	envp = &BuildEnv;
299aeecca07SMatthew Dillon 	while ((env = *envp) != NULL) {
300aeecca07SMatthew Dillon 		if (strcmp(env->label, label) == 0)
301aeecca07SMatthew Dillon 			return env->data;
302aeecca07SMatthew Dillon 		envp = &env->next;
303aeecca07SMatthew Dillon 	}
304aeecca07SMatthew Dillon 	return NULL;
305aeecca07SMatthew Dillon }
306aeecca07SMatthew Dillon 
307a67bf8dbSMatthew Dillon void
freestrp(char ** strp)3088e25f19bSMatthew Dillon freestrp(char **strp)
3098e25f19bSMatthew Dillon {
3108e25f19bSMatthew Dillon 	if (*strp) {
3118e25f19bSMatthew Dillon 		free(*strp);
3128e25f19bSMatthew Dillon 		*strp = NULL;
3138e25f19bSMatthew Dillon 	}
3148e25f19bSMatthew Dillon }
3158e25f19bSMatthew Dillon 
3168e25f19bSMatthew Dillon void
dupstrp(char ** strp)3178e25f19bSMatthew Dillon dupstrp(char **strp)
3188e25f19bSMatthew Dillon {
3198e25f19bSMatthew Dillon 	if (*strp)
3208e25f19bSMatthew Dillon 		*strp = strdup(*strp);
3218e25f19bSMatthew Dillon }
3228e25f19bSMatthew Dillon 
3238e25f19bSMatthew Dillon int
ipcreadmsg(int fd,wmsg_t * msg)3248e25f19bSMatthew Dillon ipcreadmsg(int fd, wmsg_t *msg)
3258e25f19bSMatthew Dillon {
3268e25f19bSMatthew Dillon 	size_t res;
3278e25f19bSMatthew Dillon 	ssize_t r;
3288e25f19bSMatthew Dillon 	char *ptr;
3298e25f19bSMatthew Dillon 
3308e25f19bSMatthew Dillon 	res = sizeof(*msg);
3318e25f19bSMatthew Dillon 	ptr = (char *)(void *)msg;
3328e25f19bSMatthew Dillon 	while (res) {
3338e25f19bSMatthew Dillon 		r = read(fd, ptr, res);
3348e25f19bSMatthew Dillon 		if (r <= 0) {
3358e25f19bSMatthew Dillon 			if (errno == EINTR)
3368e25f19bSMatthew Dillon 				continue;
3378e25f19bSMatthew Dillon 			return -1;
3388e25f19bSMatthew Dillon 		}
3398e25f19bSMatthew Dillon 		res -= (size_t)r;
3408e25f19bSMatthew Dillon 		ptr += r;
3418e25f19bSMatthew Dillon 	}
3428e25f19bSMatthew Dillon 	return 0;
3438e25f19bSMatthew Dillon }
3448e25f19bSMatthew Dillon 
3458e25f19bSMatthew Dillon int
ipcwritemsg(int fd,wmsg_t * msg)3468e25f19bSMatthew Dillon ipcwritemsg(int fd, wmsg_t *msg)
3478e25f19bSMatthew Dillon {
3488e25f19bSMatthew Dillon 	size_t res;
3498e25f19bSMatthew Dillon 	ssize_t r;
3508e25f19bSMatthew Dillon 	char *ptr;
3518e25f19bSMatthew Dillon 
3528e25f19bSMatthew Dillon 	res = sizeof(*msg);
3538e25f19bSMatthew Dillon 	ptr = (char *)(void *)msg;
3548e25f19bSMatthew Dillon 	while (res) {
3558e25f19bSMatthew Dillon 		r = write(fd, ptr, res);
3568e25f19bSMatthew Dillon 		if (r < 0) {
3578e25f19bSMatthew Dillon 			if (errno == EINTR)
3588e25f19bSMatthew Dillon 				continue;
3598e25f19bSMatthew Dillon 			return -1;
3608e25f19bSMatthew Dillon 		}
3618e25f19bSMatthew Dillon 		res -= (size_t)r;
3628e25f19bSMatthew Dillon 		ptr += r;
3638e25f19bSMatthew Dillon 	}
3648e25f19bSMatthew Dillon 	return 0;
3658e25f19bSMatthew Dillon }
3661645cafeSMatthew Dillon 
3671645cafeSMatthew Dillon int
askyn(const char * ctl,...)3681645cafeSMatthew Dillon askyn(const char *ctl, ...)
3691645cafeSMatthew Dillon {
3701645cafeSMatthew Dillon 	va_list va;
3711645cafeSMatthew Dillon 	char buf[256];
3721645cafeSMatthew Dillon 	int res = 0;
3731645cafeSMatthew Dillon 
3741645cafeSMatthew Dillon 	if (YesOpt)
3751645cafeSMatthew Dillon 		return 1;
3761645cafeSMatthew Dillon 
3771645cafeSMatthew Dillon 	for (;;) {
3781645cafeSMatthew Dillon 		va_start(va, ctl);
3791645cafeSMatthew Dillon 		vprintf(ctl, va);
3801645cafeSMatthew Dillon 		va_end(va);
3811645cafeSMatthew Dillon 		fflush(stdout);
3821645cafeSMatthew Dillon 		if (fgets(buf, sizeof(buf), stdin) == NULL)
3831645cafeSMatthew Dillon 			break;
3841645cafeSMatthew Dillon 		if (buf[0] == 'y' || buf[0] == 'Y') {
3851645cafeSMatthew Dillon 			res = 1;
3861645cafeSMatthew Dillon 			break;
3871645cafeSMatthew Dillon 		}
3881645cafeSMatthew Dillon 		if (buf[0] == 'n' || buf[0] == 'N') {
3891645cafeSMatthew Dillon 			res = 0;
3901645cafeSMatthew Dillon 			break;
3911645cafeSMatthew Dillon 		}
3921645cafeSMatthew Dillon 		printf("Please type y/n\n");
3931645cafeSMatthew Dillon 	}
3941645cafeSMatthew Dillon 	return res;
3951645cafeSMatthew Dillon }
3963699ee09SMatthew Dillon 
3973699ee09SMatthew Dillon /*
3983699ee09SMatthew Dillon  * Get swap% used 0.0-1.0.
3993699ee09SMatthew Dillon  *
4003699ee09SMatthew Dillon  * NOTE: This routine is intended to return quickly.
401f7f25838SMatthew Dillon  *
402f7f25838SMatthew Dillon  * NOTE: swap_cache (caching for hard drives) is persistent and should
403f7f25838SMatthew Dillon  *	 not be counted for our purposes.
4043699ee09SMatthew Dillon  */
4053699ee09SMatthew Dillon double
getswappct(int * noswapp)4063699ee09SMatthew Dillon getswappct(int *noswapp)
4073699ee09SMatthew Dillon {
4083699ee09SMatthew Dillon 	long swap_size = 0;
4093699ee09SMatthew Dillon 	long swap_anon = 0;
410f7f25838SMatthew Dillon 	long swap_cache __unused = 0;
4113699ee09SMatthew Dillon 	size_t len;
4123699ee09SMatthew Dillon 	double dswap;
4133699ee09SMatthew Dillon 
4143699ee09SMatthew Dillon 	len = sizeof(swap_size);
4153699ee09SMatthew Dillon 	sysctlbyname("vm.swap_size", &swap_size, &len, NULL, 0);
4163699ee09SMatthew Dillon 	len = sizeof(swap_size);
4173699ee09SMatthew Dillon 	sysctlbyname("vm.swap_anon_use", &swap_anon, &len, NULL, 0);
4183699ee09SMatthew Dillon 	len = sizeof(swap_size);
4193699ee09SMatthew Dillon 	sysctlbyname("vm.swap_cache_use", &swap_cache, &len, NULL, 0);
4203699ee09SMatthew Dillon 	if (swap_size) {
421f7f25838SMatthew Dillon 		dswap = (double)(swap_anon /*+swap_cache*/) / (double)swap_size;
4223699ee09SMatthew Dillon 		*noswapp = 0;
4233699ee09SMatthew Dillon 	} else {
4243699ee09SMatthew Dillon 		dswap = 0.0;
4253699ee09SMatthew Dillon 		*noswapp = 1;
4263699ee09SMatthew Dillon 	}
4273699ee09SMatthew Dillon 	return dswap;
4283699ee09SMatthew Dillon }
4296fd67931SMatthew Dillon 
4306fd67931SMatthew Dillon /*
4316fd67931SMatthew Dillon  * dexec_open()/fgets/dexec_close()
4326fd67931SMatthew Dillon  *
4336fd67931SMatthew Dillon  * Similar to popen() but directly exec()s the argument list (cav[0] must
4346fd67931SMatthew Dillon  * be an absolute path).
4356fd67931SMatthew Dillon  *
43668dc2eeaSMatthew Dillon  * If xenv is non-NULL its an array of local buildenv_t's to be used.
43768dc2eeaSMatthew Dillon  * The array is terminated with a NULL xenv->label.
43868dc2eeaSMatthew Dillon  *
4396fd67931SMatthew Dillon  * If with_env is non-zero the configured environment is included.
4406fd67931SMatthew Dillon  *
4416fd67931SMatthew Dillon  * If with_mvars is non-zero the make environment is passed as VAR=DATA
4426fd67931SMatthew Dillon  * elements on the command line.
4436fd67931SMatthew Dillon  */
4446fd67931SMatthew Dillon FILE *
dexec_open(const char * logid,const char ** cav,int cac,pid_t * pidp,buildenv_t * xenv,int with_env,int with_mvars)445f9d29536SMatthew Dillon dexec_open(const char *logid, const char **cav, int cac,
446f9d29536SMatthew Dillon 	   pid_t *pidp, buildenv_t *xenv, int with_env, int with_mvars)
4476fd67931SMatthew Dillon {
4486fd67931SMatthew Dillon 	buildenv_t *benv;
4496fd67931SMatthew Dillon 	const char **cenv;
4506fd67931SMatthew Dillon 	char *allocary[MAXCAC*2];
4516fd67931SMatthew Dillon 	int env_basei;
4526fd67931SMatthew Dillon 	int envi;
4536fd67931SMatthew Dillon 	int alloci;
4546fd67931SMatthew Dillon 	int nullfd;
455f9d29536SMatthew Dillon 	int fds[2];	/* stdout */
4566fd67931SMatthew Dillon 	pid_t pid;
4576fd67931SMatthew Dillon 	FILE *fp;
458f9d29536SMatthew Dillon 	struct logerrinfo *einfo;
459f9d29536SMatthew Dillon 	static int warned;
460f9d29536SMatthew Dillon 
461f9d29536SMatthew Dillon 	/*
462f9d29536SMatthew Dillon 	 * Error logging thread setup
463f9d29536SMatthew Dillon 	 */
464f9d29536SMatthew Dillon 	if (ETid == 0) {
465f9d29536SMatthew Dillon 		pthread_mutex_lock(&DLogFdMutex);
466f9d29536SMatthew Dillon 		if (ETid == 0) {
467f9d29536SMatthew Dillon 			if (socketpair(AF_UNIX, SOCK_DGRAM, 0, EFds) < 0)
468f9d29536SMatthew Dillon 				dfatal_errno("socketpair");
469f9d29536SMatthew Dillon #ifdef SO_PASSCRED
470f9d29536SMatthew Dillon 			int optval = 1;
471f9d29536SMatthew Dillon 			if (setsockopt(EFds[0], SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval)) < 0) {
472f9d29536SMatthew Dillon 				if (warned == 0) {
473f9d29536SMatthew Dillon 					warned = 1;
474f9d29536SMatthew Dillon 					fprintf(stderr, "SO_PASSCRED not supported\n");
475f9d29536SMatthew Dillon 				}
476f9d29536SMatthew Dillon 			}
477f9d29536SMatthew Dillon #endif
478f9d29536SMatthew Dillon 
479f9d29536SMatthew Dillon 			pthread_cond_init(&ECond, NULL);
480f9d29536SMatthew Dillon 			pthread_create(&ETid, NULL, dexec_logerr_thread, NULL);
481f9d29536SMatthew Dillon 		}
482f9d29536SMatthew Dillon 		pthread_mutex_unlock(&DLogFdMutex);
483f9d29536SMatthew Dillon 	}
4846fd67931SMatthew Dillon 
4856fd67931SMatthew Dillon 	env_basei = 0;
486943ee1f8SMatthew Dillon #if 0
487943ee1f8SMatthew Dillon 	/*
488943ee1f8SMatthew Dillon 	 * For now we are ignoring the passed-in environment, so don't
489943ee1f8SMatthew Dillon 	 * copy the existing environment into the exec environment.
490943ee1f8SMatthew Dillon 	 */
4916fd67931SMatthew Dillon 	while (environ[env_basei])
4926fd67931SMatthew Dillon 		++env_basei;
493943ee1f8SMatthew Dillon #endif
4946fd67931SMatthew Dillon 	cenv = calloc(env_basei + MAXCAC, sizeof(char *));
4956fd67931SMatthew Dillon 	for (envi = 0; envi < env_basei; ++envi)
4966fd67931SMatthew Dillon 		cenv[envi] = environ[envi];
4976fd67931SMatthew Dillon 
4986fd67931SMatthew Dillon 	alloci = 0;
4996fd67931SMatthew Dillon 	for (benv = BuildEnv; benv; benv = benv->next) {
50031f2ea22SMatthew Dillon 		if (with_mvars &&
50131f2ea22SMatthew Dillon 		    (benv->type & BENV_CMDMASK) == BENV_MAKECONF) {
5026fd67931SMatthew Dillon 			asprintf(&allocary[alloci], "%s=%s",
5036fd67931SMatthew Dillon 				 benv->label, benv->data);
5046fd67931SMatthew Dillon 			cav[cac++] = allocary[alloci];
5056fd67931SMatthew Dillon 			++alloci;
5066fd67931SMatthew Dillon 		}
50731f2ea22SMatthew Dillon 		if (with_env &&
50831f2ea22SMatthew Dillon 		    (benv->type & BENV_PKGLIST) &&
50931f2ea22SMatthew Dillon 		    (benv->type & BENV_CMDMASK) == BENV_ENVIRONMENT) {
5106fd67931SMatthew Dillon 			asprintf(&allocary[alloci], "%s=%s",
5116fd67931SMatthew Dillon 				 benv->label, benv->data);
5126fd67931SMatthew Dillon 			cenv[envi++] = allocary[alloci];
5136fd67931SMatthew Dillon 			++alloci;
5146fd67931SMatthew Dillon 		}
5156fd67931SMatthew Dillon 		ddassert(cac < MAXCAC && envi - env_basei < MAXCAC);
5166fd67931SMatthew Dillon 	}
51768dc2eeaSMatthew Dillon 
51868dc2eeaSMatthew Dillon 	/*
51968dc2eeaSMatthew Dillon 	 * Extra environment specific to this particular dexec
52068dc2eeaSMatthew Dillon 	 */
52168dc2eeaSMatthew Dillon 	while (xenv && xenv->label) {
52268dc2eeaSMatthew Dillon 		asprintf(&allocary[alloci], "%s=%s",
52368dc2eeaSMatthew Dillon 			 xenv->label, xenv->data);
52468dc2eeaSMatthew Dillon 		cenv[envi++] = allocary[alloci];
52568dc2eeaSMatthew Dillon 		++alloci;
52668dc2eeaSMatthew Dillon 		++xenv;
52768dc2eeaSMatthew Dillon 	}
52868dc2eeaSMatthew Dillon 
5296fd67931SMatthew Dillon 	cav[cac] = NULL;
5306fd67931SMatthew Dillon 	cenv[envi] = NULL;
5316fd67931SMatthew Dillon 
532f9d29536SMatthew Dillon 	if (pipe2(fds, O_CLOEXEC) < 0)
5336fd67931SMatthew Dillon 		dfatal_errno("pipe");
534f9d29536SMatthew Dillon 	nullfd = open("/dev/null", O_RDWR | O_CLOEXEC);
5356fd67931SMatthew Dillon 	if (nullfd < 0)
5366fd67931SMatthew Dillon 		dfatal_errno("open(\"/dev/null\")");
5376fd67931SMatthew Dillon 
5386fd67931SMatthew Dillon 	/*
5396fd67931SMatthew Dillon 	 * We have to be very careful using vfork(), do only the bare
5406fd67931SMatthew Dillon 	 * minimum necessary in the child to set it up and exec it.
5416fd67931SMatthew Dillon 	 */
5426fd67931SMatthew Dillon 	pid = vfork();
5436fd67931SMatthew Dillon 	if (pid == 0) {
5446fd67931SMatthew Dillon #if 0
5456fd67931SMatthew Dillon 		int i;
5466fd67931SMatthew Dillon 		printf("%s", cav[0]);
5476fd67931SMatthew Dillon 		for (i = 0; cav[i]; ++i)
5486fd67931SMatthew Dillon 			printf(" %s", cav[i]);
5496fd67931SMatthew Dillon 		printf("\n");
5506fd67931SMatthew Dillon 		printf("ENV: ");
5516fd67931SMatthew Dillon 		for (i = 0; cenv[i]; ++i)
5526fd67931SMatthew Dillon 			printf(" %s", cenv[i]);
5536fd67931SMatthew Dillon #endif
5546fd67931SMatthew Dillon 
5556fd67931SMatthew Dillon 		if (fds[1] != 1) {
5566fd67931SMatthew Dillon 			dup2(fds[1], 1);
5576fd67931SMatthew Dillon 			close(fds[1]);
5586fd67931SMatthew Dillon 		}
559f9d29536SMatthew Dillon 		if (EFds[1] != 2) {
560f9d29536SMatthew Dillon 			dup2(EFds[1], 2);
561f9d29536SMatthew Dillon 			close(EFds[1]);
562f9d29536SMatthew Dillon 		}
5636fd67931SMatthew Dillon 		close(fds[0]);		/* safety */
564f9d29536SMatthew Dillon 		close(EFds[0]);		/* safety */
5656fd67931SMatthew Dillon 		dup2(nullfd, 0);	/* no questions! */
5666fd67931SMatthew Dillon 		closefrom(3);		/* be nice */
5676fd67931SMatthew Dillon 
5686d1478d9SMatthew Dillon 		/*
5696d1478d9SMatthew Dillon 		 * Self-nice to be nice (ignore any error)
5706d1478d9SMatthew Dillon 		 */
5716d1478d9SMatthew Dillon 		if (NiceOpt)
5726d1478d9SMatthew Dillon 			setpriority(PRIO_PROCESS, 0, NiceOpt);
5736d1478d9SMatthew Dillon 
5742b3f93eaSMatthew Dillon 		/*
5752b3f93eaSMatthew Dillon 		 * Throw in some capability restrictions
5762b3f93eaSMatthew Dillon 		 */
5772b3f93eaSMatthew Dillon 		set_capability_restrictions();
5782b3f93eaSMatthew Dillon 
5796fd67931SMatthew Dillon 		execve(cav[0], (void *)cav, (void *)cenv);
5806fd67931SMatthew Dillon 		write(2, "EXEC FAILURE\n", 13);
5816fd67931SMatthew Dillon 		_exit(1);
5826fd67931SMatthew Dillon 	}
5836fd67931SMatthew Dillon 	close(nullfd);
5846fd67931SMatthew Dillon 	close(fds[1]);
5856fd67931SMatthew Dillon 	if (pid < 0) {
5866fd67931SMatthew Dillon 		close(fds[0]);
5876fd67931SMatthew Dillon 		dfatal_errno("vfork failed");
5886fd67931SMatthew Dillon 	}
5896fd67931SMatthew Dillon 	fp = fdopen(fds[0], "r");
5906fd67931SMatthew Dillon 	*pidp = pid;
5916fd67931SMatthew Dillon 
592f9d29536SMatthew Dillon 	/*
593f9d29536SMatthew Dillon 	 * einfo setup
594f9d29536SMatthew Dillon 	 */
595f9d29536SMatthew Dillon 	einfo = calloc(1, sizeof(*einfo));
596f9d29536SMatthew Dillon 	if (logid)
597f9d29536SMatthew Dillon 		einfo->logid = strdup(logid);
598f9d29536SMatthew Dillon 
599f9d29536SMatthew Dillon 	pthread_mutex_lock(&DLogFdMutex);
600f9d29536SMatthew Dillon 	einfo->pid = pid;
601f9d29536SMatthew Dillon 	einfo->next = *einfohash(pid);
602f9d29536SMatthew Dillon 	*einfohash(pid) = einfo;
603f9d29536SMatthew Dillon 	pthread_cond_signal(&ECond);
604f9d29536SMatthew Dillon 	pthread_mutex_unlock(&DLogFdMutex);
605f9d29536SMatthew Dillon 
6066fd67931SMatthew Dillon 	while (--alloci >= 0)
6076fd67931SMatthew Dillon 		free(allocary[alloci]);
6086fd67931SMatthew Dillon 	free(cenv);
6096fd67931SMatthew Dillon 
6106fd67931SMatthew Dillon 	return fp;
6116fd67931SMatthew Dillon }
6126fd67931SMatthew Dillon 
6136fd67931SMatthew Dillon int
dexec_close(FILE * fp,pid_t pid)6146fd67931SMatthew Dillon dexec_close(FILE *fp, pid_t pid)
6156fd67931SMatthew Dillon {
616f9d29536SMatthew Dillon 	struct logerrinfo **einfop;
617f9d29536SMatthew Dillon 	struct logerrinfo *einfo;
6186fd67931SMatthew Dillon 	pid_t rpid;
6196fd67931SMatthew Dillon 	int status;
6206fd67931SMatthew Dillon 
6216fd67931SMatthew Dillon 	fclose(fp);
6226fd67931SMatthew Dillon 	while ((rpid = waitpid(pid, &status, 0)) != pid) {
6236fd67931SMatthew Dillon 		if (rpid < 0) {
6246fd67931SMatthew Dillon 			if (errno == EINTR)
6256fd67931SMatthew Dillon 				continue;
6266fd67931SMatthew Dillon 			return 1;
6276fd67931SMatthew Dillon 		}
6286fd67931SMatthew Dillon 	}
629f9d29536SMatthew Dillon 
630f9d29536SMatthew Dillon 	pthread_mutex_lock(&DLogFdMutex);
631f9d29536SMatthew Dillon 	einfop = einfohash(pid);
632f9d29536SMatthew Dillon 	while ((einfo = *einfop) != NULL) {
633f9d29536SMatthew Dillon 		if (einfo->pid == pid) {
634f9d29536SMatthew Dillon 			einfo->exited = 1;
635f9d29536SMatthew Dillon 			break;
636f9d29536SMatthew Dillon 		}
637f9d29536SMatthew Dillon 		einfop = &einfo->next;
638f9d29536SMatthew Dillon 	}
639f9d29536SMatthew Dillon 	pthread_mutex_unlock(&DLogFdMutex);
640f9d29536SMatthew Dillon 
6416fd67931SMatthew Dillon 	return (WEXITSTATUS(status));
6426fd67931SMatthew Dillon }
6433cebe4a8SMatthew Dillon 
644f9d29536SMatthew Dillon static void *
dexec_logerr_thread(void * dummy __unused)645f9d29536SMatthew Dillon dexec_logerr_thread(void *dummy __unused)
646f9d29536SMatthew Dillon {
647f9d29536SMatthew Dillon 	char buf[4096];
648f9d29536SMatthew Dillon 	union {
649f9d29536SMatthew Dillon 		char cbuf[CMSG_SPACE(sizeof(struct ucred))];
650f9d29536SMatthew Dillon 		struct cmsghdr cbuf_align;
651f9d29536SMatthew Dillon 	} cmsg_buf;
652f9d29536SMatthew Dillon 	struct cmsghdr *cmsg;
653f9d29536SMatthew Dillon 	struct logerrinfo **einfop;
654f9d29536SMatthew Dillon 	struct logerrinfo *einfo;
655f9d29536SMatthew Dillon 	struct msghdr msg;
656f9d29536SMatthew Dillon 	struct iovec iov;
657f9d29536SMatthew Dillon 	ssize_t len;
658f9d29536SMatthew Dillon 	int mflags = MSG_DONTWAIT;
659f9d29536SMatthew Dillon 	int fd;
660f9d29536SMatthew Dillon 
661f9d29536SMatthew Dillon 	pthread_detach(pthread_self());
662f9d29536SMatthew Dillon 
663f9d29536SMatthew Dillon 	msg.msg_name = NULL;
664f9d29536SMatthew Dillon 	msg.msg_namelen = 0;
665f9d29536SMatthew Dillon 	msg.msg_iov = &iov;
666f9d29536SMatthew Dillon 
667f9d29536SMatthew Dillon 	msg.msg_control = cmsg_buf.cbuf;
668f9d29536SMatthew Dillon 	msg.msg_controllen = sizeof(cmsg_buf.cbuf);
669f9d29536SMatthew Dillon 
670f9d29536SMatthew Dillon 	fd = EFds[0];
671f9d29536SMatthew Dillon 	for (;;) {
672f9d29536SMatthew Dillon 		int i;
673f9d29536SMatthew Dillon 
674f9d29536SMatthew Dillon 		msg.msg_iovlen = 1;
675f9d29536SMatthew Dillon 		iov.iov_base = buf;
676f9d29536SMatthew Dillon 		iov.iov_len = sizeof(buf) - 1;
677f9d29536SMatthew Dillon 
678f9d29536SMatthew Dillon 		/*
679f9d29536SMatthew Dillon 		 * Wait for message, if none are pending then clean-up
680f9d29536SMatthew Dillon 		 * exited einfos (this ensures that we have flushed all
681f9d29536SMatthew Dillon 		 * error output before freeing the structure).
682f9d29536SMatthew Dillon 		 *
683f9d29536SMatthew Dillon 		 * Don't obtain the mutex until we really need it.  The
684f9d29536SMatthew Dillon 		 * parent thread can only 'add' einfo entries to the hash
685f9d29536SMatthew Dillon 		 * table so we are basically scan-safe.
686f9d29536SMatthew Dillon 		 */
687f9d29536SMatthew Dillon 		len = recvmsg(fd, &msg, mflags);
688f9d29536SMatthew Dillon 		if (len < 0) {
689f9d29536SMatthew Dillon 			if (errno != EAGAIN) {	/* something messed up */
690f9d29536SMatthew Dillon 				fprintf(stderr, "ERRNO %d\n", errno);
691f9d29536SMatthew Dillon 				break;
692f9d29536SMatthew Dillon 			}
693f9d29536SMatthew Dillon 
694f9d29536SMatthew Dillon 			for (i = 0; i < EINFO_HSIZE; ++i) {
695f9d29536SMatthew Dillon 				einfo = EInfo[i];
696f9d29536SMatthew Dillon 				while (einfo) {
697f9d29536SMatthew Dillon 					if (einfo->exited)
698f9d29536SMatthew Dillon 						break;
699f9d29536SMatthew Dillon 					einfo = einfo->next;
700f9d29536SMatthew Dillon 				}
701f9d29536SMatthew Dillon 				if (einfo == NULL)
702f9d29536SMatthew Dillon 					continue;
703f9d29536SMatthew Dillon 				pthread_mutex_lock(&DLogFdMutex);
704f9d29536SMatthew Dillon 				einfop = &EInfo[i];
705f9d29536SMatthew Dillon 				while ((einfo = *einfop) != NULL) {
706f9d29536SMatthew Dillon 					if (einfo->exited) {
707f9d29536SMatthew Dillon 						*einfop = einfo->next;
708f9d29536SMatthew Dillon 						if (einfo->logid)
709f9d29536SMatthew Dillon 							free(einfo->logid);
710f9d29536SMatthew Dillon 						free(einfo);
711f9d29536SMatthew Dillon 					} else {
712f9d29536SMatthew Dillon 						einfop = &einfo->next;
713f9d29536SMatthew Dillon 					}
714f9d29536SMatthew Dillon 				}
715f9d29536SMatthew Dillon 				pthread_mutex_unlock(&DLogFdMutex);
716f9d29536SMatthew Dillon 			}
717f9d29536SMatthew Dillon 			mflags = 0;
718f9d29536SMatthew Dillon 			continue;
719f9d29536SMatthew Dillon 		}
720f9d29536SMatthew Dillon 
721f9d29536SMatthew Dillon 		/*
722f9d29536SMatthew Dillon 		 * Process SCM_CREDS, if present.  Throw away SCM_RIGHTS
723f9d29536SMatthew Dillon 		 * if some sub-process stupidly sent it.
724f9d29536SMatthew Dillon 		 */
725f9d29536SMatthew Dillon 		einfo = NULL;
726f9d29536SMatthew Dillon 		mflags = MSG_DONTWAIT;
727f9d29536SMatthew Dillon 
728f9d29536SMatthew Dillon 		if (len && buf[len-1] == '\n')
729f9d29536SMatthew Dillon 			--len;
730f9d29536SMatthew Dillon 		buf[len] = 0;
731f9d29536SMatthew Dillon 
732f9d29536SMatthew Dillon 		for (cmsg = CMSG_FIRSTHDR(&msg);
733f9d29536SMatthew Dillon 		     cmsg;
734f9d29536SMatthew Dillon 		     cmsg = CMSG_NXTHDR(&msg, cmsg)) {
735f9d29536SMatthew Dillon 			struct cmsgcred *cred;
736f9d29536SMatthew Dillon 			int *fds;
737f9d29536SMatthew Dillon 			int n;
738f9d29536SMatthew Dillon 
739f9d29536SMatthew Dillon 			if (cmsg->cmsg_level != SOL_SOCKET)
740f9d29536SMatthew Dillon 				continue;
741f9d29536SMatthew Dillon 
742f9d29536SMatthew Dillon 			switch(cmsg->cmsg_type) {
743f9d29536SMatthew Dillon 			case SCM_CREDS:
744f9d29536SMatthew Dillon 
745f9d29536SMatthew Dillon 				cred = (void *)CMSG_DATA(cmsg);
746f9d29536SMatthew Dillon 
747f9d29536SMatthew Dillon 				einfo = *einfohash(cred->cmcred_pid);
748f9d29536SMatthew Dillon 				while (einfo && einfo->pid != cred->cmcred_pid)
749f9d29536SMatthew Dillon 					einfo = einfo->next;
750f9d29536SMatthew Dillon 				break;
751f9d29536SMatthew Dillon 			case SCM_RIGHTS:
752f9d29536SMatthew Dillon 				fds = (void *)CMSG_DATA(cmsg);
753f9d29536SMatthew Dillon 				n = (cmsg->cmsg_len - sizeof(cmsg)) /
754f9d29536SMatthew Dillon 				    sizeof(int);
755f9d29536SMatthew Dillon 				for (i = 0; i < n; ++i)
756f9d29536SMatthew Dillon 					close(fds[i]);
757f9d29536SMatthew Dillon 				break;
758f9d29536SMatthew Dillon 			}
759f9d29536SMatthew Dillon 		}
760f9d29536SMatthew Dillon 
761f9d29536SMatthew Dillon 		if (einfo && einfo->logid) {
762f9d29536SMatthew Dillon 			dlog(DLOG_ALL | DLOG_STDOUT,
763f9d29536SMatthew Dillon 			     "%s: %s\n",
764f9d29536SMatthew Dillon 			     einfo->logid, buf);
765f9d29536SMatthew Dillon 		} else {
766f9d29536SMatthew Dillon 			dlog(DLOG_ALL | DLOG_STDOUT, "%s", buf);
767f9d29536SMatthew Dillon 		}
768f9d29536SMatthew Dillon 	}
769f9d29536SMatthew Dillon 	return NULL;
770f9d29536SMatthew Dillon }
771f9d29536SMatthew Dillon 
7723cebe4a8SMatthew Dillon const char *
getphasestr(worker_phase_t phaseid)7733cebe4a8SMatthew Dillon getphasestr(worker_phase_t phaseid)
7743cebe4a8SMatthew Dillon {
7753cebe4a8SMatthew Dillon 	const char *phase;
7763cebe4a8SMatthew Dillon 
7773cebe4a8SMatthew Dillon 	switch(phaseid) {
7783cebe4a8SMatthew Dillon 	case PHASE_PENDING:
7793cebe4a8SMatthew Dillon 		phase = "pending";
7803cebe4a8SMatthew Dillon 		break;
7813cebe4a8SMatthew Dillon 	case PHASE_INSTALL_PKGS:
7823cebe4a8SMatthew Dillon 		phase = "install-pkgs";
7833cebe4a8SMatthew Dillon 		break;
7843cebe4a8SMatthew Dillon 	case PHASE_CHECK_SANITY:
7853cebe4a8SMatthew Dillon 		phase = "check-sanity";
7863cebe4a8SMatthew Dillon 		break;
7873cebe4a8SMatthew Dillon 	case PHASE_PKG_DEPENDS:
7883cebe4a8SMatthew Dillon 		phase = "pkg-depends";
7893cebe4a8SMatthew Dillon 		break;
7903cebe4a8SMatthew Dillon 	case PHASE_FETCH_DEPENDS:
7913cebe4a8SMatthew Dillon 		phase = "fetch-depends";
7923cebe4a8SMatthew Dillon 		break;
7933cebe4a8SMatthew Dillon 	case PHASE_FETCH:
7943cebe4a8SMatthew Dillon 		phase = "fetch";
7953cebe4a8SMatthew Dillon 		break;
7963cebe4a8SMatthew Dillon 	case PHASE_CHECKSUM:
7973cebe4a8SMatthew Dillon 		phase = "checksum";
7983cebe4a8SMatthew Dillon 		break;
7993cebe4a8SMatthew Dillon 	case PHASE_EXTRACT_DEPENDS:
8003cebe4a8SMatthew Dillon 		phase = "extract-depends";
8013cebe4a8SMatthew Dillon 		break;
8023cebe4a8SMatthew Dillon 	case PHASE_EXTRACT:
8033cebe4a8SMatthew Dillon 		phase = "extract";
8043cebe4a8SMatthew Dillon 		break;
8053cebe4a8SMatthew Dillon 	case PHASE_PATCH_DEPENDS:
8063cebe4a8SMatthew Dillon 		phase = "patch-depends";
8073cebe4a8SMatthew Dillon 		break;
8083cebe4a8SMatthew Dillon 	case PHASE_PATCH:
8093cebe4a8SMatthew Dillon 		phase = "patch";
8103cebe4a8SMatthew Dillon 		break;
8113cebe4a8SMatthew Dillon 	case PHASE_BUILD_DEPENDS:
8123cebe4a8SMatthew Dillon 		phase = "build-depends";
8133cebe4a8SMatthew Dillon 		break;
8143cebe4a8SMatthew Dillon 	case PHASE_LIB_DEPENDS:
8153cebe4a8SMatthew Dillon 		phase = "lib-depends";
8163cebe4a8SMatthew Dillon 		break;
8173cebe4a8SMatthew Dillon 	case PHASE_CONFIGURE:
8183cebe4a8SMatthew Dillon 		phase = "configure";
8193cebe4a8SMatthew Dillon 		break;
8203cebe4a8SMatthew Dillon 	case PHASE_BUILD:
8213cebe4a8SMatthew Dillon 		phase = "build";
8223cebe4a8SMatthew Dillon 		break;
8233cebe4a8SMatthew Dillon 	case PHASE_RUN_DEPENDS:
8243cebe4a8SMatthew Dillon 		phase = "run-depends";
8253cebe4a8SMatthew Dillon 		break;
8263cebe4a8SMatthew Dillon 	case PHASE_STAGE:
8273cebe4a8SMatthew Dillon 		phase = "stage";
8283cebe4a8SMatthew Dillon 		break;
8293cebe4a8SMatthew Dillon 	case PHASE_TEST:
8303cebe4a8SMatthew Dillon 		phase = "test";
8313cebe4a8SMatthew Dillon 		break;
8323cebe4a8SMatthew Dillon 	case PHASE_CHECK_PLIST:
8333cebe4a8SMatthew Dillon 		phase = "check-plist";
8343cebe4a8SMatthew Dillon 		break;
8353cebe4a8SMatthew Dillon 	case PHASE_PACKAGE:
8363cebe4a8SMatthew Dillon 		phase = "package";
8373cebe4a8SMatthew Dillon 		break;
8383cebe4a8SMatthew Dillon 	case PHASE_INSTALL:
8393cebe4a8SMatthew Dillon 		phase = "install";
8403cebe4a8SMatthew Dillon 		break;
8413cebe4a8SMatthew Dillon 	case PHASE_DEINSTALL:
8423cebe4a8SMatthew Dillon 		phase = "deinstall";
8433cebe4a8SMatthew Dillon 		break;
844569a9afdSAntonio Huete Jimenez 	case PHASE_DUMP_ENV:
845569a9afdSAntonio Huete Jimenez 		phase = "dump-env";
846569a9afdSAntonio Huete Jimenez 		break;
847569a9afdSAntonio Huete Jimenez 	case PHASE_DUMP_VAR:
848569a9afdSAntonio Huete Jimenez 		phase = "dump-var";
849569a9afdSAntonio Huete Jimenez 		break;
850569a9afdSAntonio Huete Jimenez 	case PHASE_SHOW_CONFIG:
851569a9afdSAntonio Huete Jimenez 		phase = "show-config";
852569a9afdSAntonio Huete Jimenez 		break;
853569a9afdSAntonio Huete Jimenez 	case PHASE_DUMP_MAKECONF:
854569a9afdSAntonio Huete Jimenez 		phase = "make-conf";
855569a9afdSAntonio Huete Jimenez 		break;
8563cebe4a8SMatthew Dillon 	default:
8573cebe4a8SMatthew Dillon 		phase = "Run-Unknown";
8583cebe4a8SMatthew Dillon 		break;
8593cebe4a8SMatthew Dillon 	}
8603cebe4a8SMatthew Dillon 	return phase;
8613cebe4a8SMatthew Dillon }
862aac7a6d9SMatthew Dillon 
863aac7a6d9SMatthew Dillon int
readlogline(monitorlog_t * log,char ** bufp)864aac7a6d9SMatthew Dillon readlogline(monitorlog_t *log, char **bufp)
865aac7a6d9SMatthew Dillon {
866aac7a6d9SMatthew Dillon 	int r;
867aac7a6d9SMatthew Dillon 	int n;
868aac7a6d9SMatthew Dillon 
869aac7a6d9SMatthew Dillon 	/*
870aac7a6d9SMatthew Dillon 	 * Reset buffer as an optimization to avoid unnecessary
871aac7a6d9SMatthew Dillon 	 * shifts.
872aac7a6d9SMatthew Dillon 	 */
873aac7a6d9SMatthew Dillon 	*bufp = NULL;
874aac7a6d9SMatthew Dillon 	if (log->buf_beg == log->buf_end) {
875aac7a6d9SMatthew Dillon 		log->buf_beg = 0;
876aac7a6d9SMatthew Dillon 		log->buf_end = 0;
877aac7a6d9SMatthew Dillon 		log->buf_scan = 0;
878aac7a6d9SMatthew Dillon 	}
879aac7a6d9SMatthew Dillon 
880aac7a6d9SMatthew Dillon 	/*
881aac7a6d9SMatthew Dillon 	 * Look for newline, handle discard mode
882aac7a6d9SMatthew Dillon 	 */
883aac7a6d9SMatthew Dillon again:
884aac7a6d9SMatthew Dillon 	for (n = log->buf_scan; n < log->buf_end; ++n) {
885aac7a6d9SMatthew Dillon 		if (log->buf[n] == '\n') {
886aac7a6d9SMatthew Dillon 			*bufp = log->buf + log->buf_beg;
887aac7a6d9SMatthew Dillon 			r = n - log->buf_beg;
888aac7a6d9SMatthew Dillon 			log->buf_beg = n + 1;
889aac7a6d9SMatthew Dillon 			log->buf_scan = n + 1;
890aac7a6d9SMatthew Dillon 
891aac7a6d9SMatthew Dillon 			if (log->buf_discard_mode == 0)
892aac7a6d9SMatthew Dillon 				return r;
893aac7a6d9SMatthew Dillon 			log->buf_discard_mode = 0;
894aac7a6d9SMatthew Dillon 			goto again;
895aac7a6d9SMatthew Dillon 		}
896aac7a6d9SMatthew Dillon 	}
897aac7a6d9SMatthew Dillon 
898aac7a6d9SMatthew Dillon 	/*
899aac7a6d9SMatthew Dillon 	 * Handle overflow
900aac7a6d9SMatthew Dillon 	 */
901aac7a6d9SMatthew Dillon 	if (n == sizeof(log->buf)) {
902aac7a6d9SMatthew Dillon 		if (log->buf_beg) {
903aac7a6d9SMatthew Dillon 			/*
904aac7a6d9SMatthew Dillon 			 * Shift the buffer to make room and read more data.
905aac7a6d9SMatthew Dillon 			 */
906aac7a6d9SMatthew Dillon 			bcopy(log->buf + log->buf_beg,
907aac7a6d9SMatthew Dillon 			      log->buf,
908aac7a6d9SMatthew Dillon 			      n - log->buf_beg);
909aac7a6d9SMatthew Dillon 			log->buf_end -= log->buf_beg;
910aac7a6d9SMatthew Dillon 			log->buf_scan -= log->buf_beg;
911aac7a6d9SMatthew Dillon 			n -= log->buf_beg;
912aac7a6d9SMatthew Dillon 			log->buf_beg = 0;
913aac7a6d9SMatthew Dillon 		} else if (log->buf_discard_mode) {
914aac7a6d9SMatthew Dillon 			/*
915aac7a6d9SMatthew Dillon 			 * Overflow.  If in discard mode just throw it all
916aac7a6d9SMatthew Dillon 			 * away.  Stay in discard mode.
917aac7a6d9SMatthew Dillon 			 */
918aac7a6d9SMatthew Dillon 			log->buf_beg = 0;
919aac7a6d9SMatthew Dillon 			log->buf_end = 0;
920aac7a6d9SMatthew Dillon 			log->buf_scan = 0;
921aac7a6d9SMatthew Dillon 		} else {
922aac7a6d9SMatthew Dillon 			/*
923aac7a6d9SMatthew Dillon 			 * Overflow.  If not in discard mode return a truncated
924aac7a6d9SMatthew Dillon 			 * line and enter discard mode.
925aac7a6d9SMatthew Dillon 			 *
926aac7a6d9SMatthew Dillon 			 * The caller will temporarily set ptr[r] = 0 so make
927aac7a6d9SMatthew Dillon 			 * sure that does not overflow our buffer as we are not
928aac7a6d9SMatthew Dillon 			 * at a newline.
929aac7a6d9SMatthew Dillon 			 *
930aac7a6d9SMatthew Dillon 			 * (log->buf_beg is 0);
931aac7a6d9SMatthew Dillon 			 */
932aac7a6d9SMatthew Dillon 			*bufp = log->buf + log->buf_beg;
933aac7a6d9SMatthew Dillon 			r = n - 1;
934aac7a6d9SMatthew Dillon 			log->buf_beg = n;
935aac7a6d9SMatthew Dillon 			log->buf_scan = n;
936aac7a6d9SMatthew Dillon 			log->buf_discard_mode = 1;
937aac7a6d9SMatthew Dillon 
938aac7a6d9SMatthew Dillon 			return r;
939aac7a6d9SMatthew Dillon 		}
940aac7a6d9SMatthew Dillon 	}
941aac7a6d9SMatthew Dillon 
942aac7a6d9SMatthew Dillon 	/*
943aac7a6d9SMatthew Dillon 	 * Read more data.  If there is no data pending then return -1,
944aac7a6d9SMatthew Dillon 	 * otherwise loop up to see if more complete line(s) are available.
945aac7a6d9SMatthew Dillon 	 */
946aac7a6d9SMatthew Dillon 	r = pread(log->fd,
947aac7a6d9SMatthew Dillon 		  log->buf + log->buf_end,
948aac7a6d9SMatthew Dillon 		  sizeof(log->buf) - log->buf_end,
949aac7a6d9SMatthew Dillon 		  log->offset);
950aac7a6d9SMatthew Dillon 	if (r <= 0)
951aac7a6d9SMatthew Dillon 		return -1;
952aac7a6d9SMatthew Dillon 	log->offset += r;
953aac7a6d9SMatthew Dillon 	log->buf_end += r;
954aac7a6d9SMatthew Dillon 	goto again;
955aac7a6d9SMatthew Dillon }
956b6bd007bSMatthew Dillon 
957b6bd007bSMatthew Dillon uint32_t
crcDirTree(const char * path)958b6bd007bSMatthew Dillon crcDirTree(const char *path)
959b6bd007bSMatthew Dillon {
960b6bd007bSMatthew Dillon 	FTS *fts;
961b6bd007bSMatthew Dillon 	FTSENT *fen;
962b6bd007bSMatthew Dillon 	struct stat *st;
963b6bd007bSMatthew Dillon 	char *pav[2];
964b6bd007bSMatthew Dillon 	uint32_t crc;
965b6bd007bSMatthew Dillon 	uint32_t val;
966b6bd007bSMatthew Dillon 
967b6bd007bSMatthew Dillon 	crc = 0;
968b6bd007bSMatthew Dillon 	pav[0] = strdup(path);
969b6bd007bSMatthew Dillon 	pav[1] = NULL;
970b6bd007bSMatthew Dillon 
971b6bd007bSMatthew Dillon 	fts = fts_open(pav, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
972b6bd007bSMatthew Dillon 	if (fts == NULL)
973b6bd007bSMatthew Dillon 		goto failed;
974b6bd007bSMatthew Dillon 	while ((fen = fts_read(fts)) != NULL) {
975b6bd007bSMatthew Dillon 		if (fen->fts_info != FTS_F && fen->fts_info != FTS_SL)
976b6bd007bSMatthew Dillon 			continue;
977e42d129cSzrj 		/*
978e42d129cSzrj 		 * Ignore hidden dot files or ones ending with .core from the
979e42d129cSzrj 		 * calculated CRC sum to prevent unnecessary rebuilds.
980e42d129cSzrj 		 */
981e42d129cSzrj 		if (fen->fts_name[0] == '.')
982e42d129cSzrj 			continue;
983b6bd007bSMatthew Dillon 		if (fen->fts_namelen >= 5 &&
984b6bd007bSMatthew Dillon 		    !strcmp(fen->fts_name + fen->fts_namelen - 5, ".core")) {
985b6bd007bSMatthew Dillon 			continue;
986b6bd007bSMatthew Dillon 		}
987b6bd007bSMatthew Dillon 
988b6bd007bSMatthew Dillon 		st = fen->fts_statp;
989b6bd007bSMatthew Dillon 
990b6bd007bSMatthew Dillon 		val = iscsi_crc32(&st->st_mtime, sizeof(st->st_mtime));
991b6bd007bSMatthew Dillon 		val = iscsi_crc32_ext(&st->st_size, sizeof(st->st_size), val);
992b6bd007bSMatthew Dillon 		val = iscsi_crc32_ext(fen->fts_path, fen->fts_pathlen, val);
993b6bd007bSMatthew Dillon 		crc ^= val;
994b6bd007bSMatthew Dillon 	}
995b6bd007bSMatthew Dillon 	fts_close(fts);
996b6bd007bSMatthew Dillon failed:
997b6bd007bSMatthew Dillon 	free(pav[0]);
998b6bd007bSMatthew Dillon 
999b6bd007bSMatthew Dillon 	return crc;
1000b6bd007bSMatthew Dillon }
10012b3f93eaSMatthew Dillon 
10022b3f93eaSMatthew Dillon void
set_capability_restrictions(void)10032b3f93eaSMatthew Dillon set_capability_restrictions(void)
10042b3f93eaSMatthew Dillon {
10052b3f93eaSMatthew Dillon 	if (CapabilityRestrictions) {
1006*a361ab31SMatthew Dillon #if !defined(SYSCAP_UNAVAILABLE)
10072b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_RESTRICTEDROOT, __SYSCAP_ALL,
10082b3f93eaSMatthew Dillon 			   NULL, 0);
10092b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_SENSITIVEROOT, __SYSCAP_ALL,
10102b3f93eaSMatthew Dillon 			   NULL, 0);
10112b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_NONET_SENSITIVE, __SYSCAP_ALL,
10122b3f93eaSMatthew Dillon 			   NULL, 0);
10132b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_NOVFS_SENSITIVE, __SYSCAP_ALL,
10142b3f93eaSMatthew Dillon 			   NULL, 0);
10152b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_NOMOUNT, __SYSCAP_ALL,
10162b3f93eaSMatthew Dillon 			   NULL, 0);
10172b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_NOJAIL, __SYSCAP_ALL,
10182b3f93eaSMatthew Dillon 			   NULL, 0);
10192b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_NONET_RESPORT, __SYSCAP_ALL,
10202b3f93eaSMatthew Dillon 			   NULL, 0);
10212b3f93eaSMatthew Dillon 		syscap_set(SYSCAP_NONET_RAW, __SYSCAP_ALL,
10222b3f93eaSMatthew Dillon 			   NULL, 0);
1023*a361ab31SMatthew Dillon #endif
10242b3f93eaSMatthew Dillon 	}
10252b3f93eaSMatthew Dillon }
1026