summaryrefslogtreecommitdiff
path: root/sbin/shutdown/shutdown.c
diff options
context:
space:
mode:
authorcheloha <cheloha@cvs.openbsd.org>2018-03-02 02:30:16 +0000
committercheloha <cheloha@cvs.openbsd.org>2018-03-02 02:30:16 +0000
commitadb35576ad0c187a50e3f247c5a2ef6a4e62dcd1 (patch)
treef2fbbc767613a3940436ddfcf1c81427d246097d /sbin/shutdown/shutdown.c
parent120187090a82c3b189412f13e620335ebbb7e845 (diff)
Refactor the countdown loop() to simplify it.
If we insert our offset into tlist[] and then process tlist[] like an array we can eliminate many of the special cases and duplicate calls in loop(). While we're at it, change struct interval and timewarn() to use time_t to eliminate the need for some of the casting and add explicit long-long suffixes to the constants in tlist[] to head off overflow if the code wanders off. With type-related input from tb@ and a style tweak from anton@. ok tb@
Diffstat (limited to 'sbin/shutdown/shutdown.c')
-rw-r--r--sbin/shutdown/shutdown.c83
1 files changed, 43 insertions, 40 deletions
diff --git a/sbin/shutdown/shutdown.c b/sbin/shutdown/shutdown.c
index 1689bb32430..a11f73ae862 100644
--- a/sbin/shutdown/shutdown.c
+++ b/sbin/shutdown/shutdown.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: shutdown.c,v 1.48 2018/02/24 20:00:07 cheloha Exp $ */
+/* $OpenBSD: shutdown.c,v 1.49 2018/03/02 02:30:15 cheloha Exp $ */
/* $NetBSD: shutdown.c,v 1.9 1995/03/18 15:01:09 cgd Exp $ */
/*
@@ -59,13 +59,16 @@
#define _PATH_FASTBOOT "./fastboot"
#endif
-#define H *60*60
-#define M *60
-#define S *1
-#define NOLOG_TIME 5*60
+#define H *60*60LL
+#define M *60LL
+#define S *1LL
+#define TEN_HOURS (10*60*60)
+#define NOLOG_TIME (5*60)
struct interval {
- int timeleft, timetowait;
+ time_t timeleft;
+ time_t timetowait;
} tlist[] = {
+ { 0, 0 },
{ 10 H, 5 H },
{ 5 H, 3 H },
{ 2 H, 1 H },
@@ -79,6 +82,7 @@ struct interval {
{ 30 S, 30 S },
{ 0, 0 }
};
+const int tlistlen = sizeof(tlist) / sizeof(tlist[0]);
#undef H
#undef M
#undef S
@@ -96,7 +100,7 @@ void getoffset(char *);
void __dead loop(void);
void nolog(void);
void timeout(int);
-void timewarn(int);
+void timewarn(time_t);
void usage(void);
int
@@ -229,40 +233,39 @@ main(int argc, char *argv[])
void
loop(void)
{
- struct interval *tp;
- u_int sltime;
- int logged;
+ struct timespec timeout;
+ int broadcast, i, logged;
- if (offset <= NOLOG_TIME) {
- logged = 1;
- nolog();
- } else
- logged = 0;
- tp = tlist;
- if (tp->timeleft < offset)
- (void)sleep((u_int)(offset - tp->timeleft));
- else {
- while (offset < tp->timeleft)
- ++tp;
- /*
- * Warn now, if going to sleep more than a fifth of
- * the next wait time.
- */
- if ((sltime = offset - tp->timeleft)) {
- if (sltime > tp->timetowait / 5)
- timewarn(offset);
- (void)sleep(sltime);
+ broadcast = 1;
+
+ for (i = 0; i < tlistlen - 1; i++) {
+ if (offset > tlist[i + 1].timeleft) {
+ tlist[i].timeleft = offset;
+ tlist[i].timetowait = offset - tlist[i + 1].timeleft;
+ break;
}
}
- for (;; ++tp) {
- timewarn(tp->timeleft);
- if (!logged && tp->timeleft <= NOLOG_TIME) {
+
+ /*
+ * Don't spam the users: skip our offset's warning broadcast if
+ * there's a broadcast scheduled after ours and it's relatively
+ * imminent.
+ */
+ if (offset > TEN_HOURS ||
+ (offset > 0 && tlist[i].timetowait < tlist[i+1].timetowait / 5))
+ broadcast = 0;
+
+ for (logged = 0; i < tlistlen; i++) {
+ if (broadcast)
+ timewarn(tlist[i].timeleft);
+ broadcast = 1;
+ if (!logged && tlist[i].timeleft <= NOLOG_TIME) {
logged = 1;
nolog();
}
- (void)sleep((u_int)tp->timetowait);
- if (!tp->timeleft)
- break;
+ timeout.tv_sec = tlist[i].timetowait;
+ timeout.tv_nsec = 0;
+ nanosleep(&timeout, NULL);
}
die_you_gravy_sucking_pig_dog();
}
@@ -273,7 +276,7 @@ static char *restricted_environ[] = {
};
void
-timewarn(int timeleft)
+timewarn(time_t timeleft)
{
static char hostname[HOST_NAME_MAX+1];
static int first;
@@ -319,10 +322,10 @@ timewarn(int timeleft)
dprintf(fd[1], "System going down at %d:%02d\n\n",
tm->tm_hour, tm->tm_min);
- } else if (timeleft > 59)
- dprintf(fd[1], "System going down in %d minute%s\n\n",
- timeleft / 60, (timeleft > 60) ? "s" : "");
- else if (timeleft)
+ } else if (timeleft > 59) {
+ dprintf(fd[1], "System going down in %lld minute%s\n\n",
+ (long long)(timeleft / 60), (timeleft > 60) ? "s" : "");
+ } else if (timeleft)
dprintf(fd[1], "System going down in 30 seconds\n\n");
else
dprintf(fd[1], "System going down IMMEDIATELY\n\n");