Remove unused variable realuid from main().
[sysvinit.git] / src / shutdown.c
index 093a05395e94ce8b9c01b3aa10fe2abd37baaa61..11c616fecc6ad8c9f8b1f227674c4e85fcb2965b 100644 (file)
  *             along with this program; if not, write to the Free Software
  *             Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
+#ifndef _GNU_SOURCE
+# define _GNU_SOURCE   /* otherwise `extern char **environ' is missed */
+#endif
+#ifndef ACCTON_OFF
+# define ACCTON_OFF    0
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
 #include <time.h>
 #include <string.h>
+#include <errno.h>
 #include <unistd.h>
 #include <errno.h>
 #include <stdlib.h>
@@ -49,6 +56,8 @@
 #include "paths.h"
 #include "reboot.h"
 #include "initreq.h"
+#include "init.h"
+
 
 char *Version = "@(#) shutdown 2.86-1 31-Jul-2004 miquels@cistron.nl";
 
@@ -67,14 +76,12 @@ int got_alrm = 0;
 
 char *clean_env[] = {
        "HOME=/",
-       "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
+       "PATH=" PATH_DEFAULT,
        "TERM=dumb",
+       "SHELL=/bin/sh",
        NULL,
 };
 
-/* From "wall.c" */
-extern void wall(char *, int, int);
-
 /* From "utmp.c" */
 extern void write_wtmp(char *user, char *id, int pid, int type, char *line);
 
@@ -95,7 +102,12 @@ void hardsleep(int secs)
 /*
  *     Break off an already running shutdown.
  */
+# ifdef __GNUC__
+void stopit(int sig __attribute__((unused)))
+# else
 void stopit(int sig)
+# endif
+
 {
        unlink(NOLOGIN);
        unlink(FASTBOOT);
@@ -111,7 +123,7 @@ void stopit(int sig)
 void usage(void)
 {
        fprintf(stderr,
-       "Usage:\t  shutdown [-akrhHPfnc] [-t secs] time [warning message]\n"
+       "Usage:\t  shutdown [-akrhPHfFnc] [-t sec] time [warning message]\n"
        "\t\t  -a:      use /etc/shutdown.allow\n"
        "\t\t  -k:      don't really shutdown, only warn.\n"
        "\t\t  -r:      reboot after shutdown.\n"
@@ -142,7 +154,7 @@ int init_setenv(char *name, char *value)
        struct init_request     request;
        struct sigaction        sa;
        int                     fd;
-       int                     nl, vl;
+       size_t                  nl, vl;
 
        memset(&request, 0, sizeof(request));
        request.magic = INIT_MAGIC;
@@ -167,29 +179,41 @@ int init_setenv(char *name, char *value)
        sa.sa_handler = alrm_handler;
        sigaction(SIGALRM, &sa, NULL);
        got_alrm = 0;
-        alarm(3);
-        if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
-            write(fd, &request, sizeof(request)) == sizeof(request)) {
-                close(fd);
-                alarm(0);
-                return 0;
-        }
+       alarm(3);
+       if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
+               ssize_t p = 0;
+               size_t s  = sizeof(request);
+               void *ptr = &request;
+               while (s > 0) {
+                       p = write(fd, ptr, s);
+                       if (p < 0) {
+                               if (errno == EINTR || errno == EAGAIN)
+                                       continue;
+                               break;
+                       }
+                       ptr += p;
+                       s -= p;
+               }
+               close(fd);
+               alarm(0);
+               return 0;
+       }
                                                                                 
-        fprintf(stderr, "shutdown: ");
-        if (got_alrm) {
-                fprintf(stderr, "timeout opening/writing control channel %s\n",
-                        INIT_FIFO);
-        } else {
-                perror(INIT_FIFO);
-        }
-        return -1;
+       fprintf(stderr, "shutdown: ");
+       if (got_alrm) {
+               fprintf(stderr, "timeout opening/writing control channel %s\n",
+                       INIT_FIFO);
+       } else {
+               perror(INIT_FIFO);
+       }
+       return -1;
 }
 
 
 /*
  *     Tell everyone the system is going down in 'mins' minutes.
  */
