* 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>
#include <time.h>
#include <string.h>
+#include <errno.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
char *clean_env[] = {
"HOME=/",
- "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
+ "PATH=" PATH_DEFAULT,
"TERM=dumb",
"SHELL=/bin/sh",
NULL,
/*
* Break off an already running shutdown.
*/
+# ifdef __GNUC__
+void stopit(int sig __attribute__((unused)))
+# else
void stopit(int sig)
+# endif
+
{
unlink(NOLOGIN);
unlink(FASTBOOT);
struct init_request request;
struct sigaction sa;
int fd;
- int nl, vl;
+ size_t nl, vl;
memset(&request, 0, sizeof(request));
request.magic = INIT_MAGIC;
sigaction(SIGALRM, &sa, NULL);
got_alrm = 0;
alarm(3);
- if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) { &&
+ if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0) {
ssize_t p = 0;
size_t s = sizeof(request);
void *ptr = &request;
/*
* Tell everyone the system is going down in 'mins' minutes.
*/
-void warn(int mins)
+void issue_warn(int mins)
{
char buf[MESSAGELEN + sizeof(newstate)];
int len;
argv[i] = NULL;
va_end(ap);
- chdir("/");
+ if (chdir("/"))
+ exit(1);
environ = clean_env;
execvp(argv[0], argv);
/* First idle init. */
if (kill(1, SIGTSTP) < 0) {
- fprintf(stderr, "shutdown: can't idle init.\r\n");
+ fprintf(stderr, "shutdown: can't idle init: %s.\r\n", strerror(errno));
exit(1);
}
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();
/*
* Go to runlevel 0, 1 or 6.
*/
-void shutdown(char *halttype)
+void issue_shutdown(char *halttype)
{
char *args[8];
int argp = 0;
int do_halt = (down_level[0] == '0');
/* Warn for the last time */
- warn(0);
+ issue_warn(0);
if (dontshut) {
hardsleep(1);
stopit(0);
struct stat st;
struct utmp *ut;
time_t t;
- uid_t realuid;
char *halttype;
char *downusers[32];
char buf[128];
int user_ok = 0;
/* We can be installed setuid root (executable for a special group) */
- realuid = getuid();
setuid(geteuid());
if (getuid() != 0) {
/* Read pid of running shutdown from a file */
if ((fp = fopen(SDPID, "r")) != NULL) {
- fscanf(fp, "%d", &pid);
+ if (fscanf(fp, "%d", &pid) != 1)
+ pid = 0;
fclose(fp);
}
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);
sa.sa_handler = stopit;
sigaction(SIGINT, &sa, NULL);
- /* Go to the root directory */
- chdir("/");
if (fastboot) close(open(FASTBOOT, O_CREAT | O_RDWR, 0644));
if (forcefsck) close(open(FORCEFSCK, O_CREAT | O_RDWR, 0644));
if (wt < 0) wt += 1440;
}
/* Shutdown NOW if time == 0 */
- if (wt == 0) shutdown(halttype);
+ if (wt == 0) issue_shutdown(halttype);
/* Give warnings on regular intervals and finally shutdown. */
- if (wt < 15 && !needwarning(wt)) warn(wt);
+ if (wt < 15 && !needwarning(wt)) issue_warn(wt);
while(wt) {
if (wt <= 5 && !didnolog) {
donologin(wt);
didnolog++;
}
- if (needwarning(wt)) warn(wt);
+ if (needwarning(wt)) issue_warn(wt);
hardsleep(60);
wt--;
}
- shutdown(halttype);
+ issue_shutdown(halttype);
return 0; /* Never happens */
}