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.
204 lines
6.2 KiB
204 lines
6.2 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 |
|
}; |
|
|
|
#ifndef __SIGRTMIN |
|
#define __SIGRTMIN 32 |
|
#endif |
|
#ifndef __SIGRTMAX |
|
#define __SIGRTMAX (NSIG-1) |
|
#endif |
|
|
|
/* 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; |
|
} |
|
|
|
|