Пример #1
0
int main(int argc, char *argv[])
{
	int 	i;
	struct sigaction sa;

	/*
	 * setup all the signal handlers here
	 */

	memset(&sa, 0, sizeof(sa));
	/* sa.sa_flags = SA_RESETHAND we want to keep the handlers armed */

	sa.sa_handler = tstp_handler;
	sigaction(SIGTSTP, &sa, NULL);

	sa.sa_handler = cont_handler;
	sigaction(SIGCONT, &sa, NULL);

	sa.sa_handler = int_handler;
	sigaction(SIGINT, &sa, NULL);

	sa.sa_handler = respawn_children;
	sigaction(SIGALRM, &sa, NULL);

	sa.sa_handler = hup_handler;
	sigaction(SIGHUP, &sa, NULL);

#if defined(CONSOLE_BAUD_RATE) && LINUX_VERSION_CODE < 0x020100
	set_console_baud(CONSOLE_BAUD_RATE);
#endif

	/* 
	 * start up in single user mode if /etc/singleboot exists or if
	 * argv[1] is "single".
	 */
	if(boot_single(0, argc, argv)) enter_single();
#ifdef CONFIG_RTL865X
	for(i = 1; i < argc; i++) {
	    if(argv[i] && !strcmp(argv[i], "uart1"))
			boot_uart1=1;;
	}
#endif
#ifdef RUN_RC
	/* Register console if defined by boot */
#if LINUX_VERSION_CODE < 0x020100
	if ((console_device = getenv("CONSOLE"))) {
	char	*sp;
		unsetenv("CONSOLE");
		if ((sp = strchr(console_device, ','))) {
			*sp++ = 0;
			set_console_baud(atoi(sp));
		}
	}

	make_ascii_tty();
#else
{
	struct stat st;

	if (isatty(1)) {
		have_console = 1;
		make_ascii_tty();
	} else if (fstat(1, &st) == -1 && errno == EBADF) {
		close(0); close(1); close(2);
		open("/dev/null", O_RDWR);
		dup(0);
		dup(0);
	}
}
#endif

	/*If we get a SIGTSTP before multi-user mode, do nothing*/
	while(stopped)	
		pause();
	if(do_rc() != 0 && boot_single(1, argc, argv) && !stopped)
		enter_single();
	while(stopped)	/*Also if /etc/rc fails & we get SIGTSTP*/
		pause();
#endif

	write_wtmp();	/* write boottime record */
	read_inittab();

#ifdef DEBUGGING
	for(i = 0; i < numcmd; i++) {
	char **p;
		p = inittab[i].toks;
		printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);
		printf("tty= %s\n", inittab[i].tty);
		printf("termcap= %s\n", inittab[i].termcap);
	}
	/*exit(0);*/
#endif

#if LINUX_VERSION_CODE < 0x020100
	for(i = 0; i < getdtablesize(); i++) close(i);
#else
	i = 0;
	if (have_console)
		i = 3;
	for(; i < getdtablesize(); i++) close(i);
