Hello community,

here is the log from the commit of package sysvinit for openSUSE:Factory 
checked in at 2020-12-09 22:12:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/sysvinit (Old)
 and      /work/SRC/openSUSE:Factory/.sysvinit.new.2328 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "sysvinit"

Wed Dec  9 22:12:12 2020 rev:173 rq:853762 version:2.98

Changes:
--------
--- /work/SRC/openSUSE:Factory/sysvinit/sysvinit.changes        2020-10-07 
14:16:13.945378132 +0200
+++ /work/SRC/openSUSE:Factory/.sysvinit.new.2328/sysvinit.changes      
2020-12-09 22:12:13.675116097 +0100
@@ -1,0 +2,8 @@
+Tue Nov 17 11:26:22 UTC 2020 - Dr. Werner Fink <wer...@suse.de>
+
+- Update to sysvinit 2.98:
+  * Fixed time parsing in shutdown when there is a + in front of a 0 time 
offset.
+    Commands with a postiive time offset (+1) would work but +0 fails.
+    This has been corrected by Arkadiusz Miskiewicz.
+
+-------------------------------------------------------------------

Old:
----
  sysvinit-2.97.tar.xz

New:
----
  sysvinit-2.98.tar.xz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ sysvinit.spec ++++++
--- /var/tmp/diff_new_pack.9eYeDQ/_old  2020-12-09 22:12:14.407116840 +0100
+++ /var/tmp/diff_new_pack.9eYeDQ/_new  2020-12-09 22:12:14.411116843 +0100
@@ -18,7 +18,7 @@
 
 Name:           sysvinit
 %define KPVER  2.23
-%define SIVER  2.97
+%define SIVER  2.98
 %define START  0.65
 Version:        %{SIVER}
 Release:        0

++++++ sysvinit-2.97.tar.xz -> sysvinit-2.98.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sysvinit-2.97/doc/Changelog 
new/sysvinit-2.98/doc/Changelog
--- old/sysvinit-2.97/doc/Changelog     2020-07-07 01:53:15.000000000 +0200
+++ new/sysvinit-2.98/doc/Changelog     2020-11-17 02:52:07.000000000 +0100
@@ -1,4 +1,10 @@
-sysvinit (2.97) unreleased; urgency=low
+sysvinit (2.98) released; urgency=low
+
+    * Fixed time parsing in shutdown when there is a + in front of a 0 time 
offset.
+      Commands with a postiive time offset (+1) would work but +0 fails.
+      This has been corrected by Arkadiusz Miskiewicz.
+
+sysvinit (2.97) released; urgency=low
 
     * Check $(ROOT) filesystem for libcrypt instead of a hardcoded path to 
/usr.
       Added logsave and readbootlog to list of files git ignores.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sysvinit-2.97/src/shutdown.c 
new/sysvinit-2.98/src/shutdown.c
--- old/sysvinit-2.97/src/shutdown.c    2020-07-07 01:53:15.000000000 +0200
+++ new/sysvinit-2.98/src/shutdown.c    2020-11-17 02:52:07.000000000 +0100
@@ -777,16 +777,18 @@
        if (!strcmp(when, "now")) strcpy(when, "0");
 
         sp = when;
-       if (when[0] == '+') sp++;
-       /* Decode shutdown time. */
+       /* Validate time argument. */
        for ( ; *sp; sp++) {
-               if (*sp != ':' && (*sp < '0' || *sp > '9'))
+               if (*sp != '+' && *sp != ':' && (*sp < '0' || *sp > '9'))
                        usage();
        }
