Initial revision
This commit is contained in:
42
commands/reboot/Makefile
Executable file
42
commands/reboot/Makefile
Executable file
@@ -0,0 +1,42 @@
|
||||
# Makefile for shutdown / halt / reboot.
|
||||
|
||||
CFLAGS=$(OPT) -D_MINIX -D_POSIX_SOURCE
|
||||
LDFLAGS=-i
|
||||
|
||||
PROGRAMS= shutdown halt tinyhalt
|
||||
MANUALS= shutdown.8 halt.8 reboot.2 reboot.8
|
||||
|
||||
all: $(PROGRAMS)
|
||||
|
||||
shutdown: shutdown.o sh_wall.o log.o
|
||||
$(CC) $(LDFLAGS) -o shutdown shutdown.o sh_wall.o log.o
|
||||
install -S 4kw $@
|
||||
|
||||
halt: halt.o log.o
|
||||
$(CC) $(LDFLAGS) -o halt halt.o log.o
|
||||
install -S 4kw $@
|
||||
|
||||
tinyhalt: tinyhalt.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $?
|
||||
install -S 4kw $@
|
||||
|
||||
install: /usr/bin/halt /usr/bin/reboot /usr/bin/shutdown \
|
||||
/bin/halt /bin/reboot
|
||||
|
||||
/usr/bin/halt: halt
|
||||
install -cs -o root -g operator -m 744 $? $@
|
||||
|
||||
/usr/bin/reboot: /usr/bin/halt
|
||||
install -l $? $@
|
||||
|
||||
/usr/bin/shutdown: shutdown
|
||||
install -cs -o root -g operator -m 4754 $? $@
|
||||
|
||||
/bin/halt: tinyhalt
|
||||
install -cs -o root -g operator -m 744 $? $@
|
||||
|
||||
/bin/reboot: /bin/halt
|
||||
install -l $? $@
|
||||
|
||||
clean:
|
||||
rm -f *.o a.out core $(PROGRAMS)
|
||||
52
commands/reboot/README
Executable file
52
commands/reboot/README
Executable file
@@ -0,0 +1,52 @@
|
||||
This a new implementation of a shutdown procedure. It allows
|
||||
the system to go down graciously with informing the
|
||||
users. This package contains 3 programs:
|
||||
|
||||
- halt = Immediately stop the system, no info to users
|
||||
- shutdown = Inform users, close down the system properly
|
||||
- wall = Vincent Archer's implementation of wall (Write all)
|
||||
|
||||
Installing
|
||||
|
||||
Shutdown and halt use a new systemcall, which I've added to
|
||||
MM. Therefor there are several diff's which should be applied:
|
||||
|
||||
callnr.hd - New callnr for reboot(2)
|
||||
Diff against /usr/include/minix/callnr.h.
|
||||
Those of you using a symlink package should
|
||||
change the number and mm/table.c into a free
|
||||
number. I used 54, LSTAT.
|
||||
param.hd - Defines reboot_flag as a part of the messages
|
||||
proto.hd - Add's prototype for do_reboot()
|
||||
table.cd - Interpretation of the systemcall to MM
|
||||
mm.cd - I have added the do_reboot code to mm/getset.c but
|
||||
I couldn't find a getset.c to create a useable diff :-(
|
||||
So you can add where you want it. It is pure code, no diff.
|
||||
|
||||
Now edit log.c and search for ``host''. Change this into your
|
||||
systemname or make it empty.
|
||||
|
||||
Shutdown and halt log their actions in /usr/adm/log, edit the
|
||||
makefile and undefine -DLOG if you don't want this (this at the end of
|
||||
the makefile). You can change SHUT_LOG in shutdown.c and log.c if you
|
||||
want it in another file.
|
||||
|
||||
Then type a `make'. This will take a minute or so (13 sec. with bcc :-).
|
||||
Remember to build a new image and update the ps_database.
|
||||
|
||||
Type `make install' to place the program's where I've got them.
|
||||
Use them, try them and let me now if you've got problems running
|
||||
something.
|
||||
|
||||
I have tested to sources both on 16-bits and 32-bits MINIX. I have compiled
|
||||
it with gcc, bcc and ACK, so that shouldn't really give a problem. Maybe
|
||||
the standard MINIX-make chokes on the makefile, atleast mine did.
|
||||
|
||||
NOTE:
|
||||
Make install does not place the man-pages somewhere. You should
|
||||
do this yourself.
|
||||
|
||||
--
|
||||
Edvard Tuinder ed@pulstar.NL.mugnet.org v892231@si.hhs.NL
|
||||
Student Computer Science
|
||||
Haagse Hogeschool, The Hague, The Netherlands
|
||||
135
commands/reboot/halt.c
Executable file
135
commands/reboot/halt.c
Executable file
@@ -0,0 +1,135 @@
|
||||
/* halt / reboot - halt or reboot system (depends on name)
|
||||
|
||||
halt - calling reboot() with RBT_HALT
|
||||
reboot - calling reboot() with RBT_REBOOT
|
||||
|
||||
author: Edvard Tuinder v892231@si.hhs.NL
|
||||
|
||||
This program calls the library function reboot(2) which performs
|
||||
the system-call do_reboot.
|
||||
|
||||
*/
|
||||
|
||||
#define _POSIX_SOURCE 1
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
void write_log _ARGS(( void ));
|
||||
void usage _ARGS(( void ));
|
||||
int main _ARGS(( int argc, char *argv[] ));
|
||||
|
||||
char *prog;
|
||||
|
||||
void
|
||||
usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-hrRf] [-x reboot-code]\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int
|
||||
main(argc,argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
int flag = -1; /* default action unknown */
|
||||
int fast = 0; /* fast halt/reboot, don't bother being nice. */
|
||||
int i;
|
||||
struct stat dummy;
|
||||
char *monitor_code = "";
|
||||
pid_t pid;
|
||||
|
||||
if ((prog = strrchr(argv[0],'/')) == NULL) prog = argv[0]; else prog++;
|
||||
|
||||
if (strcmp(prog, "halt") == 0) flag = RBT_HALT;
|
||||
if (strcmp(prog, "reboot") == 0) flag = RBT_REBOOT;
|
||||
|
||||
i = 1;
|
||||
while (i < argc && argv[i][0] == '-') {
|
||||
char *opt = argv[i++] + 1;
|
||||
|
||||
if (*opt == '-' && opt[1] == 0) break; /* -- */
|
||||
|
||||
while (*opt != 0) switch (*opt++) {
|
||||
case 'h':
|
||||
flag = RBT_HALT;
|
||||
break;
|
||||
case 'r':
|
||||
flag = RBT_REBOOT;
|
||||
break;
|
||||
case 'R':
|
||||
flag = RBT_RESET;
|
||||
break;
|
||||
case 'f':
|
||||
fast = 1;
|
||||
break;
|
||||
case 'x':
|
||||
flag = RBT_MONITOR;
|
||||
if (*opt == 0) {
|
||||
if (i == argc) usage();
|
||||
opt = argv[i++];
|
||||
}
|
||||
monitor_code = opt;
|
||||
opt = "";
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
if (i != argc) usage();
|
||||
|
||||
if (flag == -1) {
|
||||
fprintf(stderr, "Don't know what to do when named '%s'\n", prog);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (stat("/usr/bin", &dummy) < 0) {
|
||||
/* It seems that /usr isn't present, let's assume "-f." */
|
||||
fast = 1;
|
||||
}
|
||||
|
||||
write_log();
|
||||
|
||||
if (fast) {
|
||||
/* But not too fast... */
|
||||
sleep(1);
|
||||
|
||||
} else {
|
||||
/* Run the shutdown scripts. */
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
switch ((pid = fork())) {
|
||||
case -1:
|
||||
fprintf(stderr, "%s: can't fork(): %s\n", prog, strerror(errno));
|
||||
exit(1);
|
||||
case 0:
|
||||
execl("/bin/sh", "sh", "/etc/rc", "down", (char *) NULL);
|
||||
fprintf(stderr, "%s: can't execute: /bin/sh: %s\n",
|
||||
prog, strerror(errno));
|
||||
exit(1);
|
||||
default:
|
||||
while (waitpid(pid, NULL, 0) != pid) {}
|
||||
}
|
||||
|
||||
/* Tell init to stop spawning getty's. */
|
||||
kill(1, SIGTERM);
|
||||
|
||||
/* Give everybody a chance to die peacefully. */
|
||||
kill(-1, SIGTERM);
|
||||
sleep(3);
|
||||
}
|
||||
|
||||
reboot(flag, monitor_code, strlen(monitor_code));
|
||||
fprintf(stderr, "%s: reboot(): %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
81
commands/reboot/log.c
Executable file
81
commands/reboot/log.c
Executable file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
log - log the shutdown's and the halt's
|
||||
|
||||
Author: Edvard Tuinder <v892231@si.hhs.NL>
|
||||
|
||||
shutdown is logged in /usr/adm/wtmp and in /usr/adm/log (if desired)
|
||||
halt is logged only in /usr/adm/wtmp as `halt' to prevent last from
|
||||
reporting halt's as crashes.
|
||||
|
||||
*/
|
||||
|
||||
#define _POSIX_SOURCE 1
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <utmp.h>
|
||||
#include <pwd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
#undef WTMP
|
||||
|
||||
static char WTMP[] = "/usr/adm/wtmp"; /* Record of logins and logouts. */
|
||||
static char SHUT_LOG[] = "/usr/adm/log";
|
||||
|
||||
char who[8];
|
||||
extern char *prog;
|
||||
static char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
void write_log _ARGS(( void ));
|
||||
|
||||
void write_log()
|
||||
{
|
||||
int fd;
|
||||
static struct utmp wtmp;
|
||||
static struct passwd *pwd;
|
||||
char mes[90];
|
||||
struct tm *tm;
|
||||
time_t now;
|
||||
struct utsname utsname;
|
||||
char *host = "localhost";
|
||||
|
||||
time(&now);
|
||||
tm = localtime(&now);
|
||||
|
||||
if (uname(&utsname) >= 0) host = utsname.nodename;
|
||||
|
||||
pwd = getpwuid(getuid());
|
||||
if (pwd == (struct passwd *)0)
|
||||
strcpy (who,"root");
|
||||
else
|
||||
strcpy (who,pwd->pw_name);
|
||||
fd = open(WTMP,O_APPEND|O_WRONLY,1);
|
||||
if (fd) {
|
||||
if (strcmp(prog,"reboot"))
|
||||
strcpy (wtmp.ut_user, prog);
|
||||
else
|
||||
strcpy (wtmp.ut_user, "shutdown"); /* last ... */
|
||||
strcpy (wtmp.ut_id, "~~");
|
||||
strcpy (wtmp.ut_line, "~");
|
||||
wtmp.ut_pid = 0;
|
||||
wtmp.ut_type = BOOT_TIME;
|
||||
wtmp.ut_time = now;
|
||||
wtmp.ut_host[0]= '\0';
|
||||
write (fd, (char *) &wtmp,sizeof(struct utmp));
|
||||
close(fd);
|
||||
}
|
||||
fd = open(SHUT_LOG,O_APPEND|O_WRONLY,1);
|
||||
if (!fd)
|
||||
perror ("open");
|
||||
else {
|
||||
sprintf (mes,"%s %02d %02d:%02d:%02d %s: system %s by %s@%s\n",
|
||||
month[tm->tm_mon],tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
|
||||
prog,prog,who,host);
|
||||
write (fd,mes,strlen(mes));
|
||||
close(fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
109
commands/reboot/sh_wall.c
Executable file
109
commands/reboot/sh_wall.c
Executable file
@@ -0,0 +1,109 @@
|
||||
/* wall - write to all logged in users Author: V. Archer */
|
||||
/*
|
||||
Edvard Tuinder v892231@si.hhs.NL
|
||||
Modified some things to include this with my shutdown/halt
|
||||
package
|
||||
*/
|
||||
|
||||
#define _POSIX_SOURCE 1
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <utmp.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/stat.h>
|
||||
#undef UTMP
|
||||
|
||||
static char UTMP[] = "/etc/utmp"; /* Currently logged in users. */
|
||||
|
||||
void wall _ARGS(( char *when, char *extra ));
|
||||
void crnlcat _ARGS(( char *message, char *more ));
|
||||
|
||||
void
|
||||
wall(when, extra)
|
||||
char *when; /* When is shutdown */
|
||||
char *extra; /* If non-nil, why is the shutdown */
|
||||
{
|
||||
struct utmp utmp;
|
||||
char utmptty[5 + sizeof(utmp.ut_line) + 1];
|
||||
char message[1024];
|
||||
struct passwd *pw;
|
||||
int utmpfd, ttyfd;
|
||||
char *ourtty, *ourname;
|
||||
time_t now;
|
||||
struct utsname utsname;
|
||||
struct stat con_st, tty_st;
|
||||
|
||||
if (ourtty = ttyname(1)) {
|
||||
if (ourname = strrchr(ourtty, '/')) ourtty = ourname+1;
|
||||
} else ourtty = "system task";
|
||||
if (pw = getpwuid(getuid())) ourname = pw->pw_name;
|
||||
else ourname = "unknown";
|
||||
|
||||
time(&now);
|
||||
if (uname(&utsname) != 0) strcpy(utsname.nodename, "?");
|
||||
sprintf(message, "\r\nBroadcast message from %s@%s (%s)\r\n%.24s...\007\007\007\r\n",
|
||||
ourname, utsname.nodename, ourtty, ctime(&now));
|
||||
|
||||
crnlcat(message, when);
|
||||
crnlcat(message, extra);
|
||||
|
||||
/* Search the UTMP database for all logged-in users. */
|
||||
|
||||
if ((utmpfd = open(UTMP, O_RDONLY)) < 0) {
|
||||
fprintf(stderr, "Cannot open utmp file\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* first the console */
|
||||
strcpy(utmptty, "/dev/console");
|
||||
if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
|
||||
perror(utmptty);
|
||||
} else {
|
||||
fstat(ttyfd, &con_st);
|
||||
write(ttyfd, message, strlen(message));
|
||||
close(ttyfd);
|
||||
}
|
||||
|
||||
while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
|
||||
/* is this the user we are looking for? */
|
||||
if (utmp.ut_type != USER_PROCESS) continue;
|
||||
|
||||
strncpy(utmptty+5, utmp.ut_line, sizeof(utmp.ut_line));
|
||||
utmptty[5 + sizeof(utmp.ut_line) + 1] = 0;
|
||||
if ((ttyfd = open(utmptty, O_WRONLY | O_NONBLOCK)) < 0) {
|
||||
perror(utmptty);
|
||||
continue;
|
||||
}
|
||||
fstat(ttyfd, &tty_st);
|
||||
if (tty_st.st_rdev != con_st.st_rdev)
|
||||
write(ttyfd, message, strlen(message));
|
||||
close(ttyfd);
|
||||
}
|
||||
close(utmpfd);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
crnlcat(message, more)
|
||||
char *message, *more;
|
||||
{
|
||||
char *p = message;
|
||||
char *m = more;
|
||||
char *end = message + 1024 - 1;
|
||||
|
||||
while (p < end && *p != 0) *p++;
|
||||
|
||||
while (p < end && *m != 0) {
|
||||
if (*m == '\n' && (p == message || p[-1] != '\n')) {
|
||||
*p++ = '\r';
|
||||
if (p == end) p--;
|
||||
}
|
||||
*p++ = *m++;
|
||||
}
|
||||
*p = 0;
|
||||
}
|
||||
408
commands/reboot/shutdown.c
Executable file
408
commands/reboot/shutdown.c
Executable file
@@ -0,0 +1,408 @@
|
||||
/*
|
||||
shutdown - close down the system graciously
|
||||
|
||||
Author: Edvard Tuinder <v892231@si.hhs.NL>
|
||||
|
||||
This program informs the users that the system is going
|
||||
down, when and why. After that a shutdown notice is written in
|
||||
both /usr/adm/wtmp and by syslog(3). Then reboot(2) is called
|
||||
to really close the system.
|
||||
|
||||
This actually is a ``nice'' halt(8).
|
||||
|
||||
Options are supposed to be as with BSD
|
||||
-h: shutdown and halt the system
|
||||
-r: shutdown and reboot
|
||||
-k: stop an already running shutdown
|
||||
-o: obsolete: not implemented
|
||||
|
||||
New Minix options:
|
||||
-C: crash check, i.e. is the last wtmp entry a shutdown entry?
|
||||
-x: let the monitor execute the given code
|
||||
-R: reset the system
|
||||
*/
|
||||
|
||||
#define _POSIX_SOURCE 1
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
#include <errno.h>
|
||||
#undef WTMP
|
||||
|
||||
static char WTMP[] = "/usr/adm/wtmp";
|
||||
static char SHUT_PID[] = "/usr/run/shutdown.pid";
|
||||
static char NOLOGIN[] = "/etc/nologin";
|
||||
|
||||
#ifndef __STDC__
|
||||
#define inform_user_time inf_time
|
||||
#define inform_user inf_user
|
||||
#endif
|
||||
|
||||
void usage _ARGS(( void ));
|
||||
void write_pid _ARGS(( void ));
|
||||
int inform_user_time _ARGS(( void ));
|
||||
void inform_user _ARGS(( void ));
|
||||
void terminate _ARGS(( void ));
|
||||
void wall _ARGS(( char *when, char *extra ));
|
||||
int crash_check _ARGS(( void ));
|
||||
void parse_time _ARGS(( char *arg ));
|
||||
void get_message _ARGS(( void ));
|
||||
void main _ARGS(( int argc, char *argv[] ));
|
||||
char *itoa _ARGS(( int n ));
|
||||
|
||||
long wait_time=0L;
|
||||
char message[1024];
|
||||
char info[80];
|
||||
int reboot_flag='h'; /* default is halt */
|
||||
char *reboot_code=""; /* optional monitor code */
|
||||
int info_min, info_hour;
|
||||
char *prog;
|
||||
|
||||
void parse_time (arg)
|
||||
char *arg;
|
||||
{
|
||||
char *p = arg;
|
||||
int hours, minutes;
|
||||
time_t now;
|
||||
struct tm *tm;
|
||||
int delta = 0;
|
||||
int bad = 0;
|
||||
|
||||
if (p[0] == '+') { delta = 1; p++; }
|
||||
|
||||
hours = strtoul(p, &p, 10);
|
||||
if (*p == 0 && delta) {
|
||||
minutes = hours;
|
||||
hours = 0;
|
||||
} else {
|
||||
if (*p != ':' && *p != '.')
|
||||
bad = 1;
|
||||
else
|
||||
p++;
|
||||
minutes = strtoul(p, &p, 10);
|
||||
if (*p != 0) bad = 1;
|
||||
}
|
||||
if (bad) {
|
||||
fprintf(stderr,"Invalid time specification `%s'\n",arg);
|
||||
usage();
|
||||
}
|
||||
|
||||
time(&now);
|
||||
tm = localtime(&now);
|
||||
|
||||
if (!delta) {
|
||||
hours -= tm->tm_hour;
|
||||
minutes -= tm->tm_min;
|
||||
}
|
||||
|
||||
if (minutes < 0) {
|
||||
minutes += 60;
|
||||
hours--;
|
||||
}
|
||||
if (hours < 0) hours += 24; /* Time after midnight. */
|
||||
|
||||
tm->tm_hour += hours;
|
||||
tm->tm_min += minutes;
|
||||
(void) mktime(tm);
|
||||
info_hour = tm->tm_hour;
|
||||
info_min = tm->tm_min;
|
||||
|
||||
sprintf(info,
|
||||
"The system will shutdown in %d hour%s and %d minute%s at %02d:%02d\n\n",
|
||||
hours,hours==1?"":"s",minutes,minutes==1?"":"s",info_hour,info_min);
|
||||
|
||||
wait_time += hours * 3600 + minutes * 60;
|
||||
return;
|
||||
}
|
||||
|
||||
void main(argc,argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int i, now = 0, nologin = 0, want_terminate = 0, want_message = 0, check = 0;
|
||||
char *opt;
|
||||
int tty;
|
||||
static char HALT1[] = "-?";
|
||||
static char *HALT[] = { "shutdown", HALT1, NULL, NULL };
|
||||
|
||||
/* Parse options. */
|
||||
for (i = 1; i < argc && argv[i][0] == '-'; i++) {
|
||||
if (argv[i][1] == '-' && argv[i][2] == 0) {
|
||||
/* -- */
|
||||
i++;
|
||||
break;
|
||||
}
|
||||
for (opt = argv[i] + 1; *opt != 0; opt++) {
|
||||
switch (*opt) {
|
||||
case 'k':
|
||||
want_terminate = 1;
|
||||
break;
|
||||
case 'h':
|
||||
case 'r':
|
||||
case 'x':
|
||||
reboot_flag = *opt;
|
||||
if (reboot_flag == 'x') {
|
||||
if (*++opt == 0) {
|
||||
if (++i == argc) {
|
||||
fprintf (stderr,"shutdown: option '-x' requires an argument\n");
|
||||
usage();
|
||||
}
|
||||
opt=argv[i];
|
||||
}
|
||||
reboot_code=opt;
|
||||
opt="";
|
||||
}
|
||||
break;
|
||||
case 'R':
|
||||
reboot_flag = 'R';
|
||||
break;
|
||||
case 'm':
|
||||
want_message = 1;
|
||||
break;
|
||||
case 'C':
|
||||
check = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf (stderr,"shutdown: invalid option '-%c'\n",*opt);
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((argc - i) > 2) usage();
|
||||
|
||||
if (check) exit(crash_check() ? 0 : 2);
|
||||
|
||||
if (i == argc) {
|
||||
/* No timespec, assume "now". */
|
||||
now = 1;
|
||||
} else {
|
||||
if (!strcmp(argv[i], "now"))
|
||||
now++;
|
||||
else
|
||||
parse_time(argv[i]);
|
||||
}
|
||||
|
||||
if ((argc - i) == 2) {
|
||||
/* One line message */
|
||||
strcat(message, argv[i+1]);
|
||||
strcat(message, "\n");
|
||||
}
|
||||
|
||||
if (want_terminate) terminate();
|
||||
if (want_message) get_message();
|
||||
|
||||
puts(info);
|
||||
|
||||
prog = strrchr(*argv,'/');
|
||||
if (prog == (char *)0)
|
||||
prog = *argv;
|
||||
else
|
||||
prog++;
|
||||
|
||||
if (!now) {
|
||||
/* Daemonize. */
|
||||
switch (fork()) {
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
fprintf(stderr, "%s: can't fork\n", prog);
|
||||
exit(1);
|
||||
default:
|
||||
exit(0);
|
||||
}
|
||||
/* Detach from the terminal (if any). */
|
||||
if ((tty = open("/dev/tty", O_RDONLY)) != -1) {
|
||||
close(tty);
|
||||
setsid();
|
||||
}
|
||||
write_pid();
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
if (wait_time <= 5 * 60 && !nologin && !now) {
|
||||
close(creat(NOLOGIN,00644));
|
||||
nologin = 1;
|
||||
}
|
||||
if (wait_time <= 60) break;
|
||||
if(inform_user_time())
|
||||
inform_user();
|
||||
sleep (60);
|
||||
wait_time -= 60;
|
||||
}
|
||||
|
||||
if (!now) {
|
||||
inform_user();
|
||||
sleep (30); /* Last minute before shutdown */
|
||||
wait_time -= 30;
|
||||
inform_user();
|
||||
sleep (30); /* Last 30 seconds before shutdown */
|
||||
}
|
||||
wait_time = 0;
|
||||
inform_user();
|
||||
|
||||
unlink(SHUT_PID); /* No way of stopping anymore */
|
||||
unlink(NOLOGIN);
|
||||
|
||||
HALT[1][1] = reboot_flag;
|
||||
if (reboot_flag == 'x') HALT[2] = reboot_code;
|
||||
#if __minix_vmd
|
||||
execv("/usr/sbin/halt", HALT);
|
||||
#else
|
||||
execv("/usr/bin/halt", HALT);
|
||||
#endif
|
||||
if (errno != ENOENT)
|
||||
fprintf(stderr, "Can't execute 'halt': %s\n", strerror(errno));
|
||||
|
||||
sleep(2);
|
||||
reboot(RBT_HALT);
|
||||
fprintf(stderr, "Reboot call failed: %s\n", strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void usage()
|
||||
{
|
||||
fputs("Usage: shutdown [-hrRmk] [-x code] [time [message]]\n", stderr);
|
||||
fputs(" -h -> halt system after shutdown\n", stderr);
|
||||
fputs(" -r -> reboot system after shutdown\n", stderr);
|
||||
fputs(" -R -> reset system after shutdown\n", stderr);
|
||||
fputs(" -x -> return to the monitor doing...\n", stderr);
|
||||
fputs(" -m -> read a shutdown message from standard input\n", stderr);
|
||||
fputs(" -k -> stop an already running shutdown\n", stderr);
|
||||
fputs(" code -> boot monitor code to be executed\n", stderr);
|
||||
fputs(" time -> keyword ``now'', minutes before shutdown ``+5'',\n", stderr);
|
||||
fputs(" or absolute time specification ``11:20''\n", stderr);
|
||||
fputs(" message -> short shutdown message\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void terminate()
|
||||
{
|
||||
FILE *in;
|
||||
pid_t pid;
|
||||
char c_pid[5];
|
||||
char buf[80];
|
||||
|
||||
in = fopen(SHUT_PID,"r");
|
||||
if (in == (FILE *)0) {
|
||||
fputs ("Can't get pid of shutdown process, probably not running shutdown\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
fgets(c_pid,5,in);
|
||||
fclose(in);
|
||||
pid = atoi(c_pid);
|
||||
if (kill(pid,9) == -1)
|
||||
fputs("Can't kill the shutdown process, probably not running anymore\n",stderr);
|
||||
else
|
||||
puts("Shutdown process terminated");
|
||||
unlink(SHUT_PID);
|
||||
unlink(NOLOGIN);
|
||||
#ifdef not_very_useful
|
||||
in = fopen (SHUT_LOG,"a");
|
||||
if (in == (FILE *)0)
|
||||
exit(0);
|
||||
sprintf (buf, "Shutdown with pid %d terminated\n",pid);
|
||||
fputs(buf,in);
|
||||
fclose(in);
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void get_message()
|
||||
{
|
||||
char line[80];
|
||||
int max_lines=12;
|
||||
|
||||
puts ("Type your message. End with ^D at an empty line");
|
||||
fputs ("shutdown> ",stdout);fflush(stdout);
|
||||
while (fgets(line,80,stdin) != (char *)0) {
|
||||
strcat (message,line);
|
||||
bzero(line,strlen(line));
|
||||
fputs ("shutdown> ",stdout);fflush(stdout);
|
||||
}
|
||||
putc('\n',stdout);fflush(stdout);
|
||||
}
|
||||
|
||||
int inform_user_time()
|
||||
{
|
||||
int min;
|
||||
|
||||
min = wait_time /60;
|
||||
|
||||
if (min == 60 || min == 30 || min == 15 || min == 10 || min <= 5)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inform_user()
|
||||
{
|
||||
int hour, minute;
|
||||
char mes[80];
|
||||
|
||||
hour = 0;
|
||||
minute = wait_time / 60;
|
||||
while (minute >= 60) {
|
||||
minute -= 60;
|
||||
hour++;
|
||||
}
|
||||
|
||||
if (hour)
|
||||
sprintf(mes,
|
||||
"\nThe system will shutdown in %d hour%s and %d minute%s at %.02d:%.02d\n\n",
|
||||
hour,hour==1?"":"s",minute,minute==1?"":"s",info_hour,info_min);
|
||||
else
|
||||
if (minute > 1)
|
||||
sprintf(mes,
|
||||
"\nThe system will shutdown in %d minutes at %.02d:%.02d\n\n",
|
||||
minute,info_hour,info_min);
|
||||
else
|
||||
if (wait_time > 1)
|
||||
sprintf(mes,
|
||||
"\nThe system will shutdown in %d seconds\n\n",
|
||||
wait_time);
|
||||
else
|
||||
sprintf(mes,
|
||||
"\nThe system will shutdown NOW\n\n");
|
||||
|
||||
wall(mes,message);
|
||||
}
|
||||
|
||||
void write_pid()
|
||||
{
|
||||
char pid[5];
|
||||
int fd;
|
||||
|
||||
fd = creat(SHUT_PID,00600);
|
||||
if (!fd)
|
||||
return;
|
||||
strncpy (pid,itoa(getpid()), sizeof(pid));
|
||||
write (fd,pid,sizeof(pid));
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
int crash_check()
|
||||
{
|
||||
struct utmp last;
|
||||
int fd, crashed;
|
||||
struct stat st;
|
||||
|
||||
if (stat(WTMP, &st) < 0 || st.st_size == 0) return 0;
|
||||
if ((fd = open(WTMP, O_RDONLY)) < 0) return 0;
|
||||
|
||||
crashed = (lseek(fd, - (off_t) sizeof(last), SEEK_END) == -1
|
||||
|| read(fd, (void *) &last, sizeof(last)) != sizeof(last)
|
||||
|| last.ut_line[0] != '~'
|
||||
|| strncmp(last.ut_user, "shutdown", sizeof(last.ut_user)));
|
||||
close(fd);
|
||||
return crashed;
|
||||
}
|
||||
35
commands/reboot/tinyhalt.c
Executable file
35
commands/reboot/tinyhalt.c
Executable file
@@ -0,0 +1,35 @@
|
||||
/* tinyhalt 1.0 - small forerunner Author: Kees J. Bot
|
||||
*
|
||||
* Disk space on the root file system is a scarce resource. This little
|
||||
* program sits in /sbin. It normally calls the real halt/reboot, but if
|
||||
* that isn't available then it simply calls reboot(). Can't do any logging
|
||||
* of the event anyhow.
|
||||
*/
|
||||
#define nil 0
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int flag;
|
||||
char *prog;
|
||||
|
||||
/* Try to run the real McCoy. */
|
||||
#if __minix_vmd
|
||||
execv("/usr/sbin/halt", argv);
|
||||
#else
|
||||
execv("/usr/bin/halt", argv);
|
||||
#endif
|
||||
|
||||
if ((prog = strrchr(*argv,'/')) == nil) prog= argv[0]; else argv++;
|
||||
|
||||
sleep(2); /* Not too fast. */
|
||||
|
||||
reboot(strcmp(prog, "reboot") == 0 ? RBT_REBOOT : RBT_HALT);
|
||||
|
||||
write(2, "reboot call failed\n", 19);
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user