diff options
author | Karel Zak | 2006-12-07 00:25:37 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:37 +0100 |
commit | 5c36a0eb7cdb0360f9afd5d747c321f423b35984 (patch) | |
tree | 147599a77eaff2b5fbc0d389e89d2b51602326c0 /login-utils | |
parent | Imported from util-linux-2.8 tarball. (diff) | |
download | kernel-qcow2-util-linux-5c36a0eb7cdb0360f9afd5d747c321f423b35984.tar.gz kernel-qcow2-util-linux-5c36a0eb7cdb0360f9afd5d747c321f423b35984.tar.xz kernel-qcow2-util-linux-5c36a0eb7cdb0360f9afd5d747c321f423b35984.zip |
Imported from util-linux-2.9i tarball.
Diffstat (limited to 'login-utils')
-rw-r--r-- | login-utils/Makefile | 51 | ||||
-rw-r--r-- | login-utils/agetty.c | 8 | ||||
-rw-r--r-- | login-utils/checktty.c | 24 | ||||
-rw-r--r-- | login-utils/chfn.c | 17 | ||||
-rw-r--r-- | login-utils/chsh.1 | 4 | ||||
-rw-r--r-- | login-utils/chsh.c | 5 | ||||
-rw-r--r-- | login-utils/last.1.orig | 49 | ||||
-rw-r--r-- | login-utils/last.c | 26 | ||||
-rw-r--r-- | login-utils/last.c.orig | 381 | ||||
-rw-r--r-- | login-utils/login.1 | 6 | ||||
-rw-r--r-- | login-utils/login.c | 141 | ||||
-rw-r--r-- | login-utils/passwd.1 | 9 | ||||
-rw-r--r-- | login-utils/passwd.c | 19 | ||||
-rw-r--r-- | login-utils/shutdown.8 | 32 | ||||
-rw-r--r-- | login-utils/shutdown.c | 239 | ||||
-rw-r--r-- | login-utils/simpleinit.c | 18 | ||||
-rw-r--r-- | login-utils/vipw.c | 5 |
17 files changed, 386 insertions, 648 deletions
diff --git a/login-utils/Makefile b/login-utils/Makefile index 9f41fcd19..f4bbc5a99 100644 --- a/login-utils/Makefile +++ b/login-utils/Makefile @@ -82,54 +82,53 @@ all-misc: $(USRBIN.MISC) # Rules for everything else -agetty.o: $(BSD)/pathnames.h +agetty.o: $(LIB)/pathnames.h agetty: agetty.o chfn: chfn.o islocal.o setpwnam.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) chsh: chsh.o islocal.o setpwnam.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) -islocal.o: $(BSD)/pathnames.h -last.o: $(BSD)/pathnames.h -last: last.o $(BSD)/getopt.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) +islocal.o: $(LIB)/pathnames.h +last.o: $(LIB)/pathnames.h +last: last.o ifeq "$(HAVE_PAM)" "yes" -login: login.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) +login: login.o $(LIB)/setproctitle.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) else -login: login.o checktty.o - $(CC) -o $@ $^ $(CRYPT) +login: login.o $(LIB)/setproctitle.o checktty.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) endif -mesg: mesg.o $(BSD)/getopt.o $(BSD)/err.o +mesg: mesg.o $(ERR_O) newgrp: newgrp.o - $(CC) -o $@ $^ $(CRYPT) $(PAM) -setpwnam.o: $(BSD)/pathnames.h -shutdown.o: $(BSD)/pathnames.h -shutdown: shutdown.o -simpleinit.o: $(BSD)/pathnames.h -simpleinit: simpleinit.o $(CRYPT) -vipw.o: $(BSD)/pathnames.h + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) $(PAM) +setpwnam.o: $(LIB)/pathnames.h +shutdown.o: $(LIB)/pathnames.h $(LIB)/linux_reboot.h +shutdown: shutdown.o $(LIB)/my_reboot.o +simpleinit.o: $(LIB)/pathnames.h $(LIB)/linux_reboot.h +simpleinit: simpleinit.o $(LIB)/my_reboot.o +vipw.o: $(LIB)/pathnames.h vipw: vipw.o -newgrp.o: $(BSD)/pathnames.h +newgrp.o: $(LIB)/pathnames.h $(CC) -c $(CFLAGS) $(PAMFL) newgrp.c wall: wall.o ttymsg.o ifeq "$(USE_TTY_GROUP)" "yes" -login.o: login.c $(BSD)/pathnames.h +login.o: login.c $(LIB)/pathnames.h $(LIB)/setproctitle.c $(LIB)/setproctitle.h $(CC) -c $(CFLAGS) $(PAMFL) -DUSE_TTY_GROUP login.c -mesg.o: mesg.c $(BSD)/err.h +mesg.o: mesg.c $(LIB)/err.h $(CC) -c $(CFLAGS) -DUSE_TTY_GROUP mesg.c else -login.o: $(BSD)/pathnames.h +login.o: $(LIB)/pathnames.h $(CC) -c $(CFLAGS) $(PAMFL) login.c -mesg.o: $(BSD)/err.h +mesg.o: $(LIB)/err.h endif -passwd: passwd.o islocal.o setpwnam.o $(CRYPT) -passwd.o: passwd.c - $(CC) -c $(CFLAGS) passwd.c +passwd: passwd.o islocal.o setpwnam.o + $(CC) $(LDFLAGS) -o $@ $^ $(CRYPT) ifeq "$(REQUIRE_PASSWORD)" "yes" CHSH_FLAGS:=$(CHSH_FLAGS) -DREQUIRE_PASSWORD diff --git a/login-utils/agetty.c b/login-utils/agetty.c index 039589591..96d7b38d0 100644 --- a/login-utils/agetty.c +++ b/login-utils/agetty.c @@ -545,6 +545,9 @@ update_utmp(line) endutent(); { +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) + updwtmp(_PATH_WTMP, &ut); +#else int lf; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { @@ -556,8 +559,9 @@ update_utmp(line) flock(lf, LOCK_UN); close(lf); } +#endif } -#else +#else /* not __linux__ */ if ((ut_fd = open(UTMP_FILE, 2)) < 0) { error("%s: open for update: %m", UTMP_FILE); } else { @@ -769,7 +773,7 @@ do_prompt(op, tp) #ifdef ISSUE FILE *fd; int oflag; - char c; + int c; struct utsname uts; (void) uname(&uts); diff --git a/login-utils/checktty.c b/login-utils/checktty.c index f01d0ee82..15873aa44 100644 --- a/login-utils/checktty.c +++ b/login-utils/checktty.c @@ -135,6 +135,8 @@ add_to_class(struct ttyclass *tc, char *tty) /* return true if tty is a pty. Very linux dependent */ +/* Note that the new dynamic ptys (say /dev/pty/0 etc) have major in 128-135 */ +/* We might try TIOCGPTN or so to recognise these new ones, if desired */ static int isapty(const char *tty) { @@ -146,20 +148,18 @@ isapty(const char *tty) return 0; sprintf(devname, "/dev/%s", tty); -#if defined(__linux__) && defined(PTY_SLAVE_MAJOR) - /* this is for linux 1.3 and newer */ - if((stat(devname, &stb) >= 0) - && major(stb.st_rdev) == PTY_SLAVE_MAJOR) { - return 1; - } +#if defined(__linux__) + if((stat(devname, &stb) >= 0) && S_ISCHR(stb.st_mode)) { + +#if defined(PTY_SLAVE_MAJOR) + /* this is for linux 1.3 and newer */ + if(major(stb.st_rdev) == PTY_SLAVE_MAJOR) + return 1; #endif -#if defined(__linux__) - /* this is for linux versions before 1.3, backward compat. */ - if((stat(devname, &stb) >= 0) - && major(stb.st_rdev) == TTY_MAJOR - && minor(stb.st_rdev) >= 192) { - return 1; + /* this is for linux versions before 1.3, backward compat. */ + if(major(stb.st_rdev) == TTY_MAJOR && minor(stb.st_rdev) >= 192) + return 1; } #endif return 0; diff --git a/login-utils/chfn.c b/login-utils/chfn.c index 8e962db05..3da2360f1 100644 --- a/login-utils/chfn.c +++ b/login-utils/chfn.c @@ -14,9 +14,6 @@ * patches from Zefram <A.Main@dcs.warwick.ac.uk> * * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - * to allow peaceful coexistence with yp: using the changes by - * Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, from - * passwd.c (now moved to setpwnam.c); * to remove trailing empty fields. Oct 5, 96. * */ @@ -32,6 +29,7 @@ #include <errno.h> #include <ctype.h> #include <getopt.h> +#include <locale.h> #include "my_crypt.h" #include "../version.h" @@ -81,6 +79,9 @@ extern int setpwnam P((struct passwd *pwd)); #define memzero(ptr, size) memset((char *) ptr, 0, size) +/* we do not accept gecos field sizes lengther than MAX_FIELD_SIZE */ +#define MAX_FIELD_SIZE 256 + int main (argc, argv) int argc; char *argv[]; @@ -103,6 +104,9 @@ int main (argc, argv) for (cp = whoami; *cp; cp++) if (*cp == '/') whoami = cp + 1; + /* iscntrl() below should not reject actual names */ + setlocale(LC_ALL,""); + /* * "oldf" contains the users original finger information. * "newf" contains the changed finger information, and contains NULL @@ -393,6 +397,13 @@ static int check_gecos_string (msg, gecos) { int i, c; + if (strlen(gecos) > MAX_FIELD_SIZE) { + if (msg != NULL) + printf("%s: ", msg); + printf("field is too long.\n"); + return -1; + } + for (i = 0; i < strlen (gecos); i++) { c = gecos[i]; if (c == ',' || c == ':' || c == '=' || c == '"' || c == '\n') { diff --git a/login-utils/chsh.1 b/login-utils/chsh.1 index 57ded2902..42e87ca60 100644 --- a/login-utils/chsh.1 +++ b/login-utils/chsh.1 @@ -10,7 +10,7 @@ .\" $Revision: 1.1 $ .\" $Date: 1995/03/12 01:28:58 $ .\" -.TH CHSH 1 "October 13 1994" "chsh" "Linux Reference Manual" +.TH CHSH 1 "7 October 1998" "chsh" "Linux Reference Manual" .SH NAME chsh \- change your login shell .SH SYNOPSIS @@ -28,6 +28,8 @@ will accept the full pathname of any executable file on the system. However, it will issue a warning if the shell is not listed in the .I /etc/shells file. +On the other hand, it can also be configured such that it will +only accept shells listed in this file, unless you are root. .SH OPTIONS .TP .I "\-s, \-\-shell" diff --git a/login-utils/chsh.c b/login-utils/chsh.c index f64cd0b78..8e8a51bc0 100644 --- a/login-utils/chsh.c +++ b/login-utils/chsh.c @@ -17,11 +17,6 @@ * suggestion from Zefram. Disallowing users with shells not in /etc/shells * from changing their shell. * - * Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - * to allow peaceful coexistence with yp: using the changes by - * Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, from - * passwd.c (now moved to setpwnam.c). Oct 5, 96. - * */ #if 0 diff --git a/login-utils/last.1.orig b/login-utils/last.1.orig deleted file mode 100644 index 4d0deb882..000000000 --- a/login-utils/last.1.orig +++ /dev/null @@ -1,49 +0,0 @@ -.TH LAST 1 "20 March 1992" -.SH NAME -last \(em indicate last logins by user or terminal -.SH SYNOPSIS -.ad l -.B last -.RB [ \-\fP\fInumber\fP ] -.RB [ \-f -.IR filename ] -.RB [ \-t -.IR tty ] -.RB [ \-h -.IR hostname ] -.RI [ name ...] -.ad b -.SH DESCRIPTION -\fBLast\fP looks back in the \fBwtmp\fP file which records all logins -and logouts for information about a user, a teletype or any group of -users and teletypes. Arguments specify names of users or teletypes of -interest. If multiple arguments are given, the information which -applies to any of the arguments is printed. For example ``\fBlast root -console\fP'' would list all of root's sessions as well as all sessions -on the console terminal. \fBLast\fP displays the sessions of the -specified users and teletypes, most recent first, indicating the times -at which the session began, the duration of the session, and the -teletype which the session took place on. If the session is still -continuing or was cut short by a reboot, \fBlast\fP so indicates. -.LP -The pseudo-user \fBreboot\fP logs in at reboots of the system. -.LP -\fBLast\fP with no arguments displays a record of all logins and -logouts, in reverse order. -.LP -If \fBlast\fP is interrupted, it indicates how far the search has -progressed in \fBwtmp\fP. If interrupted with a quit signal \fBlast\fP -indicates how far the search has progressed so far, and the search -continues. -.SH OPTIONS -.IP \fB\-\fP\fInumber\fP -limit the number of entries displayed to that specified by \fInumber\fP. -.IP "\fB\-\fP \fIfilename\fP" -Use \fIfilename\fP as the name of the accounting file instead of -.BR /etc/wtmp . -.IP "\fB\-t\fP \fItty\fP" -List only logins on \fItty\fP. -.IP "\fB\-h\fP \fIhostname\fP" -List only logins from \fhostname\fP. -.SH FILES -/etc/wtmp \(em login data base diff --git a/login-utils/last.c b/login-utils/last.c index 98ffef38f..cf59b8ea6 100644 --- a/login-utils/last.c +++ b/login-utils/last.c @@ -45,6 +45,16 @@ static struct utmp buf[1024]; /* utmp read buffer */ #define LMAX (int)sizeof(buf[0].ut_line) /* size of utmp tty field */ #define NMAX (int)sizeof(buf[0].ut_name) /* size of utmp name field */ +#ifndef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +/* maximum sizes used for printing */ +/* probably we want a two-pass version that computes the right length */ +int hmax = MIN(HMAX, 16); +int lmax = MIN(LMAX, 8); +int nmax = MIN(NMAX, 16); + typedef struct arg { char *name; /* argument */ #define HOST_TYPE -2 @@ -142,19 +152,19 @@ print_partial_line(bp) char *ct; ct = ctime(&bp->ut_time); - printf("%-*.*s %-*.*s ", NMAX, NMAX, bp->ut_name, - LMAX, LMAX, bp->ut_line); + printf("%-*.*s %-*.*s ", nmax, nmax, bp->ut_name, + lmax, lmax, bp->ut_line); if (dolong) { if (bp->ut_addr) { struct in_addr foo; foo.s_addr = bp->ut_addr; - printf("%-*.*s ", HMAX, HMAX, inet_ntoa(foo)); + printf("%-*.*s ", hmax, hmax, inet_ntoa(foo)); } else { - printf("%-*.*s ", HMAX, HMAX, ""); + printf("%-*.*s ", hmax, hmax, ""); } } else { - printf("%-*.*s ", HMAX, HMAX, bp->ut_host); + printf("%-*.*s ", hmax, hmax, bp->ut_host); } if (doyear) { @@ -178,7 +188,7 @@ wtmp() lseek(), time(); int bytes, wfd; void onintr(); - char *ct, *crmsg; + char *ct, *crmsg = NULL; if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) { perror(file); @@ -191,7 +201,7 @@ wtmp() (void)signal(SIGQUIT, onintr); while (--bl >= 0) { - if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 || + if (lseek(wfd, (long)(bl * sizeof(buf)), SEEK_SET) == -1 || (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) { fprintf(stderr, "last: %s: ", file); perror((char *)NULL); @@ -206,7 +216,7 @@ wtmp() /* * utmp(5) also mentions that the user * name should be 'shutdown' or 'reboot'. - * Not checking the name causes i.e. runlevel + * Not checking the name causes e.g. runlevel * changes to be displayed as 'crash'. -thaele */ if (!strncmp(bp->ut_user, "reboot", NMAX) || diff --git a/login-utils/last.c.orig b/login-utils/last.c.orig deleted file mode 100644 index 788aa66a0..000000000 --- a/login-utils/last.c.orig +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Berkeley. The name of the - * University may not be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -char copyright[] = -"@(#) Copyright (c) 1987 Regents of the University of California.\n\ - All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)last.c 5.11 (Berkeley) 6/29/88"; -#endif /* not lint */ - -/* - * last - */ -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/file.h> -#include <signal.h> -#include <string.h> -#include <time.h> -#include <utmp.h> -#include <stdio.h> -#include <getopt.h> -#include <stdlib.h> -#include <unistd.h> -#include "pathnames.h" - -#define SECDAY (24*60*60) /* seconds in a day */ -#define NO 0 /* false/no */ -#define YES 1 /* true/yes */ - -static struct utmp buf[1024]; /* utmp read buffer */ - -#define HMAX (int)sizeof(buf[0].ut_host) /* size of utmp host field */ -#define LMAX (int)sizeof(buf[0].ut_line) /* size of utmp tty field */ -#define NMAX (int)sizeof(buf[0].ut_name) /* size of utmp name field */ - -typedef struct arg { - char *name; /* argument */ -#define HOST_TYPE -2 -#define TTY_TYPE -3 -#define USER_TYPE -4 - int type; /* type of arg */ - struct arg *next; /* linked list pointer */ -} ARG; -ARG *arglist; /* head of linked list */ - -typedef struct ttytab { - long logout; /* log out time */ - char tty[LMAX + 1]; /* terminal name */ - struct ttytab *next; /* linked list pointer */ -} TTY; -TTY *ttylist; /* head of linked list */ - -static long currentout, /* current logout value */ - maxrec; /* records to display */ -static char *file = _PATH_WTMP; /* wtmp file */ - -static void wtmp(), addarg(), hostconv(); -static int want(); -TTY *addtty(); -static char *ttyconv(); - -int -main(argc, argv) - int argc; - char **argv; -{ - extern int optind; - extern char *optarg; - int ch; - - while ((ch = getopt(argc, argv, "0123456789f:h:t:")) != EOF) - switch((char)ch) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - /* - * kludge: last was originally designed to take - * a number after a dash. - */ - if (!maxrec) - maxrec = atol(argv[optind - 1] + 1); - break; - case 'f': - file = optarg; - break; - case 'h': - hostconv(optarg); - addarg(HOST_TYPE, optarg); - break; - case 't': - addarg(TTY_TYPE, ttyconv(optarg)); - break; - case '?': - default: - fputs("usage: last [-#] [-f file] [-t tty] [-h hostname] [user ...]\n", stderr); - exit(1); - } - for (argv += optind; *argv; ++argv) { -#define COMPATIBILITY -#ifdef COMPATIBILITY - /* code to allow "last p5" to work */ - addarg(TTY_TYPE, ttyconv(*argv)); -#endif - addarg(USER_TYPE, *argv); - } - wtmp(); - exit(0); -} - -/* - * wtmp -- - * read through the wtmp file - */ -static void -wtmp() -{ - register struct utmp *bp; /* current structure */ - register TTY *T; /* tty list entry */ - struct stat stb; /* stat of file for size */ - long bl, delta, /* time difference */ - lseek(), time(); - int bytes, wfd; - void onintr(); - char *ct, *crmsg; - - if ((wfd = open(file, O_RDONLY, 0)) < 0 || fstat(wfd, &stb) == -1) { - perror(file); - exit(1); - } - bl = (stb.st_size + sizeof(buf) - 1) / sizeof(buf); - - (void)time(&buf[0].ut_time); - (void)signal(SIGINT, onintr); - (void)signal(SIGQUIT, onintr); - - while (--bl >= 0) { - if (lseek(wfd, (long)(bl * sizeof(buf)), L_SET) == -1 || - (bytes = read(wfd, (char *)buf, sizeof(buf))) == -1) { - fprintf(stderr, "last: %s: ", file); - perror((char *)NULL); - exit(1); - } - for (bp = &buf[bytes / sizeof(buf[0]) - 1]; bp >= buf; --bp) { - /* - * if the terminal line is '~', the machine stopped. - * see utmp(5) for more info. - */ - if (!strncmp(bp->ut_line, "~", LMAX)) { - /* everybody just logged out */ - for (T = ttylist; T; T = T->next) - T->logout = -bp->ut_time; - currentout = -bp->ut_time; - crmsg = strncmp(bp->ut_name, "shutdown", NMAX) ? "crash" : "down "; - if (!bp->ut_name[0]) - (void)strcpy(bp->ut_name, "reboot"); - if (want(bp, NO)) { - ct = ctime(&bp->ut_time); - if(bp->ut_type != LOGIN_PROCESS) - printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s \n", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11); - if (maxrec && !--maxrec) - return; - } - continue; - } - /* find associated tty */ - for (T = ttylist;; T = T->next) { - if (!T) { - /* add new one */ - T = addtty(bp->ut_line); - break; - } - if (!strncmp(T->tty, bp->ut_line, LMAX)) - break; - } - if (bp->ut_name[0] && bp->ut_type != LOGIN_PROCESS - && want(bp, YES)) { - ct = ctime(&bp->ut_time); - printf("%-*.*s %-*.*s %-*.*s %10.10s %5.5s ", NMAX, NMAX, bp->ut_name, LMAX, LMAX, bp->ut_line, HMAX, HMAX, bp->ut_host, ct, ct + 11); - if (!T->logout) - puts(" still logged in"); - else { - if (T->logout < 0) { - T->logout = -T->logout; - printf("- %s", crmsg); - } - else - printf("- %5.5s", ctime(&T->logout)+11); - delta = T->logout - bp->ut_time; - if (delta < SECDAY) - printf(" (%5.5s)\n", asctime(gmtime(&delta))+11); - else - printf(" (%ld+%5.5s)\n", delta / SECDAY, asctime(gmtime(&delta))+11); - } - if (maxrec != -1 && !--maxrec) - return; - } - T->logout = bp->ut_time; - } - } - ct = ctime(&buf[0].ut_time); - printf("\nwtmp begins %10.10s %5.5s \n", ct, ct + 11); -} - -/* - * want -- - * see if want this entry - */ -static int -want(bp, check) - register struct utmp *bp; - int check; -{ - register ARG *step; - - if (check) - /* - * when uucp and ftp log in over a network, the entry in - * the utmp file is the name plus their process id. See - * etc/ftpd.c and usr.bin/uucp/uucpd.c for more information. - */ - if (!strncmp(bp->ut_line, "ftp", sizeof("ftp") - 1)) - bp->ut_line[3] = '\0'; - else if (!strncmp(bp->ut_line, "uucp", sizeof("uucp") - 1)) - bp->ut_line[4] = '\0'; - if (!arglist) - 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); - break; - case TTY_TYPE: - if (!strncmp(step->name, bp->ut_line, LMAX)) - return(YES); - break; - case USER_TYPE: - if (!strncmp(step->name, bp->ut_name, NMAX)) - return(YES); - break; - } - return(NO); -} - -/* - * addarg -- - * add an entry to a linked list of arguments - */ -static void -addarg(type, arg) - int type; - char *arg; -{ - register ARG *cur; - - if (!(cur = (ARG *)malloc((unsigned int)sizeof(ARG)))) { - fputs("last: malloc failure.\n", stderr); - exit(1); - } - cur->next = arglist; - cur->type = type; - cur->name = arg; - arglist = cur; -} - -/* - * addtty -- - * add an entry to a linked list of ttys - */ -TTY * -addtty(ttyname) - char *ttyname; -{ - register TTY *cur; - - if (!(cur = (TTY *)malloc((unsigned int)sizeof(TTY)))) { - fputs("last: malloc failure.\n", stderr); - exit(1); - } - cur->next = ttylist; - cur->logout = currentout; - memcpy(cur->tty, ttyname, LMAX); - return(ttylist = cur); -} - -/* - * hostconv -- - * convert the hostname to search pattern; if the supplied host name - * has a domain attached that is the same as the current domain, rip - * off the domain suffix since that's what login(1) does. - */ -static void -hostconv(arg) - char *arg; -{ - static int first = 1; - static char *hostdot, - name[MAXHOSTNAMELEN]; - char *argdot; - - if (!(argdot = strchr(arg, '.'))) - return; - if (first) { - first = 0; - if (gethostname(name, sizeof(name))) { - perror("last: gethostname"); - exit(1); - } - hostdot = strchr(name, '.'); - } - if (hostdot && !strcmp(hostdot, argdot)) - *argdot = '\0'; -} - -/* - * ttyconv -- - * convert tty to correct name. - */ -static char * -ttyconv(arg) - char *arg; -{ - char *mval; - - /* - * kludge -- we assume that all tty's end with - * a two character suffix. - */ - 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); - } - if (!strcmp(arg, "co")) - (void)strcpy(mval, "console"); - else { - (void)strcpy(mval, "tty"); - (void)strcpy(mval + 3, arg); - } - return(mval); - } - if (!strncmp(arg, "/dev/", sizeof("/dev/") - 1)) - return(arg + 5); - return(arg); -} - -/* - * onintr -- - * on interrupt, we inform the user how far we've gotten - */ -void -onintr(signo) - int signo; -{ - char *ct; - - ct = ctime(&buf[0].ut_time); - printf("\ninterrupted %10.10s %5.5s \n", ct, ct + 11); - if (signo == SIGINT) - exit(1); - (void)fflush(stdout); /* fix required for rsh */ -} diff --git a/login-utils/login.1 b/login-utils/login.1 index 92a082c67..a2acbd9f7 100644 --- a/login-utils/login.1 +++ b/login-utils/login.1 @@ -243,8 +243,7 @@ the user to for example run the command: xterm -e /bin/login. .PP .IP o A domain name suffix such as @.some.dom, meaning that the user may -rlogin/telnet from any host whose domain name has the suffix -.some.dom. +rlogin/telnet from any host whose domain name has the suffix .some.dom. .PP .IP o A range of IPv4 addresses, written @x.x.x.x/y.y.y.y where x.x.x.x is @@ -303,9 +302,6 @@ are allowed to log in from anywhere as is standard behavior. .BR shutdown (8) .SH BUGS -Linux, unlike other draconian operating systems, does not check -quotas. - The undocumented BSD .B \-r option is not supported. This may be required by some diff --git a/login-utils/login.c b/login-utils/login.c index ebb0a22da..c742af75c 100644 --- a/login-utils/login.c +++ b/login-utils/login.c @@ -148,6 +148,14 @@ #define SLEEP_EXIT_TIMEOUT 5 +#ifdef __linux__ +#define DO_PS_FIDDLING +#endif + +#ifdef DO_PS_FIDDLING +#include "setproctitle.h" +#endif + #if 0 /* from before we had a lastlog.h file in linux */ struct lastlog @@ -260,9 +268,7 @@ consoletty(int fd) int -main(argc, argv) - int argc; - char **argv; +main(int argc, char **argv) { extern int errno, optind; extern char *optarg, **environ; @@ -270,8 +276,8 @@ main(argc, argv) register int ch; register char *p; int ask, fflag, hflag, pflag, cnt; - int quietlog, passwd_req, ioctlval; - char *domain, *salt, *ttyn, *pp; + int quietlog, passwd_req; + char *domain, *ttyn; char tbuf[MAXPATHLEN + 2], tname[sizeof(_PATH_TTY) + 10]; char *ctime(), *ttyname(), *stypeof(); time_t time(); @@ -286,7 +292,12 @@ main(argc, argv) pam_handle_t *pamh = NULL; struct pam_conv conv = { misc_conv, NULL }; pid_t childPid; - int childStatus; + void (*oldSigHandler) (); +#else + char *salt, *pp; +#endif +#ifndef __linux__ + int ioctlval; #endif signal(SIGALRM, timedout); @@ -298,6 +309,9 @@ main(argc, argv) #ifdef HAVE_QUOTA quota(Q_SETUID, 0, 0, 0); #endif +#ifdef DO_PS_FIDDLING + initproctitle(argc, argv); +#endif /* * -p is used by getty to tell login not to destroy the environment @@ -313,6 +327,7 @@ main(argc, argv) username = tty = hostname = NULL; fflag = hflag = pflag = 0; passwd_req = 1; + while ((ch = getopt(argc, argv, "fh:p")) != EOF) switch (ch) { case 'f': @@ -353,8 +368,13 @@ main(argc, argv) argc -= optind; argv += optind; if (*argv) { - username = *argv; + char *p = *argv; + username = strdup(p); ask = 0; + /* wipe name - some people mistype their password here */ + /* (of course we are too late, but perhaps this helps a little ..) */ + while(*p) + *p++ = ' '; } else ask = 1; @@ -377,7 +397,7 @@ main(argc, argv) */ ioctlval = 0; ioctl(0, FIOSNBIO, &ioctlval); -#endif +#endif /* ! __linux__ */ for (cnt = getdtablesize(); cnt > 2; cnt--) close(cnt); @@ -472,7 +492,7 @@ main(argc, argv) (retcode == PAM_AUTHINFO_UNAVAIL))) { pam_get_item(pamh, PAM_USER, (const void **) &username); syslog(LOG_NOTICE,"FAILED LOGIN %d FROM %s FOR %s, %s", - failcount, hostname,username,pam_strerror(pamh, retcode)); + failcount, hostname, username, pam_strerror(pamh, retcode)); fprintf(stderr,"Login incorrect\n\n"); pam_set_item(pamh,PAM_USER,NULL); retcode = pam_authenticate(pamh, 0); @@ -520,8 +540,8 @@ main(argc, argv) #else /* ! USE_PAM */ for (cnt = 0;; ask = 1) { - ioctlval = 0; # ifndef __linux__ + ioctlval = 0; ioctl(0, TIOCSETD, &ioctlval); # endif @@ -770,7 +790,7 @@ main(argc, argv) utmp.ut_line[sizeof(utmp.ut_line)-1] = 0; login(&utmp); } -#else +#else /* __linux__ defined */ /* for linux, write entries in utmp and wtmp */ { struct utmp ut; @@ -781,8 +801,19 @@ main(argc, argv) utmpname(_PATH_UTMP); setutent(); - while ((utp = getutent()) - && !(utp->ut_pid == mypid)) /* nothing */; + + /* Find mypid in utmp. +login sometimes overwrites the runlevel entry in /var/run/utmp, +confusing sysvinit. I added a test for the entry type, and the problem +was gone. (In a runlevel entry, st_pid is not really a pid but some number +calculated from the previous and current runlevel). +Michael Riepe <michael@stud.uni-hannover.de> + */ + while ((utp = getutent())) + if (utp->ut_pid == mypid + && utp->ut_type >= INIT_PROCESS + && utp->ut_type <= DEAD_PROCESS) + break; if (utp) { memcpy(&ut, utp, sizeof(ut)); @@ -813,7 +844,20 @@ main(argc, argv) pututline(&ut); endutent(); - + +#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 1) + updwtmp(_PATH_WTMP, &ut); +#else +#if 0 + /* The O_APPEND open() flag should be enough to guarantee + atomic writes at end of file. */ + if((wtmp = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) { + write(wtmp, (char *)&ut, sizeof(ut)); + close(wtmp); + } +#else + /* Probably all this locking below is just nonsense, + and the short version is OK as well. */ { int lf; if ((lf = open(_PATH_WTMPLOCK, O_CREAT|O_WRONLY, 0660)) >= 0) { @@ -826,8 +870,10 @@ main(argc, argv) close(lf); } } - } #endif +#endif /* __GLIBC__ */ + } +#endif /* __linux__ */ dolastlog(quietlog); @@ -903,7 +949,8 @@ main(argc, argv) setenv("TERM", termenv, 1); /* mailx will give a funny error msg if you forget this one */ - { char tmp[MAXPATHLEN]; + { + char tmp[MAXPATHLEN]; /* avoid snprintf */ if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < MAXPATHLEN) { sprintf(tmp, "%s/%s", _PATH_MAILDIR, pwd->pw_name); @@ -932,6 +979,10 @@ main(argc, argv) } } #endif + +#ifdef DO_PS_FIDDLING + setproctitle("login", username); +#endif if (tty[sizeof("tty")-1] == 'S') syslog(LOG_INFO, "DIALUP AT %s BY %s", tty, pwd->pw_name); @@ -956,41 +1007,53 @@ main(argc, argv) if (!quietlog) { struct stat st; + char *mail; motd(); - /* avoid snprintf */ - if (sizeof(_PATH_MAILDIR) + strlen(pwd->pw_name) + 1 < sizeof(tbuf)) { - sprintf(tbuf, "%s/%s", _PATH_MAILDIR, pwd->pw_name); - if (stat(tbuf, &st) == 0 && st.st_size != 0) - printf("You have %smail.\n", - (st.st_mtime > st.st_atime) ? "new " : ""); + mail = getenv("MAIL"); + if (mail && stat(mail, &st) == 0 && st.st_size != 0) { + printf("You have %smail.\n", + (st.st_mtime > st.st_atime) ? "new " : ""); } } signal(SIGALRM, SIG_DFL); signal(SIGQUIT, SIG_DFL); - signal(SIGINT, SIG_DFL); signal(SIGTSTP, SIG_IGN); signal(SIGHUP, SIG_DFL); + +#ifdef USE_PAM + /* We must fork before setuid() because we need to call + * pam_close_session() as root. + */ + signal(SIGINT, SIG_IGN); + childPid = fork(); + if (childPid < 0) { + /* error in fork() */ + fprintf(stderr,"login: failure forking: %s", strerror(errno)); + PAM_END; + exit(0); + } else if (childPid) { + /* parent - wait for child to finish, then cleanup session */ + wait(NULL); + PAM_END; + exit(0); + } + /* child */ +#endif + signal(SIGINT, SIG_DFL); /* 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"); -#ifdef USE_PAM - PAM_END; -#endif exit(1); } /* wait until here to change directory! */ if (chdir(pwd->pw_dir) < 0) { printf("No directory %s!\n", pwd->pw_dir); - if (chdir("/")) { -#ifdef USE_PAM - PAM_END; -#endif + if (chdir("/")) exit(0); - } pwd->pw_dir = "/"; printf("Logging in with home = \"/\".\n"); } @@ -1023,15 +1086,6 @@ main(argc, argv) childArgv[childArgc++] = NULL; -#ifdef USE_PAM - /* There was some junk with fork()/exec()/signal()/wait() here - that was incorrect, and util-linux-2.7-11.src.rpm contains - a patch that makes the fork entirely useless. - If you introduce one again, please document in the source - what its purpose is. - aeb */ - PAM_END; -#endif /* USE_PAM */ - execvp(childArgv[0], childArgv + 1); if (!strcmp(childArgv[0], "/bin/sh")) @@ -1070,7 +1124,7 @@ getloginname() exit(0); } } - if (p > nbuf) + if (p > nbuf) { if (nbuf[0] == '-') fprintf(stderr, "login names may not start with '-'.\n"); @@ -1079,6 +1133,7 @@ getloginname() username = nbuf; break; } + } cnt2++; if (cnt2 > 50) { @@ -1190,7 +1245,7 @@ dolastlog(quiet) int fd; if ((fd = open(_PATH_LASTLOG, O_RDWR, 0)) >= 0) { - lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); if (!quiet) { if (read(fd, (char *)&ll, sizeof(ll)) == sizeof(ll) && ll.ll_time != 0) { @@ -1204,7 +1259,7 @@ dolastlog(quiet) printf("on %.*s\n", (int)sizeof(ll.ll_line), ll.ll_line); } - lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), L_SET); + lseek(fd, (off_t)pwd->pw_uid * sizeof(ll), SEEK_SET); } memset((char *)&ll, 0, sizeof(ll)); time(&ll.ll_time); diff --git a/login-utils/passwd.1 b/login-utils/passwd.1 index db44aa8e9..b6a25a3f6 100644 --- a/login-utils/passwd.1 +++ b/login-utils/passwd.1 @@ -34,10 +34,8 @@ reasons to choose a non-conformant password. The two argument form gives the .IR user " the " password -stated as the second argument. This may be useful when giving many -users an initial generated password. But it can also be extremely -dangerous. A simple script bug might change to root password to -something unknown. +stated as the second argument. Note that this password will +be visible to people doing `ps' or so. Avoid this form. Giving an empty string as the second argument erases the password for the user, but only in combination with the @@ -111,6 +109,3 @@ Peter Orbaek (poe@daimi.aau.dk). .br Martin Schulze (joey@infodrom.north.de) with extensive rewriting and improving done. -.br -.SH MAINTAINER -Nicolai Langfeldt (janl@math.uio.no) diff --git a/login-utils/passwd.c b/login-utils/passwd.c index 4ed1b74d7..0057a283b 100644 --- a/login-utils/passwd.c +++ b/login-utils/passwd.c @@ -3,17 +3,12 @@ * * Initially written for Linux by Peter Orbaek <poe@daimi.aau.dk> * Currently maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/ - - Hacked by Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, - to allow peaceful coexistence with yp. Nov 94. - - Hacked to allow root to set passwd from command line. - by Arpad Magossanyi (mag@tas.vein.hu) - - Hacked by Peter Breitenlohner, peb@mppmu.mpg.de, - moved Alvaro's changes to setpwnam.c (so they get used - by chsh and chfn as well). Oct 5, 96. - + * + * Hacked by Alvaro Martinez Echevarria, alvaro@enano.etsit.upm.es, + * to allow peaceful coexistence with yp. Nov 94. + * + * Hacked to allow root to set passwd from command line. + * by Arpad Magossanyi (mag@tas.vein.hu) */ /* @@ -26,7 +21,7 @@ or running a background job that just collects all command lines) * work and second I wanted simplicity checks to be done for - * root, too. Only root can turn this of using the -f + * root, too. Only root can turn this off using the -f * switch. Okay, I started with this to support -V version * information, but one thing comes to the next. *sigh* * In a later step perhaps we'll be able to support shadow diff --git a/login-utils/shutdown.8 b/login-utils/shutdown.8 index 443acc2af..961579bdc 100644 --- a/login-utils/shutdown.8 +++ b/login-utils/shutdown.8 @@ -1,6 +1,8 @@ .\" Copyright 1992 Rickard E. Faith (faith@cs.unc.edu) .\" May be distributed under the GNU General Public License -.TH SHUTDOWN 8 "20 November 1993" "Linux 1.2" "Linux Programmer's Manual" +.\" +.\" +.TH SHUTDOWN 8 "24 July 1998" "Linux 2.0" "Linux Programmer's Manual" .SH NAME shutdown \- close down the system .SH SYNOPSIS @@ -98,7 +100,29 @@ detects (and deletes). .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), @@ -112,6 +136,6 @@ 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 -Peter Orbaek (poe@daimi.aau.dk) -.br -Modified by jrs@world.std.com +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 index a63cbd6e9..8ba13b647 100644 --- a/login-utils/shutdown.c +++ b/login-utils/shutdown.c @@ -1,6 +1,6 @@ /* shutdown.c - shutdown a Linux system * Initially written by poe@daimi.aau.dk - * Currently maintained at ftp://ftp.daimi.aau.dk/pub/linux/poe/ + * Currently maintained at ftp://ftp.daimi.aau.dk/pub/Software/Linux/ */ /* @@ -24,6 +24,9 @@ * 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. */ #include <stdio.h> @@ -35,6 +38,7 @@ #include <string.h> #include <ctype.h> #include <signal.h> +#include <errno.h> #include <sys/param.h> #include <termios.h> #include <mntent.h> @@ -42,11 +46,12 @@ #include <sys/wait.h> #include <syslog.h> #include <sys/resource.h> +#include "linux_reboot.h" #include "pathnames.h" -void usage(), int_handler(), write_user(struct utmp *); -void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves(); -void swap_off(); +static void usage(), int_handler(), write_user(struct utmp *); +static void wall(), write_wtmp(), unmount_disks(), unmount_disks_ourselves(); +static void swap_off(), do_halt(char *); char *prog; /* name of the program */ int opt_reboot; /* true if -r option or reboot command */ @@ -57,10 +62,15 @@ 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 ERRSTRING sys_errlist[errno] + void usage() @@ -70,19 +80,31 @@ usage() exit(1); } +void +my_puts(char *s) +{ + /* Use a fresh stdout after forking */ + freopen(_PATH_CONSOLE, "w", stdout); + puts(s); + fflush(stdout); +} + void int_handler() { unlink(_PATH_NOLOGIN); signal(SIGINT, SIG_DFL); - puts("Shutdown process aborted\n"); + my_puts("Shutdown process aborted"); exit(1); } int -main(argc, argv) - int argc; - char *argv[]; +iswhitespace(int a) { + return (a == ' ' || a == '\t'); +} + +int +main(int argc, char *argv[]) { int c,i; int fd; @@ -90,7 +112,8 @@ main(argc, argv) #ifndef DEBUGGING if(geteuid()) { - fprintf(stderr, "%s: Only root can shut a system down.\n", argv[0]); + fprintf(stderr, "%s: Only root can shut a system down.\n", + argv[0]); exit(1); } #endif @@ -98,7 +121,10 @@ main(argc, argv) 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; @@ -114,78 +140,105 @@ main(argc, argv) opt_quiet = 1; opt_fast = 0; timeout = 0; - if(argc > 1 && !strcmp(argv[1], "-s")) opt_single = 1; } else if(!strcmp("fastboot", prog)) { opt_reboot = 1; opt_quiet = 1; opt_fast = 1; timeout = 0; - if(argc > 1 && !strcmp(argv[1], "-s")) opt_single = 1; } 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++) { + c = 0; + while(++c < argc) { + if(argv[c][0] == '-') { + for(i = 1; argv[c][i]; i++) { switch(argv[c][i]) { - 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; + 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(); + 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; + } + } 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(); + if((colon = strchr(argv[c], ':'))) { + *colon = '\0'; + hour = atoi(argv[c]); + minute = atoi(++colon); + } else usage(); - (void) time(&tics); - tt = localtime(&tics); + (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 { - strncpy(message, argv[c], sizeof(message)); - message[sizeof(message)-1] = '\0'; - opt_msgset = 1; + 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 { + strncpy(message, argv[c], sizeof(message)); + message[sizeof(message)-1] = '\0'; + 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 = line+11; + while(iswhitespace(*p)) + p++; + strcpy(halt_action, p); } + fclose (fp); } } @@ -212,6 +265,7 @@ main(argc, argv) /* so much for option-processing, now begin termination... */ if(!(whom = getlogin())) whom = "ghost"; + if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */ setpriority(PRIO_PROCESS, 0, PRIO_MIN); signal(SIGINT, int_handler); @@ -261,7 +315,8 @@ main(argc, argv) kill(1, SIGTSTP); /* tell init not to spawn more getty's */ write_wtmp(); if(opt_single) - close(open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)); + if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0) + close(fd); sync(); @@ -272,7 +327,7 @@ main(argc, argv) #ifndef DEBUGGING /* a gentle kill of all other processes except init */ kill(-1, SIGTERM); - sleep(2); + sleep(2); /* default 2, some people need 5 */ /* now use brute force... */ kill(-1, SIGKILL); @@ -292,14 +347,14 @@ main(argc, argv) sleep(1); if(opt_reboot) { - reboot(0xfee1dead, 672274793, 0x1234567); + my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */ + my_puts("\nWhy am I still alive after reboot?"); } else { - freopen(_PATH_CONSOLE, "w", stdout); - printf("\nNow you can turn off the power...\n"); - fflush(stdout); + my_puts("\nNow you can turn off the power..."); + /* allow C-A-D now, faith@cs.unc.edu, re-fixed 8-Jul-96 */ - reboot(0xfee1dead, 672274793, 0x89abcdef); - reboot(0xfee1dead, 672274793, 0xcdef0123); + my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */ + do_halt(halt_action); } /* NOTREACHED */ exit(0); /* to quiet gcc */ @@ -308,6 +363,31 @@ main(argc, argv) /*** 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; @@ -319,7 +399,7 @@ write_user(struct utmp *ut) (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_RDWR|O_NONBLOCK)) < 0) + if((fd = open(term, O_WRONLY|O_NONBLOCK)) < 0) return; sprintf(msg, "\007\r\nURGENT: broadcast message from %s:\r\n", whom); @@ -393,7 +473,7 @@ swap_off() sync(); if ((pid = fork()) < 0) { - printf("Cannot fork for swapoff. Shrug!\n"); + my_puts("Cannot fork for swapoff. Shrug!"); return; } if (!pid) { @@ -401,7 +481,8 @@ swap_off() execl("/etc/swapoff", SWAPOFF_ARGS, NULL); execl("/bin/swapoff", SWAPOFF_ARGS, NULL); execlp("swapoff", SWAPOFF_ARGS, NULL); - puts("Cannot exec swapoff, hoping umount will do the trick."); + my_puts("Cannot exec swapoff, " + "hoping umount will do the trick."); exit(0); } while ((result = wait(&status)) != -1 && result != pid) @@ -419,20 +500,20 @@ unmount_disks() sync(); if ((pid = fork()) < 0) { - printf("Cannot fork for umount, trying manually.\n"); + my_puts("Cannot fork for umount, trying manually."); unmount_disks_ourselves(); return; } if (!pid) { execl(_PATH_UMOUNT, UMOUNT_ARGS, NULL); - printf("Cannot exec %s, trying umount.\n", _PATH_UMOUNT); + my_puts("Cannot exec " _PATH_UMOUNT ", trying umount."); execlp("umount", UMOUNT_ARGS, NULL); - puts("Cannot exec umount, giving up on umount."); + my_puts("Cannot exec umount, giving up on umount."); exit(0); } while ((result = wait(&status)) != -1 && result != pid) ; - puts("Unmounting any remaining filesystems..."); + my_puts("Unmounting any remaining filesystems..."); unmount_disks_ourselves(); } @@ -450,7 +531,7 @@ unmount_disks_ourselves() sync(); if (!(mtab = setmntent(_PATH_MTAB, "r"))) { - printf("shutdown: Cannot open %s.\n", _PATH_MTAB); + my_puts("shutdown: Cannot open " _PATH_MTAB "."); return; } n = 0; diff --git a/login-utils/simpleinit.c b/login-utils/simpleinit.c index 14d8cfad2..1664404c3 100644 --- a/login-utils/simpleinit.c +++ b/login-utils/simpleinit.c @@ -16,10 +16,11 @@ #include <sys/sysmacros.h> #include <utmp.h> #ifdef SHADOW_PWD -#include <shadow.h> +# include <shadow.h> #endif - +#include "my_crypt.h" #include "pathnames.h" +#include "linux_reboot.h" #define CMDSIZ 150 /* max size of a line in inittab */ #define NUMCMD 30 /* max number of lines in inittab */ @@ -411,13 +412,14 @@ void int_handler() sync(); sync(); - if((pid = fork()) == 0) { - /* reboot properly... */ + pid = fork(); + if (pid > 0) + return; + if (pid == 0) /* reboot properly... */ execl(_PATH_REBOOT, _PATH_REBOOT, (char *)0); - reboot(0xfee1dead, 672274793, 0x1234567); - } else if(pid < 0) - /* fork failed, try the hard way... */ - reboot(0xfee1dead, 672274793, 0x1234567); + + /* fork or exec failed, try the hard way... */ + my_reboot(LINUX_REBOOT_CMD_RESTART); } void set_tz() diff --git a/login-utils/vipw.c b/login-utils/vipw.c index a5763b105..50270a6e3 100644 --- a/login-utils/vipw.c +++ b/login-utils/vipw.c @@ -190,15 +190,14 @@ pw_unlock() void -pw_edit(notsetuid) - int notsetuid; +pw_edit(int notsetuid) { int pstat; pid_t pid; char *p, *editor; if (!(editor = getenv("EDITOR"))) - editor = _PATH_VI; + editor = strdup(_PATH_VI); /* adia@egnatia.ee.auth.gr */ if ((p = strrchr(strtok(editor," \t"), '/')) != NULL) ++p; else |