/[baselayout]/trunk/src/start-stop-daemon.c
Gentoo

Diff of /trunk/src/start-stop-daemon.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 2563 Revision 2569
128 return (-1); 128 return (-1);
129 129
130 if (sscanf (sig, "%u", &i) == 1) 130 if (sscanf (sig, "%u", &i) == 1)
131 { 131 {
132 if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0])) 132 if (i > 0 && i < sizeof (signallist) / sizeof (signallist[0]))
133 return (i); 133 return (i);
134 eerrorx ("%s: `%s' is not a valid signal", progname, sig); 134 eerrorx ("%s: `%s' is not a valid signal", progname, sig);
135 } 135 }
136 136
137 if (strncmp (sig, "SIG", 3) == 0) 137 if (strncmp (sig, "SIG", 3) == 0)
138 s = (char *) sig + 3; 138 s = (char *) sig + 3;
139 else 139 else
140 s = NULL; 140 s = NULL;
141 141
142 for (i = 0; i < sizeof (signallist) / sizeof (signallist[0]); i++) 142 for (i = 0; i < sizeof (signallist) / sizeof (signallist[0]); i++)
143 if (strcmp (sig, signallist[i].name) == 0 || 143 if (strcmp (sig, signallist[i].name) == 0 ||
144 (s && strcmp (s, signallist[i].name) == 0)) 144 (s && strcmp (s, signallist[i].name) == 0))
145 return (signallist[i].signal); 145 return (signallist[i].signal);
146 146
147 eerrorx ("%s: `%s' is not a valid signal", progname, sig); 147 eerrorx ("%s: `%s' is not a valid signal", progname, sig);
148} 148}
149 149
157 else if (isdigit (string[0])) 157 else if (isdigit (string[0]))
158 { 158 {
159 item->type = schedule_timeout; 159 item->type = schedule_timeout;
160 errno = 0; 160 errno = 0;
161 if (sscanf (string, "%d", &item->value) != 1) 161 if (sscanf (string, "%d", &item->value) != 1)
162 eerrorx ("%s: invalid timeout value in schedule `%s'", progname, 162 eerrorx ("%s: invalid timeout value in schedule `%s'", progname,
163 string); 163 string);
164 } 164 }
165 else if ((after_hyph = string + (string[0] == '-')) && 165 else if ((after_hyph = string + (string[0] == '-')) &&
166 ((sig = parse_signal (after_hyph)) != -1)) 166 ((sig = parse_signal (after_hyph)) != -1))
167 { 167 {
168 item->type = schedule_signal; 168 item->type = schedule_signal;
169 item->value = (int) sig; 169 item->value = (int) sig;
170 } 170 }
171 else 171 else
182 schedulelist_t *next; 182 schedulelist_t *next;
183 183
184 if (string) 184 if (string)
185 for (slash = string; *slash; slash++) 185 for (slash = string; *slash; slash++)
186 if (*slash == '/') 186 if (*slash == '/')
187 count++; 187 count++;
188 188
189 if (schedule) 189 if (schedule)
190 free_schedulelist (&schedule); 190 free_schedulelist (&schedule);
191 191
192 schedule = rc_xmalloc (sizeof (schedulelist_t)); 192 schedule = rc_xmalloc (sizeof (schedulelist_t));
199 schedule->next = rc_xmalloc (sizeof (schedulelist_t)); 199 schedule->next = rc_xmalloc (sizeof (schedulelist_t));
200 next = schedule->next; 200 next = schedule->next;
201 next->type = schedule_timeout; 201 next->type = schedule_timeout;
202 next->gotolist = NULL; 202 next->gotolist = NULL;
203 if (string) 203 if (string)
204 { 204 {
205 if (sscanf (string, "%d", &next->value) != 1) 205 if (sscanf (string, "%d", &next->value) != 1)
206 eerrorx ("%s: invalid timeout value in schedule", progname); 206 eerrorx ("%s: invalid timeout value in schedule", progname);
207 } 207 }
208 else 208 else
209 next->value = 5; 209 next->value = 5;
210 next->next = NULL; 210 next->next = NULL;
211 211
212 return; 212 return;
213 } 213 }
214 214
215 next = schedule; 215 next = schedule;
216 while (string != NULL) 216 while (string != NULL)
217 { 217 {
218 if ((slash = strchr (string, '/'))) 218 if ((slash = strchr (string, '/')))
219 len = slash - string; 219 len = slash - string;
220 else 220 else
221 len = strlen (string); 221 len = strlen (string);
222 222
223 if (len >= (ptrdiff_t) sizeof (buffer)) 223 if (len >= (ptrdiff_t) sizeof (buffer))
224 eerrorx ("%s: invalid schedule item, far too long", progname); 224 eerrorx ("%s: invalid schedule item, far too long", progname);
225 225
226 memcpy (buffer, string, len); 226 memcpy (buffer, string, len);
227 buffer[len] = 0; 227 buffer[len] = 0;
228 string = slash ? slash + 1 : NULL; 228 string = slash ? slash + 1 : NULL;
229 229
230 parse_schedule_item (next, buffer); 230 parse_schedule_item (next, buffer);
231 if (next->type == schedule_forever) 231 if (next->type == schedule_forever)
232 { 232 {
233 if (repeatat) 233 if (repeatat)
234 eerrorx ("%s: invalid schedule, `forever' appears more than once", 234 eerrorx ("%s: invalid schedule, `forever' appears more than once",
235 progname); 235 progname);
236 236
237 repeatat = next; 237 repeatat = next;
238 continue; 238 continue;
239 } 239 }
240 240
241 if (string) 241 if (string)
242 { 242 {
243 next->next = rc_xmalloc (sizeof (schedulelist_t)); 243 next->next = rc_xmalloc (sizeof (schedulelist_t));
244 next = next->next; 244 next = next->next;
245 next->gotolist = NULL; 245 next->gotolist = NULL;
246 } 246 }
247 } 247 }
248 248
249 if (repeatat) 249 if (repeatat)
250 { 250 {
251 next->next = rc_xmalloc (sizeof (schedulelist_t)); 251 next->next = rc_xmalloc (sizeof (schedulelist_t));
268 return (-1); 268 return (-1);
269 269
270 if ((fp = fopen (pidfile, "r")) == NULL) 270 if ((fp = fopen (pidfile, "r")) == NULL)
271 { 271 {
272 if (! quiet) 272 if (! quiet)
273 eerror ("%s: fopen `%s': %s", progname, pidfile, strerror (errno)); 273 eerror ("%s: fopen `%s': %s", progname, pidfile, strerror (errno));
274 return (-1); 274 return (-1);
275 } 275 }
276 276
277 if (fscanf (fp, "%d", &pid) != 1) 277 if (fscanf (fp, "%d", &pid) != 1)
278 { 278 {
279 if (! quiet) 279 if (! quiet)
280 eerror ("%s: no pid found in `%s'", progname, pidfile); 280 eerror ("%s: no pid found in `%s'", progname, pidfile);
281 fclose (fp); 281 fclose (fp);
282 return (-1); 282 return (-1);
283 } 283 }
284 fclose (fp); 284 fclose (fp);
285 285
286 return (pid); 286 return (pid);
287} 287}
288 288
289/* return number of processed killed, -1 on error */ 289/* return number of processed killed, -1 on error */
290static int do_stop (const char *exec, const char *cmd, 290static int do_stop (const char *exec, const char *cmd,
291 const char *pidfile, uid_t uid,int sig, 291 const char *pidfile, uid_t uid,int sig,
292 bool quiet, bool verbose, bool test) 292 bool quiet, bool verbose, bool test)
293{ 293{
294 pid_t *pids; 294 pid_t *pids;
295 bool killed; 295 bool killed;
296 int nkilled = 0; 296 int nkilled = 0;
297 pid_t pid = 0; 297 pid_t pid = 0;
305 return (0); 305 return (0);
306 306
307 for (i = 0; pids[i]; i++) 307 for (i = 0; pids[i]; i++)
308 { 308 {
309 if (test) 309 if (test)
310 { 310 {
311 if (! quiet) 311 if (! quiet)
312 einfo ("Would send signal %d to PID %d", sig, pids[i]); 312 einfo ("Would send signal %d to PID %d", sig, pids[i]);
313 nkilled++; 313 nkilled++;
314 continue; 314 continue;
315 } 315 }
316 316
317 if (verbose) 317 if (verbose)
318 ebegin ("Sending signal %d to PID %d", sig, pids[i]); 318 ebegin ("Sending signal %d to PID %d", sig, pids[i]);
319 errno = 0; 319 errno = 0;
320 killed = (kill (pids[i], sig) == 0 || errno == ESRCH ? true : false); 320 killed = (kill (pids[i], sig) == 0 || errno == ESRCH ? true : false);
321 if (! killed) 321 if (! killed)
322 { 322 {
323 if (! quiet) 323 if (! quiet)
324 eerror ("%s: failed to send signal %d to PID %d: %s", 324 eerror ("%s: failed to send signal %d to PID %d: %s",
325 progname, sig, pids[i], strerror (errno)); 325 progname, sig, pids[i], strerror (errno));
326 if (verbose) 326 if (verbose)
327 eend (1, NULL); 327 eend (1, NULL);
328 nkilled = -1; 328 nkilled = -1;
329 } 329 }
330 else 330 else
331 { 331 {
332 if (verbose) 332 if (verbose)
333 eend (0, NULL); 333 eend (0, NULL);
334 if (nkilled != -1) 334 if (nkilled != -1)
335 nkilled++; 335 nkilled++;
336 } 336 }
337 } 337 }
338 338
339 free (pids); 339 free (pids);
340 return (nkilled); 340 return (nkilled);
341} 341}
342 342
343static int run_stop_schedule (const char *exec, const char *cmd, 343static int run_stop_schedule (const char *exec, const char *cmd,
344 const char *pidfile, uid_t uid, 344 const char *pidfile, uid_t uid,
345 bool quiet, bool verbose, bool test) 345 bool quiet, bool verbose, bool test)
346{ 346{
347 schedulelist_t *item = schedule; 347 schedulelist_t *item = schedule;
348 int nkilled = 0; 348 int nkilled = 0;
349 int tkilled = 0; 349 int tkilled = 0;
350 int nrunning = 0; 350 int nrunning = 0;
353 struct timeval stopat; 353 struct timeval stopat;
354 354
355 if (verbose) 355 if (verbose)
356 { 356 {
357 if (pidfile) 357 if (pidfile)
358 einfo ("Will stop PID in pidfile `%s'", pidfile); 358 einfo ("Will stop PID in pidfile `%s'", pidfile);
359 if (uid) 359 if (uid)
360 einfo ("Will stop processes owned by UID %d", uid); 360 einfo ("Will stop processes owned by UID %d", uid);
361 if (exec) 361 if (exec)
362 einfo ("Will stop processes of `%s'", exec); 362 einfo ("Will stop processes of `%s'", exec);
363 if (cmd) 363 if (cmd)
364 einfo ("Will stop processes called `%s'", cmd); 364 einfo ("Will stop processes called `%s'", cmd);
365 } 365 }
366 366
367 while (item) 367 while (item)
368 { 368 {
369 switch (item->type) 369 switch (item->type)
370 { 370 {
371 case schedule_goto: 371 case schedule_goto:
372 item = item->gotolist; 372 item = item->gotolist;
373 continue; 373 continue;
374 374
375 case schedule_signal: 375 case schedule_signal:
376 nrunning = 0; 376 nrunning = 0;
377 nkilled = do_stop (exec, cmd, pidfile, uid, item->value, 377 nkilled = do_stop (exec, cmd, pidfile, uid, item->value,
378 quiet, verbose, test); 378 quiet, verbose, test);
379 if (nkilled == 0)
380 {
381 if (tkilled == 0) 379 if (nkilled == 0)
382 { 380 {
383 if (! quiet) 381 if (tkilled == 0)
382 {
383 if (! quiet)
384 eerror ("%s: no matching processes found", progname); 384 eerror ("%s: no matching processes found", progname);
385 } 385 }
386 return (tkilled); 386 return (tkilled);
387 } 387 }
388 else if (nkilled == -1) 388 else if (nkilled == -1)
389 return (0); 389 return (0);
390 390
391 tkilled += nkilled; 391 tkilled += nkilled;
392 break; 392 break;
393 case schedule_timeout: 393 case schedule_timeout:
394 if (item->value < 1) 394 if (item->value < 1)
395 { 395 {
396 item = NULL; 396 item = NULL;
397 break; 397 break;
398 } 398 }
399 399
400 if (gettimeofday (&stopat, NULL) != 0) 400 if (gettimeofday (&stopat, NULL) != 0)
401 { 401 {
402 eerror ("%s: gettimeofday: %s", progname, strerror (errno)); 402 eerror ("%s: gettimeofday: %s", progname, strerror (errno));
403 return (0); 403 return (0);
404 } 404 }
405 405
406 stopat.tv_sec += item->value; 406 stopat.tv_sec += item->value;
407 while (1) 407 while (1)
408 { 408 {
409 if ((nrunning = do_stop (exec, cmd, pidfile, 409 if ((nrunning = do_stop (exec, cmd, pidfile,
410 uid, 0, true, false, true)) == 0) 410 uid, 0, true, false, true)) == 0)
411 return (true); 411 return (true);
412 412
413 tv.tv_sec = 0; 413 tv.tv_sec = 0;
414 tv.tv_usec = POLL_INTERVAL; 414 tv.tv_usec = POLL_INTERVAL;
415 if (select (0, 0, 0, 0, &tv) < 0) 415 if (select (0, 0, 0, 0, &tv) < 0)
416 { 416 {
417 if (errno == EINTR) 417 if (errno == EINTR)
418 eerror ("%s: caught an interupt", progname); 418 eerror ("%s: caught an interupt", progname);
419 else 419 else
420 eerror ("%s: select: %s", progname, strerror (errno)); 420 eerror ("%s: select: %s", progname, strerror (errno));
421 return (0); 421 return (0);
422 } 422 }
423 423
424 if (gettimeofday (&now, NULL) != 0) 424 if (gettimeofday (&now, NULL) != 0)
425 { 425 {
426 eerror ("%s: gettimeofday: %s", progname, strerror (errno)); 426 eerror ("%s: gettimeofday: %s", progname, strerror (errno));
427 return (0); 427 return (0);
428 } 428 }
429 if (timercmp (&now, &stopat, >)) 429 if (timercmp (&now, &stopat, >))
430 break; 430 break;
431 } 431 }
432 break; 432 break;
433 433
434 default: 434 default:
435 eerror ("%s: invalid schedule item `%d'", progname, item->type); 435 eerror ("%s: invalid schedule item `%d'", progname, item->type);
436 return (0); 436 return (0);
437 } 437 }
438 438
439 if (item) 439 if (item)
440 item = item->next; 440 item = item->next;
441 } 441 }
442 442
443 if (test || (tkilled > 0 && nrunning == 0)) 443 if (test || (tkilled > 0 && nrunning == 0))
444 return (nkilled); 444 return (nkilled);
445 445
446 if (! quiet) 446 if (! quiet)
447 { 447 {
448 if (nrunning == 1) 448 if (nrunning == 1)
449 eerror ("%s: %d process refused to stop", progname, nrunning); 449 eerror ("%s: %d process refused to stop", progname, nrunning);
450 else 450 else
451 eerror ("%s: %d process(es) refused to stop", progname, nrunning); 451 eerror ("%s: %d process(es) refused to stop", progname, nrunning);
452 } 452 }
453 453
454 return (-nrunning); 454 return (-nrunning);
455} 455}
456 456
463 463
464 switch (sig) 464 switch (sig)
465 { 465 {
466 case SIGINT: 466 case SIGINT:
467 if (! signame[0]) 467 if (! signame[0])
468 snprintf (signame, sizeof (signame), "SIGINT"); 468 snprintf (signame, sizeof (signame), "SIGINT");
469 case SIGTERM: 469 case SIGTERM:
470 if (! signame[0]) 470 if (! signame[0])
471 snprintf (signame, sizeof (signame), "SIGTERM"); 471 snprintf (signame, sizeof (signame), "SIGTERM");
472 case SIGQUIT: 472 case SIGQUIT:
473 if (! signame[0]) 473 if (! signame[0])
474 snprintf (signame, sizeof (signame), "SIGQUIT"); 474 snprintf (signame, sizeof (signame), "SIGQUIT");
475 eerrorx ("%s: caught %s, aborting", progname, signame); 475 eerrorx ("%s: caught %s, aborting", progname, signame);
476 476
477 case SIGCHLD: 477 case SIGCHLD:
478 while (1) 478 while (1)
479 { 479 {
480 if ((pid = waitpid (-1, &status, WNOHANG)) < 0) 480 if ((pid = waitpid (-1, &status, WNOHANG)) < 0)
481 { 481 {
482 if (errno != ECHILD) 482 if (errno != ECHILD)
483 eerror ("%s: waitpid: %s", progname, strerror (errno)); 483 eerror ("%s: waitpid: %s", progname, strerror (errno));
484 break; 484 break;
485 } 485 }
486 } 486 }
487 break; 487 break;
488 488
489 default: 489 default:
490 eerror ("%s: caught unknown signal %d", progname, sig); 490 eerror ("%s: caught unknown signal %d", progname, sig);
491 } 491 }
492 492
493 /* Restore errno */ 493 /* Restore errno */
566 signal (SIGINT, handle_signal); 566 signal (SIGINT, handle_signal);
567 signal (SIGQUIT, handle_signal); 567 signal (SIGQUIT, handle_signal);
568 signal (SIGTERM, handle_signal); 568 signal (SIGTERM, handle_signal);
569 569
570 while ((c = getopt_long (argc, argv, 570 while ((c = getopt_long (argc, argv,
571 "KN:R:Sbc:d:g:mn:op:qs:tu:r:vx:1:2:", 571 "KN:R:Sbc:d:g:mn:op:qs:tu:r:vx:1:2:",
572 longopts, (int *) 0)) != -1) 572 longopts, (int *) 0)) != -1)
573 switch (c) 573 switch (c)
574 { 574 {
575 case 'K': /* --stop */ 575 case 'K': /* --stop */
576 stop = true; 576 stop = true;
577 break; 577 break;
578 578
579 case 'N': /* --nice */ 579 case 'N': /* --nice */
580 if (sscanf (optarg, "%d", &nicelevel) != 1) 580 if (sscanf (optarg, "%d", &nicelevel) != 1)
581 eerrorx ("%s: invalid nice level `%s'", progname, optarg); 581 eerrorx ("%s: invalid nice level `%s'", progname, optarg);
582 break; 582 break;
583 583
584 case 'R': /* --retry <schedule>|<timeout> */ 584 case 'R': /* --retry <schedule>|<timeout> */
585 parse_schedule (optarg, sig); 585 parse_schedule (optarg, sig);
586 break; 586 break;
587 587
588 case 'S': /* --start */ 588 case 'S': /* --start */
589 start = true; 589 start = true;
590 break; 590 break;
591 591
592 case 'b': /* --background */ 592 case 'b': /* --background */
593 background = true; 593 background = true;
594 break; 594 break;
595 595
596 case 'c': /* --chuid <username>|<uid> */ 596 case 'c': /* --chuid <username>|<uid> */
597 /* we copy the string just in case we need the 597 /* we copy the string just in case we need the
598 * argument later. */ 598 * argument later. */
599 { 599 {
600 char *p = optarg; 600 char *p = optarg;
601 char *cu = strsep (&p, ":"); 601 char *cu = strsep (&p, ":");
602 changeuser = strdup (cu); 602 changeuser = strdup (cu);
603 if (sscanf (cu, "%d", &tid) != 1) 603 if (sscanf (cu, "%d", &tid) != 1)
604 { 604 {
605 struct passwd *pw = getpwnam (cu); 605 struct passwd *pw = getpwnam (cu);
606 if (! pw) 606 if (! pw)
607 eerrorx ("%s: user `%s' not found", progname, cu); 607 eerrorx ("%s: user `%s' not found", progname, cu);
608 ch_uid = pw->pw_uid; 608 ch_uid = pw->pw_uid;
609 } 609 }
610 else 610 else
611 ch_uid = tid; 611 ch_uid = tid;
612 if (p) 612 if (p)
613 { 613 {
614 char *cg = strsep (&p, ":"); 614 char *cg = strsep (&p, ":");
615 if (sscanf (cg, "%d", &tid) != 1) 615 if (sscanf (cg, "%d", &tid) != 1)
616 { 616 {
617 struct group *gr = getgrnam (cg); 617 struct group *gr = getgrnam (cg);
618 if (! gr) 618 if (! gr)
619 eerrorx ("%s: group `%s' not found", progname, cg); 619 eerrorx ("%s: group `%s' not found", progname, cg);
620 ch_gid = gr->gr_gid; 620 ch_gid = gr->gr_gid;
621 } 621 }
622 else 622 else
623 ch_gid = tid; 623 ch_gid = tid;
624 } 624 }
625 } 625 }
626 break; 626 break;
627 627
628 case 'd': /* --chdir /new/dir */ 628 case 'd': /* --chdir /new/dir */
629 ch_dir = optarg; 629 ch_dir = optarg;
630 break; 630 break;
631 631
632 case 'g': /* --group <group>|<gid> */ 632 case 'g': /* --group <group>|<gid> */
633 if (sscanf (optarg, "%d", &tid) != 1) 633 if (sscanf (optarg, "%d", &tid) != 1)
634 { 634 {
635 struct group *gr = getgrnam (optarg); 635 struct group *gr = getgrnam (optarg);
636 if (! gr) 636 if (! gr)
637 eerrorx ("%s: group `%s' not found", progname, optarg); 637 eerrorx ("%s: group `%s' not found", progname, optarg);
638 ch_gid = gr->gr_gid; 638 ch_gid = gr->gr_gid;
639 } 639 }
640 else 640 else
641 ch_gid = tid; 641 ch_gid = tid;
642 break; 642 break;
643 643
644 case 'm': /* --make-pidfile */ 644 case 'm': /* --make-pidfile */
645 makepidfile = true; 645 makepidfile = true;
646 break; 646 break;
647 647
648 case 'n': /* --name <process-name> */ 648 case 'n': /* --name <process-name> */
649 cmd = optarg; 649 cmd = optarg;
650 break; 650 break;
651 651
652 case 'o': /* --oknodo */ 652 case 'o': /* --oknodo */
653 oknodo = true; 653 oknodo = true;
654 break; 654 break;
655 655
656 case 'p': /* --pidfile <pid-file> */ 656 case 'p': /* --pidfile <pid-file> */
657 pidfile = optarg; 657 pidfile = optarg;
658 break; 658 break;
659 659
660 case 'q': /* --quiet */ 660 case 'q': /* --quiet */
661 quiet = true; 661 quiet = true;
662 break; 662 break;
663 663
664 case 's': /* --signal <signal> */ 664 case 's': /* --signal <signal> */
665 sig = parse_signal (optarg); 665 sig = parse_signal (optarg);
666 break; 666 break;
667 667
668 case 't': /* --test */ 668 case 't': /* --test */
669 test = true; 669 test = true;
670 break; 670 break;
671 671
672 case 'u': /* --user <username>|<uid> */ 672 case 'u': /* --user <username>|<uid> */
673 if (sscanf (optarg, "%d", &tid) != 1) 673 if (sscanf (optarg, "%d", &tid) != 1)
674 { 674 {
675 struct passwd *pw = getpwnam (optarg); 675 struct passwd *pw = getpwnam (optarg);
676 if (! pw) 676 if (! pw)
677 eerrorx ("%s: user `%s' not found", progname, optarg); 677 eerrorx ("%s: user `%s' not found", progname, optarg);
678 uid = pw->pw_uid; 678 uid = pw->pw_uid;
679 } 679 }
680 else 680 else
681 uid = tid; 681 uid = tid;
682 break; 682 break;
683 683
684 case 'r': /* --chroot /new/root */ 684 case 'r': /* --chroot /new/root */
685 ch_root = optarg; 685 ch_root = optarg;
686 break; 686 break;
687 687
688 case 'v': /* --verbose */ 688 case 'v': /* --verbose */
689 verbose = true; 689 verbose = true;
690 break; 690 break;
691 691
692 case 'x': /* --exec <executable> */ 692 case 'x': /* --exec <executable> */
693 exec = optarg; 693 exec = optarg;
694 break; 694 break;
695 695
696 case '1': /* --stdout /path/to/stdout.lgfile */ 696 case '1': /* --stdout /path/to/stdout.lgfile */
697 redirect_stdout = optarg; 697 redirect_stdout = optarg;
698 break; 698 break;
699 699
700 case '2': /* --stderr /path/to/stderr.logfile */ 700 case '2': /* --stderr /path/to/stderr.logfile */
701 redirect_stderr = optarg; 701 redirect_stderr = optarg;
702 break; 702 break;
703 703
704 default: 704 default:
705 exit (EXIT_FAILURE); 705 exit (EXIT_FAILURE);
706 } 706 }
707 707
708 /* Respect RC as well as how we are called */ 708 /* Respect RC as well as how we are called */
709 if (rc_is_env ("RC_QUIET", "yes") && ! verbose) 709 if (rc_is_env ("RC_QUIET", "yes") && ! verbose)
710 quiet = true; 710 quiet = true;
724 if (background && ! start) 724 if (background && ! start)
725 eerrorx ("%s: --background is only relevant with --start", progname); 725 eerrorx ("%s: --background is only relevant with --start", progname);
726 726
727 if ((redirect_stdout || redirect_stderr) && ! background) 727 if ((redirect_stdout || redirect_stderr) && ! background)
728 eerrorx ("%s: --stdout and --stderr are only relevant with --background", 728 eerrorx ("%s: --stdout and --stderr are only relevant with --background",
729 progname); 729 progname);
730 730
731 argc -= optind; 731 argc -= optind;
732 argv += optind; 732 argv += optind;
733 733
734 /* Validate that the binary rc_exists if we are starting */ 734 /* Validate that the binary rc_exists if we are starting */
735 if (exec && start) 735 if (exec && start)
736 { 736 {
737 char *tmp; 737 char *tmp;
738 if (ch_root) 738 if (ch_root)
739 tmp = rc_strcatpaths (ch_root, exec, (char *) NULL); 739 tmp = rc_strcatpaths (ch_root, exec, (char *) NULL);
740 else 740 else
741 tmp = exec; 741 tmp = exec;
742 if (! rc_is_file (tmp)) 742 if (! rc_is_file (tmp))
743 { 743 {
744 eerror ("%s: %s does not exist", progname, tmp); 744 eerror ("%s: %s does not exist", progname, tmp);
745 if (ch_root) 745 if (ch_root)
746 free (tmp); 746 free (tmp);
747 exit (EXIT_FAILURE); 747 exit (EXIT_FAILURE);
748 } 748 }
749 if (ch_root) 749 if (ch_root)
750 free (tmp); 750 free (tmp);
751 } 751 }
752 752
753 if (stop) 753 if (stop)
754 { 754 {
755 int result; 755 int result;
756 756
757 if (! schedule) 757 if (! schedule)
758 { 758 {
759 if (test || oknodo) 759 if (test || oknodo)
760 parse_schedule ("0", sig); 760 parse_schedule ("0", sig);
761 else 761 else
762 parse_schedule (NULL, sig); 762 parse_schedule (NULL, sig);
763 } 763 }
764 764
765 result = run_stop_schedule (exec, cmd, pidfile, uid, quiet, verbose, test); 765 result = run_stop_schedule (exec, cmd, pidfile, uid, quiet, verbose, test);
766 if (test || oknodo) 766 if (test || oknodo)
767 return (result > 0 ? EXIT_SUCCESS : EXIT_FAILURE); 767 return (result > 0 ? EXIT_SUCCESS : EXIT_FAILURE);
768 if (result < 1) 768 if (result < 1)
769 exit (result == 0 ? EXIT_SUCCESS : EXIT_FAILURE); 769 exit (result == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
770 770
771 if (pidfile && rc_is_file (pidfile)) 771 if (pidfile && rc_is_file (pidfile))
772 unlink (pidfile); 772 unlink (pidfile);
773 773
774 if (svcname) 774 if (svcname)
775 rc_set_service_daemon (svcname, exec, cmd, pidfile, false); 775 rc_set_service_daemon (svcname, exec, cmd, pidfile, false);
776 776
777 exit (EXIT_SUCCESS); 777 exit (EXIT_SUCCESS);
778 } 778 }
779 779
780 if (do_stop (exec, cmd, pidfile, uid, 0, true, false, true) > 0) 780 if (do_stop (exec, cmd, pidfile, uid, 0, true, false, true) > 0)
781 eerrorx ("%s: %s is already running", progname, exec); 781 eerrorx ("%s: %s is already running", progname, exec);
782 782
783 if (test) 783 if (test)
784 { 784 {
785 if (quiet) 785 if (quiet)
786 exit (EXIT_SUCCESS); 786 exit (EXIT_SUCCESS);
787 787
788 einfon ("Would start %s", exec); 788 einfon ("Would start %s", exec);
789 while (argc-- > 0) 789 while (argc-- > 0)
790 printf("%s ", *argv++); 790 printf("%s ", *argv++);
791 printf ("\n"); 791 printf ("\n");
792 eindent (); 792 eindent ();
793 if (ch_uid != 0) 793 if (ch_uid != 0)
794 einfo ("as user %d", ch_uid); 794 einfo ("as user %d", ch_uid);
795 if (ch_gid != 0) 795 if (ch_gid != 0)
796 einfo ("as group %d", ch_gid); 796 einfo ("as group %d", ch_gid);
797 if (ch_root) 797 if (ch_root)
798 einfo ("in root `%s'", ch_root); 798 einfo ("in root `%s'", ch_root);
799 if (ch_dir) 799 if (ch_dir)
800 einfo ("in dir `%s'", ch_dir); 800 einfo ("in dir `%s'", ch_dir);
801 if (nicelevel != 0) 801 if (nicelevel != 0)
802 einfo ("with a priority of %d", nicelevel); 802 einfo ("with a priority of %d", nicelevel);
803 eoutdent (); 803 eoutdent ();
804 exit (EXIT_SUCCESS); 804 exit (EXIT_SUCCESS);
805 } 805 }
806 806
807 /* Ensure this is unset, so if the daemon does /etc/init.d/foo 807 /* Ensure this is unset, so if the daemon does /etc/init.d/foo
831#endif 831#endif
832 832
833 devnull_fd = open("/dev/null", O_RDWR); 833 devnull_fd = open("/dev/null", O_RDWR);
834 834
835 if (nicelevel) 835 if (nicelevel)
836 { 836 {
837 if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1) 837 if (setpriority (PRIO_PROCESS, mypid, nicelevel) == -1)
838 eerrorx ("%s: setpritory %d: %s", progname, nicelevel, 838 eerrorx ("%s: setpritory %d: %s", progname, nicelevel,
839 strerror(errno)); 839 strerror(errno));
840 } 840 }
841 841
842 if (ch_root && chroot (ch_root) < 0) 842 if (ch_root && chroot (ch_root) < 0)
843 eerrorx ("%s: chroot `%s': %s", progname, ch_root, strerror (errno)); 843 eerrorx ("%s: chroot `%s': %s", progname, ch_root, strerror (errno));
844 844
845 if (ch_dir && chdir (ch_dir) < 0) 845 if (ch_dir && chdir (ch_dir) < 0)
846 eerrorx ("%s: chdir `%s': %s", progname, ch_dir, strerror (errno)); 846 eerrorx ("%s: chdir `%s': %s", progname, ch_dir, strerror (errno));
847 847
848 if (makepidfile && pidfile) 848 if (makepidfile && pidfile)
849 { 849 {
850 FILE *fp = fopen (pidfile, "w"); 850 FILE *fp = fopen (pidfile, "w");
851 if (! fp) 851 if (! fp)
852 eerrorx ("%s: fopen `%s': %s", progname, pidfile, strerror 852 eerrorx ("%s: fopen `%s': %s", progname, pidfile, strerror
853 (errno)); 853 (errno));
854 fprintf (fp, "%d\n", mypid); 854 fprintf (fp, "%d\n", mypid);
855 fclose (fp); 855 fclose (fp);
856 } 856 }
857 857
858#ifdef HAVE_PAM 858#ifdef HAVE_PAM
859 if (changeuser != NULL) 859 if (changeuser != NULL)
860 pamr = pam_start ("start-stop-daemon", changeuser, &conv, &pamh); 860 pamr = pam_start ("start-stop-daemon", changeuser, &conv, &pamh);
861 else 861 else
862 pamr = pam_start ("start-stop-daemon", "nobody", &conv, &pamh); 862 pamr = pam_start ("start-stop-daemon", "nobody", &conv, &pamh);
863 863
864 if (pamr == PAM_SUCCESS) 864 if (pamr == PAM_SUCCESS)
865 pamr = pam_authenticate (pamh, PAM_SILENT); 865 pamr = pam_authenticate (pamh, PAM_SILENT);
866 if (pamr == PAM_SUCCESS) 866 if (pamr == PAM_SUCCESS)
867 pamr = pam_acct_mgmt (pamh, PAM_SILENT); 867 pamr = pam_acct_mgmt (pamh, PAM_SILENT);
868 if (pamr == PAM_SUCCESS) 868 if (pamr == PAM_SUCCESS)
869 pamr = pam_open_session (pamh, PAM_SILENT); 869 pamr = pam_open_session (pamh, PAM_SILENT);
870 if (pamr != PAM_SUCCESS) 870 if (pamr != PAM_SUCCESS)
871 eerrorx ("%s: pam error: %s", progname, pam_strerror(pamh, pamr)); 871 eerrorx ("%s: pam error: %s", progname, pam_strerror(pamh, pamr));
872#endif 872#endif
873 873
874 if ((ch_gid) && setgid(ch_gid)) 874 if ((ch_gid) && setgid(ch_gid))
875 eerrorx ("%s: unable to set groupid to %d", progname, ch_gid); 875 eerrorx ("%s: unable to set groupid to %d", progname, ch_gid);
876 if (changeuser && ch_gid) 876 if (changeuser && ch_gid)
877 if (initgroups (changeuser, ch_gid)) 877 if (initgroups (changeuser, ch_gid))
878 eerrorx ("%s: initgroups (%s, %d)", progname, changeuser, ch_gid); 878 eerrorx ("%s: initgroups (%s, %d)", progname, changeuser, ch_gid);
879 if (ch_uid && setuid (ch_uid)) 879 if (ch_uid && setuid (ch_uid))
880 eerrorx ("%s: unable to set userid to %d", progname, ch_uid); 880 eerrorx ("%s: unable to set userid to %d", progname, ch_uid);
881 else 881 else
882 { 882 {
883 struct passwd *passwd = getpwuid (ch_uid); 883 struct passwd *passwd = getpwuid (ch_uid);
884 if (passwd) 884 if (passwd)
885 { 885 {
886 unsetenv ("HOME"); 886 unsetenv ("HOME");
887 if (passwd->pw_dir) 887 if (passwd->pw_dir)
888 setenv ("HOME", passwd->pw_dir, 1); 888 setenv ("HOME", passwd->pw_dir, 1);
889 unsetenv ("USER"); 889 unsetenv ("USER");
890 if (passwd->pw_name) 890 if (passwd->pw_name)
891 setenv ("USER", passwd->pw_name, 1); 891 setenv ("USER", passwd->pw_name, 1);
892 } 892 }
893 } 893 }
894 894
895 /* Close any fd's to the passwd database */ 895 /* Close any fd's to the passwd database */
896 endpwent (); 896 endpwent ();
897 897
898#ifdef TIOCNOTTY 898#ifdef TIOCNOTTY
901#endif 901#endif
902 902
903 /* Clean the environment of any RC_ variables */ 903 /* Clean the environment of any RC_ variables */
904 STRLIST_FOREACH (environ, env, i) 904 STRLIST_FOREACH (environ, env, i)
905 if (env && strncmp (env, "RC_", 3) != 0) 905 if (env && strncmp (env, "RC_", 3) != 0)
906 { 906 {
907 /* For the path character, remove the rcscript bin dir from it */ 907 /* For the path character, remove the rcscript bin dir from it */
908 if (strncmp (env, "PATH=" RC_LIBDIR "bin:", 908 if (strncmp (env, "PATH=" RC_LIBDIR "bin:",
909 strlen ("PATH=" RC_LIBDIR "bin:")) == 0) 909 strlen ("PATH=" RC_LIBDIR "bin:")) == 0)
910 { 910 {
911 char *path = env; 911 char *path = env;
912 char *newpath; 912 char *newpath;
913 int len; 913 int len;
914 path += strlen ("PATH=" RC_LIBDIR "bin:"); 914 path += strlen ("PATH=" RC_LIBDIR "bin:");
915 len = sizeof (char *) * strlen (path) + 6; 915 len = sizeof (char *) * strlen (path) + 6;
916 newpath = rc_xmalloc (len); 916 newpath = rc_xmalloc (len);
917 snprintf (newpath, len, "PATH=%s", path); 917 snprintf (newpath, len, "PATH=%s", path);
918 newenv = rc_strlist_add (newenv, newpath); 918 newenv = rc_strlist_add (newenv, newpath);
919 free (newpath); 919 free (newpath);
920 } 920 }
921 else 921 else
922 newenv = rc_strlist_add (newenv, env); 922 newenv = rc_strlist_add (newenv, env);
923 } 923 }
924 924
925 umask (022); 925 umask (022);
926 926
927 stdout_fd = devnull_fd; 927 stdout_fd = devnull_fd;
928 stderr_fd = devnull_fd; 928 stderr_fd = devnull_fd;
929 if (redirect_stdout) 929 if (redirect_stdout)
930 { 930 {
931 if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND, 931 if ((stdout_fd = open (redirect_stdout, O_WRONLY | O_CREAT | O_APPEND,
932 S_IRUSR | S_IWUSR)) == -1) 932 S_IRUSR | S_IWUSR)) == -1)
933 eerrorx ("%s: unable to open the logfile for stdout `%s': %s", 933 eerrorx ("%s: unable to open the logfile for stdout `%s': %s",
934 progname, redirect_stdout, strerror (errno)); 934 progname, redirect_stdout, strerror (errno));
935 } 935 }
936 if (redirect_stderr) 936 if (redirect_stderr)
937 { 937 {
938 if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND, 938 if ((stderr_fd = open (redirect_stderr, O_WRONLY | O_CREAT | O_APPEND,
939 S_IRUSR | S_IWUSR)) == -1) 939 S_IRUSR | S_IWUSR)) == -1)
940 eerrorx ("%s: unable to open the logfile for stderr `%s': %s", 940 eerrorx ("%s: unable to open the logfile for stderr `%s': %s",
941 progname, redirect_stderr, strerror (errno)); 941 progname, redirect_stderr, strerror (errno));
942 } 942 }
943 943
944 dup2 (devnull_fd, STDIN_FILENO); 944 dup2 (devnull_fd, STDIN_FILENO);
945 if (background) 945 if (background)
946 { 946 {
947 dup2 (stdout_fd, STDOUT_FILENO); 947 dup2 (stdout_fd, STDOUT_FILENO);
948 dup2 (stderr_fd, STDERR_FILENO); 948 dup2 (stderr_fd, STDERR_FILENO);
949 } 949 }
950 950
951 for (i = getdtablesize () - 1; i >= 3; --i) 951 for (i = getdtablesize () - 1; i >= 3; --i)
952 close(i); 952 close(i);
953 953
954 setsid (); 954 setsid ();
955 955
956 execve (exec, argv, newenv); 956 execve (exec, argv, newenv);
957#ifdef HAVE_PAM 957#ifdef HAVE_PAM
958 if (pamr == PAM_SUCCESS) 958 if (pamr == PAM_SUCCESS)
959 pam_close_session (pamh, PAM_SILENT); 959 pam_close_session (pamh, PAM_SILENT);
960#endif 960#endif
961 eerrorx ("%s: failed to exec `%s': %s", progname, exec, strerror (errno)); 961 eerrorx ("%s: failed to exec `%s': %s", progname, exec, strerror (errno));
962 } 962 }
963 963
964 /* Parent process */ 964 /* Parent process */
968 int status = 0; 968 int status = 0;
969 int savepid = pid; 969 int savepid = pid;
970 970
971 errno = 0; 971 errno = 0;
972 do 972 do
973 { 973 {
974 pid = waitpid (savepid, &status, 0); 974 pid = waitpid (savepid, &status, 0);
975 if (pid < 1) 975 if (pid < 1)
976 { 976 {
977 eerror ("waitpid %d: %s", savepid, strerror (errno)); 977 eerror ("waitpid %d: %s", savepid, strerror (errno));
978 return (-1); 978 return (-1);
979 } 979 }
980 } while (! WIFEXITED (status) && ! WIFSIGNALED (status)); 980 } while (! WIFEXITED (status) && ! WIFSIGNALED (status));
981 981
982 if (! WIFEXITED (status) || WEXITSTATUS (status) != 0) 982 if (! WIFEXITED (status) || WEXITSTATUS (status) != 0)
983 { 983 {
984 if (! quiet) 984 if (! quiet)
985 eerrorx ("%s: failed to started `%s'", progname, exec); 985 eerrorx ("%s: failed to started `%s'", progname, exec);
986 exit (EXIT_FAILURE); 986 exit (EXIT_FAILURE);
987 } 987 }
988 988
989 pid = savepid; 989 pid = savepid;
990 } 990 }
991 991
992 /* Wait a little bit and check that process is still running 992 /* Wait a little bit and check that process is still running
995 { 995 {
996 struct timeval stopat; 996 struct timeval stopat;
997 struct timeval now; 997 struct timeval now;
998 998
999 if (gettimeofday (&stopat, NULL) != 0) 999 if (gettimeofday (&stopat, NULL) != 0)
1000 eerrorx ("%s: gettimeofday: %s", progname, strerror (errno)); 1000 eerrorx ("%s: gettimeofday: %s", progname, strerror (errno));
1001 1001
1002 stopat.tv_usec += START_WAIT; 1002 stopat.tv_usec += START_WAIT;
1003 while (1) 1003 while (1)
1004 { 1004 {
1005 bool alive = false; 1005 bool alive = false;
1006 1006
1007 tv.tv_sec = 0; 1007 tv.tv_sec = 0;
1008 tv.tv_usec = POLL_INTERVAL; 1008 tv.tv_usec = POLL_INTERVAL;
1009 if (select (0, 0, 0, 0, &tv) < 0) 1009 if (select (0, 0, 0, 0, &tv) < 0)
1010 { 1010 {
1011 /* Let our signal handler handle the interupt */ 1011 /* Let our signal handler handle the interupt */
1012 if (errno != EINTR) 1012 if (errno != EINTR)
1013 eerrorx ("%s: select: %s", progname, strerror (errno)); 1013 eerrorx ("%s: select: %s", progname, strerror (errno));
1014 } 1014 }
1015 1015
1016 if (gettimeofday (&now, NULL) != 0) 1016 if (gettimeofday (&now, NULL) != 0)
1017 eerrorx ("%s: gettimeofday: %s", progname, strerror (errno)); 1017 eerrorx ("%s: gettimeofday: %s", progname, strerror (errno));
1018 1018
1019 /* This is knarly. 1019 /* This is knarly.
1020 If we backgrounded then we know the exact pid. 1020 If we backgrounded then we know the exact pid.
1021 Otherwise if we have a pidfile then it *may* know the exact pid. 1021 Otherwise if we have a pidfile then it *may* know the exact pid.
1022 Failing that, we'll have to query processes. 1022 Failing that, we'll have to query processes.
1023 We sleep first as some programs like ntp like to fork, and write 1023 We sleep first as some programs like ntp like to fork, and write
1024 their pidfile a LONG time later. */ 1024 their pidfile a LONG time later. */
1025 if (background) 1025 if (background)
1026 { 1026 {
1027 if (kill (pid, 0) == 0) 1027 if (kill (pid, 0) == 0)
1028 alive = true; 1028 alive = true;
1029 } 1029 }
1030 else 1030 else
1031 { 1031 {
1032 if (pidfile && rc_exists (pidfile)) 1032 if (pidfile && rc_exists (pidfile))
1033 { 1033 {
1034 if (do_stop (NULL, NULL, pidfile, uid, 0, true, false, true) > 0) 1034 if (do_stop (NULL, NULL, pidfile, uid, 0, true, false, true) > 0)
1035 alive = true; 1035 alive = true;
1036 } 1036 }
1037 else 1037 else
1038 { 1038 {
1039 if (do_stop (exec, cmd, NULL, uid, 0, true, false, true) > 0) 1039 if (do_stop (exec, cmd, NULL, uid, 0, true, false, true) > 0)
1040 alive = true; 1040 alive = true;
1041 } 1041 }
1042 } 1042 }
1043 1043
1044 if (! alive) 1044 if (! alive)
1045 eerrorx ("%s: %s died", progname, exec); 1045 eerrorx ("%s: %s died", progname, exec);
1046 1046
1047 if (timercmp (&now, &stopat, >)) 1047 if (timercmp (&now, &stopat, >))
1048 break; 1048 break;
1049 } 1049 }
1050 } 1050 }
1051 1051
1052 if (svcname) 1052 if (svcname)
1053 rc_set_service_daemon (svcname, exec, cmd, pidfile, true); 1053 rc_set_service_daemon (svcname, exec, cmd, pidfile, true);
1054 1054

Legend:
Removed from v.2563  
changed lines
  Added in v.2569

  ViewVC Help
Powered by ViewVC 1.1.20