mirror of the now-defunct rocklinux.org
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.

206 lines
6.7 KiB

  1. /*
  2. * --- ROCK-COPYRIGHT-NOTE-BEGIN ---
  3. *
  4. * This copyright note is auto-generated by ./scripts/Create-CopyPatch.
  5. * Please add additional copyright information _after_ the line containing
  6. * the ROCK-COPYRIGHT-NOTE-END tag. Otherwise it might get removed by
  7. * the ./scripts/Create-CopyPatch script. Do not edit this copyright text!
  8. *
  9. * ROCK Linux: rock-src/package/base/sysfiles/rc.c
  10. * ROCK Linux is Copyright (C) 1998 - 2006 Clifford Wolf
  11. *
  12. * This program is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2 of the License, or
  15. * (at your option) any later version. A copy of the GNU General Public
  16. * License can be found at Documentation/COPYING.
  17. *
  18. * Many people helped and are helping developing ROCK Linux. Please
  19. * have a look at http://www.rocklinux.org/ and the Documentation/TEAM
  20. * file for details.
  21. *
  22. * --- ROCK-COPYRIGHT-NOTE-END ---
  23. */
  24. #include <errno.h>
  25. #include <grp.h>
  26. #include <sched.h>
  27. #include <signal.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <sys/resource.h>
  32. #include <sys/stat.h>
  33. #include <sys/time.h>
  34. #include <sys/types.h>
  35. #include <unistd.h>
  36. char env_PATH[100]="PATH=/bin:/usr/bin:/sbin:/usr/sbin";
  37. char env_INIT_VERSION[100]="INIT_VERSION=";
  38. char env_PREVLEVEL[100]="PREVLEVEL=N";
  39. char env_RUNLEVEL[100]="RUNLEVEL=N";
  40. char env_CONSOLE[100]="CONSOLE=/dev/console";
  41. char env_TERM[100]="TERM=linux";
  42. char * clean_env[] = {
  43. env_PATH,
  44. env_INIT_VERSION,
  45. env_PREVLEVEL,
  46. env_RUNLEVEL,
  47. env_CONSOLE,
  48. env_TERM,
  49. NULL
  50. };
  51. /* See bits/resource.h and asm/resource.h */
  52. struct rlimit rlim_cpu = { RLIM_INFINITY, RLIM_INFINITY };
  53. struct rlimit rlim_fsize = { RLIM_INFINITY, RLIM_INFINITY };
  54. struct rlimit rlim_data = { RLIM_INFINITY, RLIM_INFINITY };
  55. struct rlimit rlim_stack = { RLIM_INFINITY, RLIM_INFINITY };
  56. struct rlimit rlim_core = { RLIM_INFINITY, RLIM_INFINITY };
  57. struct rlimit rlim_rss = { RLIM_INFINITY, RLIM_INFINITY };
  58. struct rlimit rlim_nofile = { 1024, 1024 };
  59. struct rlimit rlim_as = { RLIM_INFINITY, RLIM_INFINITY };
  60. struct rlimit rlim_nproc = { 2048, 2048 };
  61. struct rlimit rlim_memlock = { RLIM_INFINITY, RLIM_INFINITY };
  62. struct rlimit rlim_locks = { RLIM_INFINITY, RLIM_INFINITY };
  63. #define GROUP_LIST_SIZE 1
  64. gid_t group_list[GROUP_LIST_SIZE] = { 0 };
  65. /* This prototypes are missing in unistd.h */
  66. int setresuid(uid_t ruid, uid_t euid, uid_t suid);
  67. int setresgid(gid_t rgid, gid_t egid, gid_t sgid);
  68. /* The first (and only) field in sched_param is sched_priority */
  69. struct sched_param sp = { 0 };
  70. #define handle_error(a) if ( a == -1 ) { perror("rc: " #a); return 1; }
  71. int main(int argc, char ** argv) {
  72. char command[1024];
  73. int use_btee = 1;
  74. int btee_pipe[2];
  75. int i, cmd_space;
  76. /* Copy some environment variables to the new environment if set */
  77. if ( getenv("PATH") )
  78. sprintf(env_PATH, "PATH=%.50s", getenv("PATH"));
  79. if ( getenv("INIT_VERSION") )
  80. sprintf(env_INIT_VERSION, "INIT_VERSION=%.50s", getenv("INIT_VERSION"));
  81. if ( getenv("PREVLEVEL") )
  82. sprintf(env_PREVLEVEL, "PREVLEVEL=%.50s", getenv("PREVLEVEL"));
  83. if ( getenv("RUNLEVEL") )
  84. sprintf(env_RUNLEVEL, "RUNLEVEL=%.50s", getenv("RUNLEVEL"));
  85. if ( getenv("CONSOLE") )
  86. sprintf(env_CONSOLE, "CONSOLE=%.50s", getenv("CONSOLE"));
  87. if ( getenv("TERM") )
  88. sprintf(env_TERM, "TERM=%.50s", getenv("TERM"));
  89. /* Handle --nobtee option */
  90. if ( argc > 1 && !strcmp(argv[1], "--nobtee") ) {
  91. use_btee = 0;
  92. argv++; argc--;
  93. }
  94. /* Display help message */
  95. if ( argc < 3 ) {
  96. fprintf(stderr,
  97. "\n"
  98. " Run SystemV Init-Scripts with a clean environment and detached from\n"
  99. " the terminal.\n"
  100. "\n"
  101. " Usage: rc [ --nobtee ] <service> { start | stop | ... | help } [ args ]\n"
  102. "\n"
  103. " <service> might be one of:\n"
  104. "\n");
  105. fflush(stderr);
  106. system("ls /etc/rc.d/init.d >&2");
  107. fprintf(stderr, "\n");
  108. return 1;
  109. }
  110. /* No btee when viewing the help screen for this service */
  111. if ( !strcmp(argv[2], "help") ) use_btee = 0;
  112. /* Forward output to a 'btee' process */
  113. if ( use_btee ) {
  114. if ( pipe(btee_pipe) ) {
  115. perror("rc: Can't create pipe for btee");
  116. return 1;
  117. }
  118. if ( fork() == 0 ) {
  119. dup2(btee_pipe[0], 0);
  120. close(btee_pipe[0]);
  121. close(btee_pipe[1]);
  122. execl("/sbin/btee", "btee", "a",
  123. "/var/log/init.msg", NULL);
  124. perror("rc: Can't exec btee command");
  125. return 1;
  126. } else {
  127. dup2(btee_pipe[1], 1);
  128. close(btee_pipe[0]);
  129. close(btee_pipe[1]);
  130. }
  131. }
  132. /* Set umask, process-group, nice-value and current directory */
  133. handle_error( umask(022) );
  134. handle_error( setpgid(0,0) );
  135. handle_error( setpriority(PRIO_PROCESS, 0, 0) );
  136. handle_error( chdir("/") );
  137. /* Set all ulimits */
  138. handle_error( setrlimit(RLIMIT_CPU, &rlim_cpu) );
  139. handle_error( setrlimit(RLIMIT_FSIZE, &rlim_fsize) );
  140. handle_error( setrlimit(RLIMIT_DATA, &rlim_data) );
  141. handle_error( setrlimit(RLIMIT_STACK, &rlim_stack) );
  142. handle_error( setrlimit(RLIMIT_CORE, &rlim_core) );
  143. handle_error( setrlimit(RLIMIT_RSS, &rlim_rss) );
  144. handle_error( setrlimit(RLIMIT_NOFILE, &rlim_nofile) );
  145. handle_error( setrlimit(RLIMIT_AS, &rlim_as) );
  146. handle_error( setrlimit(RLIMIT_NPROC, &rlim_nproc) );
  147. handle_error( setrlimit(RLIMIT_MEMLOCK, &rlim_memlock) );
  148. handle_error( setrlimit(RLIMIT_LOCKS, &rlim_locks) );
  149. /* Reset all signal handlers */
  150. for (i=1; i<64; i++) {
  151. if ( i == SIGKILL ) continue;
  152. if ( i == SIGSTOP ) continue;
  153. if ( signal(i, SIG_DFL) == SIG_ERR && i < 32 ) {
  154. fprintf(stderr, "rc: Can't reset signal #%d: "
  155. "%s\n", i, strerror(errno) );
  156. return 1;
  157. }
  158. }
  159. /* Close all file-descriptors > 2 (1024 seems to be a good value -
  160. * linux/fs.h defines NR_OPEN to 1024*1024, which is too big ;-) */
  161. for (i=3; i<=1024; i++) close(i);
  162. /* Set user and group ids */
  163. handle_error( setgroups(GROUP_LIST_SIZE, group_list) );
  164. handle_error( setresuid(0, 0, 0) );
  165. handle_error( setresgid(0, 0, 0) );
  166. /* clear rt scheduling */
  167. handle_error( sched_setscheduler(0, SCHED_OTHER, &sp) );
  168. /* Run the command in a (non-interactive) login shell (i.e. read
  169. * /etc/profile) and send \004 after running the script if we are
  170. * using btee. */
  171. cmd_space = snprintf(command, 1024, "%s%s",
  172. strchr(argv[1], '/') ? "" : "/etc/rc.d/init.d/", argv[1]);
  173. for (i=2; i<argc; i++)
  174. cmd_space += snprintf(command+cmd_space, 1024-cmd_space, " %s", argv[i]);
  175. cmd_space += snprintf(command+cmd_space, 1024-cmd_space, " </dev/null 2>&1%s",
  176. use_btee ? "; echo -ne '\004'" : "");
  177. if ( cmd_space < 1000 )
  178. execle("/bin/bash", "-bash", "-l", "-c", command, NULL, clean_env);
  179. /* Oups! Can't exec the shell. */
  180. if ( use_btee ) write(1, "\004", 1);
  181. perror("rc: Can't execute shell for spawning init script");
  182. return 1;
  183. }