diff options
author | LaMont Jones <lamont@debian.org> | 2010-12-29 09:33:45 -0700 |
---|---|---|
committer | LaMont Jones <lamont@debian.org> | 2010-12-29 09:33:45 -0700 |
commit | 4f9e177060fb5ad6e574598aefdf2d5f50a8b54f (patch) | |
tree | 840ca668a45e389792ccebaa1c414211c59ff620 /login-utils | |
parent | 0d32820f872a43ef8c3021dc9b9741f2b8228b40 (diff) | |
parent | 6c6f2af9e3949197cf7a70255895a2f4451f2319 (diff) | |
download | util-linux-old-4f9e177060fb5ad6e574598aefdf2d5f50a8b54f.tar.gz |
Merge remote branch 'origin/master'
Conflicts:
login-utils/Makefile.am
mount/lomount.c
text-utils/od.1
Diffstat (limited to 'login-utils')
32 files changed, 382 insertions, 3200 deletions
diff --git a/login-utils/.gitignore b/login-utils/.gitignore index 8c771830..816d1139 100644 --- a/login-utils/.gitignore +++ b/login-utils/.gitignore @@ -7,7 +7,5 @@ chsh login newgrp vipw -initctl last -shutdown -simpleinit +mesg diff --git a/login-utils/Makefile.am b/login-utils/Makefile.am index a6c50922..c490999d 100644 --- a/login-utils/Makefile.am +++ b/login-utils/Makefile.am @@ -11,24 +11,12 @@ EXTRA_DIST = README.getty README.modems-with-agetty README.poeigl if BUILD_AGETTY sbin_PROGRAMS += agetty dist_man_MANS += agetty.8 -agetty_LDADD = -lutil +agetty_SOURCES = agetty.c +if !HAVE_LANGINFO +agetty_SOURCES += $(top_srcdir)/lib/langinfo.c endif - -if BUILD_INIT - -sbin_PROGRAMS += simpleinit shutdown initctl -dist_man_MANS += fastboot.8 fasthalt.8 halt.8 reboot.8 simpleinit.8 shutdown.8 \ - initctl.8 - -simpleinit_SOURCES = simpleinit.c my_crypt.h simpleinit.h -initctl_SOURCES = initctl.c simpleinit.h - -if NEED_LIBCRYPT -simpleinit_LDADD = -lcrypt endif -endif # BUILD_INIT - if BUILD_LAST usrbin_exec_PROGRAMS += last dist_man_MANS += last.1 @@ -115,24 +103,6 @@ endif endif endif -if BUILD_INIT - -install-exec-hook:: - cd $(DESTDIR)$(sbindir) && ln -sf shutdown reboot - cd $(DESTDIR)$(sbindir) && ln -sf shutdown fastboot - cd $(DESTDIR)$(sbindir) && ln -sf shutdown halt - cd $(DESTDIR)$(sbindir) && ln -sf shutdown fasthalt - cd $(DESTDIR)$(sbindir) && ln -sf initctl need - cd $(DESTDIR)$(sbindir) && ln -sf initctl display-services - cd $(DESTDIR)$(sbindir) && ln -sf initctl provide - -install-data-hook: - cd $(DESTDIR)$(mandir)/man8 && ln -sf initctl.8 need.8 - cd $(DESTDIR)$(mandir)/man8 && ln -sf initctl.8 display-services.8 - cd $(DESTDIR)$(mandir)/man8 && ln -sf initctl.8 provide.8 - -endif - noinst_PROGRAMS = checktty_test islocal_test checktty_test_SOURCES = checktty.c login.h checktty_test_CPPFLAGS = -DMAIN_TEST_CHECKTTY $(AM_CPPFLAGS) diff --git a/login-utils/agetty.8 b/login-utils/agetty.8 index 084086fd..a7f3bd05 100644 --- a/login-utils/agetty.8 +++ b/login-utils/agetty.8 @@ -303,5 +303,5 @@ Eric Rasmussen <ear@usfirst.org> Added \-f option to display custom login messages on different terminals. .SH AVAILABILITY -The agetty command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The agetty command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/agetty.c b/login-utils/agetty.c index 3d544fb9..e66b8a53 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -32,7 +32,7 @@ #include <sys/socket.h> #include <netdb.h> -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "pathnames.h" @@ -364,7 +364,6 @@ main(argc, argv) (void) execl(options.login, options.login, "--", logname, NULL); error(_("%s: can't exec %s: %m"), options.tty, options.login); - exit(0); /* quiet GCC */ } /* parse-args - parse command-line arguments */ @@ -714,6 +713,13 @@ termio_init(tp, op) struct termios *tp; struct options *op; { + speed_t ispeed, ospeed; + + if (op->flags & F_KEEPSPEED) { + ispeed = cfgetispeed(tp); /* save the original setting */ + ospeed = cfgetospeed(tp); + } else + ospeed = ispeed = op->speeds[FIRST_SPEED]; /* * Initial termios settings: 8-bit characters, raw-mode, blocking i/o. @@ -724,18 +730,21 @@ termio_init(tp, op) /* flush input and output queues, important for modems! */ (void) tcflush(0, TCIOFLUSH); + tp->c_iflag = tp->c_lflag = tp->c_oflag = 0; + if (!(op->flags & F_KEEPCFLAGS)) tp->c_cflag = CS8 | HUPCL | CREAD | (tp->c_cflag & CLOCAL); - if (!(op->flags & F_KEEPSPEED)) { - cfsetispeed(tp, op->speeds[FIRST_SPEED]); - cfsetospeed(tp, op->speeds[FIRST_SPEED]); - } + /* Note that the speed is stored in the c_cflag termios field, so we have + * set the speed always when the cflag se reseted. + */ + cfsetispeed(tp, ispeed); + cfsetospeed(tp, ospeed); + if (op->flags & F_LOCAL) { tp->c_cflag |= CLOCAL; } - tp->c_iflag = tp->c_lflag = tp->c_oflag = 0; #ifdef HAVE_STRUCT_TERMIOS_C_LINE tp->c_line = 0; #endif @@ -911,12 +920,6 @@ do_prompt(op, tp) case 'd': case 't': { - /* TODO: use nl_langinfo() */ - char *weekday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", - "Fri", "Sat" }; - char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", - "Jun", "Jul", "Aug", "Sep", "Oct", - "Nov", "Dec" }; time_t now; struct tm *tm; @@ -925,14 +928,14 @@ do_prompt(op, tp) if (c == 'd') (void) printf ("%s %s %d %d", - weekday[tm->tm_wday], month[tm->tm_mon], - tm->tm_mday, + nl_langinfo(ABDAY_1 + tm->tm_wday), + nl_langinfo(ABMON_1 + tm->tm_mon), + tm->tm_mday, tm->tm_year < 70 ? tm->tm_year + 2000 : tm->tm_year + 1900); else (void) printf ("%02d:%02d:%02d", tm->tm_hour, tm->tm_min, tm->tm_sec); - break; } @@ -995,9 +998,18 @@ next_speed(tp, op) struct termios *tp; struct options *op; { - static int baud_index = FIRST_SPEED;/* current speed index */ + static int baud_index = -1; + + if (baud_index == -1) + /* + * if the F_KEEPSPEED flags is set then the FIRST_SPEED is not + * tested yet (see termio_init()). + */ + baud_index = (op->flags & F_KEEPSPEED) ? FIRST_SPEED : + 1 % op->numspeed; + else + baud_index = (baud_index + 1) % op->numspeed; - baud_index = (baud_index + 1) % op->numspeed; cfsetispeed(tp, op->speeds[baud_index]); cfsetospeed(tp, op->speeds[baud_index]); (void) tcsetattr(0, TCSANOW, tp); @@ -1048,13 +1060,13 @@ char *get_logname(op, cp, tp) if (read(0, &c, 1) < 1) { if (errno == EINTR || errno == EIO) - exit(0); + exit(EXIT_SUCCESS); error(_("%s: read: %m"), op->tty); } /* Do BREAK handling elsewhere. */ if ((c == 0) && op->numspeed > 1) - return (0); + return EXIT_SUCCESS; /* Do parity bit handling. */ if (op->eightbits) { @@ -1091,7 +1103,7 @@ char *get_logname(op, cp, tp) } break; case CTL('D'): - exit(0); + exit(EXIT_SUCCESS); default: if (!isascii(ascval) || !isprint(ascval)) { /* ignore garbage characters */ ; @@ -1111,7 +1123,7 @@ char *get_logname(op, cp, tp) if (isupper(*bp)) *bp = tolower(*bp); /* map name to lower case */ } - return (logname); + return logname; } /* termio_final - set the final tty mode bits */ @@ -1199,11 +1211,11 @@ caps_lock(s) for (capslock = 0; *s; s++) { if (islower(*s)) - return (0); + return EXIT_SUCCESS; if (capslock == 0) capslock = isupper(*s); } - return (capslock); + return capslock; } /* bcode - convert speed string to speed code; return 0 on failure */ @@ -1216,17 +1228,16 @@ bcode(s) for (sp = speedtab; sp->speed; sp++) if (sp->speed == speed) - return (sp->code); - return (0); + return sp->code; + return 0; } /* usage - explain */ -void -usage() +void __attribute__((__noreturn__)) usage(void) { fprintf(stderr, _("Usage: %s [-8hiLmsUw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] baud_rate,... line [termtype]\nor\t[-hiLmw] [-l login_program] [-t timeout] [-I initstring] [-H login_host] line baud_rate,... [termtype]\n"), progname); - exit(1); + exit(EXIT_FAILURE); } /* error - report errors to console or syslog; only understands %s and %m */ diff --git a/login-utils/checktty.c b/login-utils/checktty.c index c28ee833..0d1ec0ef 100644 --- a/login-utils/checktty.c +++ b/login-utils/checktty.c @@ -31,7 +31,7 @@ #include "pathnames.h" #include "login.h" -#include "xstrncpy.h" +#include "strutils.h" #ifndef TTY_MAJOR #define TTY_MAJOR 4 @@ -321,13 +321,13 @@ main(int argc, char **argv) if (getaddrinfo(item->ip, NULL, &hints, &info)==0 && info) { if (info->ai_family == AF_INET) { struct sockaddr_in *sa = - (struct sockaddr_in *) info->ai_addr; + (struct sockaddr_in *) info->ai_addr; memcpy(hostaddress, &(sa->sin_addr), sizeof(sa->sin_addr)); } else if (info->ai_family == AF_INET6) { struct sockaddr_in6 *sa = - (struct sockaddr_in6 *) info->ai_addr; + (struct sockaddr_in6 *) info->ai_addr; memcpy(hostaddress, &(sa->sin6_addr), sizeof(sa->sin6_addr)); } @@ -340,7 +340,7 @@ main(int argc, char **argv) printf("getaddrinfo() failed\n"); } - return 0; + return EXIT_SUCCESS; } #endif /* MAIN_TEST_CHECKTTY */ @@ -553,7 +553,7 @@ checktty(const char *user, const char *tty, struct passwd *pwd) /* there was a default rule, but user didn't match, reject! */ printf(_("Login on %s from %s denied by default.\n"), tty, hostname); badlogin(user); - sleepexit(1); + sleepexit(EXIT_FAILURE); } if (found_match) { @@ -564,7 +564,7 @@ checktty(const char *user, const char *tty, struct passwd *pwd) printf(_("Login on %s from %s denied.\n"), tty, hostname); badlogin(user); - sleepexit(1); + sleepexit(EXIT_FAILURE); } /* users not matched in /etc/usertty are by default allowed access diff --git a/login-utils/chfn.1 b/login-utils/chfn.1 index b63ce683..b27bec41 100644 --- a/login-utils/chfn.1 +++ b/login-utils/chfn.1 @@ -78,5 +78,5 @@ Print version information and exit. .SH AUTHOR Salvatore Valente <svalente@mit.edu> .SH AVAILABILITY -The chfn command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The chfn command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/chfn.c b/login-utils/chfn.c index 691c4f6f..2e0c82b1 100644 --- a/login-utils/chfn.c +++ b/login-utils/chfn.c @@ -18,7 +18,6 @@ * * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> * - added Native Language Support - * * */ @@ -31,14 +30,17 @@ #include <unistd.h> #include <pwd.h> #include <errno.h> +#include <err.h> #include <ctype.h> #include <getopt.h> + #include "my_crypt.h" #include "islocal.h" #include "setpwnam.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #include "env.h" +#include "xalloc.h" #ifdef HAVE_LIBSELINUX #include <selinux/selinux.h> @@ -55,7 +57,7 @@ if ((_rc) != PAM_SUCCESS) { \ fprintf(stderr, "\n%s\n", pam_strerror((_ph), (_rc))); \ pam_end((_ph), (_rc)); \ - exit(1); \ + exit(EXIT_FAILURE); \ } \ } while(0) @@ -80,20 +82,25 @@ struct finfo { }; static boolean parse_argv (int argc, char *argv[], struct finfo *pinfo); -static void usage (FILE *fp); static void parse_passwd (struct passwd *pw, struct finfo *pinfo); static void ask_info (struct finfo *oldfp, struct finfo *newfp); static char *prompt (char *question, char *def_val); static int check_gecos_string (char *msg, char *gecos); static boolean set_changed_data (struct finfo *oldfp, struct finfo *newfp); static int save_new_data (struct finfo *pinfo); -static void *xmalloc (int bytes); - -#define memzero(ptr, size) memset((char *) ptr, 0, size) /* we do not accept gecos field sizes longer than MAX_FIELD_SIZE */ #define MAX_FIELD_SIZE 256 +static void __attribute__((__noreturn__)) usage(FILE *fp) +{ + fprintf (fp, _("Usage: %s [ -f full-name ] [ -o office ] "), whoami); + fprintf (fp, _("[ -p office-phone ]\n [ -h home-phone ] ")); + fprintf (fp, _("[ --help ] [ --version ]\n")); + + exit(fp == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} + int main (int argc, char **argv) { char *cp; uid_t uid; @@ -123,28 +130,24 @@ int main (int argc, char **argv) { * specified for. */ uid = getuid (); - memzero (&oldf, sizeof (oldf)); - memzero (&newf, sizeof (newf)); + memset(&oldf, 0, sizeof(oldf)); + memset(&newf, 0, sizeof (newf)); interactive = parse_argv (argc, argv, &newf); if (! newf.username) { parse_passwd (getpwuid (uid), &oldf); - if (! oldf.username) { - fprintf (stderr, _("%s: you (user %d) don't exist.\n"), whoami, uid); - return (-1); } + if (! oldf.username) + errx(EXIT_FAILURE, _("%s: you (user %d) don't exist."), whoami, uid); } else { parse_passwd (getpwnam (newf.username), &oldf); - if (! oldf.username) { - cp = newf.username; - fprintf (stderr, _("%s: user \"%s\" does not exist.\n"), whoami, cp); - return (-1); } + if (! oldf.username) + errx(EXIT_FAILURE, _("%s: user \"%s\" does not exist."), + whoami, newf.username); } - if (!(is_local(oldf.username))) { - fprintf (stderr, _("%s: can only change local entries.\n"), whoami); - exit(1); - } + if (!(is_local(oldf.username))) + errx(EXIT_FAILURE, _("can only change local entries")); #ifdef HAVE_LIBSELINUX if (is_selinux_enabled() > 0) { @@ -152,26 +155,23 @@ int main (int argc, char **argv) { if (checkAccess(oldf.username,PASSWD__CHFN)!=0) { security_context_t user_context; if (getprevcon(&user_context) < 0) - user_context=(security_context_t) strdup(_("Unknown user context")); - fprintf(stderr, _("%s: %s is not authorized to change the finger info of %s\n"), - whoami, user_context, oldf.username); - freecon(user_context); - exit(1); + user_context = NULL; + + errx(EXIT_FAILURE, _("%s: %s is not authorized to change " + "the finger info of %s"), + whoami, user_context ? : _("Unknown user context"), + oldf.username); } } - if (setupDefaultContext("/etc/passwd") != 0) { - fprintf(stderr,_("%s: Can't set default context for /etc/passwd"), - whoami); - exit(1); - } + if (setupDefaultContext("/etc/passwd")) + errx(EXIT_FAILURE, _("can't set default context for /etc/passwd")); } #endif /* Reality check */ if (uid != 0 && uid != oldf.pw->pw_uid) { errno = EACCES; - perror (whoami); - return (-1); + err(EXIT_FAILURE, NULL); } printf (_("Changing finger information for %s.\n"), oldf.username); @@ -184,11 +184,9 @@ int main (int argc, char **argv) { int retcode; retcode = pam_start("chfn", oldf.username, &conv, &pamh); - if(retcode != PAM_SUCCESS) { - fprintf(stderr, _("%s: PAM failure, aborting: %s\n"), + if(retcode != PAM_SUCCESS) + errx(EXIT_FAILURE, _("%s: PAM failure, aborting: %s"), whoami, pam_strerror(pamh, retcode)); - exit(1); - } retcode = pam_authenticate(pamh, 0); PAM_FAIL_CHECK(pamh, retcode); @@ -212,7 +210,7 @@ int main (int argc, char **argv) { if(strncmp(oldf.pw->pw_passwd, crypt(pwdstr, oldf.pw->pw_passwd), 13)) { puts(_("Incorrect password.")); - exit(1); + exit(EXIT_FAILURE); } } # endif /* HAVE_SECURITY_PAM_MISC_H */ @@ -223,7 +221,7 @@ int main (int argc, char **argv) { if (! set_changed_data (&oldf, &newf)) { printf (_("Finger information not changed.\n")); - return 0; + return EXIT_SUCCESS; } status = save_new_data (&oldf); return status; @@ -260,17 +258,13 @@ static boolean parse_argv (argc, argv, pinfo) /* version? output version and exit. */ if (c == 'v') { printf ("%s\n", PACKAGE_STRING); - exit (0); + exit (EXIT_SUCCESS); } - if (c == 'u') { + if (c == 'u') usage (stdout); - exit (0); - } /* all other options must have an argument. */ - if (! optarg) { + if (! optarg) usage (stderr); - exit (-1); - } /* ok, we were given an argument */ info_given = true; status = 0; @@ -302,34 +296,19 @@ static boolean parse_argv (argc, argv, pinfo) break; default: usage (stderr); - status = (-1); } if (status < 0) exit (status); } /* done parsing arguments. check for a username. */ if (optind < argc) { - if (optind + 1 < argc) { + if (optind + 1 < argc) usage (stderr); - exit (-1); - } pinfo->username = argv[optind]; } return (! info_given); } /* - * usage () -- - * print out a usage message. - */ -static void usage (fp) - FILE *fp; -{ - fprintf (fp, _("Usage: %s [ -f full-name ] [ -o office ] "), whoami); - fprintf (fp, _("[ -p office-phone ]\n [ -h home-phone ] ")); - fprintf (fp, _("[ --help ] [ --version ]\n")); -} - -/* * parse_passwd () -- * take a struct password and fill in the fields of the * struct finfo. @@ -345,7 +324,7 @@ static void parse_passwd (pw, pinfo) pinfo->pw = pw; pinfo->username = pw->pw_name; /* use pw_gecos - we take a copy since PAM destroys the original */ - gecos = strdup(pw->pw_gecos); + gecos = xstrdup(pw->pw_gecos); cp = (gecos ? gecos : ""); pinfo->full_name = cp; cp = strchr (cp, ','); @@ -398,7 +377,7 @@ static char *prompt (question, def_val) *buf = 0; if (fgets (buf, sizeof (buf), stdin) == NULL) { printf (_("\nAborted.\n")); - exit (-1); + exit (EXIT_FAILURE); } /* remove the newline at the end of buf. */ ans = buf; @@ -439,15 +418,15 @@ static int check_gecos_string (msg, gecos) if (c == ',' || c == ':' || c == '=' || c == '"' || c == '\n') { if (msg) printf ("%s: ", msg); printf (_("'%c' is not allowed.\n"), c); - return (-1); + return -1; } if (iscntrl (c)) { if (msg) printf ("%s: ", msg); printf (_("Control characters are not allowed.\n")); - return (-1); + return -1; } } - return (0); + return 0; } /* @@ -509,24 +488,8 @@ static int save_new_data (pinfo) if (setpwnam (pinfo->pw) < 0) { perror ("setpwnam"); printf( _("Finger information *NOT* changed. Try again later.\n" )); - return (-1); + return -1; } printf (_("Finger information changed.\n")); return 0; } - -/* - * xmalloc () -- malloc that never fails. - */ -static void *xmalloc (bytes) - int bytes; -{ - void *vp; - - vp = malloc (bytes); - if (! vp && bytes > 0) { - perror (_("malloc failed")); - exit (-1); - } - return vp; -} diff --git a/login-utils/chsh.1 b/login-utils/chsh.1 index bc9bc432..90514b8f 100644 --- a/login-utils/chsh.1 +++ b/login-utils/chsh.1 @@ -61,5 +61,5 @@ Print version information and exit. .SH AUTHOR Salvatore Valente <svalente@mit.edu> .SH AVAILABILITY -The chsh command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The chsh command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/chsh.c b/login-utils/chsh.c index a893ef99..22b33506 100644 --- a/login-utils/chsh.c +++ b/login-utils/chsh.c @@ -22,11 +22,7 @@ * * */ - -#if 0 -#define _POSIX_SOURCE 1 -#endif - +#include <err.h> #include <sys/types.h> #include <stdio.h> #include <string.h> @@ -36,12 +32,15 @@ #include <errno.h> #include <ctype.h> #include <getopt.h> + +#include "c.h" #include "my_crypt.h" #include "islocal.h" #include "setpwnam.h" #include "nls.h" #include "env.h" #include "pathnames.h" +#include "xalloc.h" #if defined(REQUIRE_PASSWORD) && defined(HAVE_SECURITY_PAM_MISC_H) #include <security/pam_appl.h> @@ -52,7 +51,7 @@ if ((_rc) != PAM_SUCCESS) { \ fprintf(stderr, "\n%s\n", pam_strerror((_ph), (_rc))); \ pam_end((_ph), (_rc)); \ - exit(1); \ + exit(EXIT_FAILURE); \ } \ } while(0) @@ -71,24 +70,27 @@ typedef unsigned char boolean; /* Only root is allowed to assign a luser a non-listed shell, by default */ #define ONLY_LISTED_SHELLS 1 - static char *whoami; -static char buf[FILENAME_MAX]; - struct sinfo { char *username; char *shell; }; static void parse_argv (int argc, char *argv[], struct sinfo *pinfo); -static void usage (FILE *fp); static char *prompt (char *question, char *def_val); static int check_shell (char *shell); static boolean get_shell_list (char *shell); -static void *xmalloc (int bytes); -#define memzero(ptr, size) memset((char *) ptr, 0, size) +static void __attribute__((__noreturn__)) usage (FILE *fp) +{ + fprintf (fp, + _("Usage: %s [ -s shell ] [ --list-shells ] " + "[ --help ] [ --version ]\n" + " [ username ]\n"), whoami); + + exit(fp == stderr ? EXIT_FAILURE : EXIT_SUCCESS); +} int main (int argc, char *argv[]) { @@ -109,28 +111,24 @@ main (int argc, char *argv[]) { if (*cp == '/') whoami = cp + 1; uid = getuid (); - memzero (&info, sizeof (info)); + memset(&info, 0, sizeof(info)); parse_argv (argc, argv, &info); pw = NULL; if (! info.username) { pw = getpwuid (uid); - if (! pw) { - fprintf (stderr, _("%s: you (user %d) don't exist.\n"), whoami, uid); - return (-1); } + if (! pw) + errx(EXIT_FAILURE, _("%s: you (user %d) don't exist."), whoami, uid); } else { pw = getpwnam (info.username); - if (! pw) { - cp = info.username; - fprintf (stderr, _("%s: user \"%s\" does not exist.\n"), whoami, cp); - return (-1); } + if (! pw) + errx(EXIT_FAILURE, _("%s: user \"%s\" does not exist."), + whoami, info.username); } - if (!(is_local(pw->pw_name))) { - fprintf (stderr, _("%s: can only change local entries.\n"), whoami); - exit(1); - } + if (!(is_local(pw->pw_name))) + errx(EXIT_FAILURE, _("%s: can only change local entries."), whoami); #ifdef HAVE_LIBSELINUX if (is_selinux_enabled() > 0) { @@ -138,18 +136,16 @@ main (int argc, char *argv[]) { if (checkAccess(pw->pw_name,PASSWD__CHSH)!=0) { security_context_t user_context; if (getprevcon(&user_context) < 0) - user_context=(security_context_t) strdup(_("Unknown user context")); - fprintf(stderr, _("%s: %s is not authorized to change the shell of %s\n"), - whoami, user_context, pw->pw_name); - freecon(user_context); - exit(1); + user_context = (security_context_t) NULL; + + errx(EXIT_FAILURE, _("%s: %s is not authorized to change the shell of %s"), + whoami, user_context ? : _("Unknown user context"), + pw->pw_name); } } - if (setupDefaultContext("/etc/passwd") != 0) { - fprintf(stderr,_("%s: Can't set default context for /etc/passwd"), + if (setupDefaultContext("/etc/passwd") != 0) + errx(EXIT_FAILURE, _("%s: can't set default context for /etc/passwd"), whoami); - exit(1); - } } #endif @@ -160,15 +156,13 @@ main (int argc, char *argv[]) { /* reality check */ if (uid != 0 && uid != pw->pw_uid) { errno = EACCES; - fprintf(stderr,_("%s: Running UID doesn't match UID of user we're " - "altering, shell change denied\n"), whoami); - return (-1); + err(EXIT_FAILURE, _("%s: running UID doesn't match UID of user we're " + "altering, shell change denied"), whoami); } if (uid != 0 && !get_shell_list(oldshell)) { errno = EACCES; - fprintf(stderr,_("%s: Your shell is not in /etc/shells, shell change" - " denied\n"),whoami); - return (-1); + err(EXIT_FAILURE, _("%s: your shell is not in /etc/shells, " + "shell change denied"), whoami); } shell = info.shell; @@ -177,17 +171,15 @@ main (int argc, char *argv[]) { #ifdef REQUIRE_PASSWORD #ifdef HAVE_SECURITY_PAM_MISC_H - if(uid != 0) { + if (uid != 0) { pam_handle_t *pamh = NULL; struct pam_conv conv = { misc_conv, NULL }; int retcode; retcode = pam_start("chsh", pw->pw_name, &conv, &pamh); - if(retcode != PAM_SUCCESS) { - fprintf(stderr, _("%s: PAM failure, aborting: %s\n"), + if(retcode != PAM_SUCCESS) + errx(EXIT_FAILURE, _("%s: PAM failure, aborting: %s"), whoami, pam_strerror(pamh, retcode)); - exit(1); - } retcode = pam_authenticate(pamh, 0); PAM_FAIL_CHECK(pamh, retcode); @@ -211,7 +203,7 @@ main (int argc, char *argv[]) { if(strncmp(pw->pw_passwd, crypt(pwdstr, pw->pw_passwd), 13)) { puts(_("Incorrect password.")); - exit(1); + return EXIT_FAILURE; } } #endif /* HAVE_SECURITY_PAM_MISC_H */ @@ -219,23 +211,25 @@ main (int argc, char *argv[]) { if (! shell) { shell = prompt (_("New shell"), oldshell); - if (! shell) return 0; + if (! shell) + return EXIT_SUCCESS; } - if (check_shell (shell) < 0) return (-1); + if (check_shell (shell) < 0) + return EXIT_FAILURE; if (! strcmp (pw->pw_shell, shell)) { printf (_("Shell not changed.\n")); - return 0; + return EXIT_SUCCESS; } pw->pw_shell = shell; if (setpwnam (pw) < 0) { - perror ("setpwnam"); + warn(_("setpwnam failed")); printf( _("Shell *NOT* changed. Try again later.\n") ); - return (-1); + return EXIT_FAILURE; } printf (_("Shell changed.\n")); - return 0; + return EXIT_SUCCESS; } /* @@ -263,46 +257,29 @@ parse_argv (int argc, char *argv[], struct sinfo *pinfo) { break; case 'v': printf ("%s\n", PACKAGE_STRING); - exit (0); + exit (EXIT_SUCCESS); case 'u': usage (stdout); - exit (0); case 'l': get_shell_list (NULL); - exit (0); + exit (EXIT_SUCCESS); case 's': - if (! optarg) { + if (! optarg) usage (stderr); - exit (-1); - } pinfo->shell = optarg; break; default: usage (stderr); - exit (-1); } } /* done parsing arguments. check for a username. */ if (optind < argc) { - if (optind + 1 < argc) { + if (optind + 1 < argc) usage (stderr); - exit (-1); - } pinfo->username = argv[optind]; } } -/* - * usage () -- - * print out a usage message. - */ -static void -usage (FILE *fp) { - fprintf (fp, - _("Usage: %s [ -s shell ] [ --list-shells ] " - "[ --help ] [ --version ]\n" - " [ username ]\n"), whoami); -} /* * prompt () -- @@ -312,13 +289,14 @@ static char * prompt (char *question, char *def_val) { int len; char *ans, *cp; + char buf[BUFSIZ]; if (! def_val) def_val = ""; printf("%s [%s]: ", question, def_val); *buf = 0; if (fgets (buf, sizeof (buf), stdin) == NULL) { printf (_("\nAborted.\n")); - exit (-1); + exit (EXIT_FAILURE); } /* remove the newline at the end of buf. */ ans = buf; @@ -342,30 +320,30 @@ check_shell (char *shell) { int i, c; if (!shell) - return (-1); + return -1; if (*shell != '/') { printf (_("%s: shell must be a full path name.\n"), whoami); - return (-1); + return -1; } if (access (shell, F_OK) < 0) { printf (_("%s: \"%s\" does not exist.\n"), whoami, shell); - return (-1); + return -1; } if (access (shell, X_OK) < 0) { printf (_("%s: \"%s\" is not executable.\n"), whoami, shell); - return (-1); + return -1; } /* keep /etc/passwd clean. */ for (i = 0; i < strlen (shell); i++) { c = shell[i]; if (c == ',' || c == ':' || c == '=' || c == '"' || c == '\n') { printf (_("%s: '%c' is not allowed.\n"), whoami, c); - return (-1); + return -1; } if (iscntrl (c)) { printf (_("%s: Control characters are not allowed.\n"), whoami); - return (-1); + return -1; } } #ifdef ONLY_LISTED_SHELLS @@ -376,7 +354,7 @@ check_shell (char *shell) { printf (_("%s: \"%s\" is not listed in /etc/shells.\n"), whoami, shell); printf( _("%s: Use -l option to see list.\n"), whoami ); - exit(1); + exit(EXIT_FAILURE); } } #else @@ -398,6 +376,7 @@ get_shell_list (char *shell_name) { FILE *fp; boolean found; int len; + char buf[PATH_MAX]; found = false; fp = fopen ("/etc/shells", "r"); @@ -425,18 +404,3 @@ get_shell_list (char *shell_name) { fclose (fp); return found; } - -/* - * xmalloc () -- malloc that never fails. - */ -static void * -xmalloc (int bytes) { - void *vp; - - vp = malloc (bytes); - if (! vp && bytes > 0) { - perror (_("malloc failed")); - exit (-1); - } - return vp; -} diff --git a/login-utils/fastboot.8 b/login-utils/fastboot.8 deleted file mode 100644 index 386d9715..00000000 --- a/login-utils/fastboot.8 +++ /dev/null @@ -1 +0,0 @@ -.so man8/shutdown.8 diff --git a/login-utils/fasthalt.8 b/login-utils/fasthalt.8 deleted file mode 100644 index 386d9715..00000000 --- a/login-utils/fasthalt.8 +++ /dev/null @@ -1 +0,0 @@ -.so man8/shutdown.8 diff --git a/login-utils/halt.8 b/login-utils/halt.8 deleted file mode 100644 index 386d9715..00000000 --- a/login-utils/halt.8 +++ /dev/null @@ -1 +0,0 @@ -.so man8/shutdown.8 diff --git a/login-utils/initctl.8 b/login-utils/initctl.8 deleted file mode 100644 index 3dd26e30..00000000 --- a/login-utils/initctl.8 +++ /dev/null @@ -1,110 +0,0 @@ -.\" Copyright (C) 2000-2001 Richard Gooch -.\" -.\" 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 -.\" the Free Software Foundation; either version 2 of the License, or -.\" (at your option) any later version. -.\" -.\" This program is distributed in the hope that it will be useful, -.\" but WITHOUT ANY WARRANTY; without even the implied warranty of -.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -.\" GNU General Public License for more details. -.\" -.\" You should have received a copy of the GNU General Public License -.\" along with this program; if not, write to the Free Software -.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -.\" -.\" Richard Gooch may be reached by email at rgooch@atnf.csiro.au -.\" The postal address is: -.\" Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. -.\" -.\" initctl.8 Richard Gooch 21-FEB-2001 -.\" -.TH INITCTL 8 "21 Feb 2001" "Util-Linux Package" -.SH NAME -initctl \- utility to control simpleinit(8) -.SH SYNOPSIS -.B need -.RB [ \-r ] -.I service -.br -.B display-services -.br -.B provide -.I service -.SH OVERVIEW -The \fBinitctl\fP programme is designed to help improve the -robustness, scalability and readability of system boot scripts. It is -now possible to write a modularised set of boot scripts without the -complex and fragile numbered symlink scheme used in SysV-style boot -scripts. Each script can simply declare, using \fBneed\fP(8), what -must run before them. -.SH DESCRIPTION for need -The \fBneed\fP programme is a utility that tells \fBsimpleinit\fP(8) -to start a \fIservice\fP (usually a script in \fI/sbin/init.d\fP) and -will wait for the service to become available. If the service is -already available, it will not be started again. - -The \fB-r\fP option is used to tell \fBsimpleinit\fP(8) to "roll back" -(stop) services up to (but not including) \fIservice\fP. If -\fIservice\fP is not specified, all services are stopped. The \fB-r\fP -option thus allows the system to be partially or wholly shut down in -an orderly fashion. The \fBshutdown\fP(8) programme still needs to be -run. - -.SH DESCRIPTION for display-services -When invoked as \fBdisplay-services\fP it will write the list of -currently available services and the list of failed services to the -standard output. - -.SH DESCRIPTION for provide -When invoked as \fBprovide\fP it tells \fBsimpleinit\fP(8) that the -parent (calling) process will be providing a service with name -\fIservice\fP. If the calling process exits successfully (status 0) -the service is deemed to be available. Only one instance of -\fIservice\fP may be started, so alternate providers will block and -may fail. - -Using \fBprovide\fP it is possible to have multiple potential -providers for the same (generic) service (e.g. \fBsendmail\fP and -\fBqmail\fP both provide a \fBmta\fP service), where only one actually -provides the service. This may be used by service startup scripts -which check for configuration files. -.SH EXIT CODE -The exit code from \fBneed\fP is 0 if the service was successfully -started, 1 if the service failed badly, and 2 if the service is -unavailable (i.e. disabled in configuration files). These exit codes -reflect the exit codes from the service startup scripts. - -The exit code from \fBneed -r\fP is 0 if the service was successfully -stopped, 1 if the service could not be stopped, and 2 if the service -was not available to start with. The service shutdown scripts may only -return 0 (for success) or 1 (for failure). - -The exit code from \fBprovide\fP is 0 if the service may be provided, -1 if it may not, and 2 if the parent process is not a child of -init. It may block waiting for another provider which is initialising -the service. -.SH SIGNALS -\fBinitctl\fP(8) uses \fBSIGUSR1\fP, \fBSIGUSR2\fP and \fBSIGPOLL\fP -for communication with \fBsimpleinit\fP(8). Don't send these signals -to it. -.SH FILES -.PD 0 -.TP 20 -.BI /dev/initctl -This is the control FIFO, created by \fBsimpleinit\fP(8), which -\fBinitctl\fP(8) writes commands to. -.SH SEE ALSO -.BR simpleinit (8), -.BR init (8) -.PP -A more complete discussion of the new boot script system, based on -\fBneed\fP(8), is available from: -http://www.atnf.csiro.au/~rgooch/linux/boot-scripts/ -.SH AUTHOR -Richard Gooch (rgooch@atnf.csiro.au) - -.SH AVAILABILITY -The initctl command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. diff --git a/login-utils/initctl.c b/login-utils/initctl.c deleted file mode 100644 index 3b38b496..00000000 --- a/login-utils/initctl.c +++ /dev/null @@ -1,217 +0,0 @@ -/* initctl.c - - Source file for initctl (init(8) control tool). - - Copyright (C) 2000 Richard Gooch - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - Richard Gooch may be reached by email at rgooch@atnf.csiro.au - The postal address is: - Richard Gooch, c/o ATNF, P. O. Box 76, Epping, N.S.W., 2121, Australia. -*/ - -/* - This tool will send control messages to init(8). For example, it may - request init(8) to start a service and will wait for that service to be - available. If the service is already available, init(8) will not start it - again. - This tool may also be used to inspect the list of currently available - services. - - - Written by Richard Gooch 28-FEB-2000 - - Updated by Richard Gooch 11-OCT-2000: Added provide support. - - Last updated by Richard Gooch 6-NOV-2000: Renamed to initctl.c - - -*/ -#include <unistd.h> -#include <stdio.h> -#include <limits.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <signal.h> -#include <stdlib.h> -#include <string.h> -#include "simpleinit.h" - - -static void signal_handler (int sig); - - -static int caught_signal = 0; - - -int main (int argc, char **argv) -{ - int fd, nbytes; - struct sigaction sa; - sigset_t ss; - char *ptr; - long *buffer; - struct command_struct *command; - - buffer = calloc(COMMAND_SIZE / sizeof (long) + 1, sizeof(long)); - if (!buffer) { - fprintf (stderr, "Unable allocate buffer for command\n"); - exit(1); - } - command = (struct command_struct *) buffer; - - sigemptyset (&ss); - sigaddset (&ss, SIG_PRESENT); - sigaddset (&ss, SIG_NOT_PRESENT); - sigaddset (&ss, SIG_FAILED); - sigprocmask (SIG_BLOCK, &ss, NULL); - sigemptyset (&sa.sa_mask); - sa.sa_flags = 0; - sa.sa_handler = signal_handler; - sigaction (SIG_PRESENT, &sa, NULL); - sigaction (SIG_NOT_PRESENT, &sa, NULL); - sigaction (SIG_FAILED, &sa, NULL); - command->pid = getpid (); - command->ppid = getppid (); - if ( ( ptr = strrchr (argv[0], '/') ) == NULL ) ptr = argv[0]; - else ++ptr; - /* First generate command number by looking at invocation name */ - if (strcmp (ptr, "display-services") == 0) - command->command = COMMAND_DUMP_LIST; - else if (strcmp (ptr, "need") == 0) command->command = COMMAND_NEED; - else if (strcmp (ptr, "provide") == 0) command->command = COMMAND_PROVIDE; - else command->command = COMMAND_TEST; - /* Now check for switches */ - if ( (argc > 1) && (argv[1][0] == '-') ) - { - switch (argv[1][1]) - { - case 'n': - command->command = COMMAND_NEED; - break; - case 'r': - command->command = COMMAND_ROLLBACK; - break; - case 'd': - command->command = COMMAND_DUMP_LIST; - break; - case 'p': - command->command = COMMAND_PROVIDE; - break; - default: - fprintf (stderr, "Illegal switch: \"%s\"\n", argv[1]); - exit (1); - /*break;*/ - } - --argc; - ++argv; - } - switch (command->command) - { - case COMMAND_NEED: - case COMMAND_PROVIDE: - if (argc < 2) - { - fprintf (stderr, "Usage:\tneed|provide programme\n"); - exit (1); - } - /* Fall through */ - case COMMAND_ROLLBACK: - if (argc > 1) strcpy (command->name, argv[1]); - else command->name[0] = '\0'; - break; - case COMMAND_DUMP_LIST: - if (tmpnam (command->name) == NULL) - { - fprintf (stderr, "Unable to create a unique filename\t%s\n", - ERRSTRING); - exit (1); - } - if (mkfifo (command->name, S_IRUSR) != 0) - { - fprintf (stderr, "Unable to create FIFO: \"%s\"\t%s\n", - command->name, ERRSTRING); - exit (1); - } - break; - } - if ( ( fd = open ("/dev/initctl", O_WRONLY, 0) ) < 0 ) - { - fprintf (stderr, "Error opening\t%s\n", ERRSTRING); - exit (1); - } - if (write (fd, buffer, COMMAND_SIZE) < COMMAND_SIZE) - { - fprintf (stderr, "Error writing\t%s\n", ERRSTRING); - exit (1); - } - close (fd); - if (command->command != COMMAND_DUMP_LIST) - { - sigemptyset (&ss); - while (caught_signal == 0) sigsuspend (&ss); - switch (command->command) - { - case COMMAND_PROVIDE: - switch (caught_signal) - { - case SIG_PRESENT: - return 1; - case SIG_NOT_PRESENT: - return 0; - case SIG_NOT_CHILD: - fprintf (stderr, "Error\n"); - return 2; - default: - return 3; - } - break; - default: - switch (caught_signal) - { - case SIG_PRESENT: - return 0; - case SIG_NOT_PRESENT: - return 2; - case SIG_FAILED: - return 1; - default: - return 3; - } - break; - } - return 3; - } - /* Read back the data and display it */ - if ( ( fd = open (command->name, O_RDONLY, 0) ) < 0 ) - { - fprintf (stderr, "Error opening:\"%s\"\t%s\n", - command->name, ERRSTRING); - exit (1); - } - unlink (command->name); - fflush (stdout); - while ( ( nbytes = read (fd, buffer, COMMAND_SIZE) ) > 0 ) - write (1, buffer, nbytes); - close (fd); - return (0); -} /* End Function main */ - -static void signal_handler (int sig) -{ - caught_signal = sig; -} /* End Function signal_handler */ diff --git a/login-utils/last.1 b/login-utils/last.1 index 314e5d9d..3e9faa40 100644 --- a/login-utils/last.1 +++ b/login-utils/last.1 @@ -58,5 +58,5 @@ Also report year of dates. .SH FILES /var/log/wtmp \(em login data base .SH AVAILABILITY -The last command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The last command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/last.c b/login-utils/last.c index 0c4c0a16..de733cd5 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -29,6 +29,7 @@ /* * last */ +#include <err.h> #include <sys/param.h> #include <sys/stat.h> #include <sys/file.h> @@ -49,6 +50,7 @@ #include "pathnames.h" #include "nls.h" +#include "xalloc.h" #define SECDAY (24*60*60) /* seconds in a day */ #define NO 0 /* false/no */ @@ -146,7 +148,7 @@ main(int argc, char **argv) { case '?': default: fputs(_("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n"), stderr); - exit(1); + exit(EXIT_FAILURE); } for (argv += optind; *argv; ++argv) { #define COMPATIBILITY @@ -157,7 +159,8 @@ main(int argc, char **argv) { addarg(USER_TYPE, *argv); } wtmp(); - exit(0); + + return EXIT_SUCCESS; } static char *utmp_ctime(struct utmp *u) @@ -234,13 +237,15 @@ wtmp(void) { (void)signal(SIGQUIT, onintr); if ((fd = open(file,O_RDONLY)) < 0) - exit(1); + err(EXIT_FAILURE, _("%s: open failed"), file); + fstat(fd, &st); utl_len = st.st_size; utl = mmap(NULL, utl_len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FILE, fd, 0); if (utl == NULL) - exit(1); + err(EXIT_FAILURE, _("%s: mmap failed"), file); + listnr = utl_len/sizeof(struct utmp); if(listnr) @@ -344,28 +349,28 @@ want(struct utmp *bp, int check) { bp->ut_line[4] = '\0'; } if (!arglist) - return(YES); + return YES; for (step = arglist; step; step = step->next) switch(step->type) { case HOST_TYPE: if (!strncmp(step->name, bp->ut_host, HMAX)) - return(YES); + return YES; break; case TTY_TYPE: if (!strncmp(step->name, bp->ut_line, LMAX)) - return(YES); + return YES; break; case USER_TYPE: if (!strncmp(step->name, bp->ut_name, NMAX)) - return(YES); + return YES; break; case INET_TYPE: if (bp->ut_addr == inet_addr(step->name)) - return(YES); + return YES; break; } - return(NO); + return NO; } /* @@ -376,10 +381,7 @@ static void addarg(int type, char *arg) { register ARG *cur; - if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) { - fputs(_("last: malloc failure.\n"), stderr); - exit(1); - } + cur = xmalloc(sizeof(ARG)); cur->next = arglist; cur->type = type; cur->name = arg; @@ -394,10 +396,7 @@ TTY * addtty(char *ttyname) { register TTY *cur; - if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) { - fputs(_("last: malloc failure.\n"), stderr); - exit(1); - } + cur = xmalloc(sizeof(TTY)); cur->next = ttylist; cur->logout = currentout; memcpy(cur->tty, ttyname, LMAX); @@ -421,10 +420,9 @@ hostconv(char *arg) { return; if (first) { first = 0; - if (gethostname(name, sizeof(name))) { - perror(_("last: gethostname")); - exit(1); - } + if (gethostname(name, sizeof(name))) + err(EXIT_FAILURE, _("gethostname failed")); + hostdot = strchr(name, '.'); } if (hostdot && !strcmp(hostdot, argdot)) @@ -445,21 +443,19 @@ ttyconv(char *arg) { */ if (strlen(arg) == 2) { /* either 6 for "ttyxx" or 8 for "console" */ - if (!(mval = malloc((unsigned int)8))) { - fputs(_("last: malloc failure.\n"), stderr); - exit(1); - } + mval = xmalloc(8); if (!strcmp(arg, "co")) (void)strcpy(mval, "console"); else { (void)strcpy(mval, "tty"); (void)strcpy(mval + 3, arg); } - return(mval); + return mval; } if (!strncmp(arg, "/dev/", sizeof("/dev/") - 1)) - return(arg + 5); - return(arg); + return arg + 5; + + return arg; } /* @@ -473,6 +469,6 @@ onintr(int signo) { ct = utmp_ctime(&utmpbuf); printf(_("\ninterrupted %10.10s %5.5s \n"), ct, ct + 11); if (signo == SIGINT) - exit(1); - (void)fflush(stdout); /* fix required for rsh */ + _exit(EXIT_FAILURE); + fflush(stdout); /* fix required for rsh */ } diff --git a/login-utils/login.1 b/login-utils/login.1 index 12273815..2b4bea31 100644 --- a/login-utils/login.1 +++ b/login-utils/login.1 @@ -340,5 +340,5 @@ for HP-UX .br Ported to Linux 0.12: Peter Orbaek (poe@daimi.aau.dk) .SH AVAILABILITY -The login command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The login command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/login.c b/login-utils/login.c index 1550388c..ad2932d0 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -97,6 +97,7 @@ #include <sys/wait.h> #include <signal.h> #include <errno.h> +#include <err.h> #include <grp.h> #include <pwd.h> #include <utmp.h> @@ -113,9 +114,9 @@ #include "pathnames.h" #include "my_crypt.h" #include "login.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" - +#include "xalloc.h" #ifdef HAVE_SECURITY_PAM_MISC_H # include <security/pam_appl.h> @@ -124,7 +125,7 @@ # define PAM_FAIL_CHECK if (retcode != PAM_SUCCESS) { \ fprintf(stderr,"\n%s\n",pam_strerror(pamh, retcode)); \ syslog(LOG_ERR,"%s",pam_strerror(pamh, retcode)); \ - pam_end(pamh, retcode); exit(1); \ + pam_end(pamh, retcode); exit(EXIT_FAILURE); \ } # define PAM_END { \ pam_setcred(pamh, PAM_DELETE_CRED); \ @@ -196,15 +197,13 @@ opentty(const char * tty) { if (fd == -1) { syslog(LOG_ERR, _("FATAL: can't reopen tty: %s"), strerror(errno)); - sleep(1); - exit(1); + sleepexit(EXIT_FAILURE); } if (!isatty(fd)) { close(fd); syslog(LOG_ERR, _("FATAL: %s is not a terminal"), tty); - sleep(1); - exit(1); + sleepexit(EXIT_FAILURE); } flags = fcntl(fd, F_GETFL); @@ -235,9 +234,9 @@ check_ttyname(char *ttyn) { || !S_ISCHR(statbuf.st_mode) || (statbuf.st_nlink > 1 && strncmp(ttyn, "/dev/", 5)) || (access(ttyn, R_OK | W_OK) != 0)) { + syslog(LOG_ERR, _("FATAL: bad tty")); - sleep(1); - exit(1); + sleepexit(EXIT_FAILURE); } } @@ -443,7 +442,7 @@ main(int argc, char **argv) if (getuid()) { fprintf(stderr, _("login: -h for super-user only.\n")); - exit(1); + exit(EXIT_FAILURE); } hflag = 1; if (domain && (p = strchr(optarg, '.')) && @@ -486,7 +485,7 @@ main(int argc, char **argv) default: fprintf(stderr, _("usage: login [-fp] [username]\n")); - exit(1); + exit(EXIT_FAILURE); } argc -= optind; argv += optind; @@ -540,7 +539,10 @@ main(int argc, char **argv) ttt.c_cflag &= ~HUPCL; /* These can fail, e.g. with ttyn on a read-only filesystem */ - fchown(0, 0, 0); + if (fchown(0, 0, 0)) { + ; /* glibc warn_unused_result */ + } + fchmod(0, TTY_MODE); /* Kill processes left on this tty */ @@ -573,11 +575,10 @@ main(int argc, char **argv) retcode = pam_start(hflag?"remote":"login",username, &conv, &pamh); if(retcode != PAM_SUCCESS) { - fprintf(stderr, _("%s: PAM failure, aborting: %s\n"), - "login", pam_strerror(pamh, retcode)); + warnx(_("PAM failure, aborting: %s"), pam_strerror(pamh, retcode)); syslog(LOG_ERR, _("Couldn't initialize PAM: %s"), pam_strerror(pamh, retcode)); - exit(99); + exit(EXIT_FAILURE); } /* hostname & tty are either set to NULL or their correct values, depending on how much we know */ @@ -661,7 +662,7 @@ main(int argc, char **argv) fprintf(stderr,_("\nLogin incorrect\n")); pam_end(pamh, retcode); - exit(0); + exit(EXIT_SUCCESS); } } @@ -687,18 +688,18 @@ main(int argc, char **argv) PAM_FAIL_CHECK; if (!username || !*username) { - fprintf(stderr, _("\nSession setup problem, abort.\n")); + warnx(_("\nSession setup problem, abort.")); syslog(LOG_ERR, _("NULL user name in %s:%d. Abort."), __FUNCTION__, __LINE__); pam_end(pamh, PAM_SYSTEM_ERR); - exit(1); + exit(EXIT_FAILURE); } if (!(pwd = getpwnam(username))) { - fprintf(stderr, _("\nSession setup problem, abort.\n")); + warnx(_("\nSession setup problem, abort.")); syslog(LOG_ERR, _("Invalid user name \"%s\" in %s:%d. Abort."), username, __FUNCTION__, __LINE__); pam_end(pamh, PAM_SYSTEM_ERR); - exit(1); + exit(EXIT_FAILURE); } /* @@ -714,10 +715,10 @@ main(int argc, char **argv) pwd->pw_shell = strdup(pwd->pw_shell); if (!pwd->pw_name || !pwd->pw_passwd || !pwd->pw_gecos || !pwd->pw_dir || !pwd->pw_shell) { - fprintf(stderr, _("login: Out of memory\n")); + warnx(_("out of memory")); syslog(LOG_ERR, "Out of memory"); pam_end(pamh, PAM_SYSTEM_ERR); - exit(1); + exit(EXIT_FAILURE); } username = pwd->pw_name; @@ -728,9 +729,9 @@ main(int argc, char **argv) */ if (initgroups(username, pwd->pw_gid) < 0) { syslog(LOG_ERR, "initgroups: %m"); - fprintf(stderr, _("\nSession setup problem, abort.\n")); + warnx(_("\nSession setup problem, abort.")); pam_end(pamh, PAM_SYSTEM_ERR); - exit(1); + exit(EXIT_FAILURE); } retcode = pam_open_session(pamh, 0); @@ -760,7 +761,7 @@ main(int argc, char **argv) if (username[0] == '+') { puts(_("Illegal username")); badlogin(username); - sleepexit(1); + sleepexit(EXIT_FAILURE); } /* (void)strcpy(tbuf, username); why was this here? */ @@ -800,8 +801,7 @@ main(int argc, char **argv) * refuse the login attempt. */ if (pwd && pwd->pw_uid == 0 && !rootterm(tty_name)) { - fprintf(stderr, - _("%s login refused on this terminal.\n"), + warnx(_("%s login refused on this terminal."), pwd->pw_name); if (hostname) @@ -871,7 +871,7 @@ main(int argc, char **argv) /* we allow 10 tries, but after 3 we start backing off */ if (++cnt > 3) { if (cnt >= 10) { - sleepexit(1); + sleepexit(EXIT_FAILURE); } sleep((unsigned int)((cnt - 3) * 5)); } @@ -1013,16 +1013,22 @@ Michael Riepe <michael@stud.uni-hannover.de> logaudit(tty_name, username, hostname, pwd, 1); dolastlog(quietlog); - fchown(0, pwd->pw_uid, - (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid); + if (fchown(0, pwd->pw_uid, + (gr = getgrnam(TTYGRPNAME)) ? gr->gr_gid : pwd->pw_gid)) + warn(_("change terminal owner failed")); + fchmod(0, TTY_MODE); #ifdef LOGIN_CHOWN_VCS /* if tty is one of the VC's then change owner and mode of the special /dev/vcs devices as well */ if (consoletty(0)) { - chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)); - chown(vcsan, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid)); + + if (chown(vcsn, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid))) + warn(_("change terminal owner failed")); + if (chown(vcsan, pwd->pw_uid, (gr ? gr->gr_gid : pwd->pw_gid))) + warn(_("change terminal owner failed")); + chmod(vcsn, TTY_MODE); chmod(vcsan, TTY_MODE); } @@ -1170,11 +1176,10 @@ Michael Riepe <michael@stud.uni-hannover.de> child_pid = fork(); if (child_pid < 0) { - int errsv = errno; /* error in fork() */ - fprintf(stderr, _("login: failure forking: %s"), strerror(errsv)); + warn(_("failure forking")); PAM_END; - exit(0); + exit(EXIT_FAILURE); } if (child_pid) { @@ -1191,7 +1196,7 @@ Michael Riepe <michael@stud.uni-hannover.de> ; openlog("login", LOG_ODELAY, LOG_AUTHPRIV); PAM_END; - exit(0); + exit(EXIT_SUCCESS); } /* child */ @@ -1200,7 +1205,7 @@ Michael Riepe <michael@stud.uni-hannover.de> sigaction(SIGHUP, &oldsa_hup, NULL); sigaction(SIGTERM, &oldsa_term, NULL); if(got_sig) - exit(1); + exit(EXIT_FAILURE); /* * Problem: if the user's shell is a shell like ash that doesnt do @@ -1226,26 +1231,21 @@ Michael Riepe <michael@stud.uni-hannover.de> /* discard permissions last so can't get killed and drop core */ if(setuid(pwd->pw_uid) < 0 && pwd->pw_uid) { syslog(LOG_ALERT, _("setuid() failed")); - exit(1); + exit(EXIT_FAILURE); } /* wait until here to change directory! */ if (chdir(pwd->pw_dir) < 0) { - printf(_("No directory %s!\n"), pwd->pw_dir); + warn(_("%s: change directory failed"), pwd->pw_dir); if (chdir("/")) - exit(0); + exit(EXIT_FAILURE); pwd->pw_dir = "/"; printf(_("Logging in with home = \"/\".\n")); } /* if the shell field has a space: treat it like a shell script */ if (strchr(pwd->pw_shell, ' ')) { - buff = malloc(strlen(pwd->pw_shell) + 6); - - if (!buff) { - fprintf(stderr, _("login: no memory for shell script.\n")); - exit(0); - } + buff = xmalloc(strlen(pwd->pw_shell) + 6); strcpy(buff, "exec "); strcat(buff, pwd->pw_shell); @@ -1270,12 +1270,11 @@ Michael Riepe <michael@stud.uni-hannover.de> errsv = errno; if (!strcmp(childArgv[0], "/bin/sh")) - fprintf(stderr, _("login: couldn't exec shell script: %s.\n"), - strerror(errsv)); + warn(_("couldn't exec shell script")); else - fprintf(stderr, _("login: no shell: %s.\n"), strerror(errsv)); + warn(_("no shell")); - exit(0); + exit(EXIT_SUCCESS); } #ifndef HAVE_SECURITY_PAM_MISC_H @@ -1292,22 +1291,20 @@ getloginname(void) { for (p = nbuf; (ch = getchar()) != '\n'; ) { if (ch == EOF) { badlogin("EOF"); - exit(0); + exit(EXIT_FAILURE); } if (p < nbuf + UT_NAMESIZE) *p++ = ch; cnt++; if (cnt > UT_NAMESIZE + 20) { - fprintf(stderr, _("login name much too long.\n")); badlogin(_("NAME too long")); - exit(0); + errx(EXIT_FAILURE, _("login name much too long.")); } } if (p > nbuf) { if (nbuf[0] == '-') - fprintf(stderr, - _("login names may not start with '-'.\n")); + warnx(_("login names may not start with '-'.")); else { *p = '\0'; username = nbuf; @@ -1317,9 +1314,8 @@ getloginname(void) { cnt2++; if (cnt2 > 50) { - fprintf(stderr, _("too many bare linefeeds.\n")); badlogin(_("EXCESSIVE linefeeds")); - exit(0); + errx(EXIT_FAILURE, _("too many bare linefeeds.")); } } } @@ -1343,14 +1339,14 @@ timedout2(int sig) { tcgetattr(0, &ti); ti.c_lflag |= ECHO; tcsetattr(0, TCSANOW, &ti); - exit(0); /* %% */ + exit(EXIT_SUCCESS); /* %% */ } static void timedout(int sig) { signal(SIGALRM, timedout2); alarm(10); - fprintf(stderr, _("Login timed out after %d seconds\n"), timeout); + warnx(_("timed out after %d seconds"), timeout); signal(SIGALRM, SIG_IGN); alarm(0); timedout2(0); @@ -1380,10 +1376,10 @@ rootterm(char * ttyn) return 1; } else continue; - } else { + } else { close(fd); return 0; - } + } } } #endif /* !HAVE_SECURITY_PAM_MISC_H */ @@ -1400,8 +1396,11 @@ motd(void) { return; oldint = signal(SIGINT, sigint); if (setjmp(motdinterrupt) == 0) - while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) - write(fileno(stdout), tbuf, nchars); + while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) { + if (write(fileno(stdout), tbuf, nchars)) { + ; /* glibc warn_unused_result */ + } + } signal(SIGINT, oldint); close(fd); } @@ -1418,10 +1417,13 @@ checknologin(void) { char tbuf[8192]; if ((fd = open(_PATH_NOLOGIN, O_RDONLY, 0)) >= 0) { - while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) - write(fileno(stdout), tbuf, nchars); + while ((nchars = read(fd, tbuf, sizeof(tbuf))) > 0) { + if (write(fileno(stdout), tbuf, nchars)) { + ; /* glibc warn_unused_result */ + } + } close(fd); - sleepexit(0); + sleepexit(EXIT_SUCCESS); } } #endif @@ -1462,7 +1464,8 @@ dolastlog(int quiet) { if (hostname) xstrncpy(ll.ll_host, hostname, sizeof(ll.ll_host)); - write(fd, (char *)&ll, sizeof(ll)); + if (write(fd, (char *)&ll, sizeof(ll)) < 0) + warn(_("write lastlog failed")); close(fd); } } diff --git a/login-utils/mesg.1 b/login-utils/mesg.1 index 38b57382..05c42e35 100644 --- a/login-utils/mesg.1 +++ b/login-utils/mesg.1 @@ -99,5 +99,5 @@ A command appeared in Version 6 AT&T UNIX. .SH AVAILABILITY -The mesg command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The mesg command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/mesg.c b/login-utils/mesg.c index e0015bdb..c24a1092 100644 --- a/login-utils/mesg.c +++ b/login-utils/mesg.c @@ -42,24 +42,27 @@ * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> * - added Native Language Support * - * + * 2010-12-01 Marek Polacek <mmpolacek@gmail.com> + * - cleanups */ -#include <sys/types.h> -#include <sys/stat.h> - +#include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <err.h> +#include <sys/types.h> +#include <sys/stat.h> #include "nls.h" -int -main(argc, argv) - int argc; - char *argv[]; +/* exit codes */ + +#define IS_ALLOWED 0 /* Receiving messages is allowed. */ +#define IS_NOT_ALLOWED 1 /* Receiving messages is not allowed. */ +#define MESG_EXIT_FAILURE 2 /* An error occurred. */ + +int main(int argc, char *argv[]) { struct stat sb; char *tty; @@ -69,46 +72,47 @@ main(argc, argv) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - while ((ch = getopt(argc, argv, "")) != -1) switch (ch) { case '?': default: goto usage; } + argc -= optind; argv += optind; if ((tty = ttyname(STDERR_FILENO)) == NULL) - err(1, "ttyname"); + err(MESG_EXIT_FAILURE, _("ttyname failed")); + if (stat(tty, &sb) < 0) - err(1, "%s", tty); + err(MESG_EXIT_FAILURE, _("stat %s failed"), tty); - if (*argv == NULL) { + if (!*argv) { if (sb.st_mode & (S_IWGRP | S_IWOTH)) { - (void)fprintf(stdout, _("is y\n")); - exit(0); + puts(_("is y")); + return IS_ALLOWED; } - (void)fprintf(stdout, _("is n\n")); - exit(1); + puts(_("is n")); + return IS_NOT_ALLOWED; } switch (*argv[0]) { case 'y': #ifdef USE_TTY_GROUP if (chmod(tty, sb.st_mode | S_IWGRP) < 0) - err(1, "%s", tty); #else if (chmod(tty, sb.st_mode | S_IWGRP | S_IWOTH) < 0) - err(1, "%s", tty); #endif - exit(0); + err(MESG_EXIT_FAILURE, _("change %s mode failed"), tty); + return IS_ALLOWED; case 'n': if (chmod(tty, sb.st_mode & ~(S_IWGRP|S_IWOTH)) < 0) - err(1, "%s", tty); - exit(1); + err(MESG_EXIT_FAILURE, _("change %s mode failed"), tty); + return IS_NOT_ALLOWED; } -usage: (void)fprintf(stderr, _("usage: mesg [y | n]\n")); - exit(2); +usage: + fprintf(stderr, _("Usage: %s [y | n]"), program_invocation_short_name); + return MESG_EXIT_FAILURE; } diff --git a/login-utils/newgrp.1 b/login-utils/newgrp.1 index fade125c..6226c15a 100644 --- a/login-utils/newgrp.1 +++ b/login-utils/newgrp.1 @@ -30,5 +30,5 @@ Originally by Michael Haardt. Currently maintained by Peter Orbaek (poe@daimi.aau.dk). .SH AVAILABILITY -The newgrp command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The newgrp command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/newgrp.c b/login-utils/newgrp.c index 976a0493..6323af19 100644 --- a/login-utils/newgrp.c +++ b/login-utils/newgrp.c @@ -14,6 +14,7 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <err.h> #include "c.h" #include "pathnames.h" @@ -54,7 +55,7 @@ get_gshadow_pwd(char *groupname) } static int -allow_setgid(struct passwd *pe, struct group *ge) +allow_setgid(struct passwd *pe, struct group *ge) { char **look; int notfound = 1; @@ -84,7 +85,7 @@ allow_setgid(struct passwd *pe, struct group *ge) return FALSE; /* default to denial */ } -int +int main(int argc, char *argv[]) { struct passwd *pw_entry; @@ -95,47 +96,37 @@ main(int argc, char *argv[]) bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - if (!(pw_entry = getpwuid(getuid()))) { - perror(_("newgrp: Who are you?")); - exit(1); - } + if (!(pw_entry = getpwuid(getuid()))) + err(EXIT_FAILURE, _("who are you?")); shell = (pw_entry->pw_shell[0] ? pw_entry->pw_shell : _PATH_BSHELL); if (argc < 2) { - if(setgid(pw_entry->pw_gid) < 0) { - perror(_("newgrp: setgid")); - exit(1); - } + if(setgid(pw_entry->pw_gid) < 0) + err(EXIT_FAILURE, _("setgid failed")); } else { errno = 0; if (!(gr_entry = getgrnam(argv[1]))) { if (errno) - perror(_("newgrp: No such group.")); /* error */ + err(EXIT_FAILURE, _("no such group")); else - fprintf(stderr, "%s\n", _("newgrp: No such group.")); /* no group */ - exit(1); + errx(EXIT_FAILURE, _("no such group")); /* No group */ } else { - if(allow_setgid(pw_entry, gr_entry)) { - if(setgid(gr_entry->gr_gid) < 0) { - perror(_("newgrp: setgid")); - exit(1); - } - } else { - puts(_("newgrp: Permission denied")); - exit(1); - } + if (allow_setgid(pw_entry, gr_entry)) { + if (setgid(gr_entry->gr_gid) < 0) + err(EXIT_FAILURE, _("setgid failed")); + } else + errx(EXIT_FAILURE, _("permission denied")); } } - if(setuid(getuid()) < 0) { - perror(_("newgrp: setuid")); - exit(1); - } + if (setuid(getuid()) < 0) + err(EXIT_FAILURE, _("setuid failed")); fflush(stdout); fflush(stderr); execl(shell,shell,(char*)0); - perror(_("No shell")); + warn(_("exec %s failed"), shell); fflush(stderr); - exit(1); + + return EXIT_FAILURE; } diff --git a/login-utils/reboot.8 b/login-utils/reboot.8 deleted file mode 100644 index 386d9715..00000000 --- a/login-utils/reboot.8 +++ /dev/null @@ -1 +0,0 @@ -.so man8/shutdown.8 diff --git a/login-utils/shutdown.8 b/login-utils/shutdown.8 deleted file mode 100644 index 371310b6..00000000 --- a/login-utils/shutdown.8 +++ /dev/null @@ -1,169 +0,0 @@ -.\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.\" -.\" -.TH SHUTDOWN 8 "2 March 2000" "Linux 2.0" "Linux Programmer's Manual" -.SH NAME -shutdown \- close down the system -.SH SYNOPSIS -.B shutdown -.RB [ \-h | \-r ] -.RB [ \-fqs ] -.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ] -.RI [ message ] -.br -.B reboot -.RB [ \-h | \-r ] -.RB [ \-fqs ] -.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ] -.RI [ message ] -.br -.B fastboot -.RB [ \-h | \-r ] -.RB [ \-fqs ] -.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ] -.RI [ message ] -.br -.B halt -.RB [ \-h | \-r ] -.RB [ \-fqs ] -.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ] -.RI [ message ] -.br -.B fasthalt -.RB [ \-h | \-r ] -.RB [ \-fqs ] -.RB [ now | \fIhh\fP:\fIss\fP | +\fImins\fP ] -.RI [ message ] -.SH DESCRIPTION -.\" " for emacs hilit19 -In general, -.B shutdown -prepares the system for a power down or reboot. A absolute or delta time -can be given, and periodic messages will be sent to all users warning of -the shutdown. If no message is specified on the command line, -.B shutdown -will ask for a message to be sent, unless the -.B \-q -option is set. - -.B halt -is the same as -.B "shutdown -h -q now" - -.B fasthalt -is the same as -.B "shutdown -h -q -f now" - -.B reboot -is the same as -.B "shutdown -r -q now" - -.B fastboot -is the same as -.B "shutdown -r -q -f now" - -The default delta time, if none is specified, is 2 minutes. - -Five minutes before shutdown (or immediately, if shutdown is less than five -minutes away), the -.I /etc/nologin -file is created with a message stating that the system is going down and -that logins are no longer permitted. The -.BR login (1) -program will not allow non-superusers to login during this period. A -message will be sent to all users at this time. - -When the shutdown time arrives, -.B shutdown -notifies all users, tells -.BR init (8) -not to spawn more -.BR getty (8)'s, -writes the shutdown time into the -.I /var/log/wtmp -file, kills all other processes on the system, -.BR sync (2)'s, -unmounts all the disks, -.BR sync (2)'s -again, waits for a second, and then either terminates or reboots the -system. - -Prior to unmounting all discs, the \fBSIGQUIT\fP signal is sent to the -\fBinit\fP process, which will in turn exec \fBshutdown\fP(8). This -allows for clean unmounting, even if the old inode for the \fBinit\fP -process was unlinked. If the current process ID (PID) equals 1, then -\fBshutdown\fP(8) will pause forever. -.SH OPTIONS -.TP -.B \-h -Halt the system. Do not reboot. This option is used when powering down -the system. -.TP -.B \-r -Reboot the system. -.TP -.B \-f -Fast. When the system is rebooted, the file systems will not be checked. -This is arranged by creating -.IR /fastboot , -which -.I /etc/rc -must detect (and delete). -.TP -.B \-q -Quiet. This uses a default broadcast message, and does not prompt the user -for one. -.TP -.B \-s -Reboot in single user mode. This is arranged by creating -.IR /etc/singleboot , -which -.BR simpleinit (8) -detects (and deletes). -.SH FILES -.nf -.I /etc/rc -.I /fastboot -.I /etc/singleboot -.I /etc/nologin -.I /var/log/wtmp -.I /etc/shutdown.conf -.fi -.SH CONFIG -The configuration file \fI/etc/shutdown.conf\fP is used to determine -the action to take when halting the machine. The currently supported -file format is extremely primitive. The first line must contain two -strings separated by whitespace. The first string must be -\fBHALT_ACTION\fP and the second specifies the action you wish to take -on halt. The options allowed are: -.TP -.B halt -This will simply halt the system. This is the default behaviour. -Note also that this is the fallback if another option fails. -.TP -.B power_off -This will use the kernel power shutdown facility. This is usually only -available on machines with Advanced Power Management (APM). -.TP -.I programname -This specifies a command to run to shut down the power. The first -character must be a "/". Bear in mind that this command will be run -with only the root filesystem mounted (and it will be read-only), and -no daemons running. -.SH "SEE ALSO" -.BR umount (8), -.BR login (1), -.BR reboot (2), -.BR simpleinit (8), -.BR init (8) -.SH BUGS -Unlike the BSD -.BR shutdown , -users are notified of shutdown only once or twice, instead of many times, -and at shorter and shorter intervals as "apocalypse approaches." -Some would construe this as a feature. -.SH AUTHOR -This page documents the version of -.B shutdown -originally written by Peter Orbaek (poe@daimi.aau.dk). diff --git a/login-utils/shutdown.c b/login-utils/shutdown.c deleted file mode 100644 index f7bc0005..00000000 --- a/login-utils/shutdown.c +++ /dev/null @@ -1,754 +0,0 @@ -/* shutdown.c - shutdown a Linux system - * Initially written by poe@daimi.aau.dk - * Currently maintained at ftp://ftp.daimi.aau.dk/pub/Software/Linux/ - */ - -/* - * Modified by jrs@world.std.com to try to exec "umount -a" and if - * that doesn't work, then umount filesystems ourselves in reverse - * order. The old-way was in forward order. Also if the device - * field of the mtab does not start with a "/" then give umount - * the mount point instead. This is needed for the nfs and proc - * filesystems and yet is compatible with older systems. - * - * We also use the mntent library interface to read the mtab file - * instead of trying to parse it directly and no longer give a - * warning about not being able to umount the root. - * - * The reason "umount -a" should be tried first is because it may do - * special processing for some filesystems (such as informing an - * nfs server about nfs umounts) that we don't want to cope with here. - */ - -/* - * Various changes and additions to resemble SunOS 4 shutdown/reboot/halt(8) - * more closely by Scott Telford (s.telford@ed.ac.uk) 93/05/18. - * (I butchered Scotts patches somewhat. - poe) - * - * Changes by Richard Gooch <rgooch@atnf.csiro.au> (butchered by aeb) - * introducing shutdown.conf. - * - * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> - * - added Native Language Support - * - * 2000-03-02 Richard Gooch <rgooch@atnf.csiro.au> - * - pause forever if (pid == 1) and send SIGQUIT to pid = 1 - * - * 2000-11-04 Richard Gooch <rgooch@atnf.csiro.au> - * - continue reaping if (pid == 1) - * - * 2000-11-06 Richard Gooch <rgooch@atnf.csiro.au> - * - shut down "finalprog" from /etc/inittab - * - kill normal user (non-root and non-daemon) processes first with SIGTERM - * - * 2000-11-08 Richard Gooch <rgooch@atnf.csiro.au> - * - rollback services - * - do not unmount devfs (otherwise get harmless but annoying messages) - * - created syncwait() for faster shutting down - * - kill getty processes - * 2001-05-12 Richard Gooch <rgooch@atnf.csiro.au> - * - unblock all signals (sigmask from simpleinit(8) stopped sleep(3)) - * - close all files - */ - -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> -#include <stdlib.h> -#include <utmp.h> -#include <time.h> -#include <string.h> -#include <ctype.h> -#include <signal.h> -#include <errno.h> -#include <sys/param.h> -#include <termios.h> -#include <mntent.h> -#include <sys/mount.h> -#include <sys/wait.h> -#include <syslog.h> -#include <sys/resource.h> -#include <sys/types.h> -#include <dirent.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include "linux_reboot.h" -#include "pathnames.h" -#include "xstrncpy.h" -#include "nls.h" -#include "usleep.h" - -static void usage(void), int_handler(int), write_user(struct utmp *); -static void wall(void), write_wtmp(void), unmount_disks(void); -static void unmount_disks_ourselves(void); -static void swap_off(void), do_halt(char *); -static void kill_mortals (int sig); -static void stop_finalprog (void); -static void syncwait (int timeval); - - -char *prog; /* name of the program */ -int opt_reboot; /* true if -r option or reboot command */ -int timeout; /* number of seconds to shutdown */ -int opt_quiet; /* true if no message is wanted */ -int opt_fast; /* true if fast boot */ -char message[90]; /* reason for shutdown if any... */ -int opt_single = 0; /* true is we want to boot singleuser */ -char *whom; /* who is shutting the system down */ -int opt_msgset = 0; /* message set on command line */ - /* change 1 to 0 if no file is to be used by default */ -int opt_use_config_file = 1; /* read _PATH_SHUTDOWN_CONF */ -char halt_action[256]; /* to find out what to do upon halt */ - -/* #define DEBUGGING */ - -#define WR(s) write(fd, s, strlen(s)) -#define WRCRLF write(fd, "\r\n", 2) -#define ERRSTRING strerror(errno) - -#define UMOUNT_ARGS "umount", "-a", "-t", "nodevfs" -#define SWAPOFF_ARGS "swapoff", "-a" - -void -usage(void) -{ - fprintf(stderr, - _("Usage: shutdown [-h|-r] [-fqs] [now|hh:ss|+mins]\n")); - exit(1); -} - -static void -my_puts(char *s) -{ - /* Use a fresh stdout after forking */ - freopen(_PATH_CONSOLE, "w", stdout); - puts(s); - fflush(stdout); -} - -void -int_handler(int sig) -{ - unlink(_PATH_NOLOGIN); - signal(SIGINT, SIG_DFL); - my_puts(_("Shutdown process aborted")); - exit(1); -} - -static int -iswhitespace(int a) { - return (a == ' ' || a == '\t'); -} - -int -main(int argc, char *argv[]) -{ - int c, i, fd; - char *ptr; - - i = getdtablesize (); - for (fd = 3; fd < i; fd++) close (fd); - if (getpid () == 1) - { - for (fd = 0; fd < 3; fd++) close (fd); - while (1) wait (NULL); /* Grim reaper never stops */ - } - sigsetmask (0); /* simpleinit(8) blocks all signals: undo for ALRM */ - for (i = 1; i < NSIG; i++) signal (i, SIG_DFL); - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - -#ifndef DEBUGGING - if(setreuid (0, 0)) { - fprintf(stderr, _("%s: Only root can shut a system down.\n"), - argv[0]); - exit(1); - } -#endif - - if(*argv[0] == '-') argv[0]++; /* allow shutdown as login shell */ - prog = argv[0]; - if((ptr = strrchr(argv[0], '/'))) prog = ++ptr; - - /* All names (halt, reboot, fasthalt, fastboot, shutdown) - refer to the same program with the same options, - only the defaults differ. */ - if(!strcmp("halt", prog)) { - opt_reboot = 0; - opt_quiet = 1; - opt_fast = 0; - timeout = 0; - } else if(!strcmp("fasthalt", prog)) { - opt_reboot = 0; - opt_quiet = 1; - opt_fast = 1; - timeout = 0; - } else if(!strcmp("reboot", prog)) { - opt_reboot = 1; - opt_quiet = 1; - opt_fast = 0; - timeout = 0; - } else if(!strcmp("fastboot", prog)) { - opt_reboot = 1; - opt_quiet = 1; - opt_fast = 1; - timeout = 0; - } else { - /* defaults */ - opt_reboot = 0; - opt_quiet = 0; - opt_fast = 0; - timeout = 2*60; - } - - c = 0; - while(++c < argc) { - if(argv[c][0] == '-') { - for(i = 1; argv[c][i]; i++) { - switch(argv[c][i]) { - case 'C': - opt_use_config_file = 1; - break; - case 'h': - opt_reboot = 0; - break; - case 'r': - opt_reboot = 1; - break; - case 'f': - opt_fast = 1; - break; - case 'q': - opt_quiet = 1; - break; - case 's': - opt_single = 1; - break; - - default: - usage(); - } - } - } else if(!strcmp("now", argv[c])) { - timeout = 0; - } else if(argv[c][0] == '+') { - timeout = 60 * atoi(&argv[c][1]); - } else if (isdigit(argv[c][0])) { - char *colon; - int hour = 0; - int minute = 0; - time_t tics; - struct tm *tt; - int now, then; - - if((colon = strchr(argv[c], ':'))) { - *colon = '\0'; - hour = atoi(argv[c]); - minute = atoi(++colon); - } else usage(); - - (void) time(&tics); - tt = localtime(&tics); - - now = 3600 * tt->tm_hour + 60 * tt->tm_min; - then = 3600 * hour + 60 * minute; - timeout = then - now; - if(timeout < 0) { - fprintf(stderr, _("That must be tomorrow, " - "can't you wait till then?\n")); - exit(1); - } - } else { - xstrncpy(message, argv[c], sizeof(message)); - opt_msgset = 1; - } - } - - halt_action[0] = 0; - - /* No doubt we shall want to extend this some day - and register a series of commands to be executed - at various points during the shutdown sequence, - and to define the number of milliseconds to sleep, etc. */ - if (opt_use_config_file) { - char line[256], *p; - FILE *fp; - - /* Read and parse the config file */ - halt_action[0] = '\0'; - if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) { - if (fgets (line, sizeof(line), fp) != NULL && - strncasecmp (line, "HALT_ACTION", 11) == 0 && - iswhitespace(line[11])) { - p = strchr(line, '\n'); - if (p) - *p = 0; /* strip final '\n' */ - p = line+11; - while(iswhitespace(*p)) - p++; - strcpy(halt_action, p); - } - fclose (fp); - } - } - - if(!opt_quiet && !opt_msgset) { - /* now ask for message, gets() is insecure */ - int cnt = sizeof(message)-1; - char *ptr; - - printf("Why? "); fflush(stdout); - - ptr = message; - while(--cnt >= 0 && (*ptr = getchar()) && *ptr != '\n') { - ptr++; - } - *ptr = '\0'; - } else if (!opt_msgset) { - strcpy(message, _("for maintenance; bounce, bounce")); - } - -#ifdef DEBUGGING - printf("timeout = %d, quiet = %d, reboot = %d\n", - timeout, opt_quiet, opt_reboot); -#endif - - /* so much for option-processing, now begin termination... */ - if(!(whom = getlogin()) || !*whom) whom = "ghost"; - if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */ - - setpriority(PRIO_PROCESS, 0, PRIO_MIN); - signal(SIGINT, int_handler); - signal(SIGHUP, int_handler); - signal(SIGQUIT, int_handler); - signal(SIGTERM, int_handler); - - chdir("/"); - - if(timeout > 5*60) { - sleep(timeout - 5*60); - timeout = 5*60; - } - - - if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) { - /* keep xgettext happy and leave \r\n outside strings */ - WRCRLF; - WR(_("The system is being shut down within 5 minutes")); - WRCRLF; - write(fd, message, strlen(message)); - WRCRLF; - WR(_("Login is therefore prohibited.")); - WRCRLF; - close(fd); - } - - signal(SIGPIPE, SIG_IGN); - - if(timeout > 0) { - wall(); - sleep(timeout); - } - - timeout = 0; - wall(); - sleep(3); - - /* now there's no turning back... */ - signal(SIGINT, SIG_IGN); - - /* do syslog message... */ - openlog(prog, LOG_CONS, LOG_AUTH); - if (opt_reboot) - syslog(LOG_NOTICE, _("rebooted by %s: %s"), - whom, message); - else - syslog(LOG_NOTICE, _("halted by %s: %s"), - whom, message); - closelog(); - - if(opt_fast) - if((fd = open("/fastboot", O_WRONLY|O_CREAT, 0644)) >= 0) - close(fd); - - kill(1, SIGTSTP); /* tell init not to spawn more getty's */ - write_wtmp(); - if(opt_single) - if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0) - close(fd); - - sync(); - - signal(SIGTERM, SIG_IGN); - if(fork() > 0) sleep(1000); /* the parent will die soon... */ - setpgrp(); /* so the shell wont kill us in the fall */ - -#ifndef DEBUGGING - /* a gentle kill of all other processes except init */ - kill_mortals (SIGTERM); - for (fd = 0; fd < 3; fd++) close (fd); - stop_finalprog (); - sleep (1); /* Time for saves to start */ - kill (1, SIGTERM); /* Tell init to kill spawned gettys */ - usleep (100000); /* Wait for gettys to die */ - my_puts (""); /* Get past the login prompt */ - system ("/sbin/initctl -r"); /* Roll back services */ - syncwait (1); - my_puts ("Sending SIGTERM to all remaining processes..."); - kill (-1, SIGTERM); - sleep (2); /* Default 2, some people need 5 */ - - kill (-1, SIGKILL); /* Now use brute force... */ - - /* turn off accounting */ - acct(NULL); -#endif - /* RedHat and SuSE like to remove /etc/nologin. - Perhaps the usual sequence is - touch nologin; shutdown -h; fiddle with hardware; - boot; fiddle with software; rm nologin - and removing it here will be counterproductive. - Let us see whether people complain. */ - unlink(_PATH_NOLOGIN); - - /* Tell init(8) to exec so that the old inode may be freed cleanly if - required. Need to sleep before remounting root read-only */ - kill (1, SIGQUIT); - - sleep (1); /* Time for processes to die and close files */ - syncwait (2); - - /* remove swap files and partitions using swapoff */ - swap_off(); - - /* unmount disks... */ - unmount_disks(); - syncwait (1); - - if(opt_reboot) { - my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */ - my_puts(_("\nWhy am I still alive after reboot?")); - } else { - my_puts(_("\nNow you can turn off the power...")); - - /* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */ - my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */ - sleep (1); /* Wait for devices to finish writing to media */ - do_halt(halt_action); - } - /* NOTREACHED */ - exit(0); /* to quiet gcc */ -} - -/*** end of main() ***/ - -void -do_halt(char *action) { - if (strcasecmp (action, "power_off") == 0) { - printf(_("Calling kernel power-off facility...\n")); - fflush(stdout); - my_reboot(LINUX_REBOOT_CMD_POWER_OFF); - printf(_("Error powering off\t%s\n"), ERRSTRING); - fflush(stdout); - sleep (2); - } else - - /* This should be improved; e.g. Mike Jagdis wants "/sbin/mdstop -a" */ - /* Maybe we should also fork and wait */ - if (action[0] == '/') { - printf(_("Executing the program \"%s\" ...\n"), action); - fflush(stdout); - execl(action, action, NULL); - printf(_("Error executing\t%s\n"), ERRSTRING); - fflush(stdout); - sleep (2); - } - - my_reboot(LINUX_REBOOT_CMD_HALT); /* RB_HALT_SYSTEM */ -} - -void -write_user(struct utmp *ut) -{ - int fd; - int minutes, hours; - char term[40] = {'/','d','e','v','/',0}; - char msg[100]; - - minutes = timeout / 60; - hours = minutes / 60; - minutes %= 60; - - (void) strncat(term, ut->ut_line, sizeof(ut->ut_line)); - - /* try not to get stuck on a mangled ut_line entry... */ - if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0) - return; - - msg[0] = '\007'; /* gettext crashes on \a */ - sprintf(msg+1, _("URGENT: broadcast message from %s:"), whom); - WRCRLF; - WR(msg); - WRCRLF; - - if (hours > 1) - sprintf(msg, _("System going down in %d hours %d minutes"), - hours, minutes); - else if (hours == 1) - sprintf(msg, _("System going down in 1 hour %d minutes"), - minutes); - else if (minutes > 1) - sprintf(msg, _("System going down in %d minutes\n"), - minutes); - else if (minutes == 1) - sprintf(msg, _("System going down in 1 minute\n")); - else - sprintf(msg, _("System going down IMMEDIATELY!\n")); - - WR(msg); - WRCRLF; - - sprintf(msg, _("\t... %s ...\n"), message); - WR(msg); - WRCRLF; - - close(fd); -} - -void -wall(void) -{ - /* write to all users, that the system is going down. */ - struct utmp *ut; - - utmpname(_PATH_UTMP); - setutent(); - - while((ut = getutent())) { - if(ut->ut_type == USER_PROCESS) - write_user(ut); - } - endutent(); -} - -void -write_wtmp(void) -{ - /* write in wtmp that we are dying */ - int fd; - struct utmp ut; - - memset((char *)&ut, 0, sizeof(ut)); - strcpy(ut.ut_line, "~"); - memcpy(ut.ut_name, "shutdown", sizeof(ut.ut_name)); - - time(&ut.ut_time); - ut.ut_type = BOOT_TIME; - - if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND, 0644)) >= 0) { - write(fd, (char *)&ut, sizeof(ut)); - close(fd); - } -} - -void -swap_off(void) -{ - /* swapoff esp. swap FILES so the underlying partition can be - unmounted. It you don't have swapoff(1) or use mount to - add swapspace, this may not be necessary, but I guess it - won't hurt */ - - int pid; - int result; - int status; - - sync(); - if ((pid = fork()) < 0) { - my_puts(_("Cannot fork for swapoff. Shrug!")); - return; - } - if (!pid) { - execl("/sbin/swapoff", SWAPOFF_ARGS, NULL); - execl("/etc/swapoff", SWAPOFF_ARGS, NULL); - execl("/bin/swapoff", SWAPOFF_ARGS, NULL); - execlp("swapoff", SWAPOFF_ARGS, NULL); - my_puts(_("Cannot exec swapoff, " - "hoping umount will do the trick.")); - exit(0); - } - while ((result = wait(&status)) != -1 && result != pid) - ; -} - -void -unmount_disks(void) -{ - /* better to use umount directly because it may be smarter than us */ - - int pid; - int result; - int status; - - sync(); - if ((pid = fork()) < 0) { - my_puts(_("Cannot fork for umount, trying manually.")); - unmount_disks_ourselves(); - return; - } - if (!pid) { - execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL); - - /* need my_printf instead of my_puts here */ - freopen(_PATH_CONSOLE, "w", stdout); - printf(_("Cannot exec %s, trying umount.\n"), _PATH_UMOUNT); - fflush(stdout); - - execlp("umount", UMOUNT_ARGS, NULL); - my_puts(_("Cannot exec umount, giving up on umount.")); - exit(0); - } - while ((result = wait(&status)) != -1 && result != pid) - ; - my_puts(_("Unmounting any remaining filesystems...")); - unmount_disks_ourselves(); -} - -void -unmount_disks_ourselves(void) -{ - /* unmount all disks */ - - FILE *mtab; - struct mntent *mnt; - char *mntlist[128]; - int i; - int n; - char *filesys; - - sync(); - if (!(mtab = setmntent(_PATH_MOUNTED, "r"))) { - my_puts("shutdown: Cannot open " _PATH_MOUNTED "."); - return; - } - n = 0; - while (n < 100 && (mnt = getmntent(mtab))) { - /* - * Neil Phillips: trying to unmount temporary / kernel - * filesystems is pointless and may cause error messages; - * /dev can be a ramfs managed by udev. - */ - if (strcmp(mnt->mnt_type, "devfs") == 0 || - strcmp(mnt->mnt_type, "proc") == 0 || - strcmp(mnt->mnt_type, "sysfs") == 0 || - strcmp(mnt->mnt_type, "ramfs") == 0 || - strcmp(mnt->mnt_type, "tmpfs") == 0 || - strcmp(mnt->mnt_type, "devpts") == 0) - continue; - mntlist[n++] = strdup(mnt->mnt_dir); - } - endmntent(mtab); - - /* we are careful to do this in reverse order of the mtab file */ - - for (i = n - 1; i >= 0; i--) { - filesys = mntlist[i]; -#ifdef DEBUGGING - printf("umount %s\n", filesys); -#else - if (umount(mntlist[i]) < 0) - printf(_("shutdown: Couldn't umount %s: %s\n"), - filesys, ERRSTRING); -#endif - } -} - -static void kill_mortals (int sig) -{ - int npids = 0; - int index = 0; - int pid; - struct stat statbuf; - DIR *dp; - struct dirent *de; - pid_t *pids = NULL; - char path[256]; - - if ( ( dp = opendir ("/proc") ) == NULL ) return; - while ( ( de = readdir (dp) ) != NULL ) - { - if ( !isdigit (de->d_name[0]) ) continue; - pid = atoi (de->d_name); - sprintf (path, "/proc/%d", pid); - if (stat (path, &statbuf) != 0) continue; - if (statbuf.st_uid < 100) continue; - if (index <= npids) - { - pids = realloc (pids, npids + 16384); - if (pids == NULL) return; - npids += 16384; - } - pids[index++] = pid; - } - fputs ("Sending SIGTERM to mortals...", stderr); - for (--index; index >= 0; --index) kill (pids[index], sig); - free (pids); - closedir (dp); -} /* End Function kill_mortals */ - -static void stop_finalprog (void) -{ - char *p1, *p2; - FILE *fp; - char line[256]; - - if ( ( fp = fopen (_PATH_INITTAB, "r") ) == NULL ) return; - while (fgets (line, 256, fp) != NULL) - { - pid_t pid; - - line[strlen (line) - 1] = '\0'; - p1 = line; - while ( isspace (*p1) ) ++p1; - if (strncmp (p1, "finalprog", 9) != 0) continue; - if ( ( p1 = strchr (p1 + 9, '=') ) == NULL ) continue; - for (++p1; isspace (*p1); ++p1); - if (*p1 == '\0') continue; - for (p2 = p1; !isspace (*p2); ++p2); - *p2 = '\0'; - switch ( pid = fork () ) - { - case 0: /* Child */ - execl (p1, p1, "stop", NULL); - break; - case -1: /* Error */ - break; - default: /* Parent */ - waitpid (pid, NULL, 0); - break; - } - fclose (fp); - return; - } - fclose (fp); -} /* End Function stop_finalprog */ - -static void syncwait (int timeval) -{ - static int do_wait = 0; - static int first_time = 1; - - sync (); - /* Kernel version 1.3.20 and after are supposed to wait automatically */ - if (first_time) - { - struct utsname uts; - - first_time = 0; - uname (&uts); - if (uts.release[0] < '2') do_wait = 1; - } - if (do_wait) sleep (timeval); -} /* End Function syncwait */ diff --git a/login-utils/simpleinit.8 b/login-utils/simpleinit.8 deleted file mode 100644 index cbaf093b..00000000 --- a/login-utils/simpleinit.8 +++ /dev/null @@ -1,180 +0,0 @@ -.\" Copyright 1992, 1993 Rickard E. Faith (faith@cs.unc.edu) -.\" May be distributed under the GNU General Public License -.\" " for emacs's hilit19 mode :-) -.TH SIMPLEINIT 8 "25 February 2001" "Linux 0.99" "Linux Programmer's Manual" -.SH NAME -simpleinit \- process control initialization -.SH SYNOPSIS -.B init -.RB [ single ] -.RI [ script ] -.SH DESCRIPTION -.B init -is invoked as the last step in the Linux boot sequence. If the -.B single -option is used, or if the file -.I /etc/singleboot -exists, then single user mode will be entered, by starting -.IR /bin/sh . -If the file -.I /etc/securesingle -exists, then the root password will be required to start single user mode. -If the root password does not exist, or if -.I /etc/passwd -does not exist, the checking of the password will be skipped. - -If the file -.I /etc/TZ -exists, then the contents of that file will be read, and used to set the TZ -environment variable for each process started by -.BR simpleinit . -This "feature" is only available if it's configured at compile-time. It's -not normally needed. - -After single user mode is terminated, the -.I /etc/rc -file is executed, and the information in -.I /etc/inittab -will be used to start processes. Alternatively, the \fI/etc/inittab\fP -file may be configured to run a different boot script. See below for -details. - -.SH "THE INITTAB FILE" -Because of the number of init programs which are appearing in the Linux -community, the documentation for the -.I /etc/inittab -file, which is usually found with the -.BR inittab (5) -man page, is presented here: - -The format is - -.RS -.B bootprog=file - -.B fileprefix=string - -.B PATH=search path - -.B INIT_PATH=search path - -.B "ttyline:termcap-entry:getty-command" - -.B finalprog=path -.RE - -An example is as follows: - -.nf -.RS -bootprog = -fileprefix = /sbin/init.d/ -PATH = /usr/sbin:/usr/bin:/sbin:/bin -INIT_PATH = /sbin/init.d - -tty1:linux:/sbin/getty 9600 tty1 -tty2:linux:/sbin/getty 9600 tty2 -tty3:linux:/sbin/getty 9600 tty3 -tty4:linux:/sbin/getty 9600 tty4 -# tty5:linux:/sbin/getty 9600 tty5 -# ttyS1:dumb:/sbin/getty 9600 ttyS1 -# ttyS2:dumb:/sbin/getty -m -t60 2400 ttyS2 - -finalprog = /sbin/rc.xdm -.RE -.fi - -Lines beginning with the -.B # -character are treated as comments. Please see documentation for the -.BR getty (8) -command that you are using, since there are several of these in the Linux -community at this time. - -The \fBbootprog\fP value is appended to the \fBfileprefix\fP value, -and the result specifies the boot programme (script) to run. If -unspecified, the default is \fI/etc/rc\fP. If the boot programme is a -directory, then all scripts in that directory tree are executed, in -parallel. See the \fBneed\fP(8) programme for details on how to -elegantly control order of execution and manage dependencies. - -The \fBPATH\fP value is assigned to the PATH environment variable of -child processes (boot scripts). - -The \fBINIT_PATH\fP value is used by simpleinit(8) itself to find the -location of scripts to run (if an absolute path is not given). If -unset and the boot programme is a directory, that directory is used. -Finally, if the script cannot be found in this path, the standard -\fBPATH\fP is used. This separation allows boot scripts to invoke -programmes of the same name without conflict and without needing to -specify absolute paths. - -The \fBfinalprog\fP value specifies the path of the programme to run -after all \fBgetty\fP(8) instances are spawned. At bootup, it is -passed a single argument: "start". At shutdown, it is called again, -this time with the argument: "stop". -.SH SIGNALS -\fBsimpleinit\fP(8) responds to signals in a variety of ways: -.TP -.B SIGHUP -The \fI/etc/inittab\fP configuration file will be read again. -.TP -.B SIGTSTP -This flips a toggle, which controls whether more processes will be -spawned. -.TP -.B SIGINT -\fBsimpleinit\fP(8) will sync a few times, and try to start -\fBreboot\fP(8). Failing this, it will execute the system -\fBreboot\fP(2) call. Under Linux, it is possible to configure the -Ctrl-Alt-Del sequence to send a signal to the \fBinit\fP process -instead of rebooting the system (\fBsimpleinit\fP(8) does this by -default). -.TP -.B SIGQUIT -The \fBreboot\fP(8) programme is executed in place of the -\fBsimpleinit\fP(8) programme. This allows \fBreboot\fP(8) to cleanly -remount (read-only) the root filesystem, even if the old inode for the -\fBinit\fP process was unlinked. -.SH FILES -.I /etc/inittab -.br -.I /etc/singleboot -.br -.I /etc/securesingle -.br -.I /etc/TZ -.br -.I /etc/passwd -.br -.I /etc/rc -.SH "SEE ALSO" -.BR inittab (5), -.BR ctrlaltdel (8) -.BR reboot (8), -.BR termcap (5), -.BR getty (8), -.BR agetty (8), -.BR shutdown (8), -.BR initctl (8) -.SH BUGS -This program is called -.B simpleinit -to distinguish it from the System V compatible versions of init which are -starting to appear in the Linux community. -.B simpleinit -should be linked to, or made identical with, -.I init -for correct functionality. -.SH AUTHOR -Peter Orbaek (poe@daimi.aau.dk) -.br -Version 1.20, with patches for singleuser mode by Werner Almesberger -.br -Richard Gooch <rgooch@atnf.csiro.au> -.br -Dependency support - -.SH AVAILABILITY -The simpleinit command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c deleted file mode 100644 index 8cff848c..00000000 --- a/login-utils/simpleinit.c +++ /dev/null @@ -1,1246 +0,0 @@ -/* simpleinit.c - poe@daimi.aau.dk */ -/* Version 2.0.2 */ - -/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> - * - added Native Language Support - * 2001-01-25 Richard Gooch <rgooch@atnf.csiro.au> - * - fixed bug with failed services so they may be later "reclaimed" - * 2001-02-02 Richard Gooch <rgooch@atnf.csiro.au> - * - fixed race when reading from pipe and reaping children - * 2001-02-18 sam@quux.dropbear.id.au - * - fixed bug in <get_path>: multiple INIT_PATH components did not work - * 2001-02-21 Richard Gooch <rgooch@atnf.csiro.au> - * - block signals in handlers, so that longjmp() doesn't kill context - * 2001-02-25 Richard Gooch <rgooch@atnf.csiro.au> - * - make default INIT_PATH the boot_prog (if it is a directory) - YECCH - * 2002-11-20 patch from SuSE - * - refuse initctl_fd if setting FD_CLOEXEC fails - */ - -#include <sys/types.h> -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <ctype.h> -#include <fcntl.h> -#include <string.h> -#include <signal.h> -#include <errno.h> -#include <time.h> -#include <pwd.h> -#include <sys/file.h> -#include <sys/wait.h> -#include <sys/stat.h> -#include <sys/sysmacros.h> -#include <sys/time.h> -#include <sys/ioctl.h> -#include <dirent.h> -#include <termios.h> -#include <utmp.h> -#include <setjmp.h> -#include <sched.h> -#ifdef SHADOW_PWD -# include <shadow.h> -#endif -#include "my_crypt.h" -#include "pathnames.h" -#include "linux_reboot.h" -#include "xstrncpy.h" -#include "nls.h" -#include "simpleinit.h" - -#define CMDSIZ 150 /* max size of a line in inittab */ -#define NUMCMD 30 /* max number of lines in inittab */ -#define NUMTOK 20 /* max number of tokens in inittab command */ -#define PATH_SIZE (CMDSIZ+CMDSIZ+1) - -#define MAX_RESPAWN_RATE 5 /* number of respawns per 100 seconds */ - -#define TZFILE "/etc/TZ" -char tzone[CMDSIZ]; -/* #define DEBUGGING */ - -/* Define this if you want init to ignore the termcap field in inittab for - console ttys. */ -/* #define SPECIAL_CONSOLE_TERM */ - -#define ever (;;) - -struct initline { - pid_t pid; - char tty[10]; - char termcap[30]; - char *toks[NUMTOK]; - char line[CMDSIZ]; - struct timeval last_start; - signed long rate; -}; - -struct initline inittab[NUMCMD]; -int numcmd; -int stopped = 0; /* are we stopped */ -static char boot_prog[PATH_SIZE] = _PATH_RC; -static char script_prefix[PATH_SIZE] = "\0"; -static char final_prog[PATH_SIZE] = "\0"; -static char init_path[PATH_SIZE] = "\0"; -static int caught_sigint = 0; -static int no_reboot = 0; -static pid_t rc_child = -1; -static const char *initctl_name = "/dev/initctl"; -static int initctl_fd = -1; -static volatile int do_longjmp = 0; -static sigjmp_buf jmp_env; - - -static void do_single (void); -static int do_rc_tty (const char *path); -static int process_path (const char *path, int (*func) (const char *path), - int ignore_dangling_symlink); -static int preload_file (const char *path); -static int run_file (const char *path); -static void spawn (int i), read_inittab (void); -static void sighup_handler (int sig); -static void sigtstp_handler (int sig); -static void sigint_handler (int sig); -static void sigchild_handler (int sig); -static void sigquit_handler (int sig); -static void sigterm_handler (int sig); -#ifdef SET_TZ -static void set_tz (void); -#endif -static void write_wtmp (void); -static pid_t mywait (int *status); -static int run_command (const char *file, const char *name, pid_t pid); - - -static void err (char *s) -{ - int fd; - - if((fd = open("/dev/console", O_WRONLY)) < 0) return; - - write(fd, "init: ", 6); - write(fd, s, strlen(s)); - close(fd); -} - -static void enter_single (void) -{ - pid_t pid; - int i; - - err(_("Booting to single user mode.\n")); - if((pid = fork()) == 0) { - /* the child */ - execl(_PATH_BSHELL, _PATH_BSHELL, NULL); - err(_("exec of single user shell failed\n")); - } else if(pid > 0) { - while (waitpid (pid, &i, 0) != pid) /* Nothing */; - } else if(pid < 0) { - err(_("fork of single user shell failed\n")); - } - unlink(_PATH_SINGLE); -} - -int main(int argc, char *argv[]) -{ - int vec, i; - int want_single = 0; - pid_t pid; - struct sigaction sa; - - -#ifdef SET_TZ - set_tz(); -#endif - sigfillset (&sa.sa_mask); /* longjmp and nested signals don't mix */ - sa.sa_flags = SA_ONESHOT; - sa.sa_handler = sigint_handler; - sigaction (SIGINT, &sa, NULL); - sa.sa_flags = 0; - sa.sa_handler = sigtstp_handler; - sigaction (SIGTSTP, &sa, NULL); - sa.sa_handler = sigterm_handler; - sigaction (SIGTERM, &sa, NULL); - sa.sa_handler = sigchild_handler; - sigaction (SIGCHLD, &sa, NULL); - sa.sa_handler = sigquit_handler; - sigaction (SIGQUIT, &sa, NULL); - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - my_reboot (LINUX_REBOOT_CMD_CAD_OFF); - /* Find script to run. Command-line overrides config file overrides - built-in default */ - for (i = 0; i < NUMCMD; i++) inittab[i].pid = -1; - read_inittab (); - for (i = 1; i < argc; i++) { - if (strcmp (argv[i], "single") == 0) - want_single = 1; - else if (strcmp (argv[i], "-noreboot") == 0) - no_reboot = 1; - else if (strlen(script_prefix) + strlen(argv[i]) < PATH_SIZE) { - char path[PATH_SIZE]; - - strcpy (path, script_prefix); - strcat (path, argv[i]); - if (access (path, R_OK | X_OK) == 0) - strcpy (boot_prog, path); - } - } - if (init_path[0] == '\0') - { - struct stat statbuf; - - if ( (stat (boot_prog, &statbuf) == 0) && S_ISDIR (statbuf.st_mode) ) - { - strcpy (init_path, boot_prog); - i = strlen (init_path); - if (init_path[i - 1] == '/') init_path[i - 1] = '\0'; - } - } - - if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 ) { - mkfifo (initctl_name, S_IRUSR | S_IWUSR); - if ( ( initctl_fd = open (initctl_name, O_RDWR, 0) ) < 0 ) - err ( _("error opening fifo\n") ); - } - - if (initctl_fd >= 0 && fcntl(initctl_fd, F_SETFD, FD_CLOEXEC) != 0) { - err ( _("error setting close-on-exec on /dev/initctl") ); - - /* Can the fcntl ever fail? If it does, and we leave - the descriptor open in child processes, then any - process on the system will be able to write to - /dev/initctl and have us execute arbitrary commands - as root. So let's refuse to use the fifo in this case. */ - - close(initctl_fd); - initctl_fd = -1; - } - - if ( want_single || (access (_PATH_SINGLE, R_OK) == 0) ) do_single (); - - /*If we get a SIGTSTP before multi-user mode, do nothing*/ - while (stopped) - pause(); - - if ( do_rc_tty (boot_prog) ) do_single (); - - while (stopped) /* Also if /etc/rc fails & we get SIGTSTP */ - pause(); - - write_wtmp(); /* write boottime record */ -#ifdef DEBUGGING - for(i = 0; i < numcmd; i++) { - char **p; - p = inittab[i].toks; - printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]); - printf("tty= %s\n", inittab[i].tty); - printf("termcap= %s\n", inittab[i].termcap); - } - exit(0); -#endif - signal (SIGHUP, sighup_handler); /* Better semantics with signal(2) */ - - for (i = 0; i < getdtablesize (); i++) - if (i != initctl_fd) close (i); - - for(i = 0; i < numcmd; i++) - spawn(i); - - if (final_prog[0] != '\0') { - switch ( fork () ) - { - case 0: /* Child */ - execl (final_prog, final_prog, "start", NULL); - err ( _("error running finalprog\n") ); - _exit (1); - break; - case -1: /* Error */ - err ( _("error forking finalprog\n") ); - break; - default: /* Parent */ - break; - } - } - - for ever { - pid = mywait (&vec); - if (pid < 1) continue; - - /* clear utmp entry, and append to wtmp if possible */ - { - struct utmp *ut; - int ut_fd, lf; - - utmpname(_PATH_UTMP); - setutent(); - while((ut = getutent())) { - if(ut->ut_pid == pid) { - time(&ut->ut_time); - memset(&ut->ut_user, 0, UT_NAMESIZE); - memset(&ut->ut_host, 0, sizeof(ut->ut_host)); - ut->ut_type = DEAD_PROCESS; - ut->ut_pid = 0; - ut->ut_addr = 0; - /*endutent();*/ - pututline(ut); - - if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { - flock(lf, LOCK_EX|LOCK_NB); - if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) { - write(ut_fd, ut, sizeof(struct utmp)); - close(ut_fd); - } - flock(lf, LOCK_UN|LOCK_NB); - close(lf); - } - break; - } - } - endutent(); - } - - for(i = 0; i < numcmd; i++) { - if(pid == inittab[i].pid || inittab[i].pid < 0) { - if (stopped) - inittab[i].pid = -1; - else - spawn(i); - if (pid == inittab[i].pid) - break; - } - } - } -} - -#define MAXTRIES 3 /* number of tries allowed when giving the password */ - -/* - * return true if singleuser mode is allowed. - * If /etc/securesingle exists ask for root password, otherwise always OK. - */ -static int check_single_ok (void) -{ - char *pass, *rootpass = NULL; - struct passwd *pwd; - int i; - - if (access (_PATH_SECURE, R_OK) != 0) return 1; - if ( ( pwd = getpwnam ("root") ) || ( pwd = getpwuid (0) ) ) - rootpass = pwd->pw_passwd; - else - return 1; /* a bad /etc/passwd should not lock out */ - - for (i = 0; i < MAXTRIES; i++) - { - pass = getpass (_("Password: ")); - if (pass == NULL) continue; - - if ( !strcmp (crypt (pass, rootpass), rootpass) ) return 1; - - puts (_("\nWrong password.\n")); - } - return 0; -} - -static void do_single (void) -{ - char path[PATH_SIZE]; - - if (caught_sigint) return; - strcpy (path, script_prefix); - strcat (path, "single"); - if (access (path, R_OK | X_OK) == 0) - if (do_rc_tty (path) == 0) return; - if ( check_single_ok () ) enter_single (); -} /* End Function do_single */ - -/* - * run boot script(s). The environment is passed to the script(s), so the RC - * environment variable can be used to decide what to do. - * RC may be set from LILO. - * [RETURNS] 0 on success (exit status convention), otherwise error. - */ -static int do_rc_tty (const char *path) -{ - int status; - pid_t pid; - sigset_t ss; - - if (caught_sigint) return 0; - process_path (path, preload_file, 0); - /* Launch off a subprocess to start a new session (required for frobbing - the TTY) and capture control-C */ - switch ( rc_child = fork () ) - { - case 0: /* Child */ - for (status = 1; status < NSIG; status++) signal (status, SIG_DFL); - sigfillset (&ss); - sigprocmask (SIG_UNBLOCK, &ss, NULL); - sigdelset (&ss, SIGINT); - sigdelset (&ss, SIGQUIT); - setsid (); - ioctl (0, TIOCSCTTY, 0); /* I want my control-C */ - sigsuspend (&ss); /* Should never return, should just be killed */ - break; /* No-one else is controlled by this TTY now */ - case -1: /* Error */ - return (1); - /*break;*/ - default: /* Parent */ - break; - } - /* Parent */ - process_path (path, run_file, 0); - while (1) - { - if ( ( pid = mywait (&status) ) == rc_child ) - return (WTERMSIG (status) == SIGINT) ? 0 : 1; - if (pid < 0) break; - } - kill (rc_child, SIGKILL); - while (waitpid (rc_child, NULL, 0) != rc_child) /* Nothing */; - return 0; -} /* End Function do_rc_tty */ - -static int process_path (const char *path, int (*func) (const char *path), - int ignore_dangling_symlink) -{ - struct stat statbuf; - DIR *dp; - struct dirent *de; - - if (lstat (path, &statbuf) != 0) - { - err (_("lstat of path failed\n") ); - return 1; - } - if ( S_ISLNK (statbuf.st_mode) ) - { - if (stat (path, &statbuf) != 0) - { - if ( (errno == ENOENT) && ignore_dangling_symlink ) return 0; - err (_("stat of path failed\n") ); - return 1; - } - } - if ( !( statbuf.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH) ) ) return 0; - if ( !S_ISDIR (statbuf.st_mode) ) return (*func) (path); - if ( ( dp = opendir (path) ) == NULL ) - { - err (_("open of directory failed\n") ); - return 1; - } - while ( ( de = readdir (dp) ) != NULL ) - { - int retval; - char newpath[PATH_SIZE]; - - if (de->d_name[0] == '.') continue; - retval = snprintf (newpath, sizeof(newpath), "%s/%s", path, de->d_name); - if (newpath[retval - 1] == '~') continue; /* Common mistake */ - if ( ( retval = process_path (newpath, func, 1) ) ) return retval; - } - closedir (dp); - return 0; -} /* End Function process_path */ - -static int preload_file (const char *path) -{ - int fd; - char ch; - - if ( ( fd = open (path, O_RDONLY, 0) ) < 0) return 0; - while (read (fd, &ch, 1) == 1) lseek (fd, 1024, SEEK_CUR); - close (fd); - return 0; -} /* End Function preload_file */ - -static int run_file (const char *path) -{ - const char *ptr; - - if ( ( ptr = strrchr ( (char *) path, '/' ) ) == NULL ) ptr = path; - else ++ptr; - return (run_command (path, ptr, 0) == SIG_FAILED) ? 1 : 0; -} /* End Function run_file */ - -static void spawn (int i) -{ - pid_t pid; - int j; - signed long ds_taken; - struct timeval ct; - - if (inittab[i].toks[0] == NULL) return; - - /* Check if respawning too fast */ - gettimeofday (&ct, NULL); - ds_taken = ct.tv_sec - inittab[i].last_start.tv_sec; - - /* On the first iteration last_start==0 and ds_taken - may be very large. Avoid overflow. -- Denis Vlasenko */ - if (ds_taken > 10000) - ds_taken = 10000; - - ds_taken *= 10; - ds_taken += (ct.tv_usec - inittab[i].last_start.tv_usec) / 100000; - if (ds_taken < 1) - ds_taken = 1; - inittab[i].rate = (9 * inittab[i].rate + 1000 / ds_taken) / 10; - if (inittab[i].rate > MAX_RESPAWN_RATE) { - char txt[256]; - - inittab[i].toks[0] = NULL; - inittab[i].pid = -1; - inittab[i].rate = 0; - snprintf (txt, sizeof(txt), - _("respawning: \"%s\" too fast: quenching entry\n"), - inittab[i].tty); - err (txt); - return; - } - - if((pid = fork()) < 0) { - inittab[i].pid = -1; - err(_("fork failed\n")); - return; - } - if(pid) { - /* this is the parent */ - inittab[i].pid = pid; - inittab[i].last_start = ct; - sched_yield (); - return; - } else { - /* this is the child */ - char term[40]; -#ifdef SET_TZ - char tz[CMDSIZ]; -#endif - char *env[3]; - - setsid(); - for(j = 0; j < getdtablesize(); j++) - (void) close(j); - - snprintf(term, sizeof(term), "TERM=%s", inittab[i].termcap); - env[0] = term; - env[1] = (char *)0; -#ifdef SET_TZ - snprintf(tz, sizeof(tz), "TZ=%s", tzone); - env[1] = tz; -#endif - env[2] = (char *)0; - - execve(inittab[i].toks[0], inittab[i].toks, env); - err(_("exec failed\n")); - sleep(5); - _exit(1); - } -} - -static void read_inittab (void) -{ - FILE *f; - char buf[CMDSIZ]; - int i,j,k; - int has_prog = 0; - char *ptr, *getty; - char prog[PATH_SIZE]; -#ifdef SPECIAL_CONSOLE_TERM - char tty[50]; - struct stat stb; -#endif - char *termenv; - - termenv = getenv("TERM"); /* set by kernel */ - /* termenv = "vt100"; */ - - if(!(f = fopen(_PATH_INITTAB, "r"))) { - err(_("cannot open inittab\n")); - return; - } - - prog[0] = '\0'; - i = 0; - while(!feof(f) && i < NUMCMD - 2) { - if(fgets(buf, CMDSIZ - 1, f) == 0) break; - buf[CMDSIZ-1] = 0; - - for(k = 0; k < CMDSIZ && buf[k]; k++) { - if ((buf[k] == '#') || (buf[k] == '\n')) { - buf[k] = 0; break; - } - } - - if(buf[0] == 0 || buf[0] == '\n') continue; - ptr = strchr (buf, '='); - if (ptr) { - ptr++; - if ( !strncmp (buf, "bootprog", 8) ) { - while ( isspace (*ptr) ) ++ptr; - strcpy (prog, ptr); - has_prog = 1; - continue; - } - if ( !strncmp (buf, "fileprefix", 10) ) { - while ( isspace (*ptr) ) ++ptr; - strcpy (script_prefix, ptr); - continue; - } - if ( !strncmp (buf, "PATH", 4) ) { - while ( isspace (*ptr) ) ++ptr; - setenv ("PATH", ptr, 1); - continue; - } - if ( !strncmp (buf, "INIT_PATH", 9) ) { - while ( isspace (*ptr) ) ++ptr; - strcpy (init_path, ptr); - continue; - } - if ( !strncmp (buf, "finalprog", 8) ) { - while ( isspace (*ptr) ) ++ptr; - strcpy (final_prog, ptr); - continue; - } - } - - - (void) strcpy(inittab[i].line, buf); - - (void) strtok(inittab[i].line, ":"); - xstrncpy(inittab[i].tty, inittab[i].line, 10); - xstrncpy(inittab[i].termcap, strtok((char *)0, ":"), 30); - - getty = strtok((char *)0, ":"); - (void) strtok(getty, " \t\n"); - inittab[i].toks[0] = getty; - j = 1; - while((ptr = strtok((char *)0, " \t\n"))) - inittab[i].toks[j++] = ptr; - inittab[i].toks[j] = (char *)0; - -#ifdef SPECIAL_CONSOLE_TERM - /* special-case termcap for the console ttys */ - snprintf(tty, sizeof(tty), "/dev/%s", inittab[i].tty); - if(!termenv || stat(tty, &stb) < 0) { - err(_("no TERM or cannot stat tty\n")); - } else { - /* is it a console tty? */ - if(major(stb.st_rdev) == 4 && minor(stb.st_rdev) < 64) - xstrncpy(inittab[i].termcap, termenv, 30); - } -#endif - - i++; - } - fclose(f); - numcmd = i; - if (has_prog) { - int len; - char path[PATH_SIZE]; - - strcpy (path, script_prefix); - strcat (path, prog); - len = strlen (path); - if (path[len - 1] == '/') path[len - 1] = '\0'; - if (access (path, R_OK | X_OK) == 0) - strcpy (boot_prog, path); - } -} /* End Function read_inittab */ - -static void sighup_handler (int sig) -{ - int i,j; - int oldnum; - struct initline savetab[NUMCMD]; - int had_already; - - signal (SIGHUP, SIG_IGN); - memcpy(savetab, inittab, NUMCMD * sizeof(struct initline)); - oldnum = numcmd; - read_inittab (); - - for(i = 0; i < numcmd; i++) { - had_already = 0; - for(j = 0; j < oldnum; j++) { - if(!strcmp(savetab[j].tty, inittab[i].tty)) { - had_already = 1; - if((inittab[i].pid = savetab[j].pid) < 0) - spawn(i); - } - } - if (!had_already) spawn (i); - } - signal (SIGHUP, sighup_handler); -} /* End Function sighup_handler */ - -static void sigtstp_handler (int sig) -{ - stopped = ~stopped; - if (!stopped) sighup_handler (sig); -} /* End Function sigtstp_handler */ - -static void sigterm_handler (int sig) -{ - int i; - - for (i = 0; i < numcmd; i++) - if (inittab[i].pid > 0) kill (inittab[i].pid, SIGTERM); -} /* End Function sigterm_handler */ - -static void sigint_handler (int sig) -{ - pid_t pid; - - caught_sigint = 1; - kill (rc_child, SIGKILL); - if (no_reboot) _exit (1) /*kill (0, SIGKILL)*/; - sync (); - sync (); - pid = fork (); - if (pid > 0) return; /* Parent */ - if (pid == 0) /* Child: reboot properly... */ - execl (_PATH_REBOOT, _PATH_REBOOT, (char *) 0); - - /* fork or exec failed, try the hard way... */ - my_reboot (LINUX_REBOOT_CMD_RESTART); -} /* End Function sigint_handler */ - -static void sigchild_handler (int sig) -{ - if (!do_longjmp) return; - siglongjmp (jmp_env, 1); -} - -static void sigquit_handler (int sig) -{ - execl (_PATH_REBOOT, _PATH_REBOOT, NULL); /* It knows pid=1 must sleep */ -} - -#ifdef SET_TZ -static void set_tz (void) -{ - FILE *f; - int len; - - if((f=fopen(TZFILE, "r")) == (FILE *)NULL) return; - fgets(tzone, CMDSIZ-2, f); - fclose(f); - if((len=strlen(tzone)) < 2) return; - tzone[len-1] = 0; /* get rid of the '\n' */ - setenv("TZ", tzone, 0); -} -#endif - -static void write_wtmp (void) -{ - int fd, lf; - struct utmp ut; - - memset((char *)&ut, 0, sizeof(ut)); - strcpy(ut.ut_line, "~"); - memset(ut.ut_name, 0, sizeof(ut.ut_name)); - time(&ut.ut_time); - ut.ut_type = BOOT_TIME; - - if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { - flock(lf, LOCK_EX|LOCK_NB); /* make sure init won't hang */ - if((fd = open(_PATH_WTMP, O_WRONLY|O_APPEND)) >= 0) { - write(fd, (char *)&ut, sizeof(ut)); - close(fd); - } - flock(lf, LOCK_UN|LOCK_NB); - close(lf); - } -} /* End Function write_wtmp */ - - -struct needer_struct -{ - struct needer_struct *next; - pid_t pid; -}; - -struct service_struct -{ - struct service_struct *prev, *next; /* Script services chain */ - struct needer_struct *needers; /* Needers waiting for service */ - struct script_struct *attempting_providers; - int failed; /* TRUE if attempting provider failed badly */ - char name[1]; -}; - -struct script_struct -{ - pid_t pid; - struct script_struct *prev, *next; /* For the list */ - struct service_struct *first_service, *last_service; /*First is true name*/ - struct script_struct *next_attempting_provider; /* Provider chain */ -}; - -struct list_head -{ - struct script_struct *first, *last; - unsigned int num_entries; -}; - - -static struct list_head available_list = {NULL, NULL, 0}; -static struct list_head starting_list = {NULL, NULL, 0}; -static struct service_struct *unavailable_services = NULL; /* For needers */ -static int num_needers = 0; - - -static int process_pidstat (pid_t pid, int status); -static void process_command (const struct command_struct *command); -static struct service_struct *find_service_in_list (const char *name, - struct service_struct *sv); -static struct script_struct *find_script_byname - (const char *name,struct list_head *head, struct service_struct **service); -static struct script_struct *find_script_bypid (pid_t pid, - struct list_head *head); -static void insert_entry (struct list_head *head, struct script_struct *entry); -static void remove_entry (struct list_head *head, struct script_struct *entry); -static void signal_needers (struct service_struct *service, int sig); -static void handle_nonworking (struct script_struct *script); -static int force_progress (void); -static void show_scripts (FILE *fp, const struct script_struct *script, - const char *type); -static const char *get_path (const char *file); - - -static pid_t mywait (int *status) -/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be - reaped, and less than 0 if the boot scripts appear to have finished. -*/ -{ - pid_t pid; - sigset_t ss; - long buffer[COMMAND_SIZE / sizeof (long)]; - struct command_struct *command = (struct command_struct *) buffer; - - if (initctl_fd < 0) return wait (status); - /* Some magic to avoid races which can result in lost signals */ - command->command = -1; - if ( sigsetjmp (jmp_env, 1) ) - { /* Jump from signal handler */ - do_longjmp = 0; - process_command (command); - return 0; - } - sigemptyset (&ss); /* Block SIGCHLD so wait status cannot be lost */ - sigaddset (&ss, SIGCHLD); - sigprocmask (SIG_BLOCK, &ss, NULL); - if ( ( pid = waitpid (-1, status, WNOHANG) ) > 0 ) - { - sigprocmask (SIG_UNBLOCK, &ss, NULL); - return process_pidstat (pid, *status); - } - do_longjmp = 1; /* After this, SIGCHLD will cause a jump backwards */ - sigprocmask (SIG_UNBLOCK, &ss, NULL); - read (initctl_fd, buffer, sizeof(buffer)); - do_longjmp = 0; - process_command (command); - return 0; -} /* End Function mywait */ - -static pid_t process_pidstat (pid_t pid, int status) -/* [RETURNS] The pid for a process to be reaped, 0 if no process is to be - reaped, and less than 0 if the boot scripts appear to have finished. -*/ -{ - int failed; - struct script_struct *script; - struct service_struct *service; - - if ( ( script = find_script_bypid (pid, &starting_list) ) == NULL ) - return pid; - remove_entry (&starting_list, script); - if ( WIFEXITED (status) && (WEXITSTATUS (status) == 0) ) - { - struct script_struct *provider; - - /* Notify needers and other providers */ - for (service = script->first_service; service != NULL; - service = service->next) - { - signal_needers (service, SIG_PRESENT); - for (provider = service->attempting_providers; provider != NULL; - provider = provider->next_attempting_provider) - kill (provider->pid, SIG_PRESENT); - service->attempting_providers = NULL; - } - insert_entry (&available_list, script); - return force_progress (); - } - failed = ( WIFEXITED (status) && (WEXITSTATUS (status) == 2) ) ? 0 : 1; - for (service = script->first_service; service != NULL; - service = service->next) - service->failed = failed; - handle_nonworking (script); - return force_progress (); -} /* End Function process_pidstat */ - -static void process_command (const struct command_struct *command) -{ - int ival; - struct script_struct *script; - struct service_struct *service; - - switch (command->command) - { - case COMMAND_TEST: - kill (command->pid, - (find_script_byname (command->name, &available_list, - NULL) == NULL) ? - SIG_NOT_PRESENT : SIG_PRESENT); - break; - case COMMAND_NEED: - ival = run_command (command->name, command->name, command->pid); - if (ival == 0) - { - ++num_needers; - force_progress (); - } - else kill (command->pid, ival); - break; - case COMMAND_ROLLBACK: - if (command->name[0] == '\0') script = NULL; - else - { - if ( ( script = find_script_byname (command->name, &available_list, - NULL) ) == NULL ) - { - kill (command->pid, SIG_NOT_PRESENT); - break; - } - } - while (script != available_list.first) - { - pid_t pid; - struct script_struct *victim = available_list.first; - char txt[256]; - - if ( ( pid = fork () ) == 0 ) /* Child */ - { - for (ival = 1; ival < NSIG; ival++) signal (ival, SIG_DFL); - open ("/dev/console", O_RDONLY, 0); - open ("/dev/console", O_RDWR, 0); - dup2 (1, 2); - execlp (get_path (victim->first_service->name), - victim->first_service->name, "stop", NULL); - snprintf (txt, sizeof(txt), - _("error at stopping service \"%s\"\n"), - victim->first_service->name); - err (txt); - _exit (SIG_NOT_STOPPED); - } - else if (pid == -1) break; /* Error */ - else /* Parent */ - { - while (waitpid (pid, &ival, 0) != pid) /* Nothing */; - if ( WIFEXITED (ival) && (WEXITSTATUS (ival) == 0) ) - { - snprintf (txt, sizeof(txt), - _("Stopped service: %s\n"), - victim->first_service->name); - remove_entry (&available_list, victim); - free (victim); - err (txt); - } - else break; - } - } - kill (command->pid, - (script ==available_list.first) ? SIG_STOPPED : SIG_NOT_STOPPED); - break; - case COMMAND_DUMP_LIST: - if (fork () == 0) /* Do it in a child process so pid=1 doesn't block */ - { - FILE *fp; - - if ( ( fp = fopen (command->name, "w") ) == NULL ) _exit (1); - show_scripts (fp, available_list.first, "AVAILABLE"); - show_scripts (fp, starting_list.first, "STARTING"); - fputs ("UNAVAILABLE SERVICES:\n", fp); - for (service = unavailable_services; service != NULL; - service = service->next) - fprintf (fp, "%s (%s)\n", service->name, - service->failed ? "FAILED" : "not configured"); - fclose (fp); - _exit (0); - } - break; - case COMMAND_PROVIDE: - /* Sanity check */ - if ( ( script = find_script_bypid (command->ppid, &starting_list) ) - == NULL ) - { - kill (command->pid, SIG_NOT_CHILD); - break; - } - if (find_script_byname (command->name, &available_list, NULL) != NULL) - { - kill (command->pid, SIG_PRESENT); - break; - } - if (find_script_byname (command->name, &starting_list, &service) - != NULL) - { /* Someone else is trying to provide */ - script->next_attempting_provider = service->attempting_providers; - service->attempting_providers = script; - break; - } - if ( ( service = find_service_in_list (command->name, - unavailable_services) ) - == NULL ) - { /* We're the first to try and provide: create it */ - if ( ( service = - calloc (1, strlen (command->name) + sizeof *service) ) - == NULL ) - { - kill (command->pid, SIG_NOT_CHILD); - break; - } - strcpy (service->name, command->name); - } - else - { /* Orphaned service: unhook and grab it */ - if (service->prev == NULL) unavailable_services = service->next; - else service->prev->next = service->next; - if (service->next != NULL) service->next->prev = service->prev; - service->next = NULL; - } - service->prev = script->last_service; - script->last_service->next = service; - script->last_service = service; - kill (command->pid, SIG_NOT_PRESENT); - break; - case -1: - default: - break; - } -} /* End Function process_command */ - -static int run_command (const char *file, const char *name, pid_t pid) -{ - struct script_struct *script; - struct needer_struct *needer = NULL; - struct service_struct *service; - - if (find_script_byname (name, &available_list, NULL) != NULL) - return SIG_PRESENT; - if (pid != 0) - { - needer = calloc (1, sizeof *needer); - if (needer == NULL) return SIG_FAILED; - needer->pid = pid; - } - script = find_script_byname (name, &starting_list, &service); - if (script == NULL) - service = find_service_in_list (name, unavailable_services); - if (service == NULL) - { - int i; - char txt[1024]; - - if ( ( script = calloc (1, sizeof *script) ) == NULL ) - { - free (needer); - return SIG_FAILED; - } - service = calloc (1, strlen (name) + sizeof *service); - if (service == NULL) - { - free (script); - return SIG_FAILED; - } - strcpy (service->name, name); - switch ( script->pid = fork () ) - { - case 0: /* Child */ - for (i = 1; i < NSIG; i++) signal (i, SIG_DFL); - execlp (get_path (file), service->name, "start", NULL); - snprintf (txt, sizeof(txt), - _("error at starting service \"%s\"\n"), service->name); - err (txt); - _exit (SIG_FAILED); - break; - case -1: /* Error */ - service->next = unavailable_services; - if (unavailable_services != NULL) - unavailable_services->prev = service; - unavailable_services = service; - free (script); - free (needer); - return SIG_FAILED; - /*break;*/ - default: /* Parent */ - script->first_service = service; - script->last_service = service; - insert_entry (&starting_list, script); - sched_yield (); - break; - } - } - if (needer == NULL) return 0; - needer->next = service->needers; - service->needers = needer; - return 0; -} /* End Function run_command */ - -static struct service_struct *find_service_in_list (const char *name, - struct service_struct *sv) -{ - for (; sv != NULL; sv = sv->next) - if (strcmp (sv->name, name) == 0) return (sv); - return NULL; -} /* End Function find_service_in_list */ - -static struct script_struct *find_script_byname (const char *name, - struct list_head *head, - struct service_struct **service) -{ - struct script_struct *script; - - for (script = head->first; script != NULL; script = script->next) - { - struct service_struct *sv; - - if ( ( sv = find_service_in_list (name, script->first_service) ) - != NULL ) - { - if (service != NULL) *service = sv; - return (script); - } - } - if (service != NULL) *service = NULL; - return NULL; -} /* End Function find_script_byname */ - -static struct script_struct *find_script_bypid (pid_t pid, - struct list_head *head) -{ - struct script_struct *script; - - for (script = head->first; script != NULL; script = script->next) - if (script->pid == pid) return (script); - return NULL; -} /* End Function find_script_bypid */ - -static void insert_entry (struct list_head *head, struct script_struct *entry) -{ - if (entry == NULL) return; - entry->prev = NULL; - entry->next = head->first; - if (head->first != NULL) head->first->prev = entry; - head->first = entry; - if (head->last == NULL) head->last = entry; - ++head->num_entries; -} /* End Function insert_entry */ - -static void remove_entry (struct list_head *head, struct script_struct *entry) -{ - if (entry->prev == NULL) head->first = entry->next; - else entry->prev->next = entry->next; - if (entry->next == NULL) head->last = entry->prev; - else entry->next->prev = entry->prev; - --head->num_entries; -} /* End Function remove_entry */ - -static void signal_needers (struct service_struct *service, int sig) -{ - struct needer_struct *needer, *next_needer; - - for (needer = service->needers; needer != NULL; needer = next_needer) - { - kill (needer->pid, sig); - next_needer = needer->next; - free (needer); - --num_needers; - } - service->needers = NULL; -} /* End Function signal_needers */ - -static void handle_nonworking (struct script_struct *script) -{ - struct service_struct *service, *next; - - for (service = script->first_service; service != NULL; service = next) - { - struct script_struct *provider = service->attempting_providers; - - next = service->next; - if (provider == NULL) - { - service->prev = NULL; - service->next = unavailable_services; - if (unavailable_services != NULL) - unavailable_services->prev = service; - unavailable_services = service; - continue; - } - service->attempting_providers = provider->next_attempting_provider; - provider->last_service->next = service; - service->prev = provider->last_service; - provider->last_service = service; - service->next = NULL; - kill (provider->pid, SIG_NOT_PRESENT); - } - free (script); -} /* End Function handle_nonworking */ - -static int force_progress (void) -/* [RETURNS] 0 if boot scripts are still running, else -1. -*/ -{ - struct service_struct *service; - - if (starting_list.num_entries > num_needers) return 0; - /* No progress can be made: signal needers */ - for (service = unavailable_services; service != NULL; - service = service->next) - signal_needers (service, - service->failed ? SIG_FAILED : SIG_NOT_PRESENT); - return (starting_list.num_entries < 1) ? -1 : 0; -} /* End Function force_progress */ - -static void show_scripts (FILE *fp, const struct script_struct *script, - const char *type) -{ - fprintf (fp, "%s SERVICES:\n", type); - for (; script != NULL; script = script->next) - { - struct service_struct *service = script->first_service; - - fputs (service->name, fp); - for (service = service->next; service != NULL; service = service->next) - fprintf (fp, " (%s)", service->name); - putc ('\n', fp); - } -} /* End Function show_scripts */ - -static const char *get_path (const char *file) -{ - char *p1, *p2; - static char path[PATH_SIZE]; - - if (file[0] == '/') return file; - if (init_path[0] == '\0') return file; - for (p1 = init_path; *p1 != '\0'; p1 = p2) - { - if ( ( p2 = strchr (p1, ':') ) == NULL ) - p2 = p1 + strlen (p1); - strncpy (path, p1, p2 - p1); - path[p2 - p1] = '/'; - strcpy (path + (p2 - p1) + 1, file); - if (*p2 == ':') ++p2; - if (access (path, X_OK) == 0) return path; - } - return file; -} /* End Function get_path */ diff --git a/login-utils/simpleinit.h b/login-utils/simpleinit.h deleted file mode 100644 index 1d876297..00000000 --- a/login-utils/simpleinit.h +++ /dev/null @@ -1,28 +0,0 @@ -#include <limits.h> -#include <errno.h> - - -#define ERRSTRING strerror (errno) -#define COMMAND_SIZE (PIPE_BUF - 4) - - -#define COMMAND_TEST 0 /* No wait, signal */ -#define COMMAND_NEED 1 /* Wait, signal */ -#define COMMAND_ROLLBACK 2 /* Wait, signal */ -#define COMMAND_DUMP_LIST 3 /* No wait, no signal */ -#define COMMAND_PROVIDE 4 /* Wait, signal */ - -#define SIG_PRESENT SIGUSR1 /* Service is available */ -#define SIG_STOPPED SIGUSR1 /* Service was stopped OK */ -#define SIG_NOT_PRESENT SIGUSR2 /* Not present, but that's OK */ -#define SIG_FAILED SIGPOLL /* Startup failed */ -#define SIG_NOT_STOPPED SIGPOLL /* Failed to stop */ -#define SIG_NOT_CHILD SIGPOLL /* Not a child of init */ - -struct command_struct /* Must always be COMMAND_SIZE */ -{ - signed int command; - pid_t pid; - pid_t ppid; - char name[1]; -}; diff --git a/login-utils/vipw.8 b/login-utils/vipw.8 index e9886832..6ed482d5 100644 --- a/login-utils/vipw.8 +++ b/login-utils/vipw.8 @@ -82,5 +82,5 @@ The .Nm vigr command appeared in Util-Linux 2.6. .Sh AVAILABILITY -The vigr and vipw commands are part of the util-linux-ng package and are available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The vigr and vipw commands are part of the util-linux package and are available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/vipw.c b/login-utils/vipw.c index b3972f3b..5750e6f9 100644 --- a/login-utils/vipw.c +++ b/login-utils/vipw.c @@ -60,11 +60,12 @@ static char version_string[] = "vipw 1.4"; #include <signal.h> #include <fcntl.h> #include <errno.h> +#include <err.h> #include <paths.h> #include <unistd.h> #include "setpwnam.h" -#include "xstrncpy.h" +#include "strutils.h" #include "nls.h" #ifdef HAVE_LIBSELINUX @@ -86,7 +87,7 @@ static void copyfile(int from, int to) { int nr, nw, off; char buf[8*1024]; - + while ((nr = read(from, buf, sizeof(buf))) > 0) for (off = 0; off < nr; nr -= nw, off += nw) if ((nw = write(to, buf + off, nr)) < 0) @@ -131,7 +132,7 @@ static int pw_lock(void) { int lockfd, fd, ret; - /* + /* * If the password file doesn't exist, the system is hosed. * Might as well try to build one. Set the close-on-exec bit so * that users can't get at the encrypted passwords while editing. @@ -149,16 +150,14 @@ pw_lock(void) { } #endif - if ((fd = open(tmptmp_file, O_WRONLY|O_CREAT, 0600)) == -1) { - (void)fprintf(stderr, - "%s: %s: %s\n", progname, tmptmp_file, strerror(errno)); - exit(1); - } + if ((fd = open(tmptmp_file, O_WRONLY|O_CREAT, 0600)) == -1) + err(EXIT_FAILURE, _("%s: open failed"), tmptmp_file); + ret = link(tmptmp_file, tmp_file); (void)unlink(tmptmp_file); if (ret == -1) { if (errno == EEXIST) - (void)fprintf(stderr, + (void)fprintf(stderr, _("%s: the %s file is busy (%s present)\n"), progname, program == VIPW ? "password" : "group", @@ -168,7 +167,7 @@ pw_lock(void) { (void)fprintf(stderr, _("%s: can't link %s: %s\n"), progname, tmp_file, strerror(errsv)); } - exit(1); + exit(EXIT_FAILURE); } lockfd = open(orig_file, O_RDONLY, 0); @@ -177,13 +176,13 @@ pw_lock(void) { (void)fprintf(stderr, "%s: %s: %s\n", progname, orig_file, strerror(errno)); unlink(tmp_file); - exit(1); + exit(EXIT_FAILURE); } copyfile(lockfd, fd); (void)close(lockfd); (void)close(fd); - return(1); + return 1; } static void @@ -192,7 +191,9 @@ pw_unlock(void) { sprintf(tmp, "%s%s", orig_file, ".OLD"); unlink(tmp); - link(orig_file, tmp); + + if (link(orig_file, tmp)) + warn(_("%s: create a link to %s failed"), orig_file, tmp); #ifdef HAVE_LIBSELINUX if (is_selinux_enabled() > 0) { @@ -213,10 +214,10 @@ pw_unlock(void) { if (rename(tmp_file, orig_file) == -1) { int errsv = errno; - fprintf(stderr, - _("%s: can't unlock %s: %s (your changes are still in %s)\n"), + fprintf(stderr, + _("%s: can't unlock %s: %s (your changes are still in %s)\n"), progname, orig_file, strerror(errsv), tmp_file); - exit(1); + exit(EXIT_FAILURE); } unlink(tmp_file); } @@ -236,17 +237,18 @@ pw_edit(int notsetuid) { p = editor; pid = fork(); - if (pid < 0) { - (void)fprintf(stderr, _("%s: Cannot fork\n"), progname); - exit(1); - } + if (pid < 0) + err(EXIT_FAILURE, _("fork failed")); + if (!pid) { if (notsetuid) { (void)setgid(getgid()); (void)setuid(getuid()); } execlp(editor, p, tmp_file, NULL); - _exit(1); + + /* Shouldn't get here */ + _exit(EXIT_FAILURE); } for (;;) { pid = waitpid(pid, &pstat, WUNTRACED); @@ -325,10 +327,10 @@ int main(int argc, char *argv[]) { xstrncpy(tmptmp_file, PTMPTMP_FILE, sizeof(tmptmp_file)); } - if ((argc > 1) && + if ((argc > 1) && (!strcmp(argv[1], "-V") || !strcmp(argv[1], "--version"))) { printf("%s\n", version_string); - exit(0); + exit(EXIT_SUCCESS); } edit_file(0); @@ -358,5 +360,5 @@ int main(int argc, char *argv[]) { } } - exit(0); + exit(EXIT_SUCCESS); } diff --git a/login-utils/wall.1 b/login-utils/wall.1 index a767c7d4..1f85c409 100644 --- a/login-utils/wall.1 +++ b/login-utils/wall.1 @@ -67,5 +67,5 @@ A command appeared in .At v7 . .Sh AVAILABILITY -The wall command is part of the util-linux-ng package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +The wall command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/login-utils/wall.c b/login-utils/wall.c index 7b5f6718..2ecce126 100644 --- a/login-utils/wall.c +++ b/login-utils/wall.c @@ -47,6 +47,8 @@ #include <sys/time.h> #include <sys/uio.h> +#include <err.h> +#include <errno.h> #include <paths.h> #include <ctype.h> #include <pwd.h> @@ -58,7 +60,8 @@ #include <utmp.h> #include "nls.h" -#include "xstrncpy.h" +#include "xalloc.h" +#include "strutils.h" #include "ttymsg.h" #include "pathnames.h" #include "carefulputc.h" @@ -79,8 +82,6 @@ int nobanner; int mbufsize; char *mbuf; -char *progname = "wall"; - int main(int argc, char **argv) { extern int optind; @@ -94,12 +95,7 @@ main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - progname = argv[0]; - p = strrchr(progname, '/'); - if (p) - progname = p+1; - - while ((ch = getopt(argc, argv, "n")) != -1) + while ((ch = getopt(argc, argv, "n")) != -1) { switch (ch) { case 'n': /* undoc option for shutdown: suppress banner */ @@ -109,9 +105,11 @@ main(int argc, char **argv) { case '?': default: usage: - (void)fprintf(stderr, _("usage: %s [file]\n"), progname); - exit(1); + fprintf(stderr, _("usage: %s [file]\n"), + program_invocation_short_name); + exit(EXIT_FAILURE); } + } argc -= optind; argv += optind; if (argc > 1) @@ -141,10 +139,10 @@ usage: xstrncpy(line, utmpptr->ut_line, sizeof(utmpptr->ut_line)); if ((p = ttymsg(&iov, 1, line, 60*5)) != NULL) - (void)fprintf(stderr, "%s: %s\n", progname, p); + warnx("%s", p); } endutent(); - exit(0); + exit(EXIT_SUCCESS); } void @@ -162,12 +160,11 @@ makemsg(fname) lbuf[MAXHOSTNAMELEN + 320], tmpname[sizeof(_PATH_TMP) + 20]; - (void)sprintf(tmpname, "%s/wall.XXXXXX", _PATH_TMP); - if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) { - (void)fprintf(stderr, _("%s: can't open temporary file.\n"), progname); - exit(1); - } - (void)unlink(tmpname); + sprintf(tmpname, "%s/wall.XXXXXX", _PATH_TMP); + if (!(fd = mkstemp(tmpname)) || !(fp = fdopen(fd, "r+"))) + errx(EXIT_FAILURE, _("can't open temporary file")); + + unlink(tmpname); if (!nobanner) { if (!(whom = getlogin()) || !*whom) @@ -177,8 +174,8 @@ makemsg(fname) where = ttyname(2); if (!where || strlen(where) > 100) where = "somewhere"; - (void)gethostname(hostname, sizeof(hostname)); - (void)time(&now); + gethostname(hostname, sizeof(hostname)); + time(&now); lt = localtime(&now); /* @@ -190,15 +187,15 @@ makemsg(fname) */ /* snprintf is not always available, but the sprintf's here will not overflow as long as %d takes at most 100 chars */ - (void)fprintf(fp, "\r%79s\r\n", " "); - (void)sprintf(lbuf, _("Broadcast Message from %s@%s"), + fprintf(fp, "\r%79s\r\n", " "); + sprintf(lbuf, _("Broadcast Message from %s@%s"), whom, hostname); - (void)fprintf(fp, "%-79.79s\007\007\r\n", lbuf); - (void)sprintf(lbuf, " (%s) at %d:%02d ...", + fprintf(fp, "%-79.79s\007\007\r\n", lbuf); + sprintf(lbuf, " (%s) at %d:%02d ...", where, lt->tm_hour, lt->tm_min); - (void)fprintf(fp, "%-79.79s\r\n", lbuf); + fprintf(fp, "%-79.79s\r\n", lbuf); } - (void)fprintf(fp, "%79s\r\n", " "); + fprintf(fp, "%79s\r\n", " "); if (fname) { /* @@ -208,16 +205,12 @@ makemsg(fname) * instead of "wall file". */ int uid = getuid(); - if (uid && (uid != geteuid() || getgid() != getegid())) { - fprintf(stderr, _("%s: will not read %s - use stdin.\n"), - progname, fname); - exit(1); - } - if (!freopen(fname, "r", stdin)) { - fprintf(stderr, _("%s: can't read %s.\n"), - progname, fname); - exit(1); - } + if (uid && (uid != geteuid() || getgid() != getegid())) + errx(EXIT_FAILURE, _("will not read %s - use stdin."), + fname); + + if (!freopen(fname, "r", stdin)) + errx(EXIT_FAILURE, _("can't read %s."), fname); } while (fgets(lbuf, sizeof(lbuf), stdin)) { @@ -236,19 +229,14 @@ makemsg(fname) fprintf(fp, "%79s\r\n", " "); rewind(fp); - if (fstat(fd, &sbuf)) { - fprintf(stderr, _("%s: can't stat temporary file.\n"), - progname); - exit(1); - } + if (fstat(fd, &sbuf)) + err(EXIT_FAILURE, _("fstat failed")); + mbufsize = sbuf.st_size; - if (!(mbuf = malloc((u_int)mbufsize))) { - (void)fprintf(stderr, _("%s: Out of memory!\n"), progname); - exit(1); - } - if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) { - (void)fprintf(stderr, _("%s: can't read temporary file.\n"), progname); - exit(1); - } - (void)close(fd); + mbuf = xmalloc(mbufsize); + + if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize) + err(EXIT_FAILURE, _("fread failed")); + + close(fd); } |