#endif

	for (;;) {
		pid_t	pid;
		int	vec;

		if (run_sigint_processing) {
			run_sigint_processing = 0;
			sigint_processing();
		}

		respawn_children();

		if (reload) {
			reload = 0;
			reload_inittab();
			continue; /* process all reloads before waiting */
		}

		pid = wait(&vec);
		alarm(0);

		/* clear utmp entry, and append to wtmp if possible */
#if 0		/* DAVIDM */
		{
		    struct utmp *ut;
		    int ut_fd;

		    utmpname(_PATH_UTMP);
		    setutent();
		    while((ut = getutent())) {
			if(ut->ut_pid == pid) {
			    time(&ut->ut_time);
			    bzero(&ut->ut_user, UT_NAMESIZE);
			    bzero(&ut->ut_host, sizeof(ut->ut_host));
			    ut->ut_type = DEAD_PROCESS;
			    ut->ut_pid = 0;
			    ut->ut_addr = 0;
			    endutent();
			    pututline(ut);
			    if((ut_fd = open(_PATH_WTMP, O_APPEND|O_WRONLY)) >= 0) {
				flock(ut_fd, LOCK_EX|LOCK_NB);
				write(ut_fd, (const void *)ut, sizeof(struct utmp));
				flock(ut_fd, LOCK_UN|LOCK_NB);
				close(ut_fd);
			    }
			    break;
			}
		    }
		    endutent();
		}
#endif

		for(i = 0; i < numcmd; i++) {
			if(pid == inittab[i].pid) {
				inittab[i].pid = -1;
			}
		}
	}

}	
Пример #2
0
int halt_main(int argc UNUSED_PARAM, char **argv)
{
	static const int magic[] = {
		RB_HALT_SYSTEM,
		RB_POWER_OFF,
		RB_AUTOBOOT
	};
	static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };

	int delay = 0;
	int which, flags, rc;

	/* Figure out which applet we're running */
	for (which = 0; "hpr"[which] != applet_name[0]; which++)
		continue;

	/* Parse and handle arguments */
	opt_complementary = "d+"; /* -d N */
	/* We support -w even if !ENABLE_FEATURE_WTMP,
	 * in order to not break scripts.
	 * -i (shut down network interfaces) is ignored.
	 */
	flags = getopt32(argv, "d:nfwi", &delay);

	sleep(delay);

	write_wtmp();

	if (flags & 8) /* -w */
		return EXIT_SUCCESS;

	if (!(flags & 2)) /* no -n */
		sync();

	/* Perform action. */
	rc = 1;
	if (!(flags & 4)) { /* no -f */
//TODO: I tend to think that signalling linuxrc is wrong
// pity original author didn't comment on it...
		if (ENABLE_FEATURE_INITRD) {
			/* talk to linuxrc */
			/* bbox init/linuxrc assumed */
			pid_t *pidlist = find_pid_by_name("linuxrc");
			if (pidlist[0] > 0)
				rc = kill(pidlist[0], signals[which]);
			if (ENABLE_FEATURE_CLEAN_UP)
				free(pidlist);
		}
		if (rc) {
			/* talk to init */
			if (!ENABLE_FEATURE_CALL_TELINIT) {
				/* bbox init assumed */
				rc = kill(1, signals[which]);
			} else {
				/* SysV style init assumed */
				/* runlevels:
				 * 0 == shutdown
				 * 6 == reboot */
				rc = execlp(CONFIG_TELINIT_PATH,
						CONFIG_TELINIT_PATH,
						which == 2 ? "6" : "0",
						(char *)NULL
				);
			}
		}
	} else {
		rc = reboot(magic[which]);
	}

	if (rc)
		bb_perror_nomsg_and_die();
	return rc;
}
Пример #3
0
int
main(int argc, char *argv[])
{
	int c, i, fd;
	char *ptr;

	i = getdtablesize ();
	for (fd = 3; fd < i; fd++) close (fd);
	if (getpid () == 1)
	{
	    for (fd = 0; fd < 3; fd++) close (fd);
	    while (1) wait (NULL);  /*  Grim reaper never stops  */
	}
	sigsetmask (0); /*  simpleinit(8) blocks all signals: undo for ALRM  */
	for (i = 1; i < NSIG; i++) signal (i, SIG_DFL);

        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);

#ifndef DEBUGGING
	if(setreuid (0, 0)) {
		fprintf(stderr, _("%s: Only root can shut a system down.\n"),
			argv[0]);
		exit(1);
	}