+       sp = when;
+       /* Decode shutdown time. */
+       if (when[0] == '+') sp++;
        if (strchr(when, ':') == NULL) {
                /* Time in minutes. */
-               wt = atoi(when);
-               if (wt == 0 && when[0] != '0') usage();
+               wt = atoi(sp);
+               if (wt == 0 && sp[0] != '0') usage();
        } else {
                if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage();
                /* Time in hh:mm format. */
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/sysvinit-2.97/src/shutdown.c.orig 
new/sysvinit-2.98/src/shutdown.c.orig
--- old/sysvinit-2.97/src/shutdown.c.orig       1970-01-01 01:00:00.000000000 
+0100
+++ new/sysvinit-2.98/src/shutdown.c.orig       2020-11-17 02:52:07.000000000 
+0100
@@ -0,0 +1,844 @@
+/*
+ * shutdown.c  Shut the system down.
+ *
+ * Usage:      shutdown [-krhfnc] time [warning message]
+ *               -k: don't really shutdown, only warn.
+ *               -r: reboot after shutdown.
+ *               -h: halt after shutdown.
+ *               -f: do a 'fast' reboot (skip fsck).
+ *               -F: Force fsck on reboot.
+ *               -n: do not go through init but do it ourselves.
+ *               -c: cancel an already running shutdown.
+ *               -t secs: delay between SIGTERM and SIGKILL for init.
+ *
+ * Author:     Miquel van Smoorenburg, miqu...@cistron.nl
+ *
+ * Version:    @(#)shutdown  2.86-1  31-Jul-2004  miqu...@cistron.nl
+ *
+ *             This file is part of the sysvinit suite,
+ *             Copyright (C) 1991-2004 Miquel van Smoorenburg.
+ *
+ *             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., 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>
+#ifdef __linux__
+#include <sys/sysmacros.h>   /* brought in my LFS patch */
+#endif
+#include <time.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h> 
+#include <signal.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#ifdef __FreeBSD__
+#include <utmpx.h>
+#else
+#include <utmp.h>
+#endif
+#include <syslog.h>
+#include "paths.h"
+#include "reboot.h"
+#include "initreq.h"
+#include "init.h"
+
+#ifdef __FreeBSD__
+extern char **environ;
+#endif
+
+#define MESSAGELEN     256
+#define STATELEN        64
+#define WHEN_SIZE       64
+
+/* Whether we should warn system is shutting down */
+#define QUIET_FULL 2
+#define QUIET_PARTIAL 1
+#define QUIET_NONE 0
+
+int dontshut = 0;      /* Don't shutdown, only warn    */
+char down_level[2];    /* What runlevel to go to.      */
+int dosync = 1;                /* Sync before reboot or halt   */
+int fastboot = 0;      /* Do a 'fast' reboot           */
+int forcefsck = 0;     /* Force fsck on reboot         */
+char message[MESSAGELEN];      /* Warning message      */
+char *sltime = 0;      /* Sleep time                   */
+char newstate[STATELEN];       /* What are we gonna do         */
+int doself = 0;                /* Don't use init               */
+int got_alrm = 0;
+
+char *clean_env[] = {
+       "HOME=/",
+       "PATH=" PATH_DEFAULT,
+       "TERM=dumb",
+       "SHELL=/bin/sh",
+       NULL,
+};
+
+/* From "utmp.c" */
+extern void write_wtmp(char *user, char *id, int pid, int type, char *line);
+
+/*
+ *     Sleep without being interrupted.
+ */
+void hardsleep(int secs)
+{
+       struct timespec ts, rem;
+
+       ts.tv_sec = secs;
+       ts.tv_nsec = 0;
+
+       while(nanosleep(&ts, &rem) < 0 && errno == EINTR)
+               ts = rem;
+}
+
+/*
+ *     Break off an already running shutdown.
+ */
+# ifdef __GNUC__
+void stopit(int sig __attribute__((unused)))
+# else
+void stopit(int sig)
+# endif
+
+{
+       unlink(NOLOGIN);
+       unlink(FASTBOOT);
+       unlink(FORCEFSCK);
+       unlink(SDPID);
+       printf("\r\nShutdown cancelled.\r\n");
+       exit(0);
+}
+
+/*
+ *     Show usage message.
+ */
+void usage(void)
+{
+       fprintf(stderr,
+       "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"
+       "\t\t  -h:      halt after shutdown.\n"
+       "\t\t  -P:      halt action is to turn off power.\n"
+        "\t\t           can only be used along with -h flag.\n"
+       "\t\t  -H:      halt action is to just halt.\n"
+        "\t\t           can only be used along with -h flag.\n"
+       "\t\t  -f:      do a 'fast' reboot (skip fsck).\n"
+       "\t\t  -F:      Force fsck on reboot.\n"
+       "\t\t  -n:      do not go through \"init\" but go down real fast.\n"
+       "\t\t  -c:      cancel a running shutdown.\n"
+        "\t\t  -q:      quiet mode - display fewer shutdown warnings.\n"
+        "\t\t  -Q:      full quiet mode - display only final shutdown 
warning.\n"
+       "\t\t  -t secs: delay between warning and kill signal.\n"
+       "\t\t  ** the \"time\" argument is mandatory! (try \"now\") **\n");
+       exit(1);
+}
+
+
+void alrm_handler(int sig)
+{
+       got_alrm = sig;
+}
+
+
+/*
+ *     Set environment variables in the init process.
+ */
+int init_setenv(char *name, char *value)
+{
+       struct init_request     request;
+       struct sigaction        sa;
+       int                     fd;
+       size_t                  nl, vl;
+
+       memset(&request, 0, sizeof(request));
+       request.magic = INIT_MAGIC;
+       request.cmd = INIT_CMD_SETENV;
+       nl = strlen(name);
+       vl = value ? strlen(value) : 0;
+
+       if (nl + vl + 3 >= (int)sizeof(request.i.data))
+               return -1;
+
+       memcpy(request.i.data, name, nl);
+       if (value) {
+               request.i.data[nl] = '=';
+               memcpy(request.i.data + nl + 1, value, vl);
+       }
+
+        /*
+        *      Open the fifo and write the command.
+         *     Make sure we don't hang on opening /run/initctl
+        */
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = alrm_handler;
+       sigaction(SIGALRM, &sa, NULL);
+       got_alrm = 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;
+}
+
+
+/*
+ *     Tell everyone the system is going down in 'mins' minutes.
+ */
+void issue_warn(int mins)
+{
+       char buf[MESSAGELEN + sizeof(newstate) + 1];
+       int len;
+
+       buf[0] = 0;
+       strncpy(buf, message, MESSAGELEN);
+       len = strlen(buf);
+
+       if (mins == 0)
+               snprintf(buf + len, sizeof(buf) - len,
+                       "\rThe system is going down %s NOW!\r\n",
+                       newstate);
+       else
+               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, 0);
+}
+
+/*
+ *     Create the /etc/nologin file.
+ */
+void donologin(int min)
+{
+       FILE *fp;
+       time_t t;
+
+       time(&t);
+       t += 60 * min;
+
+       if ((fp = fopen(NOLOGIN, "w")) != NULL) {
+               fprintf(fp, "\rThe system is going down on %s\r\n", ctime(&t));
+               if (message[0]) fputs(message, fp);
+               fclose(fp);
+       }
+}
+
+/*
+ *     Spawn an external program.
+ */
+int spawn(int noerr, char *prog, ...)
+{
+       va_list ap;
+       pid_t   pid, rc;
+       int     i;
+       char    *argv[8];
+
+       i = 0;
+       while ((pid = fork()) < 0 && i < 10) {
+               perror("fork");
+               sleep(5);
+               i++;
+       }
+
+       if (pid < 0) return -1;
+
+       if (pid > 0) {
+               while((rc = wait(&i)) != pid)
+                       if (rc < 0 && errno == ECHILD)
+                               break;
+               return (rc == pid) ? WEXITSTATUS(i) : -1;
+       }
+
+       if (noerr) fclose(stderr);
+
+       argv[0] = prog;
+       va_start(ap, prog);
+       for (i = 1; i < 7 && (argv[i] = va_arg(ap, char *)) != NULL; i++)
+               ;
+       argv[i] = NULL;
+       va_end(ap);
+
+       if (chdir("/"))
+               exit(1);
+       environ = clean_env;
+
+       execvp(argv[0], argv);
+       perror(argv[0]);
+       exit(1);
+
+       /*NOTREACHED*/
+       return 0;
+}
+
+/*
+ *     Kill all processes, call /etc/init.d/halt (if present)
+ */
+void fastdown()
+{
+       int do_halt = (down_level[0] == '0');
+       int i;
+#if 0
+       char cmd[128];
+       char *script;
+
+       /*
+        *      Currently, the halt script is either init.d/halt OR rc.d/rc.0,
+        *      likewise for the reboot script. Test for the presence
+        *      of either.
+        */
+       if (do_halt) {
+               if (access(HALTSCRIPT1, X_OK) == 0)
+                       script = HALTSCRIPT1;
+               else
+                       script = HALTSCRIPT2;
+       } else {
+               if (access(REBOOTSCRIPT1, X_OK) == 0)
+                       script = REBOOTSCRIPT1;
+               else
+                       script = REBOOTSCRIPT2;
+       }
+#endif
+
+       /* First close all files. */
+       for(i = 0; i < 3; i++)
+               if (!isatty(i)) {
+                       close(i);
+                       open("/dev/null", O_RDWR);
+               }
+       for(i = 3; i < 20; i++) close(i);
+       close(255);
+
+       /* First idle init. */
+       if (kill(1, SIGTSTP) < 0) {
+               fprintf(stderr, "shutdown: can't idle init: %s.\r\n", 
strerror(errno));
+               exit(1);
+       }
+
+       /* Kill all processes. */
+       fprintf(stderr, "shutdown: sending all processes the TERM 
signal...\r\n");
+       kill(-1, SIGTERM);
+       sleep(sltime ? atoi(sltime) : WAIT_BETWEEN_SIGNALS);
+       fprintf(stderr, "shutdown: sending all processes the KILL signal.\r\n");
+       (void) kill(-1, SIGKILL);
+
+#if 0
+       /* See if we can run /etc/init.d/halt */
+       if (access(script, X_OK) == 0) {
+               spawn(1, cmd, "fast", NULL);
+               fprintf(stderr, "shutdown: %s returned - falling back "
+                               "on default routines\r\n", script);
+       }
+#endif
+
+       /* script failed or not present: do it ourself. */
+       /* Give init the chance to collect zombies. */
+        /* sleep(1); */
+
+       /* Record the fact that we're going down */
+       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();
+       fprintf(stderr, "shutdown: turning off swap\r\n");
+       spawn(0, "swapoff", "-a", NULL);
+       fprintf(stderr, "shutdown: unmounting all file systems\r\n");
+       spawn(0, "umount", "-a", NULL);
+
+       /* We're done, halt or reboot now. */
+       if (do_halt) {
+               fprintf(stderr, "The system is halted. Press CTRL-ALT-DEL "
+                               "or turn off power\r\n");
+               init_reboot(BMAGIC_HALT);
+               exit(0);
+       }
+
+       fprintf(stderr, "Please stand by while rebooting the system.\r\n");
+       init_reboot(BMAGIC_REBOOT);
+       exit(0);
+}
+
+/*
+ *     Go to runlevel 0, 1 or 6.
+ */
+void issue_shutdown(char *halttype)
+{
+       char    *args[8];
+       int     argp = 0;
+       int     do_halt = (down_level[0] == '0');
+
+       /* Warn for the last time */
+       issue_warn(0);
+       if (dontshut) {
+               hardsleep(1);
+               stopit(0);
+       }
+       openlog("shutdown", LOG_PID, LOG_USER);
+       if (do_halt)
+               syslog(LOG_NOTICE, "shutting down for system halt");
+       else
+               syslog(LOG_NOTICE, "shutting down for system reboot");
+       closelog();
+
+       /* See if we have to do it ourself. */
+       if (doself) fastdown();
+
+       /* Create the arguments for init. */
+       args[argp++] = INIT;
+       if (sltime) {
+               args[argp++] = "-t";
+               args[argp++] = sltime;
+       }
+       args[argp++] = down_level;
+       args[argp]   = (char *)NULL;
+
+       unlink(SDPID);
+       unlink(NOLOGIN);
+
+       /* Now execute init to change runlevel. */
+       sync();
+       init_setenv("INIT_HALT", halttype);
+       execv(INIT, args);
+
+       /* Oops - failed. */
+       fprintf(stderr, "\rshutdown: cannot execute %s\r\n", INIT);
+       unlink(FASTBOOT);
+       unlink(FORCEFSCK);
+       init_setenv("INIT_HALT", NULL);
+       openlog("shutdown", LOG_PID, LOG_USER);
+       syslog(LOG_NOTICE, "shutdown failed");
+       closelog();
+       exit(1);
+}
+
+/*
+ *     returns if a warning is to be sent for wt
+ */
+static int needwarning(int wt, int quiet_mode)
+{
+       int ret;
+
+        if (quiet_mode == QUIET_FULL) return FALSE;
+        else if (quiet_mode == QUIET_PARTIAL)
+        {
+            if (wt == 10)
+               return TRUE;
+            else if (wt == 5)
+               return TRUE;
+            else if ( (wt % 60) == 0)
+               return TRUE;
+            else
+               return FALSE;
+        }
+        /* no silence setting, print lots of warnings */
+       if (wt < 10)
+               ret = 1;
+       else if (wt < 60)
+               ret = (wt % 15 == 0);
+       else if (wt < 180)
+               ret = (wt % 30 == 0);
+       else
+               ret = (wt % 60 == 0);
+
+       return ret;
+}
+
+/*
+ *     Main program.
+ *     Process the options and do the final countdown.
+ */
+int main(int argc, char **argv)
+{
+       FILE                    *fp;
+       extern int              getopt();
+       extern int              optind; 
+       struct sigaction        sa;
+       struct tm               *lt;
+       struct stat             st;
+       struct utmp             *ut;
+       time_t                  t, target_time;
+       char                    *halttype;
+       char                    *downusers[32];
+       char                    buf[128];
+       char                    term[UT_LINESIZE + 6];
+       char                    *sp;
+       char                    when[WHEN_SIZE];
+       int                     c, i, wt;
+       int                     hours, mins;
+       int                     didnolog = 0;
+       int                     cancel = 0;
+       int                     useacl = 0;
+       int                     pid = 0;
+       int                     user_ok = 0;
+        int quiet_level = QUIET_NONE;   /* Whether to display shutdown warning 
*/
+
+       /* We can be installed setuid root (executable for a special group) */
+       /* 
+        This way is risky, do error check on setuid call.
+        setuid(geteuid());
+        */
+        errno = 0;
+        if (setuid(geteuid()) == -1) {
+            fprintf(stderr, "%s (%d): %s\n", __FILE__, __LINE__, 
strerror(errno));
+            abort();
+       }
+
+       if (getuid() != 0) {
+               fprintf(stderr, "shutdown: you must be root to do that!\n");
+               usage();
+               exit(1);
+       }
+       strcpy(down_level, "1");
+       halttype = NULL;
+        memset(when, '\0', WHEN_SIZE);
+
+       /* Process the options. */
+       while((c = getopt(argc, argv, "HPacqQkrhnfFyt:g:i:")) != EOF) {
+               switch(c) {
+                       case 'H':
+                               halttype = "HALT";
+                               break;
+                       case 'P':
+                               halttype = "POWEROFF";
+                               break;
+                       case 'a': /* Access control. */
+                               useacl = 1;
+                               break;
+                       case 'c': /* Cancel an already running shutdown. */
+                               cancel = 1;
+                               break;
+                       case 'k': /* Don't really shutdown, only warn.*/
+                               dontshut = 1;
+                               break;
+                       case 'r': /* Automatic reboot */
+                               down_level[0] = '6';
+                               break;
+                       case 'h': /* Halt after shutdown */
+                               down_level[0] = '0';
+                               break;
+                       case 'f': /* Don't perform fsck after next boot */
+                               fastboot = 1;
+                               break;
+                       case 'F': /* Force fsck after next boot */
+                               forcefsck = 1;
+                               break;
+                       case 'n': /* Don't switch runlevels. */
+                               doself = 1;
+                               break;
+                       case 't': /* Delay between TERM and KILL */
+                               sltime = optarg;
+                               break;
+                        case 'q': /* put into somewhat quiet mode */
+                                quiet_level = QUIET_PARTIAL;
+                                break;
+                        case 'Q': /* put into full quiet mode */
+                                quiet_level = QUIET_FULL;
+                                break;
+                       case 'y': /* Ignored for sysV compatibility */
+                               break;
+                       case 'g': /* sysv style to specify time. */
+                               strncpy(when, optarg, WHEN_SIZE - 1);
+                               break;
+                       case 'i': /* Level to go to. */
+                               if (!strchr("0156aAbBcCsS", optarg[0])) {
+                                       fprintf(stderr,
+                                       "shutdown: `%s': bad runlevel\n",
+                                       optarg);
+                                       exit(1);
+                               }
+                               down_level[0] = optarg[0];
+                               break;
+                       default:
+                               usage();
+                               break;  
+               }
+       }
+
+       if (NULL != halttype && down_level[0] != '0') {
+               fprintf(stderr, "shutdown: -H and -P flags can only be used 
along with -h flag.\n");
+               usage();
+               exit(1);
+       }
+
+       /* Do we need to use the shutdown.allow file ? */
+       if (useacl && (fp = fopen(SDALLOW, "r")) != NULL) {
+
+               /* Read /etc/shutdown.allow. */
+               i = 0;
+               while(fgets(buf, 128, fp)) {
+                       if (buf[0] == '#' || buf[0] == '\n') continue;
+                       if (i > 31) continue;
+                       for(sp = buf; *sp; sp++) if (*sp == '\n') *sp = 0;
+                       downusers[i++] = strdup(buf);
+               }
+               if (i < 32) downusers[i] = 0;
+               fclose(fp);
+
+               /* Now walk through /var/run/utmp to find logged in users. */
+               while(!user_ok && (ut = getutent()) != NULL) {
+
+                       /* See if this is a user process on a VC. */
+                       if (ut->ut_type != USER_PROCESS) continue;
+                       sprintf(term, "/dev/%.*s", UT_LINESIZE, ut->ut_line);
+                       if (stat(term, &st) < 0) continue;
+#ifdef major /* glibc */
+                       if (major(st.st_rdev) != 4 ||
+                           minor(st.st_rdev) > 63) continue;
+#else
+                       if ((st.st_rdev & 0xFFC0) != 0x0400) continue;
+#endif
+                       /* Root is always OK. */
+                       if (strcmp(ut->ut_user, "root") == 0) {
+                               user_ok++;
+                               break;
+                       }
+
+                       /* See if this is an allowed user. */
+                       for(i = 0; i < 32 && downusers[i]; i++)
+                               if (!strncmp(downusers[i], ut->ut_user,
+                                   UT_NAMESIZE)) {
+                                       user_ok++;
+                                       break;
+                               }
+               }
+               endutent();
+
+               /* See if user was allowed. */
+               if (!user_ok) {
+                       if ((fp = fopen(CONSOLE, "w")) != NULL) {
+                               fprintf(fp, "\rshutdown: no authorized users "
+                                               "logged in.\r\n");
+                               fclose(fp);
+                       }
+                       exit(1);
+               }
+       }
+
+       /* Read pid of running shutdown from a file */
+       if ((fp = fopen(SDPID, "r")) != NULL) {
+               if (fscanf(fp, "%d", &pid) != 1)
+                       pid = 0;
+               fclose(fp);
+       }
+
+       /* Read remaining words, skip time if needed. */
+       message[0] = 0;
+       for(c = optind + (!cancel && !when[0]); c < argc; c++) {
+               if (strlen(message) + strlen(argv[c]) + 4 > MESSAGELEN)
+                       break;
+               strcat(message, argv[c]);
+               strcat(message, " ");
+       }
+       if (message[0]) strcat(message, "\r\n");
+
+       /* See if we want to run or cancel. */
+       if (cancel) {
+               if (pid <= 0) {
+                       fprintf(stderr, "shutdown: cannot find pid "
+                                       "of running shutdown.\n");
+                       exit(1);
+               }
+               init_setenv("INIT_HALT", NULL);
+               if (kill(pid, SIGINT) < 0) {
+                       fprintf(stderr, "shutdown: not running.\n");
+                       exit(1);
+               }
+               if (message[0]) wall(message, 0);
+               exit(0);
+       }
+  
+       /* Check syntax. */
+       if (when[0] == '\0') {
+               if (optind == argc) usage();
+                strncpy(when, argv[optind++], WHEN_SIZE - 1);
+       }
+
+       /* See if we are already running. */
+       if (pid > 0 && kill(pid, 0) == 0) {
+               fprintf(stderr, "\rshutdown: already running.\r\n");
+               exit(1);
+       }
+
+       /* Extra check. */
+       if (doself && down_level[0] != '0' && down_level[0] != '6') {
+               fprintf(stderr,
+               "shutdown: can use \"-n\" for halt or reboot only.\r\n");
+               exit(1);
+       }
+
+       /* Tell users what we're gonna do. */
+       switch(down_level[0]) {
+               case '0':
+                       strncpy(newstate, "for system halt", STATELEN);
+                       break;
+               case '6':
+                       strncpy(newstate, "for reboot", STATELEN);
+                       break;
+               case '1':
+                       strncpy(newstate, "to maintenance mode", STATELEN);
+                       break;
+               default:
+                       snprintf(newstate, STATELEN, "to runlevel %s", 
down_level);
+                       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);
+       if ((fp = fopen(SDPID, "w")) != NULL) {
+               fprintf(fp, "%d\n", getpid());
+               fclose(fp);
+       } else if (errno != EROFS)
+               fprintf(stderr, "shutdown: warning: cannot open %s\n", SDPID);
+
+       /*
+        *      Catch some common signals.
+        */
+       signal(SIGQUIT, SIG_IGN);
+       signal(SIGCHLD, SIG_IGN);
+       signal(SIGHUP,  SIG_IGN);
+       signal(SIGTSTP, SIG_IGN);
+       signal(SIGTTIN, SIG_IGN);
+       signal(SIGTTOU, SIG_IGN);
+
+       memset(&sa, 0, sizeof(sa));
+       sa.sa_handler = stopit;
+       sigaction(SIGINT, &sa, NULL);
+
+       if (fastboot)  close(open(FASTBOOT,  O_CREAT | O_RDWR, 0644));
+       if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644));
+
+       /* Alias now and take care of old '+mins' notation. */
+       if (!strcmp(when, "now")) strcpy(when, "0");
+
+        sp = when;
+       if (when[0] == '+') sp++;
+       /* Decode shutdown time. */
+       for ( ; *sp; sp++) {
+               if (*sp != ':' && (*sp < '0' || *sp > '9'))
+                       usage();
+       }
+       if (strchr(when, ':') == NULL) {
+               /* Time in minutes. */
+               wt = atoi(when);
+               if (wt == 0 && when[0] != '0') usage();
+       } else {
+               if (sscanf(when, "%d:%2d", &hours, &mins) != 2) usage();
+               /* Time in hh:mm format. */
+               if (when[0] == '+') {
+                       /* Hours and minutes from now */
+                       if (hours > 99999 || mins > 59) usage();
+                       wt = (60*hours + mins);
+                       if (wt < 0) usage();
+               } else {
+                       /* Time of day */
+                       if (hours > 23 || mins > 59) usage();
+                       time(&t);
+                       lt = localtime(&t);
+                       wt = (60*hours + mins) - (60*lt->tm_hour + lt->tm_min);
+                       if (wt < 0) wt += 1440;
+               }
+       }
+       /* Shutdown NOW if time == 0 */
+       if (wt == 0) issue_shutdown(halttype);
+
+        /* Rather than loop and reduce wt (wait time) once per minute,
+           we shall check the current time against the target time.
+           Then calculate the remaining wating time based on the difference
+           between current time and target time.
+           This avoids missing shutdown time (target time) after the
+           computer has been asleep. -- Jesse
+        */
+        /* target time, in seconds = current time + wait time */
+        time(&t);
+        target_time = t + (60 * wt); 
+
+       /* Give warnings on regular intervals and finally shutdown. */
+       if (wt < 15 && !needwarning(wt, quiet_level)) issue_warn(wt);
+       while(wt) {
+               if (wt <= 5 && !didnolog) {
+                       donologin(wt);
+                       didnolog++;
+               }
+               if (needwarning(wt, quiet_level)) issue_warn(wt);
+               hardsleep(60);
+                time(&t);    /* get current time once per minute */
+                if (t >= target_time)     /* past the target */
+                  wt = 0;
+                else if ( (target_time - t) <= 60 )  /* less 1 min remains */
+                {
+                    hardsleep(target_time - t);
+                    wt = 0;
+                }
+                else                      /* more than 1 min remains */
+                   wt = (int) (target_time - t) / 60;
+       }
+       issue_shutdown(halttype);
+
+       return 0; /* Never happens */
+}
_______________________________________________
openSUSE Commits mailing list -- commit@lists.opensuse.org
To unsubscribe, email commit-le...@lists.opensuse.org
List Netiquette: https://en.opensuse.org/openSUSE:Mailing_list_netiquette
List Archives: 
https://lists.opensuse.org/archives/list/commit@lists.opensuse.org

Reply via email to