start_stop_daemon.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini start-stop-daemon implementation(s) for busybox
  4. *
  5. * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
  6. * Adapted for busybox David Kimdon <dwhedon@gordian.com>
  7. *
  8. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  9. */
  10. /*
  11. This is how it is supposed to work:
  12. start-stop-daemon [OPTIONS] [--start|--stop] [[--] arguments...]
  13. One (only) of these must be given:
  14. -S,--start Start
  15. -K,--stop Stop
  16. Search for matching processes.
  17. If --stop is given, stop all matching processes (by sending a signal).
  18. If --start is given, start a new process unless a matching process was found.
  19. Options controlling process matching
  20. (if multiple conditions are specified, all must match):
  21. -u,--user USERNAME|UID Only consider this user's processes
  22. -n,--name PROCESS_NAME Look for processes by matching PROCESS_NAME
  23. with comm field in /proc/$PID/stat.
  24. Only basename is compared:
  25. "ntpd" == "./ntpd" == "/path/to/ntpd".
  26. [TODO: can PROCESS_NAME be a full pathname? Should we require full match then
  27. with /proc/$PID/exe or argv[0] (comm can't be matched, it never contains path)]
  28. -x,--exec EXECUTABLE Look for processes that were started with this
  29. command in /proc/$PID/cmdline.
  30. Unlike -n, we match against the full path:
  31. "ntpd" != "./ntpd" != "/path/to/ntpd"
  32. -p,--pidfile PID_FILE Look for processes with PID from this file
  33. Options which are valid for --start only:
  34. -x,--exec EXECUTABLE Program to run (1st arg of execvp). Mandatory.
  35. -a,--startas NAME argv[0] (defaults to EXECUTABLE)
  36. -b,--background Put process into background
  37. -N,--nicelevel N Add N to process' nice level
  38. -c,--chuid USER[:[GRP]] Change to specified user [and group]
  39. -m,--make-pidfile Write PID to the pidfile
  40. (both -m and -p must be given!)
  41. Options which are valid for --stop only:
  42. -s,--signal SIG Signal to send (default:TERM)
  43. -t,--test Exit with status 0 if process is found
  44. (we don't actually start or stop daemons)
  45. Misc options:
  46. -o,--oknodo Exit with status 0 if nothing is done
  47. -q,--quiet Quiet
  48. -v,--verbose Verbose
  49. */
  50. #include <sys/resource.h>
  51. /* Override ENABLE_FEATURE_PIDFILE */
  52. #define WANT_PIDFILE 1
  53. #include "libbb.h"
  54. struct pid_list {
  55. struct pid_list *next;
  56. pid_t pid;
  57. };
  58. enum {
  59. CTX_STOP = (1 << 0),
  60. CTX_START = (1 << 1),
  61. OPT_BACKGROUND = (1 << 2), // -b
  62. OPT_QUIET = (1 << 3), // -q
  63. OPT_TEST = (1 << 4), // -t
  64. OPT_MAKEPID = (1 << 5), // -m
  65. OPT_a = (1 << 6), // -a
  66. OPT_n = (1 << 7), // -n
  67. OPT_s = (1 << 8), // -s
  68. OPT_u = (1 << 9), // -u
  69. OPT_c = (1 << 10), // -c
  70. OPT_x = (1 << 11), // -x
  71. OPT_p = (1 << 12), // -p
  72. OPT_OKNODO = (1 << 13) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -o
  73. OPT_VERBOSE = (1 << 14) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -v
  74. OPT_NICELEVEL = (1 << 15) * ENABLE_FEATURE_START_STOP_DAEMON_FANCY, // -N
  75. };
  76. #define QUIET (option_mask32 & OPT_QUIET)
  77. #define TEST (option_mask32 & OPT_TEST)
  78. struct globals {
  79. struct pid_list *found_procs;
  80. char *userspec;
  81. char *cmdname;
  82. char *execname;
  83. char *pidfile;
  84. char *execname_cmpbuf;
  85. unsigned execname_sizeof;
  86. int user_id;
  87. smallint signal_nr;
  88. } FIX_ALIASING;
  89. #define G (*(struct globals*)&bb_common_bufsiz1)
  90. #define userspec (G.userspec )
  91. #define cmdname (G.cmdname )
  92. #define execname (G.execname )
  93. #define pidfile (G.pidfile )
  94. #define user_id (G.user_id )
  95. #define signal_nr (G.signal_nr )
  96. #define INIT_G() do { \
  97. user_id = -1; \
  98. signal_nr = 15; \
  99. } while (0)
  100. #ifdef OLDER_VERSION_OF_X
  101. /* -x,--exec EXECUTABLE
  102. * Look for processes with matching /proc/$PID/exe.
  103. * Match is performed using device+inode.
  104. */
  105. static int pid_is_exec(pid_t pid)
  106. {
  107. struct stat st;
  108. char buf[sizeof("/proc/%u/exe") + sizeof(int)*3];
  109. sprintf(buf, "/proc/%u/exe", (unsigned)pid);
  110. if (stat(buf, &st) < 0)
  111. return 0;
  112. if (st.st_dev == execstat.st_dev
  113. && st.st_ino == execstat.st_ino)
  114. return 1;
  115. return 0;
  116. }
  117. #endif
  118. static int pid_is_exec(pid_t pid)
  119. {
  120. ssize_t bytes;
  121. char buf[sizeof("/proc/%u/cmdline") + sizeof(int)*3];
  122. sprintf(buf, "/proc/%u/cmdline", (unsigned)pid);
  123. bytes = open_read_close(buf, G.execname_cmpbuf, G.execname_sizeof);
  124. if (bytes > 0) {
  125. G.execname_cmpbuf[bytes] = '\0';
  126. return strcmp(execname, G.execname_cmpbuf) == 0;
  127. }
  128. return 0;
  129. }
  130. static int pid_is_name(pid_t pid)
  131. {
  132. /* /proc/PID/stat is "PID (comm_15_bytes_max) ..." */
  133. char buf[32]; /* should be enough */
  134. char *p, *pe;
  135. sprintf(buf, "/proc/%u/stat", (unsigned)pid);
  136. if (open_read_close(buf, buf, sizeof(buf) - 1) < 0)
  137. return 0;
  138. buf[sizeof(buf) - 1] = '\0'; /* paranoia */
  139. p = strchr(buf, '(');
  140. if (!p)
  141. return 0;
  142. pe = strrchr(++p, ')');
  143. if (!pe)
  144. return 0;
  145. *pe = '\0';
  146. /* we require comm to match and to not be truncated */
  147. /* in Linux, if comm is 15 chars, it may be a truncated
  148. * name, so we don't allow that to match */
  149. if (strlen(p) >= COMM_LEN - 1) /* COMM_LEN is 16 */
  150. return 0;
  151. return strcmp(p, cmdname) == 0;
  152. }
  153. static int pid_is_user(int pid)
  154. {
  155. struct stat sb;
  156. char buf[sizeof("/proc/") + sizeof(int)*3];
  157. sprintf(buf, "/proc/%u", (unsigned)pid);
  158. if (stat(buf, &sb) != 0)
  159. return 0;
  160. return (sb.st_uid == (uid_t)user_id);
  161. }
  162. static void check(int pid)
  163. {
  164. struct pid_list *p;
  165. if (execname && !pid_is_exec(pid)) {
  166. return;
  167. }
  168. if (cmdname && !pid_is_name(pid)) {
  169. return;
  170. }
  171. if (userspec && !pid_is_user(pid)) {
  172. return;
  173. }
  174. p = xmalloc(sizeof(*p));
  175. p->next = G.found_procs;
  176. p->pid = pid;
  177. G.found_procs = p;
  178. }
  179. static void do_pidfile(void)
  180. {
  181. FILE *f;
  182. unsigned pid;
  183. f = fopen_for_read(pidfile);
  184. if (f) {
  185. if (fscanf(f, "%u", &pid) == 1)
  186. check(pid);
  187. fclose(f);
  188. } else if (errno != ENOENT)
  189. bb_perror_msg_and_die("open pidfile %s", pidfile);
  190. }
  191. static void do_procinit(void)
  192. {
  193. DIR *procdir;
  194. struct dirent *entry;
  195. int pid;
  196. if (pidfile) {
  197. do_pidfile();
  198. return;
  199. }
  200. procdir = xopendir("/proc");
  201. pid = 0;
  202. while (1) {
  203. errno = 0; /* clear any previous error */
  204. entry = readdir(procdir);
  205. // TODO: this check is too generic, it's better
  206. // to check for exact errno(s) which mean that we got stale entry
  207. if (errno) /* Stale entry, process has died after opendir */
  208. continue;
  209. if (!entry) /* EOF, no more entries */
  210. break;
  211. pid = bb_strtou(entry->d_name, NULL, 10);
  212. if (errno) /* NaN */
  213. continue;
  214. check(pid);
  215. }
  216. closedir(procdir);
  217. if (!pid)
  218. bb_error_msg_and_die("nothing in /proc - not mounted?");
  219. }
  220. static int do_stop(void)
  221. {
  222. char *what;
  223. struct pid_list *p;
  224. int killed = 0;
  225. if (cmdname) {
  226. if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(cmdname);
  227. if (!ENABLE_FEATURE_CLEAN_UP) what = cmdname;
  228. } else if (execname) {
  229. if (ENABLE_FEATURE_CLEAN_UP) what = xstrdup(execname);
  230. if (!ENABLE_FEATURE_CLEAN_UP) what = execname;
  231. } else if (pidfile) {
  232. what = xasprintf("process in pidfile '%s'", pidfile);
  233. } else if (userspec) {
  234. what = xasprintf("process(es) owned by '%s'", userspec);
  235. } else {
  236. bb_error_msg_and_die("internal error, please report");
  237. }
  238. if (!G.found_procs) {
  239. if (!QUIET)
  240. printf("no %s found; none killed\n", what);
  241. killed = -1;
  242. goto ret;
  243. }
  244. for (p = G.found_procs; p; p = p->next) {
  245. if (TEST || kill(p->pid, signal_nr) == 0) {
  246. killed++;
  247. } else {
  248. p->pid = 0;
  249. bb_perror_msg("warning: killing process %u", (unsigned)p->pid);
  250. }
  251. }
  252. if (!QUIET && killed) {
  253. printf("stopped %s (pid", what);
  254. for (p = G.found_procs; p; p = p->next)
  255. if (p->pid)
  256. printf(" %u", (unsigned)p->pid);
  257. puts(")");
  258. }
  259. ret:
  260. if (ENABLE_FEATURE_CLEAN_UP)
  261. free(what);
  262. return killed;
  263. }
  264. #if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
  265. static const char start_stop_daemon_longopts[] ALIGN1 =
  266. "stop\0" No_argument "K"
  267. "start\0" No_argument "S"
  268. "background\0" No_argument "b"
  269. "quiet\0" No_argument "q"
  270. "test\0" No_argument "t"
  271. "make-pidfile\0" No_argument "m"
  272. #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
  273. "oknodo\0" No_argument "o"
  274. "verbose\0" No_argument "v"
  275. "nicelevel\0" Required_argument "N"
  276. #endif
  277. "startas\0" Required_argument "a"
  278. "name\0" Required_argument "n"
  279. "signal\0" Required_argument "s"
  280. "user\0" Required_argument "u"
  281. "chuid\0" Required_argument "c"
  282. "exec\0" Required_argument "x"
  283. "pidfile\0" Required_argument "p"
  284. #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
  285. "retry\0" Required_argument "R"
  286. #endif
  287. ;
  288. #endif
  289. int start_stop_daemon_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  290. int start_stop_daemon_main(int argc UNUSED_PARAM, char **argv)
  291. {
  292. unsigned opt;
  293. char *signame;
  294. char *startas;
  295. char *chuid;
  296. #ifdef OLDER_VERSION_OF_X
  297. struct stat execstat;
  298. #endif
  299. #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
  300. // char *retry_arg = NULL;
  301. // int retries = -1;
  302. char *opt_N;
  303. #endif
  304. INIT_G();
  305. #if ENABLE_FEATURE_START_STOP_DAEMON_LONG_OPTIONS
  306. applet_long_options = start_stop_daemon_longopts;
  307. #endif
  308. /* -K or -S is required; they are mutually exclusive */
  309. /* -p is required if -m is given */
  310. /* -xpun (at least one) is required if -K is given */
  311. /* -xa (at least one) is required if -S is given */
  312. /* -q turns off -v */
  313. opt_complementary = "K:S:K--S:S--K:m?p:K?xpun:S?xa"
  314. IF_FEATURE_START_STOP_DAEMON_FANCY("q-v");
  315. opt = getopt32(argv, "KSbqtma:n:s:u:c:x:p:"
  316. IF_FEATURE_START_STOP_DAEMON_FANCY("ovN:R:"),
  317. &startas, &cmdname, &signame, &userspec, &chuid, &execname, &pidfile
  318. IF_FEATURE_START_STOP_DAEMON_FANCY(,&opt_N)
  319. /* We accept and ignore -R <param> / --retry <param> */
  320. IF_FEATURE_START_STOP_DAEMON_FANCY(,NULL)
  321. );
  322. if (opt & OPT_s) {
  323. signal_nr = get_signum(signame);
  324. if (signal_nr < 0) bb_show_usage();
  325. }
  326. if (!(opt & OPT_a))
  327. startas = execname;
  328. if (!execname) /* in case -a is given and -x is not */
  329. execname = startas;
  330. if (execname) {
  331. G.execname_sizeof = strlen(execname) + 1;
  332. G.execname_cmpbuf = xmalloc(G.execname_sizeof + 1);
  333. }
  334. // IF_FEATURE_START_STOP_DAEMON_FANCY(
  335. // if (retry_arg)
  336. // retries = xatoi_positive(retry_arg);
  337. // )
  338. //argc -= optind;
  339. argv += optind;
  340. if (userspec) {
  341. user_id = bb_strtou(userspec, NULL, 10);
  342. if (errno)
  343. user_id = xuname2uid(userspec);
  344. }
  345. /* Both start and stop need to know current processes */
  346. do_procinit();
  347. if (opt & CTX_STOP) {
  348. int i = do_stop();
  349. return (opt & OPT_OKNODO) ? 0 : (i <= 0);
  350. }
  351. if (G.found_procs) {
  352. if (!QUIET)
  353. printf("%s is already running\n%u\n", execname, (unsigned)G.found_procs->pid);
  354. return !(opt & OPT_OKNODO);
  355. }
  356. #ifdef OLDER_VERSION_OF_X
  357. if (execname)
  358. xstat(execname, &execstat);
  359. #endif
  360. *--argv = startas;
  361. if (opt & OPT_BACKGROUND) {
  362. #if BB_MMU
  363. bb_daemonize(DAEMON_DEVNULL_STDIO + DAEMON_CLOSE_EXTRA_FDS);
  364. /* DAEMON_DEVNULL_STDIO is superfluous -
  365. * it's always done by bb_daemonize() */
  366. #else
  367. pid_t pid = xvfork();
  368. if (pid != 0) {
  369. /* parent */
  370. /* why _exit? the child may have changed the stack,
  371. * so "return 0" may do bad things */
  372. _exit(EXIT_SUCCESS);
  373. }
  374. /* Child */
  375. setsid(); /* detach from controlling tty */
  376. /* Redirect stdio to /dev/null, close extra FDs.
  377. * We do not actually daemonize because of DAEMON_ONLY_SANITIZE */
  378. bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO
  379. + DAEMON_CLOSE_EXTRA_FDS
  380. + DAEMON_ONLY_SANITIZE,
  381. NULL /* argv, unused */ );
  382. #endif
  383. }
  384. if (opt & OPT_MAKEPID) {
  385. /* User wants _us_ to make the pidfile */
  386. write_pidfile(pidfile);
  387. }
  388. if (opt & OPT_c) {
  389. struct bb_uidgid_t ugid = { -1, -1 };
  390. parse_chown_usergroup_or_die(&ugid, chuid);
  391. if (ugid.gid != (gid_t) -1) xsetgid(ugid.gid);
  392. if (ugid.uid != (uid_t) -1) xsetuid(ugid.uid);
  393. }
  394. #if ENABLE_FEATURE_START_STOP_DAEMON_FANCY
  395. if (opt & OPT_NICELEVEL) {
  396. /* Set process priority */
  397. int prio = getpriority(PRIO_PROCESS, 0) + xatoi_range(opt_N, INT_MIN/2, INT_MAX/2);
  398. if (setpriority(PRIO_PROCESS, 0, prio) < 0) {
  399. bb_perror_msg_and_die("setpriority(%d)", prio);
  400. }
  401. }
  402. #endif
  403. execvp(startas, argv);
  404. bb_perror_msg_and_die("can't execute '%s'", startas);
  405. }