#endif

	if(*argv[0] == '-') argv[0]++;	/* allow shutdown as login shell */
	prog = argv[0];
	if((ptr = strrchr(argv[0], '/'))) prog = ++ptr;

	/* All names (halt, reboot, fasthalt, fastboot, shutdown)
	   refer to the same program with the same options,
	   only the defaults differ. */
	if(!strcmp("halt", prog)) {
		opt_reboot = 0;
		opt_quiet = 1;
		opt_fast = 0;
		timeout = 0;
	} else if(!strcmp("fasthalt", prog)) {
		opt_reboot = 0;
		opt_quiet = 1;
		opt_fast = 1;
		timeout = 0;
	} else if(!strcmp("reboot", prog)) {
		opt_reboot = 1;
		opt_quiet = 1;
		opt_fast = 0;
		timeout = 0;
	} else if(!strcmp("fastboot", prog)) {
		opt_reboot = 1;
		opt_quiet = 1;
		opt_fast = 1;
		timeout = 0;
	} else {
		/* defaults */
		opt_reboot = 0;
		opt_quiet = 0;
		opt_fast = 0;
		timeout = 2*60;
	}
		
	c = 0;
	while(++c < argc) {
		if(argv[c][0] == '-') {
			for(i = 1; argv[c][i]; i++) {
				switch(argv[c][i]) {
				case 'C':
					opt_use_config_file = 1;
					break;
				case 'h': 
					opt_reboot = 0;
					break;
				case 'r':
					opt_reboot = 1;
					break;
				case 'f':
					opt_fast = 1;
					break;
				case 'q':
					opt_quiet = 1;
					break;
				case 's':
					opt_single = 1;
					break;
				    
				default:
					usage();
				}
			}
		} else if(!strcmp("now", argv[c])) {
			timeout = 0;
		} else if(argv[c][0] == '+') {
			timeout = 60 * atoi(&argv[c][1]);
		} else if (isdigit(argv[c][0])) {
			char *colon;
			int hour = 0;
			int minute = 0;
			time_t tics;
			struct tm *tt;
			int now, then;
				
			if((colon = strchr(argv[c], ':'))) {
				*colon = '\0';
				hour = atoi(argv[c]);
				minute = atoi(++colon);
			} else usage();
				
			(void) time(&tics);
			tt = localtime(&tics);
				
			now = 3600 * tt->tm_hour + 60 * tt->tm_min;
			then = 3600 * hour + 60 * minute;
			timeout = then - now;
			if(timeout < 0) {
				fprintf(stderr, _("That must be tomorrow, "
					          "can't you wait till then?\n"));
				exit(1);
			}
		} else {
			xstrncpy(message, argv[c], sizeof(message));
			opt_msgset = 1;
		}
	}

	halt_action[0] = 0;

	/* No doubt we shall want to extend this some day
	   and register a series of commands to be executed
	   at various points during the shutdown sequence,
	   and to define the number of milliseconds to sleep, etc. */
	if (opt_use_config_file) {
		char line[256], *p;
		FILE *fp;

		/*  Read and parse the config file */
		halt_action[0] = '\0';
		if ((fp = fopen (_PATH_SHUTDOWN_CONF, "r")) != NULL) {
			if (fgets (line, sizeof(line), fp) != NULL &&
			    strncasecmp (line, "HALT_ACTION", 11) == 0 &&
			    iswhitespace(line[11])) {
				p = index(line, '\n');
				if (p)
					*p = 0;		/* strip final '\n' */
				p = line+11;
				while(iswhitespace(*p))
					p++;
				strcpy(halt_action, p);
			}
			fclose (fp);
		}
	}

	if(!opt_quiet && !opt_msgset) {
		/* now ask for message, gets() is insecure */
		int cnt = sizeof(message)-1;
		char *ptr;
		
		printf("Why? "); fflush(stdout);
		
		ptr = message;
		while(--cnt >= 0 && (*ptr = getchar()) && *ptr != '\n') { 
			ptr++;
		}
		*ptr = '\0';
	} else if (!opt_msgset) {
		strcpy(message, _("for maintenance; bounce, bounce"));
	}

#ifdef DEBUGGING
	printf(_("timeout = %d, quiet = %d, reboot = %d\n"),
		timeout, opt_quiet, opt_reboot);
