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