-void warn(int mins)
+void issue_warn(int mins)
 {
        char buf[MESSAGELEN + sizeof(newstate)];
        int len;
@@ -206,7 +230,7 @@ void warn(int mins)
                snprintf(buf + len, sizeof(buf) - len,
                        "\rThe system is going DOWN %s in %d minute%s!\r\n",
                                newstate, mins, mins == 1 ? "" : "s");
-       wall(buf, 1, 0);
+       wall(buf, 0);
 }
 
 /*
@@ -262,7 +286,8 @@ int spawn(int noerr, char *prog, ...)
        argv[i] = NULL;
        va_end(ap);
 
-       chdir("/");
+       if (chdir("/"))
+               exit(1);
        environ = clean_env;
 
        execvp(argv[0], argv);
@@ -313,7 +338,7 @@ void fastdown()
 
        /* First idle init. */
        if (kill(1, SIGTSTP) < 0) {
-               fprintf(stderr, "shutdown: can't idle init.\r\n");
+               fprintf(stderr, "shutdown: can't idle init: %s.\r\n", strerror(errno));
                exit(1);
        }
 
@@ -340,7 +365,17 @@ void fastdown()
        write_wtmp("shutdown", "~~", 0, RUN_LVL, "~~");
 
        /* This is for those who have quota installed. */
+#if defined(ACCTON_OFF)
+# if (ACCTON_OFF > 1) && (_BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500))
+       /* This is an alternative way to disable accounting, saving a fork() */
+       if (acct(NULL))
+               fprintf(stderr, "shutdown: can not stop process accounting: %s.\r\n", strerror(errno));
+# elif (ACCTON_OFF > 0)
+       spawn(1, "accton", "off", NULL);
+# else
        spawn(1, "accton", NULL);
+# endif
+#endif
        spawn(1, "quotaoff", "-a", NULL);
 
        sync();
@@ -365,14 +400,14 @@ void fastdown()
 /*
  *     Go to runlevel 0, 1 or 6.
  */
-void shutdown(char *halttype)
+void issue_shutdown(char *halttype)
 {
        char    *args[8];
        int     argp = 0;
        int     do_halt = (down_level[0] == '0');
 
        /* Warn for the last time */
-       warn(0);
+       issue_warn(0);
        if (dontshut) {
                hardsleep(1);
                stopit(0);
@@ -448,7 +483,6 @@ int main(int argc, char **argv)
        struct stat             st;
        struct utmp             *ut;
        time_t                  t;
-       uid_t                   realuid;
        char                    *halttype;
        char                    *downusers[32];
        char                    buf[128];
@@ -464,7 +498,6 @@ int main(int argc, char **argv)
        int                     user_ok = 0;
 
        /* We can be installed setuid root (executable for a special group) */
-       realuid = getuid();
        setuid(geteuid());
 
        if (getuid() != 0) {
@@ -593,7 +626,8 @@ int main(int argc, char **argv)
 
        /* Read pid of running shutdown from a file */
        if ((fp = fopen(SDPID, "r")) != NULL) {
-               fscanf(fp, "%d", &pid);
+               if (fscanf(fp, "%d", &pid) != 1)
+                       pid = 0;
                fclose(fp);
        }
 
@@ -619,7 +653,7 @@ int main(int argc, char **argv)
                        fprintf(stderr, "shutdown: not running.\n");
                        exit(1);
                }
-               if (message[0]) wall(message, 1, 0);
+               if (message[0]) wall(message, 0);
                exit(0);
        }
   
@@ -658,6 +692,12 @@ int main(int argc, char **argv)
                        break;
        }
 
+       /* Go to the root directory */
+       if (chdir("/")) {
+               fprintf(stderr, "shutdown: chdir(/): %m\n");
+               exit(1);
+       }
+
        /* Create a new PID file. */
        unlink(SDPID);
        umask(022);
@@ -681,8 +721,6 @@ int main(int argc, char **argv)
        sa.sa_handler = stopit;
        sigaction(SIGINT, &sa, NULL);
 
-       /* Go to the root directory */
-       chdir("/");
        if (fastboot)  close(open(FASTBOOT,  O_CREAT | O_RDWR, 0644));
        if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644));
 
@@ -709,20 +747,20 @@ int main(int argc, char **argv)
                if (wt < 0) wt += 1440;
        }
        /* Shutdown NOW if time == 0 */
-       if (wt == 0) shutdown(halttype);
+       if (wt == 0) issue_shutdown(halttype);
 
        /* Give warnings on regular intervals and finally shutdown. */
-       if (wt < 15 && !needwarning(wt)) warn(wt);
+       if (wt < 15 && !needwarning(wt)) issue_warn(wt);
        while(wt) {
                if (wt <= 5 && !didnolog) {
                        donologin(wt);
                        didnolog++;
                }
-               if (needwarning(wt)) warn(wt);
+               if (needwarning(wt)) issue_warn(wt);
                hardsleep(60);
                wt--;
        }
-       shutdown(halttype);
+       issue_shutdown(halttype);
 
        return 0; /* Never happens */
 }