V7M/src/cmd/shutdown.c
/*
* Unix/v7m gracefull system shutdown - shutdown.c
* Fred Canter 9/25/81
*
* Thanks to Jerry Brenner for 90% of this program.
*/
#include <stdio.h>
#include <signal.h>
#include <a.out.h>
#include <core.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/tty.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <utmp.h>
struct nlist nl[] = {
{ "_proc" },
{ "_swapdev" },
{ "_nproc" },
{ "_swplo" },
{ "" },
};
struct proc mproc;
struct utmp utmp[50];
struct user u;
int chkpid;
int retcode=1;
char *tptr;
long lseek();
char *strcat();
char *strcpy();
char *strcmp();
char *strncmp();
char *ttynam;
char *ttyname();
int mem;
int swmem;
int swap;
daddr_t swplo;
int nproc;
int ndev;
struct devl {
char dname[DIRSIZ];
dev_t dev;
} devl[256];
char *coref;
int deltim;
char umntmsg[] = {"/etc/unmount"};
char cnsle[] = {"/dev/console"};
char lokfil[] = {"/etc/sdloglock"};
main(argc, argv)
char **argv;
{
int stop();
int i;
char *ap, c;
int uid, puid, pid, pgid;
int incnt;
char inbuf[80];
extern int deltim;
signal(SIGINT, stop);
chdir ("/etc");
ttynam = ttyname(0);
if (strcmp(cnsle, ttynam))
{
printf("\nShutdown can only be run from the console device\n");
exit();
}
if (argc>1)
{
ap = argv[1];
deltim = atoi(ap);
}
else
{
printf("\nHow many minutes until shutdown [1-99] ? ");
for (incnt = 0; c != '\n' ; ++incnt)
{
c = getchar();
inbuf[incnt] = c;
}
deltim = atoi(inbuf);
}
if (deltim > 99 || deltim < 0) {
printf("\nShutdown time out of range\n");
exit(0);
}
creat(&lokfil, 0);
for (;deltim >= 0; --deltim)
{
sndall();
if (deltim > 0)
sleep(60);
}
pid = getpid();
if(chdir("/dev") < 0) {
fprintf(stderr, "Can't change to /dev\n");
exit(1);
}
nlist(argc>2? argv[2]:"/unix", nl);
if (nl[0].n_type==0) {
fprintf(stderr, "No namelist\n");
exit(1);
}
coref = "/dev/mem";
if ((mem = open(coref, 0)) < 0) {
fprintf(stderr, "No mem\n");
exit(1);
}
swmem = open(coref, 0);
/*
* read mem to find swap dev.
*/
lseek(mem, (long)nl[1].n_value, 0);
read(mem, (char *)&nl[1].n_value, sizeof(nl[1].n_value));
/*
* Find base of swap
*/
lseek(mem, (long)nl[2].n_value, 0);
read(mem, (char *)&swplo, sizeof(swplo));
/*
* Find number of processes allowed - NPROC
*/
lseek(mem, (long)nl[3].n_value, 0);
read(mem, (char *)&nproc, sizeof(nproc));
/*
* Locate proc table
*/
lseek(mem, (long)nl[0].n_value, 0);
getdev();
uid = getuid();
printf("\nKill Process Phase\n\n");
while(mproc.p_pid != pid)
{
read(mem, (char *)&mproc, sizeof mproc);
}
pgid = mproc.p_pgrp;
lseek(mem, (long)nl[0].n_value, 0);
for (i=0; i<nproc; i++)
{
read(mem, (char *)&mproc, sizeof mproc);
if (mproc.p_stat==0)
continue;
if (mproc.p_pgrp==0 && mproc.p_uid==0)
continue;
puid = mproc.p_pid;
if(mproc.p_pgrp==pgid || mproc.p_pgrp==0)
continue;
kill (puid, 9);
}
printf("****** WAIT FOR SECOND # CHARACTER ******\n");
printf("****** DO A SYNC, THEN HALT THE SYSTEM ******\n");
sync();
kill(1, 2);
sync();
}
getdev()
{
#include <sys/stat.h>
register FILE *df;
struct stat sbuf;
struct direct dbuf;
if ((df = fopen("/dev", "r")) == NULL) {
fprintf(stderr, "Can't open /dev\n");
exit(1);
}
ndev = 0;
while (fread((char *)&dbuf, sizeof(dbuf), 1, df) == 1) {
if(dbuf.d_ino == 0)
continue;
if(stat(dbuf.d_name, &sbuf) < 0)
continue;
if ((sbuf.st_mode&S_IFMT) != S_IFCHR)
continue;
strcpy(devl[ndev].dname, dbuf.d_name);
devl[ndev].dev = sbuf.st_rdev;
ndev++;
}
fclose(df);
if ((swap = open("/dev/swap", 0)) < 0) {
fprintf(stderr, "Can't open /dev/swap\n");
exit(1);
}
}
within(adr,lbd,ubd)
char *adr;
long lbd, ubd;
{
return((unsigned)adr>=lbd && (unsigned)adr<ubd);
}
sndall()
{
register i;
register struct utmp *p;
FILE *f;
if((f = fopen("/etc/utmp", "r")) == NULL) {
fprintf(stderr, "Cannot open /etc/utmp\n");
exit(1);
}
fread((char *)utmp, sizeof(struct utmp), 50, f);
fclose(f);
f = stdin;
for(i=0; i<50; i++) {
p = &utmp[i];
if(p->ut_name[0] == 0)
continue;
sleep(1);
if((strcmp("root", p->ut_name) == 0)
&& (strcmp("console", p->ut_line) != 0)) {
printf("\nShutdown aborted - ");
printf("user logged in as `root' on %s\n",p->ut_line);
stop();
}
sendmes(p->ut_line);
}
}
sendmes(tty)
char *tty;
{
register i;
char t[50], buf[BUFSIZ];
FILE *f;
extern int deltim;
i = fork();
if(i == -1) {
fprintf(stderr, "Try again\n");
return;
}
if(i)
return;
strcpy(t, "/dev/");
strcat(t, tty);
if((f = fopen(t, "w")) == NULL) {
fprintf(stderr,"cannot open %s\n", t);
exit(1);
}
setbuf(f, buf);
fprintf(f, "Broadcast Message ...\n\n");
if(deltim > 0)
{
fprintf(f, "System going down in %d minutes\n\n", deltim);
fprintf(f, "Please finish up\n\n");
}
else
fprintf(f, "System going down. Bye\n\n");
exit(0);
}
/*
* The stop function clears the /etc/sdloglock file
* if the shutdown is aborted via the interrupt signal.
* This reenables logins after the sghutdown abort.
*/
stop()
{
unlink(&lokfil);
exit(1);
}