#endif
	
	/* so much for option-processing, now begin termination... */
	if(!(whom = getlogin()) || !*whom) whom = "ghost";
	if(strlen(whom) > 40) whom[40] = 0; /* see write_user() */

	setpriority(PRIO_PROCESS, 0, PRIO_MIN);
	signal(SIGINT,  int_handler);
	signal(SIGHUP,  int_handler);
	signal(SIGQUIT, int_handler);
	signal(SIGTERM, int_handler);

	chdir("/");

	if(timeout > 5*60) {
		sleep(timeout - 5*60);
		timeout = 5*60;
	}

	
	if((fd = open(_PATH_NOLOGIN, O_WRONLY|O_CREAT, 0644)) >= 0) {
		/* keep xgettext happy and leave \r\n outside strings */
		WRCRLF;
		WR(_("The system is being shut down within 5 minutes"));
		WRCRLF;
		write(fd, message, strlen(message));
		WRCRLF;
		WR(_("Login is therefore prohibited."));
		WRCRLF;
		close(fd);
	}
	
	signal(SIGPIPE, SIG_IGN);

	if(timeout > 0) {
		wall();
		sleep(timeout);
	}

	timeout = 0;
	wall();
	sleep(3);

	/* now there's no turning back... */
	signal(SIGINT,  SIG_IGN);

	/* do syslog message... */
	openlog(prog, LOG_CONS, LOG_AUTH);
	if (opt_reboot)
		syslog(LOG_NOTICE, _("rebooted by %s: %s"), 
		       whom, message);
	else
		syslog(LOG_NOTICE, _("halted by %s: %s"), 
		       whom, message);
	closelog();

	if(opt_fast)
		if((fd = open("/fastboot", O_WRONLY|O_CREAT, 0644)) >= 0)
			close(fd);

	kill(1, SIGTSTP);	/* tell init not to spawn more getty's */
	write_wtmp();
	if(opt_single)
		if((fd = open(_PATH_SINGLE, O_CREAT|O_WRONLY, 0644)) >= 0)
			close(fd);
		
	sync();

	signal(SIGTERM, SIG_IGN);
	if(fork() > 0) sleep(1000); /* the parent will die soon... */
	setpgrp();		/* so the shell wont kill us in the fall */

#ifndef DEBUGGING
	/* a gentle kill of all other processes except init */
	kill_mortals (SIGTERM);
	for (fd = 0; fd < 3; fd++) close (fd);
	stop_finalprog ();
	sleep (1);                    /*  Time for saves to start           */
	kill (1, SIGTERM);            /*  Tell init to kill spawned gettys  */
	usleep (100000);              /*  Wait for gettys to die            */
	my_puts ("");                 /*  Get past the login prompt         */
	system ("/sbin/initctl -r");  /*  Roll back services                */
	syncwait (1);
	my_puts ("Sending SIGTERM to all remaining processes...");
	kill (-1, SIGTERM);
	sleep (2);                    /*  Default 2, some people need 5     */

	kill (-1, SIGKILL);           /*  Now use brute force...            */

	/* turn off accounting */
	acct(NULL);
#endif
	/* RedHat and SuSE like to remove /etc/nologin.
	   Perhaps the usual sequence is
	      touch nologin; shutdown -h; fiddle with hardware;
	      boot; fiddle with software; rm nologin
	   and removing it here will be counterproductive.
	   Let us see whether people complain. */
	unlink(_PATH_NOLOGIN);

	/*  Tell init(8) to exec so that the old inode may be freed cleanly if
	    required. Need to sleep before remounting root read-only  */
	kill (1, SIGQUIT);

	sleep (1);	/* Time for processes to die and close files */
	syncwait (2);

	/* remove swap files and partitions using swapoff */
	swap_off();

	/* unmount disks... */
	unmount_disks();
	syncwait (1);

	if(opt_reboot) {
		my_reboot(LINUX_REBOOT_CMD_RESTART); /* RB_AUTOBOOT */
		my_puts(_("\nWhy am I still alive after reboot?"));
	} else {
		my_puts(_("\nNow you can turn off the power..."));

		/* allow C-A-D now, [email protected], re-fixed 8-Jul-96 */
		my_reboot(LINUX_REBOOT_CMD_CAD_ON); /* RB_ENABLE_CAD */
		sleep (1);  /*  Wait for devices to finish writing to media  */
		do_halt(halt_action);
	}
	/* NOTREACHED */
	exit(0); /* to quiet gcc */
}