diff --git a/doc/Changelog b/doc/Changelog index ae7d1d4..da706af 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,40 @@ +sysvinit (2.94) unreleased; urgency=low + + [ Jesse Smith ] + + * When the halt command is called with the -p flag (or as poweroff) + the command now passes the "-h -P" flags to shutdown. This + in turn sets the INIT_HALT environment variable to POWEROFF. + Assuming this value is checked by initscripts during the + shutting down procedure, it should cause the system to + be powered off. + If halt is called without -p then the value of INIT_HALT + is not set and the default action (often set in /etc/defaut/halt) + is taken. + * Removed unnecessary malloc.h includes. Memory allocation + and freeing is now handled in stdlib.h + * Added defines for FreeBSD to make some components compile + on FreeBSD 11. + * Increased the size of the kernel command line buffer in bootlogd + from 256 characters to 4096. This size is defined in KERNEL_COMMAND_LENGTH + for easy modification downstream. + * Added logsave.c and logsave.8 manual page from e2fsprogs to make + sure logsave is available to initscripts. + * Updated src/Makefile to make sure bootlogd compiles with Clang. + * Use defined constants for password length in sulogin. Makes + it easier to update/patch later. + * Minor code fixes across multiple source files to avoid buffer + overflows, or uninitialized strings. + * Changed the way the "when" variable is used internally in shutdown.c. + It starts as a NULL pointer, then might get set as a pointer to optarg, + then it might get set to point to an argv parameter, then it might have + a string value copied into it, over-writing the original data. We should + not risk over-writing internal variables which might get used for something + else (it's rude and security risk). Set up "when" as its own buffer + that has data from optargs and/or argv copied into it. + * Fixed typo in init.8 manual page. + + sysvinit (2.93) released; urgency=low [ Jesse Smith ] @@ -5,6 +42,10 @@ sysvinit (2.93) released; urgency=low * Fixed typo in pidof which would prevent the -o (omit PID) flag from working. Fixes Debian bug ##913394. + * Fixed error where pidof would not omit checking PIDs passed + to it when the -o flag was used. + Fixes Debian bug #913394. + sysvinit (2.92) released; urgency=low diff --git a/man/init.8 b/man/init.8 index cbfbf07..594784b 100644 --- a/man/init.8 +++ b/man/init.8 @@ -276,7 +276,7 @@ On receipt of this signals, init closes and re-opens its control fifo, .TP 0.5i .B SIGUSR2 When init receives SIGUSR2, init closes and leaves the control fifo, -\fB/run/initctl\f\P, closed. This may be used to make sure init is not +\fB/run/initctl\fP, closed. This may be used to make sure init is not holding open any files. However, it also prevents init from switching runlevels. Which means commands like shutdown no longer work. The fifo can be re-opened by sending init the SIGUSR1 signal. diff --git a/man/logsave.8 b/man/logsave.8 new file mode 100644 index 0000000..cc3ffde --- /dev/null +++ b/man/logsave.8 @@ -0,0 +1,61 @@ +.\" -*- nroff -*- +.\" Copyright 2003 by Theodore Ts'o. All Rights Reserved. +.\" This file may be copied under the terms of the GNU Public License. +.\" +.TH LOGSAVE 8 "@E2FSPROGS_MONTH@ @E2FSPROGS_YEAR@" "E2fsprogs version @E2FSPROGS_VERSION@" +.SH NAME +logsave \- save the output of a command in a logfile +.SH SYNOPSIS +.B logsave +[ +.B \-asv +] +.I logfile cmd_prog [ ... ] +.SH DESCRIPTION +The +.B logsave +program will execute +.I cmd_prog +with the specified argument(s), and save a copy of its output to +.IR logfile . +If the containing directory for +.I logfile +does not exist, +.B logsave +will accumulate the output in memory until it can be written out. +A copy of the output will also be written to standard output. +.PP +If +.I cmd_prog +is a single hyphen ('-'), then instead of executing a program, +.B logsave +will take its input from standard input and save it in +.I logfile +.PP +.B logsave +is useful for saving the output of initial boot scripts +until the /var partition is mounted, so the output can be written to +/var/log. +.SH OPTIONS +.TP +.B \-a +This option will cause the output to be appended to +.IR logfile , +instead of replacing its current contents. +.TP +.B \-s +This option will cause +.B logsave +to skip writing to the log file text which is bracketed with a control-A +(ASCII 001 or Start of Header) and control-B (ASCII 002 or Start of +Text). This allows progress bar information to be visible to the user +on the console, while not being written to the log file. +.TP +.B \-v +This option will make +.B logsave +to be more verbose in its output to the user. +.SH AUTHOR +Theodore Ts'o (tytso@mit.edu) +.SH SEE ALSO +.BR fsck (8) diff --git a/src/Makefile b/src/Makefile index 3c93783..e54c051 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,13 +23,13 @@ MNTPOINT= # For some known distributions we do not build all programs, otherwise we do. BIN = -SBIN = init halt shutdown runlevel killall5 fstab-decode +SBIN = init halt shutdown runlevel killall5 fstab-decode logsave USRBIN = last mesg readbootlog MAN1 = last.1 lastb.1 mesg.1 readbootlog.1 MAN5 = initscript.5 inittab.5 initctl.5 MAN8 = halt.8 init.8 killall5.8 pidof.8 poweroff.8 reboot.8 runlevel.8 -MAN8 += shutdown.8 telinit.8 fstab-decode.8 +MAN8 += shutdown.8 telinit.8 fstab-decode.8 logsave.8 ifeq ($(DISTRO),) SBIN += sulogin bootlogd @@ -115,6 +115,9 @@ halt: halt.o ifdown.o hddown.o utmp.o runlevellog.o last: LDLIBS += $(STATIC) last: last.o +logsave: LDLIBS += $(STATIC) +logsave: logsave.o + mesg: LDLIBS += $(STATIC) mesg: mesg.o @@ -137,10 +140,10 @@ shutdown: LDLIBS += $(STATIC) shutdown: dowall.o shutdown.o utmp.o bootlogd: LDLIBS += -lutil $(STATIC) -bootlogd: bootlogd.o bootlogd.h +bootlogd: bootlogd.o readbootlog: LDLIBS += $(STATIC) -readbootlog: readbootlog.o bootlogd.h +readbootlog: readbootlog.o fstab-decode: LDLIBS += $(STATIC) fstab-decode: fstab-decode.o @@ -151,7 +154,7 @@ sulogin.o: sulogin.c runlevellog.o: runlevellog.h runlevellog.c paths.h init.o: CPPFLAGS += $(SELINUX_DEF) -init.o: init.c init.h initreq.h paths.h reboot.h runlevellog.h runlevellog.c set.h paths.h +init.o: init.c init.h initreq.h paths.h reboot.h runlevellog.h runlevellog.c set.h utmp.o: @@ -159,6 +162,10 @@ init_utmp.o: CPPFLAGS += -DINIT_MAIN init_utmp.o: utmp.c init.h initreq.h paths.h $(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< +bootlogd.o: bootlogd.c bootlogd.h + +readbootlog.o: readbootlog.c + utmpdump.o: utmpdump.c oldutmp.h shutdown.o: shutdown.c paths.h reboot.h initreq.h init.h @@ -167,6 +174,8 @@ halt.o: halt.c reboot.h paths.h runlevellog.c runlevellog.h last.o: last.c oldutmp.h +logsave.o: logsave.c + consoles.o: consoles.c consoles.h cleanobjs: diff --git a/src/bootlogd.c b/src/bootlogd.c index c8c06d6..f046a01 100644 --- a/src/bootlogd.c +++ b/src/bootlogd.c @@ -24,12 +24,6 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * *NOTE* *NOTE* *NOTE* - * This is a PROOF OF CONCEPT IMPLEMENTATION - * - * I have bigger plans for Debian, but for now - * this has to do ;) - * */ #include @@ -40,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -48,7 +41,15 @@ #include #include #include +#ifdef __linux__ #include +#endif + +#ifdef __FreeBSD__ +#include +#include +#endif + #include #ifdef __linux__ #include @@ -56,6 +57,7 @@ #include "bootlogd.h" #define MAX_CONSOLES 16 +#define KERNEL_COMMAND_LENGTH 4096 char ringbuf[32768]; char *endptr = ringbuf + sizeof(ringbuf); @@ -250,7 +252,7 @@ int consolenames(struct real_cons *cons, int max_consoles) /* This appears to be unused. unsigned int kdev; */ #endif struct stat st, st2; - char buf[256]; + char buf[KERNEL_COMMAND_LENGTH]; char *p; int didmount = 0; int n; @@ -279,17 +281,14 @@ int consolenames(struct real_cons *cons, int max_consoles) perror("bootlogd: /proc/cmdline"); } else { buf[0] = 0; - if ((n = read(fd, buf, sizeof(buf) - 1)) < 0) + if ((n = read(fd, buf, KERNEL_COMMAND_LENGTH - 1)) < 0) perror("bootlogd: /proc/cmdline"); close(fd); } if (didmount) umount("/proc"); - if (n < 0) return 0; - - /* * OK, so find console= in /proc/cmdline. * Parse in reverse, opening as we go. diff --git a/src/halt.c b/src/halt.c index 98bdadf..a469147 100644 --- a/src/halt.c +++ b/src/halt.c @@ -155,13 +155,15 @@ int get_runlevel(void) /* * Switch to another runlevel. */ -void do_shutdown(char *fl, char *tm) +void do_shutdown(char *fl, int should_poweroff, char *tm) { - char *args[8]; + char *args[9]; int i = 0; args[i++] = "shutdown"; args[i++] = fl; + if ( (! strcmp(fl, "-h") ) && (should_poweroff) ) + args[i++] = "-P"; if (tm) { args[i++] = "-t"; args[i++] = tm; @@ -259,7 +261,7 @@ int main(int argc, char **argv) */ c = get_runlevel(); if (c != '0' && c != '6') - do_shutdown(do_reboot ? "-r" : "-h", tm); + do_shutdown(do_reboot ? "-r" : "-h", do_poweroff, tm); } /* diff --git a/src/init.c b/src/init.c index 0a56111..4369beb 100644 --- a/src/init.c +++ b/src/init.c @@ -13,11 +13,12 @@ Version information is not placed in the top-level Makefile by default */ #ifndef VERSION -#define VERSION "2.91" +#define VERSION "2.94" #endif /* * This file is part of the sysvinit suite, * Copyright (C) 1991-2004 Miquel van Smoorenburg. + * Copyright (C) 2017-2019 Jesse Smith * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -52,7 +53,11 @@ Version information is not placed in the top-level Makefile by default #include #include #include +#ifdef __FreeBSD__ +#include +#else #include +#endif #include #include #include @@ -62,6 +67,9 @@ Version information is not placed in the top-level Makefile by default #ifdef WITH_SELINUX # include #endif +#ifdef __FreeBSD__ +extern char **environ; +#endif #ifdef __i386__ # ifdef __GLIBC__ @@ -133,7 +141,7 @@ int wrote_wtmp_reboot = 1; /* Set when we wrote the reboot record */ int wrote_utmp_reboot = 1; /* Set when we wrote the reboot record */ int wrote_wtmp_rlevel = 1; /* Set when we wrote the runlevel record */ int wrote_utmp_rlevel = 1; /* Set when we wrote the runlevel record */ -int sltime = WAIT_BETWEEN_SIGNALS; /* Sleep time between TERM and KILL */ +int sleep_time = WAIT_BETWEEN_SIGNALS; /* Sleep time between TERM and KILL */ char *argv0; /* First arguments; show up in ps listing */ int maxproclen; /* Maximal length of argv[0] with \0 */ struct utmp utproto; /* Only used for sizeof(utproto.ut_id) */ @@ -144,7 +152,7 @@ int main(int, char **); /* Used by re-exec part */ int reload = 0; /* Should we do initialization stuff? */ -char *myname="/sbin/init"; /* What should we exec */ +char *myname=INIT; /* What should we exec */ int oops_error; /* Used by some of the re-exec code. */ const char *Signature = "12567362"; /* Signature for re-exec fd */ @@ -288,7 +296,7 @@ void send_state(int fd) fprintf(fp, "-SI%u\n", got_signals); fprintf(fp, "-WR%d\n", wrote_wtmp_reboot); fprintf(fp, "-WU%d\n", wrote_utmp_reboot); - fprintf(fp, "-ST%d\n", sltime); + fprintf(fp, "-ST%d\n", sleep_time); fprintf(fp, "-DB%d\n", did_boot); for (p = family; p; p = p->next) { @@ -416,7 +424,7 @@ static CHILD *get_record(FILE *f) } break; case D_SLTIME: - if (fscanf(f, "%d\n", &sltime) == EOF && errno != 0) { + if (fscanf(f, "%d\n", &sleep_time) == EOF && errno != 0) { fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, strerror(errno)); } break; @@ -521,8 +529,12 @@ int receive_state(int fd) * Set the process title. */ #ifdef __GNUC__ +#ifndef __FreeBSD__ __attribute__ ((format (printf, 1, 2))) #endif +#endif +/* This function already exists on FreeBSD. No need to delcare it. */ +#ifndef __FreeBSD__ static int setproctitle(char *fmt, ...) { va_list ap; @@ -542,6 +554,7 @@ static int setproctitle(char *fmt, ...) return len; } +#endif /* * Set console_dev to a working console. @@ -1705,7 +1718,7 @@ void read_inittab(void) /* * Yup, but check every second if we still have children. */ - for(f = 0; f < sltime; f++) { + for(f = 0; f < sleep_time; f++) { for(ch = family; ch; ch = ch->next) { if (!(ch->flags & KILLME)) continue; if ((ch->flags & RUNNING) && !(ch->flags & ZOMBIE)) @@ -1959,7 +1972,7 @@ int read_level(int arg) foo = arg; ok = 1; } - if (ok == 2) sltime = st; + if (ok == 2) sleep_time = st; #endif /* INITLVL */ @@ -2160,9 +2173,11 @@ int make_pipe(int fd) /* * Attempt to re-exec. + * Renaming to my_re_exec since re_exec is now a common function name + * which conflicts. */ static -void re_exec(void) +void my_re_exec(void) { CHILD *ch; sigset_t mask, oldset; @@ -2279,7 +2294,7 @@ void fifo_new_level(int level) runlevel = read_level(level); if (runlevel == 'U') { runlevel = oldlevel; - re_exec(); + my_re_exec(); } else { if (oldlevel != 'S' && runlevel == 'S') console_stty(); if (runlevel == '6' || runlevel == '0' || @@ -2460,22 +2475,22 @@ void check_init_fifo(void) } switch(request.cmd) { case INIT_CMD_RUNLVL: - sltime = request.sleeptime; + sleep_time = request.sleeptime; fifo_new_level(request.runlevel); quit = 1; break; case INIT_CMD_POWERFAIL: - sltime = request.sleeptime; + sleep_time = request.sleeptime; do_power_fail('F'); quit = 1; break; case INIT_CMD_POWERFAILNOW: - sltime = request.sleeptime; + sleep_time = request.sleeptime; do_power_fail('L'); quit = 1; break; case INIT_CMD_POWEROK: - sltime = request.sleeptime; + sleep_time = request.sleeptime; do_power_fail('O'); quit = 1; break; @@ -2681,7 +2696,7 @@ void process_signals() #endif if (runlevel == 'U') { runlevel = oldlevel; - re_exec(); + my_re_exec(); } else { if (oldlevel != 'S' && runlevel == 'S') console_stty(); if (runlevel == '6' || runlevel == '0' || @@ -2902,7 +2917,7 @@ int telinit(char *progname, int argc, char **argv) while ((f = getopt(argc, argv, "t:e:")) != EOF) switch(f) { case 't': - sltime = atoi(optarg); + sleep_time = atoi(optarg); break; case 'e': if (env == NULL) @@ -2935,7 +2950,7 @@ int telinit(char *progname, int argc, char **argv) usage(progname); request.cmd = INIT_CMD_RUNLVL; request.runlevel = argv[optind][0]; - request.sleeptime = sltime; + request.sleeptime = sleep_time; } /* Change to the root directory. */ @@ -2977,7 +2992,7 @@ int telinit(char *progname, int argc, char **argv) progname, INITLVL); exit(1); } - fprintf(fp, "%s %d", argv[optind], sltime); + fprintf(fp, "%s %d", argv[optind], sleep_time); fclose(fp); /* And tell init about the pending runlevel change. */ diff --git a/src/init.h b/src/init.h index 7a35706..1b70d6d 100644 --- a/src/init.h +++ b/src/init.h @@ -154,3 +154,12 @@ extern char prevlevel; #define D_WROTE_WTMP_RLEVEL -16 #define D_WROTE_UTMP_RLEVEL -17 +#ifdef __FreeBSD__ +#define UTMP_FILE "/var/run/utmp" +#define RUN_LVL 1 +struct utmp +{ + char ut_id[4]; +}; +#endif + diff --git a/src/killall5.c b/src/killall5.c index 25b333e..8f2ad50 100644 --- a/src/killall5.c +++ b/src/killall5.c @@ -58,8 +58,6 @@ #include #include -char *Version = "@(#)killall5 2.86 31-Jul-2004 miquels@cistron.nl"; - #ifndef PATH_MAX # ifdef MAXPATHLEN # define PATH_MAX MAXPATHLEN @@ -435,7 +433,11 @@ int check4nfs(const char * path, char * real) } while (1); - if (real) strcpy(real, curr); + if (real) /* real is defined elsewhere as being PATH_MAX + 1 */ + { + memset(real, '\0', PATH_MAX + 1); + strncpy(real, curr, PATH_MAX); + } if (errno == EINVAL) { const size_t nlen = strlen(curr); diff --git a/src/last.c b/src/last.c index 9c15b39..1c028cc 100644 --- a/src/last.c +++ b/src/last.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -49,6 +48,10 @@ # define SHUTDOWN_TIME 254 #endif +#ifndef PATH_MAX +#define PATH_MAX 2048 +#endif + char *Version = "@(#) last 2.85 31-Apr-2004 miquels"; #define CHOP_DOMAIN 0 /* Define to chop off local domainname. */ @@ -254,10 +257,11 @@ int uread(FILE *fp, struct utmp *u, int *quit) #define BTMP_FILE getbtmp() char *getbtmp() { - static char btmp[128]; + static char btmp[PATH_MAX + 5]; /* max path + btmp + null terminator */ char *p; - strcpy(btmp, WTMP_FILE); + memset(btmp, '\0', PATH_MAX + 5); + strncpy(btmp, WTMP_FILE, PATH_MAX); if ((p = strrchr(btmp, '/')) == NULL) p = btmp; else @@ -842,7 +846,7 @@ int main(int argc, char **argv) switch (ut.ut_type) { case SHUTDOWN_TIME: if (extended) { - strcpy(ut.ut_line, "system down"); + strncpy(ut.ut_line, "system down", OLD_LINESIZE - 1); quit = list(&ut, lastboot, R_NORMAL); } lastdown = lastrch = ut.ut_time; @@ -851,14 +855,14 @@ int main(int argc, char **argv) case OLD_TIME: case NEW_TIME: if (extended) { - strcpy(ut.ut_line, + strncpy(ut.ut_line, ut.ut_type == NEW_TIME ? "new time" : - "old time"); + "old time", OLD_LINESIZE - 1); quit = list(&ut, lastdown, R_TIMECHANGE); } break; case BOOT_TIME: - strcpy(ut.ut_line, "system boot"); + strncpy(ut.ut_line, "system boot", OLD_LINESIZE - 1); quit = list(&ut, lastdown, R_REBOOT); lastboot = ut.ut_time; down = 1; diff --git a/src/logsave.c b/src/logsave.c new file mode 100644 index 0000000..1c52245 --- /dev/null +++ b/src/logsave.c @@ -0,0 +1,338 @@ +/* + * logsave.c --- A program which saves the output of a program until + * /var/log is mounted. + * + * Copyright (C) 2003 Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#ifndef _XOPEN_SOURCE +#define _XOPEN_SOURCE 600 /* for inclusion of sa_handler in Solaris */ +#endif +#ifndef HAVE_SIGNAL_H +#define HAVE_SIGNAL_H +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SIGNAL_H +#include +#endif +#ifdef HAVE_GETOPT_H +#include +#else +extern char *optarg; +extern int optind; +#endif + +static int outfd = -1; +static int outbufsize = 0; +static void *outbuf = 0; +static int verbose = 0; +static int do_skip = 0; +static int skip_mode = 0; +static pid_t child_pid = -1; + +static void usage(char *progname) +{ + printf("Usage: %s [-asv] logfile program\n", progname); + exit(1); +} + +#define SEND_LOG 0x01 +#define SEND_CONSOLE 0x02 +#define SEND_BOTH 0x03 + +/* + * Helper function that does the right thing if write returns a + * partial write, or an EAGAIN/EINTR error. + */ +static int write_all(int fd, const char *buf, size_t count) +{ + ssize_t ret; + int c = 0; + + while (count > 0) { + ret = write(fd, buf, count); + if (ret < 0) { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + return -1; + } + count -= ret; + buf += ret; + c += ret; + } + return c; +} + +static void send_output(const char *buffer, int c, int flag) +{ + const char *cp; + char *n; + int cnt, d, del; + + if (c == 0) + c = strlen(buffer); + + if (flag & SEND_CONSOLE) { + cnt = c; + cp = buffer; + while (cnt) { + del = 0; + for (d=0; d < cnt; d++) { + if (skip_mode && + (cp[d] == '\001' || cp[d] == '\002')) { + del = 1; + break; + } + } + write_all(1, cp, d); + if (del) + d++; + cnt -= d; + cp += d; + } + } + if (!(flag & SEND_LOG)) + return; + if (outfd > 0) + write_all(outfd, buffer, c); + else { + n = realloc(outbuf, outbufsize + c); + if (n) { + outbuf = n; + memcpy(((char *)outbuf)+outbufsize, buffer, c); + outbufsize += c; + } + } +} + +static int do_read(int fd) +{ + int c; + char buffer[4096], *cp, *sep; + + c = read(fd, buffer, sizeof(buffer)-1); + if (c <= 0) + return c; + if (do_skip) { + send_output(buffer, c, SEND_CONSOLE); + buffer[c] = 0; + cp = buffer; + while (*cp) { + if (skip_mode) { + cp = strchr(cp, '\002'); + if (!cp) + return 0; + cp++; + skip_mode = 0; + continue; + } + sep = strchr(cp, '\001'); + if (sep) + *sep = 0; + send_output(cp, 0, SEND_LOG); + if (sep) { + cp = sep + 1; + skip_mode = 1; + } else + break; + } + } else + send_output(buffer, c, SEND_BOTH); + return c; +} + +static void signal_term(int sig) +{ + if (child_pid > 0) + kill(child_pid, sig); +} + +static int run_program(char **argv) +{ + int fds[2]; + int status, rc, pid; + char buffer[80]; +#ifdef HAVE_SIGNAL_H + struct sigaction sa; +#endif + + if (pipe(fds) < 0) { + perror("pipe"); + exit(1); + } + +#ifdef HAVE_SIGNAL_H + memset(&sa, 0, sizeof(struct sigaction)); + sa.sa_handler = signal_term; + sigaction(SIGINT, &sa, 0); + sigaction(SIGTERM, &sa, 0); +#ifdef SA_RESTART + sa.sa_flags = SA_RESTART; +#endif +#endif + + pid = fork(); + if (pid < 0) { + perror("vfork"); + exit(1); + } + if (pid == 0) { + dup2(fds[1],1); /* fds[1] replaces stdout */ + dup2(fds[1],2); /* fds[1] replaces stderr */ + close(fds[0]); /* don't need this here */ + close(fds[1]); + + execvp(argv[0], argv); + perror(argv[0]); + exit(1); + } + child_pid = pid; + close(fds[1]); + + while (!(waitpid(pid, &status, WNOHANG ))) { + do_read(fds[0]); + } + child_pid = -1; + do_read(fds[0]); + close(fds[0]); + + if ( WIFEXITED(status) ) { + rc = WEXITSTATUS(status); + if (rc) { + send_output(argv[0], 0, SEND_BOTH); + sprintf(buffer, " exited with status code %d\n", rc); + send_output(buffer, 0, SEND_BOTH); + } + } else { + if (WIFSIGNALED(status)) { + send_output(argv[0], 0, SEND_BOTH); + sprintf(buffer, "died with signal %d\n", + WTERMSIG(status)); + send_output(buffer, 0, SEND_BOTH); + return 1; + } + rc = 0; + } + return rc; +} + +static int copy_from_stdin(void) +{ + int c, bad_read = 0; + + while (1) { + c = do_read(0); + if ((c == 0 ) || + ((c < 0) && ((errno == EAGAIN) || (errno == EINTR)))) { + if (bad_read++ > 3) + break; + continue; + } + if (c < 0) { + perror("read"); + exit(1); + } + bad_read = 0; + } + return 0; +} + + + +int main(int argc, char **argv) +{ + int c, pid, rc; + char *outfn, **cpp; + int openflags = O_CREAT|O_WRONLY|O_TRUNC; + int send_flag = SEND_LOG; + int do_stdin; + time_t t; + + while ((c = getopt(argc, argv, "+asv")) != EOF) { + switch (c) { + case 'a': + openflags &= ~O_TRUNC; + openflags |= O_APPEND; + break; + case 's': + do_skip = 1; + break; + case 'v': + verbose++; + send_flag |= SEND_CONSOLE; + break; + } + } + if (optind == argc || optind+1 == argc) + usage(argv[0]); + outfn = argv[optind]; + optind++; + argv += optind; + /* argc -= optind; - this is not used */ + + outfd = open(outfn, openflags, 0644); + do_stdin = !strcmp(argv[0], "-"); + + send_output("Log of ", 0, send_flag); + if (do_stdin) + send_output("stdin", 0, send_flag); + else { + for (cpp = argv; *cpp; cpp++) { + send_output(*cpp, 0, send_flag); + send_output(" ", 0, send_flag); + } + } + send_output("\n", 0, send_flag); + t = time(0); + send_output(ctime(&t), 0, send_flag); + send_output("\n", 0, send_flag); + + if (do_stdin) + rc = copy_from_stdin(); + else + rc = run_program(argv); + + send_output("\n", 0, send_flag); + t = time(0); + send_output(ctime(&t), 0, send_flag); + send_output("----------------\n", 0, send_flag); + + if (outbuf) { + pid = fork(); + if (pid < 0) { + perror("fork"); + exit(1); + } + if (pid) { + if (verbose) + printf("Backgrounding to save %s later\n", + outfn); + exit(rc); + } + setsid(); /* To avoid getting killed by init */ + while (outfd < 0) { + outfd = open(outfn, openflags, 0644); + sleep(1); + } + write_all(outfd, outbuf, outbufsize); + free(outbuf); + } + if (outfd >= 0) + close(outfd); + + exit(rc); +} diff --git a/src/mountpoint.c b/src/mountpoint.c index 3daf470..b24335e 100644 --- a/src/mountpoint.c +++ b/src/mountpoint.c @@ -32,6 +32,10 @@ #include #include +#ifndef PATH_MAX +#define PATH_MAX 2048 +#endif + int dostat(char *path, struct stat *st, int do_lstat, int quiet) { int n; @@ -105,7 +109,7 @@ void usage(void) { int main(int argc, char **argv) { struct stat st, st2; - char buf[256]; + char buf[PATH_MAX + 1]; char *path; int quiet = 0; int showdev = 0; @@ -163,7 +167,7 @@ int main(int argc, char **argv) memset(buf, 0, sizeof(buf)); strncpy(buf, path, sizeof(buf) - 4); - strcat(buf, "/.."); + strncat(buf, "/..", 3); if (dostat(buf, &st2, 0, quiet) < 0) return 1; diff --git a/src/shutdown.c b/src/shutdown.c index 91a4097..b744a2c 100644 --- a/src/shutdown.c +++ b/src/shutdown.c @@ -54,15 +54,24 @@ #include #include #include +#ifdef __FreeBSD__ +#include +#else #include +#endif #include #include "paths.h" #include "reboot.h" #include "initreq.h" #include "init.h" +#ifdef __FreeBSD__ +extern char **environ; +#endif #define MESSAGELEN 256 +#define STATELEN 64 +#define WHEN_SIZE 64 /* Whether we should warn system is shutting down */ #define QUIET_FULL 2 @@ -76,7 +85,7 @@ int fastboot = 0; /* Do a 'fast' reboot */ int forcefsck = 0; /* Force fsck on reboot */ char message[MESSAGELEN]; /* Warning message */ char *sltime = 0; /* Sleep time */ -char newstate[64]; /* What are we gonna do */ +char newstate[STATELEN]; /* What are we gonna do */ int doself = 0; /* Don't use init */ int got_alrm = 0; @@ -225,11 +234,11 @@ int init_setenv(char *name, char *value) */ void issue_warn(int mins) { - char buf[MESSAGELEN + sizeof(newstate)]; + char buf[MESSAGELEN + sizeof(newstate) + 1]; int len; buf[0] = 0; - strncat(buf, message, sizeof(buf) - 1); + strncpy(buf, message, MESSAGELEN); len = strlen(buf); if (mins == 0) @@ -512,7 +521,7 @@ int main(int argc, char **argv) char buf[128]; char term[UT_LINESIZE + 6]; char *sp; - char *when = NULL; + char when[WHEN_SIZE]; int c, i, wt; int hours, mins; int didnolog = 0; @@ -540,6 +549,7 @@ int main(int argc, char **argv) } strcpy(down_level, "1"); halttype = NULL; + memset(when, '\0', WHEN_SIZE); /* Process the options. */ while((c = getopt(argc, argv, "HPacqQkrhnfFyt:g:i:")) != EOF) { @@ -586,7 +596,7 @@ int main(int argc, char **argv) case 'y': /* Ignored for sysV compatibility */ break; case 'g': /* sysv style to specify time. */ - when = optarg; + strncpy(when, optarg, WHEN_SIZE - 1); break; case 'i': /* Level to go to. */ if (!strchr("0156aAbBcCsS", optarg[0])) { @@ -672,7 +682,7 @@ int main(int argc, char **argv) /* Read remaining words, skip time if needed. */ message[0] = 0; - for(c = optind + (!cancel && !when); c < argc; c++) { + for(c = optind + (!cancel && !when[0]); c < argc; c++) { if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN) break; strcat(message, argv[c]); @@ -697,9 +707,9 @@ int main(int argc, char **argv) } /* Check syntax. */ - if (when == NULL) { + if (when[0] == '\0') { if (optind == argc) usage(); - when = argv[optind++]; + strncpy(when, argv[optind++], WHEN_SIZE - 1); } /* See if we are already running. */ @@ -718,16 +728,16 @@ int main(int argc, char **argv) /* Tell users what we're gonna do. */ switch(down_level[0]) { case '0': - strcpy(newstate, "for system halt"); + strncpy(newstate, "for system halt", STATELEN); break; case '6': - strcpy(newstate, "for reboot"); + strncpy(newstate, "for reboot", STATELEN); break; case '1': - strcpy(newstate, "to maintenance mode"); + strncpy(newstate, "to maintenance mode", STATELEN); break; default: - sprintf(newstate, "to runlevel %s", down_level); + snprintf(newstate, STATELEN, "to runlevel %s", down_level); break; } @@ -765,10 +775,11 @@ int main(int argc, char **argv) /* Alias now and take care of old '+mins' notation. */ if (!strcmp(when, "now")) strcpy(when, "0"); - if (when[0] == '+') when++; + sp = when; + if (when[0] == '+') sp++; /* Decode shutdown time. */ - for (sp = when; *sp; sp++) { + for ( ; *sp; sp++) { if (*sp != ':' && (*sp < '0' || *sp > '9')) usage(); } diff --git a/src/sulogin.c b/src/sulogin.c index 612f7e7..4200f8e 100644 --- a/src/sulogin.c +++ b/src/sulogin.c @@ -72,6 +72,8 @@ # include #endif +#define PASSWORD_LENGTH 256 + #include "consoles.h" #define CONMAX 16 @@ -418,8 +420,8 @@ struct passwd *getrootpwent(int try_manually) struct passwd *pw; struct spwd *spw; FILE *fp; - static char line[256]; - static char sline[256]; + static char line[PASSWORD_LENGTH]; + static char sline[PASSWORD_LENGTH]; char *p; /* @@ -453,7 +455,7 @@ struct passwd *getrootpwent(int try_manually) /* * Find root in the password file. */ - while((p = fgets(line, 256, fp)) != NULL) { + while((p = fgets(line, PASSWORD_LENGTH, fp)) != NULL) { if (strncmp(line, "root:", 5) != 0) continue; p += 5; @@ -487,7 +489,7 @@ struct passwd *getrootpwent(int try_manually) fprintf(stderr, "sulogin: %s: root password garbled\n\r", F_PASSWD); return &pwd; } - while((p = fgets(sline, 256, fp)) != NULL) { + while((p = fgets(sline, PASSWORD_LENGTH, fp)) != NULL) { if (strncmp(sline, "root:", 5) != 0) continue; p += 5; diff --git a/src/utmp.c b/src/utmp.c index c1ae0c9..fce3e32 100644 --- a/src/utmp.c +++ b/src/utmp.c @@ -32,7 +32,11 @@ #include #include #include +#ifdef __FreeBSD__ +#include +#else #include +#endif #include "init.h" #include "initreq.h" diff --git a/src/wall.c b/src/wall.c index 4352b0f..d3a2c70 100644 --- a/src/wall.c +++ b/src/wall.c @@ -34,12 +34,13 @@ #define MAXLEN 4096 +#define LINE_SIZE 80 #define MAXLINES 20 int main(int argc, char **argv) { char buf[MAXLEN]; - char line[83]; + char line[LINE_SIZE + 3]; /* leave room for \r\n\0 */ int i, f, ch; int len = 0; int remote = 0; @@ -81,7 +82,7 @@ int main(int argc, char **argv) if ((argc - optind) > 0) { for(f = optind; f < argc; f++) { len += strlen(argv[f]) + 1; - if (len >= MAXLEN-2) break; + if (len >= MAXLEN-4) break; strcat(buf, argv[f]); if (f < argc-1) strcat(buf, " "); }