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