* 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;
sa.sa_handler = alrm_handler;
sigaction(SIGALRM, &sa, NULL);
got_alrm = 0;
- alarm(3);
- if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0 &&
- write(fd, &request, sizeof(request)) == sizeof(request)) {
- close(fd);
- alarm(0);
- return 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;
+ fprintf(stderr, "shutdown: ");
+ if (got_alrm) {
+ fprintf(stderr, "timeout opening/writing control channel %s\n",
+ INIT_FIFO);
+ } else {
+ perror(INIT_FIFO);
+ }
+ return -1;
}
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();
/* 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));