You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							197 lines
						
					
					
						
							6.1 KiB
						
					
					
				
			
		
		
	
	
							197 lines
						
					
					
						
							6.1 KiB
						
					
					
				| /* | |
|  * --- SDE-COPYRIGHT-NOTE-BEGIN --- | |
|  * This copyright note is auto-generated by ./scripts/Create-CopyPatch. | |
|  * | |
|  * Filename: package/.../sysvinit/rc.c | |
|  * Copyright (C) 2007 The OpenSDE Project | |
|  * Copyright (C) 2004 - 2006 The T2 SDE Project | |
|  * Copyright (C) 1998 - 2003 Clifford Wolf | |
|  * | |
|  * More information can be found in the files COPYING and README. | |
|  * | |
|  * This program is free software; you can redistribute it and/or modify | |
|  * it under the terms of the GNU General Public License as published by | |
|  * the Free Software Foundation; version 2 of the License. A copy of the | |
|  * GNU General Public License can be found in the file COPYING. | |
|  * --- SDE-COPYRIGHT-NOTE-END --- | |
|  */ | |
|  | |
| #include <errno.h> | |
| #include <grp.h> | |
| #include <sched.h> | |
| #include <signal.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/resource.h> | |
| #include <sys/stat.h> | |
| #include <sys/time.h> | |
| #include <sys/types.h> | |
| #include <unistd.h> | |
|  | |
| char env_PREVLEVEL[100]="PREVLEVEL=N"; | |
| char env_RUNLEVEL[100]="RUNLEVEL=N"; | |
| char env_TERM[100]="TERM=linux"; | |
|  | |
| char * clean_env[] = { | |
| 	"PATH=/bin:/usr/bin:/sbin:/usr/sbin", | |
| 	env_PREVLEVEL, | |
| 	env_RUNLEVEL, | |
| 	env_TERM, | |
| 	NULL | |
| }; | |
|  | |
| /* See bits/resource.h and asm/resource.h */ | |
| struct rlimit rlim_cpu      = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_fsize    = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_data     = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_stack    = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_core     = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_rss      = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_nofile   = {          1024,          1024 }; | |
| struct rlimit rlim_as       = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_nproc    = {          2048,          2048 }; | |
| struct rlimit rlim_memlock  = { RLIM_INFINITY, RLIM_INFINITY }; | |
| struct rlimit rlim_locks    = { RLIM_INFINITY, RLIM_INFINITY }; | |
|  | |
| #define GROUP_LIST_SIZE 1 | |
| gid_t group_list[GROUP_LIST_SIZE] = { 0 }; | |
|  | |
| /* This prototypes are missing in unistd.h */ | |
| int setresuid(uid_t ruid, uid_t euid, uid_t suid); | |
| int setresgid(gid_t rgid, gid_t egid, gid_t sgid); | |
|  | |
| /* The first (and only) field in sched_param is sched_priority */ | |
| struct sched_param sp = { 0 }; | |
|  | |
| #define handle_error(a) if ( a == -1 ) { perror("rc: " #a); return 1; } | |
|  | |
| int main(int argc, char ** argv) { | |
| 	char command[1024]; | |
| 	int use_btee = 1; | |
| 	int btee_pipe[2]; | |
| 	int i; | |
|  | |
| 	/* Copy some environment variables to the new environment if set */ | |
| 	if ( getenv("PREVLEVEL") ) | |
| 		sprintf(env_PREVLEVEL, "PREVLEVEL=%.50s", getenv("PREVLEVEL")); | |
| 	if ( getenv("RUNLEVEL") ) | |
| 		sprintf(env_RUNLEVEL, "RUNLEVEL=%.50s", getenv("RUNLEVEL")); | |
| 	if ( getenv("TERM") ) | |
| 		sprintf(env_TERM, "TERM=%.50s", getenv("TERM")); | |
|  | |
| 	/* we never need argv[0] - skipt it */ | |
| 	argv++; argc--; | |
|  | |
| 	/* Handle --nobtee option */ | |
| 	if ( argc > 0 && !strcmp(*argv, "--nobtee") ) { | |
| 		use_btee = 0; | |
| 		argv++; argc--; | |
| 	} | |
|  | |
| 	/* Display help message */ | |
| 	if ( argc < 2 ) { | |
| 		fprintf(stderr, | |
| "\n" | |
| "  Run SystemV Init-Scripts with a clean environment and detached from\n" | |
| "  the terminal.\n" | |
| "\n" | |
| "  Usage: rc [ --nobtee ] <service> { start | stop | ... | help } [ script options ]\n"); | |
| 	} | |
| 	if ( argc == 0 ) { | |
| 		fprintf(stderr, "\n" | |
| "  <service> might be one of:\n" | |
| "\n"); | |
| 		fflush(stderr); | |
| 		system("ls /etc/rc.d/init.d >&2"); | |
| 	} | |
| 	if ( argc < 2 ) { | |
| 		fprintf(stderr, "\n"); | |
| 		return 1; | |
| 	} | |
|  | |
| 	/* No btee when viewing the help screen for this service */ | |
| 	if ( !strcmp(argv[1], "help") ) use_btee = 0; | |
|  | |
| 	/* Forward output to a 'btee' process */ | |
| 	if ( use_btee ) { | |
| 		if ( pipe(btee_pipe) ) { | |
| 			perror("rc: Can't create pipe for btee"); | |
| 			return 1; | |
| 		} | |
| 		if ( fork() == 0 ) { | |
| 			dup2(btee_pipe[0], 0); | |
| 			close(btee_pipe[0]); | |
| 			close(btee_pipe[1]); | |
| 			execl("/sbin/btee", "btee", "a", | |
| 			      "/var/log/init.msg", NULL); | |
| 			perror("rc: Can't exec btee command"); | |
| 			return 1; | |
| 		} else { | |
| 			dup2(btee_pipe[1], 1); | |
| 			close(btee_pipe[0]); | |
| 			close(btee_pipe[1]); | |
| 		} | |
| 	} | |
|  | |
| 	/* Set umask, process-group, nice-value and current directory */ | |
| 	handle_error( umask(022) ); | |
| 	handle_error( setpgid(0,0) ); | |
| 	handle_error( setpriority(PRIO_PROCESS, 0, 0) ); | |
| 	handle_error( chdir("/") ); | |
|  | |
| 	/* Set all ulimits */ | |
| 	handle_error( setrlimit(RLIMIT_CPU,     &rlim_cpu) ); | |
| 	handle_error( setrlimit(RLIMIT_FSIZE,   &rlim_fsize) ); | |
| 	handle_error( setrlimit(RLIMIT_DATA,    &rlim_data) ); | |
| 	handle_error( setrlimit(RLIMIT_STACK,   &rlim_stack) ); | |
| 	handle_error( setrlimit(RLIMIT_CORE,    &rlim_core) ); | |
| 	handle_error( setrlimit(RLIMIT_RSS,     &rlim_rss) ); | |
| 	handle_error( setrlimit(RLIMIT_NOFILE,  &rlim_nofile) ); | |
| 	handle_error( setrlimit(RLIMIT_AS,      &rlim_as) ); | |
| 	handle_error( setrlimit(RLIMIT_NPROC,   &rlim_nproc) ); | |
| 	handle_error( setrlimit(RLIMIT_MEMLOCK, &rlim_memlock) ); | |
| 	handle_error( setrlimit(RLIMIT_LOCKS,   &rlim_locks) ); | |
|  | |
| 	/* Reset all signal handlers */ | |
| 	for (i=1; i<NSIG; i++) { | |
| 		if ( i == SIGKILL ) continue; | |
| 		if ( i == SIGSTOP ) continue; | |
| 		if ( i >= __SIGRTMIN && i < SIGRTMIN ) continue; | |
| 		if( signal(i, SIG_DFL) == SIG_ERR ) { | |
| 			fprintf(stderr, "rc: Can't reset signal #%d: " | |
| 			        "%s\n", i, strerror(errno) ); | |
| 			return 1; | |
| 		} | |
| 	} | |
|  | |
| 	/* Close all file-descriptors > 2 (1024 seams to be a good value - | |
| 	 * linux/fs.h defines NR_OPEN to 1024*1024, which is too big ;-) */ | |
| 	for (i=3; i<=1024; i++) close(i); | |
|  | |
| 	/* Set user and group ids */ | |
| 	handle_error( setgroups(GROUP_LIST_SIZE, group_list) ); | |
| 	handle_error( setresuid(0, 0, 0) ); | |
| 	handle_error( setresgid(0, 0, 0) ); | |
|  | |
| 	/* clear rt scheduling */ | |
| 	handle_error( sched_setscheduler(0, SCHED_OTHER, &sp) ); | |
|  | |
| 	/* Run the command in a (non-interactive) login shell (i.e. read | |
| 	 * /etc/profile) and send \004 after running the script if we are | |
| 	 * using btee. */ | |
| 	i = snprintf(command, sizeof(command), "%s%s", | |
| 	         strchr(*argv, '/') ? "" : "/etc/rc.d/init.d/", *argv); | |
| 	argv++; | |
| 	while (*argv) /* copy args */ | |
| 		i += snprintf(command+i, sizeof(command)-i, " %s", *argv++); | |
| 	i+=snprintf(command+i, sizeof(command)-i, " </dev/null 2>&1%s", | |
| 	         use_btee ? "; echo -ne '\004'" : ""); | |
| 	execle("/bin/bash", "-bash", "-l", "-c", command, NULL, clean_env); | |
|  | |
| 	/* Oups! Can't exec the shell. */ | |
| 	if ( use_btee ) write(1, "\004", 1); | |
| 	perror("rc: Can't execute shell for spawning init script"); | |
| 	return 1; | |
| } | |
| 
 | |
| 
 |