LCOV - code coverage report
Current view: top level - utils - start-stop-daemon.c (source / functions) Coverage Total Hit
Test: dpkg 1.22.7-3-g89f48 C code coverage Lines: 0.0 % 974 0
Test Date: 2024-07-17 02:53:43 Functions: 0.0 % 61 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 662 0

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * A rewrite of the original Debian's start-stop-daemon Perl script
       3                 :             :  * in C (faster - it is executed many times during system startup).
       4                 :             :  *
       5                 :             :  * Written by Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>,
       6                 :             :  * public domain.  Based conceptually on start-stop-daemon.pl, by Ian
       7                 :             :  * Jackson <ijackson@gnu.ai.mit.edu>.  May be used and distributed
       8                 :             :  * freely for any purpose.  Changes by Christian Schwarz
       9                 :             :  * <schwarz@monet.m.isar.de>, to make output conform to the Debian
      10                 :             :  * Console Message Standard, also placed in public domain.  Minor
      11                 :             :  * changes by Klee Dienes <klee@debian.org>, also placed in the Public
      12                 :             :  * Domain.
      13                 :             :  *
      14                 :             :  * Changes by Ben Collins <bcollins@debian.org>, added --chuid, --background
      15                 :             :  * and --make-pidfile options, placed in public domain as well.
      16                 :             :  *
      17                 :             :  * Port to OpenBSD by Sontri Tomo Huynh <huynh.29@osu.edu>
      18                 :             :  *                 and Andreas Schuldei <andreas@schuldei.org>
      19                 :             :  *
      20                 :             :  * Changes by Ian Jackson: added --retry (and associated rearrangements).
      21                 :             :  */
      22                 :             : 
      23                 :             : #include <config.h>
      24                 :             : /* On at least Solaris <= 11.3 procfs is not compatible with LFS. */
      25                 :             : #if !DPKG_STRUCTURED_PROCFS_SUPPORTS_LFS
      26                 :             : #undef _FILE_OFFSET_BITS
      27                 :             : #endif
      28                 :             : #include <compat.h>
      29                 :             : 
      30                 :             : #include <dpkg/macros.h>
      31                 :             : 
      32                 :             : #if defined(__linux__)
      33                 :             : #  define OS_Linux
      34                 :             : #elif defined(__GNU__)
      35                 :             : #  define OS_Hurd
      36                 :             : #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
      37                 :             : #  define OS_FreeBSD
      38                 :             : #elif defined(__NetBSD__)
      39                 :             : #  define OS_NetBSD
      40                 :             : #elif defined(__OpenBSD__)
      41                 :             : #  define OS_OpenBSD
      42                 :             : #elif defined(__DragonFly__)
      43                 :             : #  define OS_DragonFlyBSD
      44                 :             : #elif defined(__APPLE__) && defined(__MACH__)
      45                 :             : #  define OS_Darwin
      46                 :             : #elif defined(__sun)
      47                 :             : #  define OS_Solaris
      48                 :             : #elif defined(_AIX)
      49                 :             : #  define OS_AIX
      50                 :             : #elif defined(__hpux)
      51                 :             : #  define OS_HPUX
      52                 :             : #else
      53                 :             : #  error Unknown architecture - cannot build start-stop-daemon
      54                 :             : #endif
      55                 :             : 
      56                 :             : #if defined(OS_NetBSD)
      57                 :             : /* NetBSD needs this to expose struct proc. */
      58                 :             : #define _KMEMUSER 1
      59                 :             : #elif defined(OS_Solaris)
      60                 :             : /* Solaris needs this to expose the new structured procfs API. */
      61                 :             : #define _STRUCTURED_PROC 1
      62                 :             : #endif
      63                 :             : 
      64                 :             : #ifdef HAVE_SYS_PARAM_H
      65                 :             : #include <sys/param.h>
      66                 :             : #endif
      67                 :             : #ifdef HAVE_SYS_SYSCALL_H
      68                 :             : #include <sys/syscall.h>
      69                 :             : #endif
      70                 :             : #ifdef HAVE_SYS_SYSCTL_H
      71                 :             : #include <sys/sysctl.h>
      72                 :             : #endif
      73                 :             : #ifdef HAVE_SYS_PROCFS_H
      74                 :             : #include <sys/procfs.h>
      75                 :             : #endif
      76                 :             : #ifdef HAVE_SYS_PROC_H
      77                 :             : #include <sys/proc.h>
      78                 :             : #endif
      79                 :             : #ifdef HAVE_SYS_USER_H
      80                 :             : #include <sys/user.h>
      81                 :             : #endif
      82                 :             : #ifdef HAVE_SYS_PSTAT_H
      83                 :             : #include <sys/pstat.h>
      84                 :             : #endif
      85                 :             : #include <sys/types.h>
      86                 :             : #include <sys/time.h>
      87                 :             : #include <sys/stat.h>
      88                 :             : #include <sys/wait.h>
      89                 :             : #include <sys/select.h>
      90                 :             : #include <sys/ioctl.h>
      91                 :             : #include <sys/socket.h>
      92                 :             : #include <sys/un.h>
      93                 :             : 
      94                 :             : #include <errno.h>
      95                 :             : #include <limits.h>
      96                 :             : #include <time.h>
      97                 :             : #include <fcntl.h>
      98                 :             : #include <dirent.h>
      99                 :             : #include <ctype.h>
     100                 :             : #include <string.h>
     101                 :             : #include <pwd.h>
     102                 :             : #include <grp.h>
     103                 :             : #include <signal.h>
     104                 :             : #include <termios.h>
     105                 :             : #include <unistd.h>
     106                 :             : #include <stddef.h>
     107                 :             : #include <stdbool.h>
     108                 :             : #include <stdarg.h>
     109                 :             : #include <stdlib.h>
     110                 :             : #include <stdio.h>
     111                 :             : #include <getopt.h>
     112                 :             : #ifdef HAVE_ERROR_H
     113                 :             : #include <error.h>
     114                 :             : #endif
     115                 :             : #ifdef HAVE_ERR_H
     116                 :             : #include <err.h>
     117                 :             : #endif
     118                 :             : 
     119                 :             : #if defined(OS_Hurd)
     120                 :             : #include <hurd.h>
     121                 :             : #include <ps.h>
     122                 :             : #endif
     123                 :             : 
     124                 :             : #if defined(OS_Darwin)
     125                 :             : #include <libproc.h>
     126                 :             : #endif
     127                 :             : 
     128                 :             : #ifdef HAVE_KVM_H
     129                 :             : #include <kvm.h>
     130                 :             : #if defined(OS_FreeBSD)
     131                 :             : #define KVM_MEMFILE "/dev/null"
     132                 :             : #else
     133                 :             : #define KVM_MEMFILE NULL
     134                 :             : #endif
     135                 :             : #endif
     136                 :             : 
     137                 :             : #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
     138                 :             : #include <sched.h>
     139                 :             : #else
     140                 :             : #define SCHED_OTHER -1
     141                 :             : #define SCHED_FIFO -1
     142                 :             : #define SCHED_RR -1
     143                 :             : #endif
     144                 :             : 
     145                 :             : /* At least macOS and AIX do not define this. */
     146                 :             : #ifndef SOCK_NONBLOCK
     147                 :             : #define SOCK_NONBLOCK 0
     148                 :             : #endif
     149                 :             : 
     150                 :             : #if defined(OS_Linux)
     151                 :             : /* This comes from TASK_COMM_LEN defined in Linux' include/linux/sched.h. */
     152                 :             : #define PROCESS_NAME_SIZE 15
     153                 :             : #elif defined(OS_Solaris)
     154                 :             : #define PROCESS_NAME_SIZE 15
     155                 :             : #elif defined(OS_Darwin)
     156                 :             : #define PROCESS_NAME_SIZE 16
     157                 :             : #elif defined(OS_AIX)
     158                 :             : /* This comes from PRFNSZ defined in AIX's <sys/procfs.h>. */
     159                 :             : #define PROCESS_NAME_SIZE 16
     160                 :             : #elif defined(OS_NetBSD)
     161                 :             : #define PROCESS_NAME_SIZE 16
     162                 :             : #elif defined(OS_OpenBSD)
     163                 :             : #define PROCESS_NAME_SIZE 16
     164                 :             : #elif defined(OS_FreeBSD)
     165                 :             : #define PROCESS_NAME_SIZE 19
     166                 :             : #elif defined(OS_DragonFlyBSD)
     167                 :             : /* On DragonFlyBSD MAXCOMLEN expands to 16. */
     168                 :             : #define PROCESS_NAME_SIZE MAXCOMLEN
     169                 :             : #endif
     170                 :             : 
     171                 :             : #if defined(SYS_ioprio_set) && defined(linux)
     172                 :             : #define HAVE_IOPRIO_SET
     173                 :             : #endif
     174                 :             : 
     175                 :             : #define IOPRIO_CLASS_SHIFT 13
     176                 :             : #define IOPRIO_PRIO_VALUE(class, prio) (((class) << IOPRIO_CLASS_SHIFT) | (prio))
     177                 :             : #define IO_SCHED_PRIO_MIN 0
     178                 :             : #define IO_SCHED_PRIO_MAX 7
     179                 :             : 
     180                 :             : enum {
     181                 :             :         IOPRIO_WHO_PROCESS = 1,
     182                 :             :         IOPRIO_WHO_PGRP,
     183                 :             :         IOPRIO_WHO_USER,
     184                 :             : };
     185                 :             : 
     186                 :             : enum {
     187                 :             :         IOPRIO_CLASS_NONE,
     188                 :             :         IOPRIO_CLASS_RT,
     189                 :             :         IOPRIO_CLASS_BE,
     190                 :             :         IOPRIO_CLASS_IDLE,
     191                 :             : };
     192                 :             : 
     193                 :             : enum action_code {
     194                 :             :         ACTION_NONE,
     195                 :             :         ACTION_START,
     196                 :             :         ACTION_STOP,
     197                 :             :         ACTION_STATUS,
     198                 :             : };
     199                 :             : 
     200                 :             : enum LIBCOMPAT_ATTR_ENUM_FLAGS match_code {
     201                 :             :         MATCH_NONE      = 0,
     202                 :             :         MATCH_PID       = 1 << 0,
     203                 :             :         MATCH_PPID      = 1 << 1,
     204                 :             :         MATCH_PIDFILE   = 1 << 2,
     205                 :             :         MATCH_EXEC      = 1 << 3,
     206                 :             :         MATCH_NAME      = 1 << 4,
     207                 :             :         MATCH_USER      = 1 << 5,
     208                 :             : };
     209                 :             : 
     210                 :             : /* Time conversion constants. */
     211                 :             : enum {
     212                 :             :         NANOSEC_IN_SEC      = 1000000000L,
     213                 :             :         NANOSEC_IN_MILLISEC = 1000000L,
     214                 :             :         NANOSEC_IN_MICROSEC = 1000L,
     215                 :             : };
     216                 :             : 
     217                 :             : /* The minimum polling interval, 20ms. */
     218                 :             : static const long MIN_POLL_INTERVAL = 20L * NANOSEC_IN_MILLISEC;
     219                 :             : 
     220                 :             : static enum action_code action;
     221                 :             : static enum match_code match_mode;
     222                 :             : static bool testmode = false;
     223                 :             : static int quietmode = 0;
     224                 :             : static int exitnodo = 1;
     225                 :             : static bool background = false;
     226                 :             : static bool close_io = true;
     227                 :             : static const char *output_io;
     228                 :             : static bool notify_await = false;
     229                 :             : static int notify_timeout = 60;
     230                 :             : static char *notify_sockdir;
     231                 :             : static char *notify_socket;
     232                 :             : static bool mpidfile = false;
     233                 :             : static bool rpidfile = false;
     234                 :             : static int signal_nr = SIGTERM;
     235                 :             : static int user_id = -1;
     236                 :             : static int runas_uid = -1;
     237                 :             : static int runas_gid = -1;
     238                 :             : static const char *userspec = NULL;
     239                 :             : static char *changeuser = NULL;
     240                 :             : static const char *changegroup = NULL;
     241                 :             : static char *changeroot = NULL;
     242                 :             : static const char *changedir = "/";
     243                 :             : static const char *cmdname = NULL;
     244                 :             : static char *execname = NULL;
     245                 :             : static char *startas = NULL;
     246                 :             : static pid_t match_pid = -1;
     247                 :             : static pid_t match_ppid = -1;
     248                 :             : static const char *pidfile = NULL;
     249                 :             : static char *what_stop = NULL;
     250                 :             : static const char *progname = "";
     251                 :             : static int nicelevel = 0;
     252                 :             : static int umask_value = -1;
     253                 :             : 
     254                 :             : static struct stat exec_stat;
     255                 :             : #if defined(OS_Hurd)
     256                 :             : static struct proc_stat_list *procset = NULL;
     257                 :             : #endif
     258                 :             : 
     259                 :             : /* LSB Init Script process status exit codes. */
     260                 :             : enum status_code {
     261                 :             :         STATUS_OK = 0,
     262                 :             :         STATUS_DEAD_PIDFILE = 1,
     263                 :             :         STATUS_DEAD_LOCKFILE = 2,
     264                 :             :         STATUS_DEAD = 3,
     265                 :             :         STATUS_UNKNOWN = 4,
     266                 :             : };
     267                 :             : 
     268                 :             : struct pid_list {
     269                 :             :         struct pid_list *next;
     270                 :             :         pid_t pid;
     271                 :             : };
     272                 :             : 
     273                 :             : static struct pid_list *found = NULL;
     274                 :             : static struct pid_list *killed = NULL;
     275                 :             : 
     276                 :             : /* Resource scheduling policy. */
     277                 :             : struct res_schedule {
     278                 :             :         const char *policy_name;
     279                 :             :         int policy;
     280                 :             :         int priority;
     281                 :             : };
     282                 :             : 
     283                 :             : struct schedule_item {
     284                 :             :         enum {
     285                 :             :                 sched_timeout,
     286                 :             :                 sched_signal,
     287                 :             :                 sched_goto,
     288                 :             :                 /* Only seen within parse_schedule and callees. */
     289                 :             :                 sched_forever,
     290                 :             :         } type;
     291                 :             :         /* Seconds, signal no., or index into array. */
     292                 :             :         int value;
     293                 :             : };
     294                 :             : 
     295                 :             : static struct res_schedule *proc_sched = NULL;
     296                 :             : static struct res_schedule *io_sched = NULL;
     297                 :             : 
     298                 :             : static int schedule_length;
     299                 :             : static struct schedule_item *schedule = NULL;
     300                 :             : 
     301                 :             : 
     302                 :             : static void LIBCOMPAT_ATTR_PRINTF(1)
     303                 :           0 : debug(const char *format, ...)
     304                 :             : {
     305                 :             :         va_list arglist;
     306                 :             : 
     307         [ #  # ]:           0 :         if (quietmode >= 0)
     308                 :           0 :                 return;
     309                 :             : 
     310                 :           0 :         va_start(arglist, format);
     311                 :           0 :         vprintf(format, arglist);
     312                 :           0 :         va_end(arglist);
     313                 :             : }
     314                 :             : 
     315                 :             : static void LIBCOMPAT_ATTR_PRINTF(1)
     316                 :           0 : info(const char *format, ...)
     317                 :             : {
     318                 :             :         va_list arglist;
     319                 :             : 
     320         [ #  # ]:           0 :         if (quietmode > 0)
     321                 :           0 :                 return;
     322                 :             : 
     323                 :           0 :         va_start(arglist, format);
     324                 :           0 :         vprintf(format, arglist);
     325                 :           0 :         va_end(arglist);
     326                 :             : }
     327                 :             : 
     328                 :             : static void LIBCOMPAT_ATTR_PRINTF(1)
     329                 :           0 : warning(const char *format, ...)
     330                 :             : {
     331                 :             :         va_list arglist;
     332                 :             : 
     333                 :           0 :         fprintf(stderr, "%s: warning: ", progname);
     334                 :           0 :         va_start(arglist, format);
     335                 :           0 :         vfprintf(stderr, format, arglist);
     336                 :           0 :         va_end(arglist);
     337                 :           0 : }
     338                 :             : 
     339                 :             : static void LIBCOMPAT_ATTR_NORET LIBCOMPAT_ATTR_VPRINTF(2)
     340                 :           0 : fatalv(int errno_fatal, const char *format, va_list args)
     341                 :             : {
     342                 :             :         va_list args_copy;
     343                 :             : 
     344                 :           0 :         fprintf(stderr, "%s: ", progname);
     345                 :           0 :         va_copy(args_copy, args);
     346                 :           0 :         vfprintf(stderr, format, args_copy);
     347                 :           0 :         va_end(args_copy);
     348         [ #  # ]:           0 :         if (errno_fatal)
     349                 :           0 :                 fprintf(stderr, " (%s)\n", strerror(errno_fatal));
     350                 :             :         else
     351                 :           0 :                 fprintf(stderr, "\n");
     352                 :             : 
     353         [ #  # ]:           0 :         if (action == ACTION_STATUS)
     354                 :           0 :                 exit(STATUS_UNKNOWN);
     355                 :             :         else
     356                 :           0 :                 exit(2);
     357                 :             : }
     358                 :             : 
     359                 :             : static void LIBCOMPAT_ATTR_NORET LIBCOMPAT_ATTR_PRINTF(1)
     360                 :           0 : fatal(const char *format, ...)
     361                 :             : {
     362                 :             :         va_list args;
     363                 :             : 
     364                 :           0 :         va_start(args, format);
     365                 :           0 :         fatalv(0, format, args);
     366                 :             :         /* cppcheck-suppress[va_end_missing]:
     367                 :             :          * False positive, fatalv() is non-returning. */
     368                 :             : }
     369                 :             : 
     370                 :             : static void LIBCOMPAT_ATTR_NORET LIBCOMPAT_ATTR_PRINTF(1)
     371                 :           0 : fatale(const char *format, ...)
     372                 :             : {
     373                 :             :         va_list args;
     374                 :             : 
     375                 :           0 :         va_start(args, format);
     376                 :           0 :         fatalv(errno, format, args);
     377                 :             :         /* cppcheck-suppress[va_end_missing]:
     378                 :             :          * False positive, fatalv() is non-returning. */
     379                 :             : }
     380                 :             : 
     381                 :             : #define BUG(...) bug(__FILE__, __LINE__, __func__, __VA_ARGS__)
     382                 :             : 
     383                 :             : static void LIBCOMPAT_ATTR_NORET LIBCOMPAT_ATTR_PRINTF(4)
     384                 :           0 : bug(const char *file, int line, const char *func, const char *format, ...)
     385                 :             : {
     386                 :             :         va_list arglist;
     387                 :             : 
     388                 :           0 :         fprintf(stderr, "%s:%s:%d:%s: internal error: ",
     389                 :             :                 progname, file, line, func);
     390                 :           0 :         va_start(arglist, format);
     391                 :           0 :         vfprintf(stderr, format, arglist);
     392                 :           0 :         va_end(arglist);
     393                 :             : 
     394         [ #  # ]:           0 :         if (action == ACTION_STATUS)
     395                 :           0 :                 exit(STATUS_UNKNOWN);
     396                 :             :         else
     397                 :           0 :                 exit(3);
     398                 :             : }
     399                 :             : 
     400                 :             : static void *
     401                 :           0 : xmalloc(int size)
     402                 :             : {
     403                 :             :         void *ptr;
     404                 :             : 
     405                 :           0 :         ptr = malloc(size);
     406         [ #  # ]:           0 :         if (ptr)
     407                 :           0 :                 return ptr;
     408                 :           0 :         fatale("malloc(%d) failed", size);
     409                 :             : }
     410                 :             : 
     411                 :             : static char *
     412                 :           0 : xstrndup(const char *str, size_t n)
     413                 :             : {
     414                 :             :         char *new_str;
     415                 :             : 
     416                 :           0 :         new_str = strndup(str, n);
     417         [ #  # ]:           0 :         if (new_str)
     418                 :           0 :                 return new_str;
     419                 :           0 :         fatale("strndup(%s, %zu) failed", str, n);
     420                 :             : }
     421                 :             : 
     422                 :             : static void
     423                 :           0 : timespec_gettime(struct timespec *ts)
     424                 :             : {
     425                 :             : #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 && \
     426                 :             :     defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK > 0
     427                 :             :         if (clock_gettime(CLOCK_MONOTONIC, ts) < 0)
     428                 :             :                 fatale("clock_gettime failed");
     429                 :             : #else
     430                 :             :         struct timeval tv;
     431                 :             : 
     432         [ #  # ]:           0 :         if (gettimeofday(&tv, NULL) != 0)
     433                 :           0 :                 fatale("gettimeofday failed");
     434                 :             : 
     435                 :           0 :         ts->tv_sec = tv.tv_sec;
     436                 :           0 :         ts->tv_nsec = tv.tv_usec * NANOSEC_IN_MICROSEC;
     437                 :             : #endif
     438                 :           0 : }
     439                 :             : 
     440                 :             : #define timespec_cmp(a, b, OP) \
     441                 :             :         (((a)->tv_sec == (b)->tv_sec) ? \
     442                 :             :          ((a)->tv_nsec OP (b)->tv_nsec) : \
     443                 :             :          ((a)->tv_sec OP (b)->tv_sec))
     444                 :             : 
     445                 :             : static void
     446                 :           0 : timespec_sub(struct timespec *a, struct timespec *b, struct timespec *res)
     447                 :             : {
     448                 :           0 :         res->tv_sec = a->tv_sec - b->tv_sec;
     449                 :           0 :         res->tv_nsec = a->tv_nsec - b->tv_nsec;
     450         [ #  # ]:           0 :         if (res->tv_nsec < 0) {
     451                 :           0 :                 res->tv_sec--;
     452                 :           0 :                 res->tv_nsec += NANOSEC_IN_SEC;
     453                 :             :         }
     454                 :           0 : }
     455                 :             : 
     456                 :             : static void
     457                 :           0 : timespec_mul(struct timespec *a, int b)
     458                 :             : {
     459                 :           0 :         long nsec = a->tv_nsec * b;
     460                 :             : 
     461                 :           0 :         a->tv_sec *= b;
     462                 :           0 :         a->tv_sec += nsec / NANOSEC_IN_SEC;
     463                 :           0 :         a->tv_nsec = nsec % NANOSEC_IN_SEC;
     464                 :           0 : }
     465                 :             : 
     466                 :             : static char *
     467                 :           0 : newpath(const char *dirname, const char *filename)
     468                 :             : {
     469                 :             :         char *path;
     470                 :             :         size_t path_len;
     471                 :             : 
     472                 :           0 :         path_len = strlen(dirname) + 1 + strlen(filename) + 1;
     473                 :           0 :         path = xmalloc(path_len);
     474                 :           0 :         snprintf(path, path_len, "%s/%s", dirname, filename);
     475                 :             : 
     476                 :           0 :         return path;
     477                 :             : }
     478                 :             : 
     479                 :             : static int
     480                 :           0 : parse_unsigned(const char *string, int base, int *value_r)
     481                 :             : {
     482                 :             :         long value;
     483                 :             :         char *endptr;
     484                 :             : 
     485                 :           0 :         errno = 0;
     486         [ #  # ]:           0 :         if (!string[0])
     487                 :           0 :                 return -1;
     488                 :             : 
     489                 :           0 :         value = strtol(string, &endptr, base);
     490   [ #  #  #  #  :           0 :         if (string == endptr || *endptr != '\0' || errno != 0)
                   #  # ]
     491                 :           0 :                 return -1;
     492   [ #  #  #  # ]:           0 :         if (value < 0 || value > INT_MAX)
     493                 :           0 :                 return -1;
     494                 :             : 
     495                 :           0 :         *value_r = value;
     496                 :           0 :         return 0;
     497                 :             : }
     498                 :             : 
     499                 :             : static long
     500                 :           0 : get_open_fd_max(void)
     501                 :             : {
     502                 :             : #ifdef HAVE_GETDTABLESIZE
     503                 :           0 :         return getdtablesize();
     504                 :             : #else
     505                 :             :         return sysconf(_SC_OPEN_MAX);
     506                 :             : #endif
     507                 :             : }
     508                 :             : 
     509                 :             : #ifndef HAVE_SETSID
     510                 :             : static void
     511                 :             : detach_controlling_tty(void)
     512                 :             : {
     513                 :             : #ifdef HAVE_TIOCNOTTY
     514                 :             :         int tty_fd;
     515                 :             : 
     516                 :             :         tty_fd = open("/dev/tty", O_RDWR);
     517                 :             : 
     518                 :             :         /* The current process does not have a controlling tty. */
     519                 :             :         if (tty_fd < 0)
     520                 :             :                 return;
     521                 :             : 
     522                 :             :         if (ioctl(tty_fd, TIOCNOTTY, 0) != 0)
     523                 :             :                 fatale("unable to detach controlling tty");
     524                 :             : 
     525                 :             :         close(tty_fd);
     526                 :             : #endif
     527                 :             : }
     528                 :             : 
     529                 :             : static pid_t
     530                 :             : setsid(void)
     531                 :             : {
     532                 :             :         if (setpgid(0, 0) < 0)
     533                 :             :                 return -1:
     534                 :             : 
     535                 :             :         detach_controlling_tty();
     536                 :             : 
     537                 :             :         return 0;
     538                 :             : }
     539                 :             : #endif
     540                 :             : 
     541                 :             : static void
     542                 :           0 : wait_for_child(pid_t pid)
     543                 :             : {
     544                 :             :         pid_t child;
     545                 :             :         int status;
     546                 :             : 
     547                 :             :         do {
     548                 :           0 :                 child = waitpid(pid, &status, 0);
     549   [ #  #  #  # ]:           0 :         } while (child < 0 && errno == EINTR);
     550                 :             : 
     551         [ #  # ]:           0 :         if (child != pid)
     552                 :           0 :                 fatal("error waiting for child");
     553                 :             : 
     554         [ #  # ]:           0 :         if (WIFEXITED(status)) {
     555                 :           0 :                 int ret = WEXITSTATUS(status);
     556                 :             : 
     557         [ #  # ]:           0 :                 if (ret != 0)
     558                 :           0 :                         fatal("child returned error exit status %d", ret);
     559         [ #  # ]:           0 :         } else if (WIFSIGNALED(status)) {
     560                 :           0 :                 int signo = WTERMSIG(status);
     561                 :             : 
     562                 :           0 :                 fatal("child was killed by signal %d", signo);
     563                 :             :         } else {
     564                 :           0 :                 fatal("unexpected status %d waiting for child", status);
     565                 :             :         }
     566                 :           0 : }
     567                 :             : 
     568                 :             : static void
     569                 :           0 : cleanup_socket_dir(void)
     570                 :             : {
     571                 :           0 :         (void)unlink(notify_socket);
     572                 :           0 :         (void)rmdir(notify_sockdir);
     573                 :           0 : }
     574                 :             : 
     575                 :             : static char *
     576                 :           0 : setup_socket_name(const char *suffix)
     577                 :             : {
     578                 :             :         const char *basedir;
     579                 :             : 
     580   [ #  #  #  # ]:           0 :         if (getuid() == 0 && access(RUNSTATEDIR, F_OK) == 0) {
     581                 :           0 :                 basedir = RUNSTATEDIR;
     582                 :             :         } else {
     583                 :           0 :                 basedir = getenv("TMPDIR");
     584         [ #  # ]:           0 :                 if (basedir == NULL)
     585                 :           0 :                         basedir = P_tmpdir;
     586                 :             :         }
     587                 :             : 
     588         [ #  # ]:           0 :         if (asprintf(&notify_sockdir, "%s/%s.XXXXXX", basedir, suffix) < 0)
     589                 :           0 :                 fatale("cannot allocate socket directory name");
     590                 :             : 
     591         [ #  # ]:           0 :         if (mkdtemp(notify_sockdir) == NULL)
     592                 :           0 :                 fatale("cannot create socket directory %s", notify_sockdir);
     593                 :             : 
     594                 :           0 :         atexit(cleanup_socket_dir);
     595                 :             : 
     596         [ #  # ]:           0 :         if (chown(notify_sockdir, runas_uid, runas_gid))
     597                 :           0 :                 fatale("cannot change socket directory ownership");
     598                 :             : 
     599         [ #  # ]:           0 :         if (asprintf(&notify_socket, "%s/notify", notify_sockdir) < 0)
     600                 :           0 :                 fatale("cannot allocate socket name");
     601                 :             : 
     602                 :           0 :         setenv("NOTIFY_SOCKET", notify_socket, 1);
     603                 :             : 
     604                 :           0 :         return notify_socket;
     605                 :             : }
     606                 :             : 
     607                 :             : static void
     608                 :           0 : set_socket_passcred(int fd)
     609                 :             : {
     610                 :             : #ifdef SO_PASSCRED
     611                 :             :         static const int enable = 1;
     612                 :             : 
     613                 :           0 :         (void)setsockopt(fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable));
     614                 :             : #endif
     615                 :           0 : }
     616                 :             : 
     617                 :             : static int
     618                 :           0 : create_notify_socket(void)
     619                 :             : {
     620                 :             :         const char *sockname;
     621                 :             :         struct sockaddr_un su;
     622                 :             :         int fd, rc, flags;
     623                 :             : 
     624                 :             :         /* Create notification socket. */
     625                 :           0 :         fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0);
     626         [ #  # ]:           0 :         if (fd < 0)
     627                 :           0 :                 fatale("cannot create notification socket");
     628                 :             : 
     629                 :             :         /* We could set SOCK_CLOEXEC instead, but then we would need to
     630                 :             :          * check whether the socket call failed, try and then do this anyway,
     631                 :             :          * when we have no threading problems to worry about. */
     632                 :           0 :         flags = fcntl(fd, F_GETFD);
     633         [ #  # ]:           0 :         if (flags < 0)
     634                 :           0 :                 fatale("cannot read fd flags for notification socket");
     635         [ #  # ]:           0 :         if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
     636                 :           0 :                 fatale("cannot set close-on-exec flag for notification socket");
     637                 :             : 
     638                 :           0 :         sockname = setup_socket_name(".s-s-d-notify");
     639                 :             : 
     640                 :             :         /* Bind to a socket in a temporary directory, selected based on
     641                 :             :          * the platform. */
     642                 :           0 :         memset(&su, 0, sizeof(su));
     643                 :           0 :         su.sun_family = AF_UNIX;
     644                 :           0 :         strncpy(su.sun_path, sockname, sizeof(su.sun_path) - 1);
     645                 :             : 
     646                 :           0 :         rc = bind(fd, (struct sockaddr *)&su, sizeof(su));
     647         [ #  # ]:           0 :         if (rc < 0)
     648                 :           0 :                 fatale("cannot bind to notification socket");
     649                 :             : 
     650                 :           0 :         rc = chmod(su.sun_path, 0660);
     651         [ #  # ]:           0 :         if (rc < 0)
     652                 :           0 :                 fatale("cannot change notification socket permissions");
     653                 :             : 
     654                 :           0 :         rc = chown(su.sun_path, runas_uid, runas_gid);
     655         [ #  # ]:           0 :         if (rc < 0)
     656                 :           0 :                 fatale("cannot change notification socket ownership");
     657                 :             : 
     658                 :             :         /* XXX: Verify we are talking to an expected child? Although it is not
     659                 :             :          * clear whether this is feasible given the knowledge we have got. */
     660                 :           0 :         set_socket_passcred(fd);
     661                 :             : 
     662                 :           0 :         return fd;
     663                 :             : }
     664                 :             : 
     665                 :             : static void
     666                 :           0 : wait_for_notify(int fd)
     667                 :             : {
     668                 :             :         struct timespec startat, now, elapsed, timeout, timeout_orig;
     669                 :             :         fd_set fdrs;
     670                 :             : 
     671                 :           0 :         timeout.tv_sec = notify_timeout;
     672                 :           0 :         timeout.tv_nsec = 0;
     673                 :           0 :         timeout_orig = timeout;
     674                 :             : 
     675                 :           0 :         timespec_gettime(&startat);
     676                 :             : 
     677   [ #  #  #  # ]:           0 :         while (timeout.tv_sec >= 0 && timeout.tv_nsec >= 0) {
     678                 :             :                 int rc;
     679                 :             : 
     680         [ #  # ]:           0 :                 FD_ZERO(&fdrs);
     681                 :           0 :                 FD_SET(fd, &fdrs);
     682                 :             : 
     683                 :             :                 /* Wait for input. */
     684                 :           0 :                 debug("Waiting for notifications... (timeout %lusec %lunsec)\n",
     685                 :             :                       timeout.tv_sec, timeout.tv_nsec);
     686                 :           0 :                 rc = pselect(fd + 1, &fdrs, NULL, NULL, &timeout, NULL);
     687                 :             : 
     688                 :             :                 /* Catch non-restartable errors, that is, not signals nor
     689                 :             :                  * kernel out of resources. */
     690   [ #  #  #  #  :           0 :                 if (rc < 0 && (errno != EINTR && errno != EAGAIN))
                   #  # ]
     691                 :           0 :                         fatale("cannot monitor notification socket for activity");
     692                 :             : 
     693                 :             :                 /* Timed-out. */
     694         [ #  # ]:           0 :                 if (rc == 0)
     695                 :           0 :                         fatal("timed out waiting for a notification");
     696                 :             : 
     697                 :             :                 /* Update the timeout, as should not rely on pselect() having
     698                 :             :                  * done that for us, which is an unportable assumption. */
     699                 :           0 :                 timespec_gettime(&now);
     700                 :           0 :                 timespec_sub(&now, &startat, &elapsed);
     701                 :           0 :                 timespec_sub(&timeout_orig, &elapsed, &timeout);
     702                 :             : 
     703                 :             :                 /* Restartable error, a signal or kernel out of resources. */
     704         [ #  # ]:           0 :                 if (rc < 0)
     705                 :           0 :                         continue;
     706                 :             : 
     707                 :             :                 /* Parse it and check for a supported notification message,
     708                 :             :                  * once we get a READY=1, we exit. */
     709                 :           0 :                 for (;;) {
     710                 :             :                         ssize_t nrecv;
     711                 :             :                         char buf[4096];
     712                 :             :                         char *line, *line_next;
     713                 :             : 
     714                 :           0 :                         nrecv = recv(fd, buf, sizeof(buf), 0);
     715   [ #  #  #  #  :           0 :                         if (nrecv < 0 && (errno != EINTR && errno != EAGAIN))
                   #  # ]
     716                 :           0 :                                 fatale("cannot receive notification packet");
     717         [ #  # ]:           0 :                         if (nrecv < 0)
     718                 :           0 :                                 break;
     719                 :             : 
     720                 :           0 :                         buf[nrecv] = '\0';
     721                 :             : 
     722         [ #  # ]:           0 :                         for (line = buf; *line; line = line_next) {
     723                 :           0 :                                 line_next = strchrnul(line, '\n');
     724         [ #  # ]:           0 :                                 if (*line_next == '\n')
     725                 :           0 :                                         *line_next++ = '\0';
     726                 :             : 
     727                 :           0 :                                 debug("Child sent some notification...\n");
     728         [ #  # ]:           0 :                                 if (strncmp(line, "EXTEND_TIMEOUT_USEC=", 20) == 0) {
     729                 :           0 :                                         int extend_usec = 0;
     730                 :             : 
     731         [ #  # ]:           0 :                                         if (parse_unsigned(line + 20, 10, &extend_usec) != 0)
     732                 :           0 :                                                 fatale("cannot parse extended timeout notification %s", line);
     733                 :             : 
     734                 :             :                                         /* Reset the current timeout. */
     735                 :           0 :                                         timeout.tv_sec = extend_usec / 1000L;
     736                 :           0 :                                         timeout.tv_nsec = (extend_usec % 1000L) *
     737                 :             :                                                           NANOSEC_IN_MILLISEC;
     738                 :           0 :                                         timeout_orig = timeout;
     739                 :             : 
     740                 :           0 :                                         timespec_gettime(&startat);
     741         [ #  # ]:           0 :                                 } else if (strncmp(line, "ERRNO=", 6) == 0) {
     742                 :           0 :                                         int suberrno = 0;
     743                 :             : 
     744         [ #  # ]:           0 :                                         if (parse_unsigned(line + 6, 10, &suberrno) != 0)
     745                 :           0 :                                                 fatale("cannot parse errno notification %s", line);
     746                 :           0 :                                         errno = suberrno;
     747                 :           0 :                                         fatale("program failed to initialize");
     748         [ #  # ]:           0 :                                 } else if (strcmp(line, "READY=1") == 0) {
     749                 :           0 :                                         debug("-> Notification => ready for service.\n");
     750                 :           0 :                                         return;
     751                 :             :                                 } else {
     752                 :           0 :                                         debug("-> Notification line '%s' received\n", line);
     753                 :             :                                 }
     754                 :             :                         }
     755                 :             :                 }
     756                 :             :         }
     757                 :             : }
     758                 :             : 
     759                 :             : static void
     760                 :           0 : write_pidfile(const char *filename, pid_t pid)
     761                 :             : {
     762                 :             :         FILE *fp;
     763                 :             :         int fd;
     764                 :             : 
     765                 :           0 :         fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666);
     766         [ #  # ]:           0 :         if (fd < 0)
     767                 :           0 :                 fp = NULL;
     768                 :             :         else
     769                 :           0 :                 fp = fdopen(fd, "w");
     770                 :             : 
     771         [ #  # ]:           0 :         if (fp == NULL)
     772                 :           0 :                 fatale("unable to open pidfile '%s' for writing", filename);
     773                 :             : 
     774                 :           0 :         fprintf(fp, "%d\n", pid);
     775                 :             : 
     776         [ #  # ]:           0 :         if (fclose(fp))
     777                 :           0 :                 fatale("unable to close pidfile '%s'", filename);
     778                 :           0 : }
     779                 :             : 
     780                 :             : static void
     781                 :           0 : remove_pidfile(const char *filename)
     782                 :             : {
     783   [ #  #  #  # ]:           0 :         if (unlink(filename) < 0 && errno != ENOENT)
     784                 :           0 :                 fatale("cannot remove pidfile '%s'", filename);
     785                 :           0 : }
     786                 :             : 
     787                 :             : static void
     788                 :           0 : daemonize(void)
     789                 :             : {
     790                 :           0 :         int notify_fd = -1;
     791                 :             :         pid_t pid;
     792                 :             :         sigset_t mask;
     793                 :             :         sigset_t oldmask;
     794                 :             : 
     795                 :           0 :         debug("Detaching to start %s...\n", startas);
     796                 :             : 
     797                 :             :         /* Block SIGCHLD to allow waiting for the child process while it is
     798                 :             :          * performing actions, such as creating a pidfile. */
     799                 :           0 :         sigemptyset(&mask);
     800                 :           0 :         sigaddset(&mask, SIGCHLD);
     801         [ #  # ]:           0 :         if (sigprocmask(SIG_BLOCK, &mask, &oldmask) < 0)
     802                 :           0 :                 fatale("cannot block SIGCHLD");
     803                 :             : 
     804         [ #  # ]:           0 :         if (notify_await)
     805                 :           0 :                 notify_fd = create_notify_socket();
     806                 :             : 
     807                 :           0 :         pid = fork();
     808         [ #  # ]:           0 :         if (pid < 0)
     809                 :           0 :                 fatale("unable to do first fork");
     810         [ #  # ]:           0 :         else if (pid) { /* First Parent. */
     811                 :             :                 /* Wait for the second parent to exit, so that if we need to
     812                 :             :                  * perform any actions there, like creating a pidfile, we do
     813                 :             :                  * not suffer from race conditions on return. */
     814                 :           0 :                 wait_for_child(pid);
     815                 :             : 
     816         [ #  # ]:           0 :                 if (notify_await) {
     817                 :             :                         /* Wait for a readiness notification from the second
     818                 :             :                          * child, so that we can safely exit when the service
     819                 :             :                          * is up. */
     820                 :           0 :                         wait_for_notify(notify_fd);
     821                 :           0 :                         close(notify_fd);
     822                 :           0 :                         cleanup_socket_dir();
     823                 :             :                 }
     824                 :             : 
     825                 :           0 :                 _exit(0);
     826                 :             :         }
     827                 :             : 
     828                 :             :         /* Close the notification socket, even though it is close-on-exec. */
     829         [ #  # ]:           0 :         if (notify_await)
     830                 :           0 :                 close(notify_fd);
     831                 :             : 
     832                 :             :         /* Create a new session. */
     833         [ #  # ]:           0 :         if (setsid() < 0)
     834                 :           0 :                 fatale("cannot set session ID");
     835                 :             : 
     836                 :           0 :         pid = fork();
     837         [ #  # ]:           0 :         if (pid < 0)
     838                 :           0 :                 fatale("unable to do second fork");
     839         [ #  # ]:           0 :         else if (pid) { /* Second parent. */
     840                 :             :                 /* Set a default umask for dumb programs, which might get
     841                 :             :                  * overridden by the --umask option later on, so that we get
     842                 :             :                  * a defined umask when creating the pidfile. */
     843                 :           0 :                 umask(022);
     844                 :             : 
     845   [ #  #  #  # ]:           0 :                 if (mpidfile && pidfile != NULL)
     846                 :             :                         /* User wants _us_ to make the pidfile. */
     847                 :           0 :                         write_pidfile(pidfile, pid);
     848                 :             : 
     849                 :           0 :                 _exit(0);
     850                 :             :         }
     851                 :             : 
     852         [ #  # ]:           0 :         if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
     853                 :           0 :                 fatale("cannot restore signal mask");
     854                 :             : 
     855                 :           0 :         debug("Detaching complete...\n");
     856                 :           0 : }
     857                 :             : 
     858                 :             : static void
     859                 :           0 : pid_list_push(struct pid_list **list, pid_t pid)
     860                 :             : {
     861                 :             :         struct pid_list *p;
     862                 :             : 
     863                 :           0 :         p = xmalloc(sizeof(*p));
     864                 :           0 :         p->next = *list;
     865                 :           0 :         p->pid = pid;
     866                 :           0 :         *list = p;
     867                 :           0 : }
     868                 :             : 
     869                 :             : static void
     870                 :           0 : pid_list_free(struct pid_list **list)
     871                 :             : {
     872                 :             :         struct pid_list *here, *next;
     873                 :             : 
     874         [ #  # ]:           0 :         for (here = *list; here != NULL; here = next) {
     875                 :           0 :                 next = here->next;
     876                 :           0 :                 free(here);
     877                 :             :         }
     878                 :             : 
     879                 :           0 :         *list = NULL;
     880                 :           0 : }
     881                 :             : 
     882                 :             : static void
     883                 :           0 : usage(void)
     884                 :             : {
     885                 :           0 :         printf(
     886                 :             : "Usage: start-stop-daemon [<option>...] <command>\n"
     887                 :             : "\n");
     888                 :             : 
     889                 :           0 :         printf(
     890                 :             : "Commands:\n"
     891                 :             : "  -S, --start -- <argument>...  start a program and pass <arguments> to it\n"
     892                 :             : "  -K, --stop                    stop a program\n"
     893                 :             : "  -T, --status                  get the program status\n"
     894                 :             : "  -H, --help                    print help information\n"
     895                 :             : "  -V, --version                 print version\n"
     896                 :             : "\n");
     897                 :             : 
     898                 :           0 :         printf(
     899                 :             : "Matching options (at least one is required):\n"
     900                 :             : "      --pid <pid>               pid to check\n"
     901                 :             : "      --ppid <ppid>             parent pid to check\n"
     902                 :             : "  -p, --pidfile <pid-file>      pid file to check\n"
     903                 :             : "  -x, --exec <executable>       program to start/check if it is running\n"
     904                 :             : "  -n, --name <process-name>     process name to check\n"
     905                 :             : "  -u, --user <username|uid>     process owner to check\n"
     906                 :             : "\n");
     907                 :             : 
     908                 :           0 :         printf(
     909                 :             : "Options:\n"
     910                 :             : "  -g, --group <group|gid>       run process as this group\n"
     911                 :             : "  -c, --chuid <name|uid[:group|gid]>\n"
     912                 :             : "                                change to this user/group before starting\n"
     913                 :             : "                                  process\n"
     914                 :             : "  -s, --signal <signal>         signal to send (default TERM)\n"
     915                 :             : "  -a, --startas <pathname>      program to start (default is <executable>)\n"
     916                 :             : "  -r, --chroot <directory>      chroot to <directory> before starting\n"
     917                 :             : "  -d, --chdir <directory>       change to <directory> (default is /)\n"
     918                 :             : "  -N, --nicelevel <incr>        add incr to the process' nice level\n"
     919                 :             : "  -P, --procsched <policy[:prio]>\n"
     920                 :             : "                                use <policy> with <prio> for the kernel\n"
     921                 :             : "                                  process scheduler (default prio is 0)\n"
     922                 :             : "  -I, --iosched <class[:prio]>  use <class> with <prio> to set the IO\n"
     923                 :             : "                                  scheduler (default prio is 4)\n"
     924                 :             : "  -k, --umask <mask>            change the umask to <mask> before starting\n"
     925                 :             : "  -b, --background              force the process to detach\n"
     926                 :             : "      --notify-await            wait for a readiness notification\n"
     927                 :             : "      --notify-timeout <int>    timeout after <int> seconds of notify wait\n"
     928                 :             : "  -C, --no-close                do not close any file descriptor\n"
     929                 :             : "  -O, --output <filename>       send stdout and stderr to <filename>\n"
     930                 :             : "  -m, --make-pidfile            create the pidfile before starting\n"
     931                 :             : "      --remove-pidfile          delete the pidfile after stopping\n"
     932                 :             : "  -R, --retry <schedule>        check whether processes die, and retry\n"
     933                 :             : "  -t, --test                    test mode, don't do anything\n"
     934                 :             : "  -o, --oknodo                  exit status 0 (not 1) if nothing done\n"
     935                 :             : "  -q, --quiet                   be more quiet\n"
     936                 :             : "  -v, --verbose                 be more verbose\n"
     937                 :             : "\n");
     938                 :             : 
     939                 :           0 :         printf(
     940                 :             : "Retry <schedule> is <item>|/<item>/... where <item> is one of\n"
     941                 :             : " -<signal-num>|[-]<signal-name>  send that signal\n"
     942                 :             : " <timeout>                       wait that many seconds\n"
     943                 :             : " forever                         repeat remainder forever\n"
     944                 :             : "or <schedule> may be just <timeout>, meaning <signal>/<timeout>/KILL/<timeout>\n"
     945                 :             : "\n");
     946                 :             : 
     947                 :           0 :         printf(
     948                 :             : "The process scheduler <policy> can be one of:\n"
     949                 :             : "  other, fifo or rr\n"
     950                 :             : "\n");
     951                 :             : 
     952                 :           0 :         printf(
     953                 :             : "The IO scheduler <class> can be one of:\n"
     954                 :             : "  real-time, best-effort or idle\n"
     955                 :             : "\n");
     956                 :             : 
     957                 :           0 :         printf(
     958                 :             : "Exit status:\n"
     959                 :             : "  0 = done\n"
     960                 :             : "  1 = nothing done (=> 0 if --oknodo)\n"
     961                 :             : "  2 = with --retry, processes would not die\n"
     962                 :             : "  3 = trouble\n"
     963                 :             : "Exit status with --status:\n"
     964                 :             : "  0 = program is running\n"
     965                 :             : "  1 = program is not running and the pid file exists\n"
     966                 :             : "  3 = program is not running\n"
     967                 :             : "  4 = unable to determine status\n");
     968                 :           0 : }
     969                 :             : 
     970                 :             : static void
     971                 :           0 : do_version(void)
     972                 :             : {
     973                 :           0 :         printf("start-stop-daemon %s for Debian\n\n", VERSION);
     974                 :             : 
     975                 :           0 :         printf("Written by Marek Michalkiewicz, public domain.\n");
     976                 :           0 : }
     977                 :             : 
     978                 :             : static void LIBCOMPAT_ATTR_NORET
     979                 :           0 : badusage(const char *msg)
     980                 :             : {
     981         [ #  # ]:           0 :         if (msg)
     982                 :           0 :                 fprintf(stderr, "%s: %s\n", progname, msg);
     983                 :           0 :         fprintf(stderr, "Try '%s --help' for more information.\n", progname);
     984                 :             : 
     985         [ #  # ]:           0 :         if (action == ACTION_STATUS)
     986                 :           0 :                 exit(STATUS_UNKNOWN);
     987                 :             :         else
     988                 :           0 :                 exit(3);
     989                 :             : }
     990                 :             : 
     991                 :             : struct sigpair {
     992                 :             :         const char *name;
     993                 :             :         int signal;
     994                 :             : };
     995                 :             : 
     996                 :             : static const struct sigpair siglist[] = {
     997                 :             :         { "ABRT",     SIGABRT },
     998                 :             :         { "ALRM",     SIGALRM },
     999                 :             :         { "FPE",      SIGFPE  },
    1000                 :             :         { "HUP",      SIGHUP  },
    1001                 :             :         { "ILL",      SIGILL  },
    1002                 :             :         { "INT",      SIGINT  },
    1003                 :             :         { "KILL",     SIGKILL },
    1004                 :             :         { "PIPE",     SIGPIPE },
    1005                 :             :         { "QUIT",     SIGQUIT },
    1006                 :             :         { "SEGV",     SIGSEGV },
    1007                 :             :         { "TERM",     SIGTERM },
    1008                 :             :         { "USR1",     SIGUSR1 },
    1009                 :             :         { "USR2",     SIGUSR2 },
    1010                 :             :         { "CHLD",     SIGCHLD },
    1011                 :             :         { "CONT",     SIGCONT },
    1012                 :             :         { "STOP",     SIGSTOP },
    1013                 :             :         { "TSTP",     SIGTSTP },
    1014                 :             :         { "TTIN",     SIGTTIN },
    1015                 :             :         { "TTOU",     SIGTTOU }
    1016                 :             : };
    1017                 :             : 
    1018                 :             : static int
    1019                 :           0 : parse_pid(const char *pid_str, int *pid_num)
    1020                 :             : {
    1021         [ #  # ]:           0 :         if (parse_unsigned(pid_str, 10, pid_num) != 0)
    1022                 :           0 :                 return -1;
    1023         [ #  # ]:           0 :         if (*pid_num == 0)
    1024                 :           0 :                 return -1;
    1025                 :             : 
    1026                 :           0 :         return 0;
    1027                 :             : }
    1028                 :             : 
    1029                 :             : static int
    1030                 :           0 : parse_signal(const char *sig_str, int *sig_num)
    1031                 :             : {
    1032                 :             :         unsigned int i;
    1033                 :             : 
    1034         [ #  # ]:           0 :         if (parse_unsigned(sig_str, 10, sig_num) == 0)
    1035                 :           0 :                 return 0;
    1036                 :             : 
    1037         [ #  # ]:           0 :         for (i = 0; i < array_count(siglist); i++) {
    1038         [ #  # ]:           0 :                 if (strcmp(sig_str, siglist[i].name) == 0) {
    1039                 :           0 :                         *sig_num = siglist[i].signal;
    1040                 :           0 :                         return 0;
    1041                 :             :                 }
    1042                 :             :         }
    1043                 :           0 :         return -1;
    1044                 :             : }
    1045                 :             : 
    1046                 :             : static int
    1047                 :           0 : parse_umask(const char *string, int *value_r)
    1048                 :             : {
    1049                 :           0 :         return parse_unsigned(string, 0, value_r);
    1050                 :             : }
    1051                 :             : 
    1052                 :             : static void
    1053                 :           0 : validate_proc_schedule(void)
    1054                 :             : {
    1055                 :             : #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
    1056                 :             :         int prio_min, prio_max;
    1057                 :             : 
    1058                 :           0 :         prio_min = sched_get_priority_min(proc_sched->policy);
    1059                 :           0 :         prio_max = sched_get_priority_max(proc_sched->policy);
    1060                 :             : 
    1061         [ #  # ]:           0 :         if (proc_sched->priority < prio_min)
    1062                 :           0 :                 badusage("process scheduler priority less than min");
    1063         [ #  # ]:           0 :         if (proc_sched->priority > prio_max)
    1064                 :           0 :                 badusage("process scheduler priority greater than max");
    1065                 :             : #endif
    1066                 :           0 : }
    1067                 :             : 
    1068                 :             : static void
    1069                 :           0 : parse_proc_schedule(const char *string)
    1070                 :             : {
    1071                 :             :         char *policy_str;
    1072                 :             :         size_t policy_len;
    1073                 :           0 :         int prio = 0;
    1074                 :             : 
    1075                 :           0 :         policy_len = strcspn(string, ":");
    1076                 :           0 :         policy_str = xstrndup(string, policy_len);
    1077                 :             : 
    1078   [ #  #  #  # ]:           0 :         if (string[policy_len] == ':' &&
    1079                 :           0 :             parse_unsigned(string + policy_len + 1, 10, &prio) != 0)
    1080                 :           0 :                 fatale("invalid process scheduler priority");
    1081                 :             : 
    1082                 :           0 :         proc_sched = xmalloc(sizeof(*proc_sched));
    1083                 :           0 :         proc_sched->policy_name = policy_str;
    1084                 :             : 
    1085         [ #  # ]:           0 :         if (strcmp(policy_str, "other") == 0) {
    1086                 :           0 :                 proc_sched->policy = SCHED_OTHER;
    1087                 :           0 :                 proc_sched->priority = 0;
    1088         [ #  # ]:           0 :         } else if (strcmp(policy_str, "fifo") == 0) {
    1089                 :           0 :                 proc_sched->policy = SCHED_FIFO;
    1090                 :           0 :                 proc_sched->priority = prio;
    1091         [ #  # ]:           0 :         } else if (strcmp(policy_str, "rr") == 0) {
    1092                 :           0 :                 proc_sched->policy = SCHED_RR;
    1093                 :           0 :                 proc_sched->priority = prio;
    1094                 :             :         } else
    1095                 :           0 :                 badusage("invalid process scheduler policy");
    1096                 :             : 
    1097                 :           0 :         validate_proc_schedule();
    1098                 :           0 : }
    1099                 :             : 
    1100                 :             : static void
    1101                 :           0 : parse_io_schedule(const char *string)
    1102                 :             : {
    1103                 :             :         char *class_str;
    1104                 :             :         size_t class_len;
    1105                 :           0 :         int prio = 4;
    1106                 :             : 
    1107                 :           0 :         class_len = strcspn(string, ":");
    1108                 :           0 :         class_str = xstrndup(string, class_len);
    1109                 :             : 
    1110   [ #  #  #  # ]:           0 :         if (string[class_len] == ':' &&
    1111                 :           0 :             parse_unsigned(string + class_len + 1, 10, &prio) != 0)
    1112                 :           0 :                 fatale("invalid IO scheduler priority");
    1113                 :             : 
    1114                 :           0 :         io_sched = xmalloc(sizeof(*io_sched));
    1115                 :           0 :         io_sched->policy_name = class_str;
    1116                 :             : 
    1117         [ #  # ]:           0 :         if (strcmp(class_str, "real-time") == 0) {
    1118                 :           0 :                 io_sched->policy = IOPRIO_CLASS_RT;
    1119                 :           0 :                 io_sched->priority = prio;
    1120         [ #  # ]:           0 :         } else if (strcmp(class_str, "best-effort") == 0) {
    1121                 :           0 :                 io_sched->policy = IOPRIO_CLASS_BE;
    1122                 :           0 :                 io_sched->priority = prio;
    1123         [ #  # ]:           0 :         } else if (strcmp(class_str, "idle") == 0) {
    1124                 :           0 :                 io_sched->policy = IOPRIO_CLASS_IDLE;
    1125                 :           0 :                 io_sched->priority = 7;
    1126                 :             :         } else
    1127                 :           0 :                 badusage("invalid IO scheduler policy");
    1128                 :             : 
    1129         [ #  # ]:           0 :         if (io_sched->priority < IO_SCHED_PRIO_MIN)
    1130                 :           0 :                 badusage("IO scheduler priority less than min");
    1131         [ #  # ]:           0 :         if (io_sched->priority > IO_SCHED_PRIO_MAX)
    1132                 :           0 :                 badusage("IO scheduler priority greater than max");
    1133                 :           0 : }
    1134                 :             : 
    1135                 :             : static void
    1136                 :           0 : set_proc_schedule(struct res_schedule *sched)
    1137                 :             : {
    1138                 :             : #if defined(_POSIX_PRIORITY_SCHEDULING) && _POSIX_PRIORITY_SCHEDULING > 0
    1139                 :             :         struct sched_param param;
    1140                 :             : 
    1141                 :           0 :         param.sched_priority = sched->priority;
    1142                 :             : 
    1143         [ #  # ]:           0 :         if (sched_setscheduler(getpid(), sched->policy, &param) < 0)
    1144                 :           0 :                 fatale("unable to set process scheduler");
    1145                 :             : #endif
    1146                 :           0 : }
    1147                 :             : 
    1148                 :             : #ifdef HAVE_IOPRIO_SET
    1149                 :             : static inline int
    1150                 :           0 : ioprio_set(int which, int who, int ioprio)
    1151                 :             : {
    1152                 :           0 :         return syscall(SYS_ioprio_set, which, who, ioprio);
    1153                 :             : }
    1154                 :             : #endif
    1155                 :             : 
    1156                 :             : static void
    1157                 :           0 : set_io_schedule(struct res_schedule *sched)
    1158                 :             : {
    1159                 :             : #ifdef HAVE_IOPRIO_SET
    1160                 :             :         int io_sched_mask;
    1161                 :             : 
    1162                 :           0 :         io_sched_mask = IOPRIO_PRIO_VALUE(sched->policy, sched->priority);
    1163         [ #  # ]:           0 :         if (ioprio_set(IOPRIO_WHO_PROCESS, getpid(), io_sched_mask) < 0)
    1164                 :           0 :                 warning("unable to alter IO priority to mask %i (%s)\n",
    1165                 :           0 :                         io_sched_mask, strerror(errno));
    1166                 :             : #endif
    1167                 :           0 : }
    1168                 :             : 
    1169                 :             : static void
    1170                 :           0 : parse_schedule_item(const char *string, struct schedule_item *item)
    1171                 :             : {
    1172                 :             :         const char *after_hyph;
    1173                 :             : 
    1174         [ #  # ]:           0 :         if (strcmp(string, "forever") == 0) {
    1175                 :           0 :                 item->type = sched_forever;
    1176         [ #  # ]:           0 :         } else if (isdigit(string[0])) {
    1177                 :           0 :                 item->type = sched_timeout;
    1178         [ #  # ]:           0 :                 if (parse_unsigned(string, 10, &item->value) != 0)
    1179                 :           0 :                         badusage("invalid timeout value in schedule");
    1180   [ #  #  #  # ]:           0 :         } else if ((after_hyph = string + (string[0] == '-')) &&
    1181                 :           0 :                    parse_signal(after_hyph, &item->value) == 0) {
    1182                 :           0 :                 item->type = sched_signal;
    1183                 :             :         } else {
    1184                 :           0 :                 badusage("invalid schedule item (must be [-]<signal-name>, "
    1185                 :             :                          "-<signal-number>, <timeout> or 'forever'");
    1186                 :             :         }
    1187                 :           0 : }
    1188                 :             : 
    1189                 :             : static void
    1190                 :           0 : parse_schedule(const char *schedule_str)
    1191                 :             : {
    1192                 :             :         const char *slash;
    1193                 :             :         int count;
    1194                 :             : 
    1195                 :           0 :         count = 0;
    1196         [ #  # ]:           0 :         for (slash = schedule_str; *slash; slash++)
    1197         [ #  # ]:           0 :                 if (*slash == '/')
    1198                 :           0 :                         count++;
    1199                 :             : 
    1200         [ #  # ]:           0 :         schedule_length = (count == 0) ? 4 : count + 1;
    1201                 :           0 :         schedule = xmalloc(sizeof(*schedule) * schedule_length);
    1202                 :             : 
    1203         [ #  # ]:           0 :         if (count == 0) {
    1204                 :           0 :                 schedule[0].type = sched_signal;
    1205                 :           0 :                 schedule[0].value = signal_nr;
    1206                 :           0 :                 parse_schedule_item(schedule_str, &schedule[1]);
    1207         [ #  # ]:           0 :                 if (schedule[1].type != sched_timeout) {
    1208                 :           0 :                         badusage("--retry takes timeout, or schedule list"
    1209                 :             :                                  " of at least two items");
    1210                 :             :                 }
    1211                 :           0 :                 schedule[2].type = sched_signal;
    1212                 :           0 :                 schedule[2].value = SIGKILL;
    1213                 :           0 :                 schedule[3] = schedule[1];
    1214                 :             :         } else {
    1215                 :             :                 int repeatat;
    1216                 :             : 
    1217                 :           0 :                 count = 0;
    1218                 :           0 :                 repeatat = -1;
    1219         [ #  # ]:           0 :                 while (*schedule_str) {
    1220                 :             :                         char item_buf[20];
    1221                 :             :                         size_t str_len;
    1222                 :             : 
    1223                 :           0 :                         slash = strchrnul(schedule_str, '/');
    1224                 :           0 :                         str_len = (size_t)(slash - schedule_str);
    1225         [ #  # ]:           0 :                         if (str_len >= sizeof(item_buf))
    1226                 :           0 :                                 badusage("invalid schedule item: far too long"
    1227                 :             :                                          " (you must delimit items with slashes)");
    1228                 :           0 :                         memcpy(item_buf, schedule_str, str_len);
    1229                 :           0 :                         item_buf[str_len] = '\0';
    1230         [ #  # ]:           0 :                         schedule_str = *slash ? slash + 1 : slash;
    1231                 :             : 
    1232                 :           0 :                         parse_schedule_item(item_buf, &schedule[count]);
    1233         [ #  # ]:           0 :                         if (schedule[count].type == sched_forever) {
    1234         [ #  # ]:           0 :                                 if (repeatat >= 0)
    1235                 :           0 :                                         badusage("invalid schedule: 'forever'"
    1236                 :             :                                                  " appears more than once");
    1237                 :           0 :                                 repeatat = count;
    1238                 :           0 :                                 continue;
    1239                 :             :                         }
    1240                 :           0 :                         count++;
    1241                 :             :                 }
    1242         [ #  # ]:           0 :                 if (repeatat == count)
    1243                 :           0 :                         badusage("invalid schedule: 'forever' appears last, "
    1244                 :             :                                  "nothing to repeat");
    1245         [ #  # ]:           0 :                 if (repeatat >= 0) {
    1246                 :           0 :                         schedule[count].type = sched_goto;
    1247                 :           0 :                         schedule[count].value = repeatat;
    1248                 :           0 :                         count++;
    1249                 :             :                 }
    1250         [ #  # ]:           0 :                 if (count != schedule_length)
    1251                 :           0 :                         BUG("count=%d != schedule_length=%d",
    1252                 :             :                             count, schedule_length);
    1253                 :             :         }
    1254                 :           0 : }
    1255                 :             : 
    1256                 :             : static void
    1257                 :           0 : set_action(enum action_code new_action)
    1258                 :             : {
    1259         [ #  # ]:           0 :         if (action == new_action)
    1260                 :           0 :                 return;
    1261                 :             : 
    1262         [ #  # ]:           0 :         if (action != ACTION_NONE)
    1263                 :           0 :                 badusage("only one command can be specified");
    1264                 :             : 
    1265                 :           0 :         action = new_action;
    1266                 :             : }
    1267                 :             : 
    1268                 :             : #define OPT_PID         500
    1269                 :             : #define OPT_PPID        501
    1270                 :             : #define OPT_RM_PIDFILE  502
    1271                 :             : #define OPT_NOTIFY_AWAIT        503
    1272                 :             : #define OPT_NOTIFY_TIMEOUT      504
    1273                 :             : 
    1274                 :             : static void
    1275                 :           0 : parse_options(int argc, char * const *argv)
    1276                 :             : {
    1277                 :             :         static struct option longopts[] = {
    1278                 :             :                 { "help",       0, NULL, 'H'},
    1279                 :             :                 { "stop",       0, NULL, 'K'},
    1280                 :             :                 { "start",      0, NULL, 'S'},
    1281                 :             :                 { "status",     0, NULL, 'T'},
    1282                 :             :                 { "version",    0, NULL, 'V'},
    1283                 :             :                 { "startas",    1, NULL, 'a'},
    1284                 :             :                 { "name",       1, NULL, 'n'},
    1285                 :             :                 { "oknodo",     0, NULL, 'o'},
    1286                 :             :                 { "pid",        1, NULL, OPT_PID},
    1287                 :             :                 { "ppid",       1, NULL, OPT_PPID},
    1288                 :             :                 { "pidfile",    1, NULL, 'p'},
    1289                 :             :                 { "quiet",      0, NULL, 'q'},
    1290                 :             :                 { "signal",     1, NULL, 's'},
    1291                 :             :                 { "test",       0, NULL, 't'},
    1292                 :             :                 { "user",       1, NULL, 'u'},
    1293                 :             :                 { "group",      1, NULL, 'g'},
    1294                 :             :                 { "chroot",     1, NULL, 'r'},
    1295                 :             :                 { "verbose",    0, NULL, 'v'},
    1296                 :             :                 { "exec",       1, NULL, 'x'},
    1297                 :             :                 { "chuid",      1, NULL, 'c'},
    1298                 :             :                 { "nicelevel",          1, NULL, 'N'},
    1299                 :             :                 { "procsched",          1, NULL, 'P'},
    1300                 :             :                 { "iosched",    1, NULL, 'I'},
    1301                 :             :                 { "umask",      1, NULL, 'k'},
    1302                 :             :                 { "background",         0, NULL, 'b'},
    1303                 :             :                 { "notify-await", 0, NULL, OPT_NOTIFY_AWAIT},
    1304                 :             :                 { "notify-timeout", 1, NULL, OPT_NOTIFY_TIMEOUT},
    1305                 :             :                 { "no-close",   0, NULL, 'C'},
    1306                 :             :                 { "output",     1, NULL, 'O'},
    1307                 :             :                 { "make-pidfile", 0, NULL, 'm'},
    1308                 :             :                 { "remove-pidfile", 0, NULL, OPT_RM_PIDFILE},
    1309                 :             :                 { "retry",      1, NULL, 'R'},
    1310                 :             :                 { "chdir",      1, NULL, 'd'},
    1311                 :             :                 { NULL,           0, NULL, 0  }
    1312                 :             :         };
    1313                 :           0 :         const char *pid_str = NULL;
    1314                 :           0 :         const char *ppid_str = NULL;
    1315                 :           0 :         const char *umask_str = NULL;
    1316                 :           0 :         const char *signal_str = NULL;
    1317                 :           0 :         const char *schedule_str = NULL;
    1318                 :           0 :         const char *proc_schedule_str = NULL;
    1319                 :           0 :         const char *io_schedule_str = NULL;
    1320                 :           0 :         const char *notify_timeout_str = NULL;
    1321                 :             :         size_t changeuser_len;
    1322                 :             :         int c;
    1323                 :             : 
    1324                 :             :         for (;;) {
    1325                 :           0 :                 c = getopt_long(argc, argv,
    1326                 :             :                                 "HKSVTa:n:op:qr:s:tu:vx:c:N:P:I:k:bCO:mR:g:d:",
    1327                 :             :                                 longopts, NULL);
    1328         [ #  # ]:           0 :                 if (c == -1)
    1329                 :           0 :                         break;
    1330   [ #  #  #  #  :           0 :                 switch (c) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1331                 :           0 :                 case 'H':  /* --help */
    1332                 :           0 :                         usage();
    1333                 :           0 :                         exit(0);
    1334                 :           0 :                 case 'K':  /* --stop */
    1335                 :           0 :                         set_action(ACTION_STOP);
    1336                 :           0 :                         break;
    1337                 :           0 :                 case 'S':  /* --start */
    1338                 :           0 :                         set_action(ACTION_START);
    1339                 :           0 :                         break;
    1340                 :           0 :                 case 'T':  /* --status */
    1341                 :           0 :                         set_action(ACTION_STATUS);
    1342                 :           0 :                         break;
    1343                 :           0 :                 case 'V':  /* --version */
    1344                 :           0 :                         do_version();
    1345                 :           0 :                         exit(0);
    1346                 :           0 :                 case 'a':  /* --startas <pathname> */
    1347                 :           0 :                         startas = optarg;
    1348                 :           0 :                         break;
    1349                 :           0 :                 case 'n':  /* --name <process-name> */
    1350                 :           0 :                         match_mode |= MATCH_NAME;
    1351                 :           0 :                         cmdname = optarg;
    1352                 :           0 :                         break;
    1353                 :           0 :                 case 'o':  /* --oknodo */
    1354                 :           0 :                         exitnodo = 0;
    1355                 :           0 :                         break;
    1356                 :           0 :                 case OPT_PID: /* --pid <pid> */
    1357                 :           0 :                         match_mode |= MATCH_PID;
    1358                 :           0 :                         pid_str = optarg;
    1359                 :           0 :                         break;
    1360                 :           0 :                 case OPT_PPID: /* --ppid <ppid> */
    1361                 :           0 :                         match_mode |= MATCH_PPID;
    1362                 :           0 :                         ppid_str = optarg;
    1363                 :           0 :                         break;
    1364                 :           0 :                 case 'p':  /* --pidfile <pid-file> */
    1365                 :           0 :                         match_mode |= MATCH_PIDFILE;
    1366                 :           0 :                         pidfile = optarg;
    1367                 :           0 :                         break;
    1368                 :           0 :                 case 'q':  /* --quiet */
    1369                 :           0 :                         quietmode = true;
    1370                 :           0 :                         break;
    1371                 :           0 :                 case 's':  /* --signal <signal> */
    1372                 :           0 :                         signal_str = optarg;
    1373                 :           0 :                         break;
    1374                 :           0 :                 case 't':  /* --test */
    1375                 :           0 :                         testmode = true;
    1376                 :           0 :                         break;
    1377                 :           0 :                 case 'u':  /* --user <username>|<uid> */
    1378                 :           0 :                         match_mode |= MATCH_USER;
    1379                 :           0 :                         userspec = optarg;
    1380                 :           0 :                         break;
    1381                 :           0 :                 case 'v':  /* --verbose */
    1382                 :           0 :                         quietmode = -1;
    1383                 :           0 :                         break;
    1384                 :           0 :                 case 'x':  /* --exec <executable> */
    1385                 :           0 :                         match_mode |= MATCH_EXEC;
    1386                 :           0 :                         execname = optarg;
    1387                 :           0 :                         break;
    1388                 :           0 :                 case 'c':  /* --chuid <username>|<uid> */
    1389                 :           0 :                         free(changeuser);
    1390                 :             :                         /* We copy the string just in case we need the
    1391                 :             :                          * argument later. */
    1392                 :           0 :                         changeuser_len = strcspn(optarg, ":");
    1393                 :           0 :                         changeuser = xstrndup(optarg, changeuser_len);
    1394         [ #  # ]:           0 :                         if (optarg[changeuser_len] == ':') {
    1395         [ #  # ]:           0 :                                 if (optarg[changeuser_len + 1] == '\0')
    1396                 :           0 :                                         fatal("missing group name");
    1397                 :           0 :                                 changegroup = optarg + changeuser_len + 1;
    1398                 :             :                         }
    1399                 :           0 :                         break;
    1400                 :           0 :                 case 'g':  /* --group <group>|<gid> */
    1401                 :           0 :                         changegroup = optarg;
    1402                 :           0 :                         break;
    1403                 :           0 :                 case 'r':  /* --chroot /new/root */
    1404                 :           0 :                         changeroot = optarg;
    1405                 :           0 :                         break;
    1406                 :           0 :                 case 'N':  /* --nice */
    1407                 :           0 :                         nicelevel = atoi(optarg);
    1408                 :           0 :                         break;
    1409                 :           0 :                 case 'P':  /* --procsched */
    1410                 :           0 :                         proc_schedule_str = optarg;
    1411                 :           0 :                         break;
    1412                 :           0 :                 case 'I':  /* --iosched */
    1413                 :           0 :                         io_schedule_str = optarg;
    1414                 :           0 :                         break;
    1415                 :           0 :                 case 'k':  /* --umask <mask> */
    1416                 :           0 :                         umask_str = optarg;
    1417                 :           0 :                         break;
    1418                 :           0 :                 case 'b':  /* --background */
    1419                 :           0 :                         background = true;
    1420                 :           0 :                         break;
    1421                 :           0 :                 case OPT_NOTIFY_AWAIT:
    1422                 :           0 :                         notify_await = true;
    1423                 :           0 :                         break;
    1424                 :           0 :                 case OPT_NOTIFY_TIMEOUT:
    1425                 :           0 :                         notify_timeout_str = optarg;
    1426                 :           0 :                         break;
    1427                 :           0 :                 case 'C': /* --no-close */
    1428                 :           0 :                         close_io = false;
    1429                 :           0 :                         break;
    1430                 :           0 :                 case 'O': /* --outout <filename> */
    1431                 :           0 :                         output_io = optarg;
    1432                 :           0 :                         break;
    1433                 :           0 :                 case 'm':  /* --make-pidfile */
    1434                 :           0 :                         mpidfile = true;
    1435                 :           0 :                         break;
    1436                 :           0 :                 case OPT_RM_PIDFILE: /* --remove-pidfile */
    1437                 :           0 :                         rpidfile = true;
    1438                 :           0 :                         break;
    1439                 :           0 :                 case 'R':  /* --retry <schedule>|<timeout> */
    1440                 :           0 :                         schedule_str = optarg;
    1441                 :           0 :                         break;
    1442                 :           0 :                 case 'd':  /* --chdir /new/dir */
    1443                 :           0 :                         changedir = optarg;
    1444                 :           0 :                         break;
    1445                 :           0 :                 default:
    1446                 :             :                         /* Message printed by getopt. */
    1447                 :           0 :                         badusage(NULL);
    1448                 :             :                 }
    1449                 :             :         }
    1450                 :             : 
    1451         [ #  # ]:           0 :         if (pid_str != NULL) {
    1452         [ #  # ]:           0 :                 if (parse_pid(pid_str, &match_pid) != 0)
    1453                 :           0 :                         badusage("pid value must be a number greater than 0");
    1454                 :             :         }
    1455                 :             : 
    1456         [ #  # ]:           0 :         if (ppid_str != NULL) {
    1457         [ #  # ]:           0 :                 if (parse_pid(ppid_str, &match_ppid) != 0)
    1458                 :           0 :                         badusage("ppid value must be a number greater than 0");
    1459                 :             :         }
    1460                 :             : 
    1461         [ #  # ]:           0 :         if (signal_str != NULL) {
    1462         [ #  # ]:           0 :                 if (parse_signal(signal_str, &signal_nr) != 0)
    1463                 :           0 :                         badusage("signal value must be numeric or name"
    1464                 :             :                                  " of signal (KILL, INT, ...)");
    1465                 :             :         }
    1466                 :             : 
    1467         [ #  # ]:           0 :         if (schedule_str != NULL) {
    1468                 :           0 :                 parse_schedule(schedule_str);
    1469                 :             :         }
    1470                 :             : 
    1471         [ #  # ]:           0 :         if (proc_schedule_str != NULL)
    1472                 :           0 :                 parse_proc_schedule(proc_schedule_str);
    1473                 :             : 
    1474         [ #  # ]:           0 :         if (io_schedule_str != NULL)
    1475                 :           0 :                 parse_io_schedule(io_schedule_str);
    1476                 :             : 
    1477         [ #  # ]:           0 :         if (umask_str != NULL) {
    1478         [ #  # ]:           0 :                 if (parse_umask(umask_str, &umask_value) != 0)
    1479                 :           0 :                         badusage("umask value must be a positive number");
    1480                 :             :         }
    1481                 :             : 
    1482   [ #  #  #  # ]:           0 :         if (output_io != NULL && output_io[0] != '/')
    1483                 :           0 :                 badusage("--output file needs to be an absolute filename");
    1484                 :             : 
    1485         [ #  # ]:           0 :         if (notify_timeout_str != NULL)
    1486         [ #  # ]:           0 :                 if (parse_unsigned(notify_timeout_str, 10, &notify_timeout) != 0)
    1487                 :           0 :                         badusage("invalid notify timeout value");
    1488                 :             : 
    1489         [ #  # ]:           0 :         if (action == ACTION_NONE)
    1490                 :           0 :                 badusage("need one of --start or --stop or --status");
    1491                 :             : 
    1492         [ #  # ]:           0 :         if (match_mode == MATCH_NONE ||
    1493   [ #  #  #  #  :           0 :             (!execname && !cmdname && !userspec &&
             #  #  #  # ]
    1494   [ #  #  #  # ]:           0 :              !pid_str && !ppid_str && !pidfile))
    1495                 :           0 :                 badusage("need at least one of --exec, --pid, --ppid, --pidfile, --user or --name");
    1496                 :             : 
    1497                 :             : #ifdef PROCESS_NAME_SIZE
    1498   [ #  #  #  # ]:           0 :         if (cmdname && strlen(cmdname) > PROCESS_NAME_SIZE)
    1499                 :           0 :                 warning("this system is not able to track process names\n"
    1500                 :             :                         "longer than %d characters, please use --exec "
    1501                 :             :                         "instead of --name.\n", PROCESS_NAME_SIZE);
    1502                 :             : #endif
    1503                 :             : 
    1504         [ #  # ]:           0 :         if (!startas)
    1505                 :           0 :                 startas = execname;
    1506                 :             : 
    1507   [ #  #  #  # ]:           0 :         if (action == ACTION_START && !startas)
    1508                 :           0 :                 badusage("--start needs --exec or --startas");
    1509                 :             : 
    1510   [ #  #  #  # ]:           0 :         if (mpidfile && pidfile == NULL)
    1511                 :           0 :                 badusage("--make-pidfile requires --pidfile");
    1512   [ #  #  #  # ]:           0 :         if (rpidfile && pidfile == NULL)
    1513                 :           0 :                 badusage("--remove-pidfile requires --pidfile");
    1514                 :             : 
    1515   [ #  #  #  # ]:           0 :         if (pid_str && pidfile)
    1516                 :           0 :                 badusage("need either --pid or --pidfile, not both");
    1517                 :             : 
    1518   [ #  #  #  # ]:           0 :         if (background && action != ACTION_START)
    1519                 :           0 :                 badusage("--background is only relevant with --start");
    1520                 :             : 
    1521   [ #  #  #  # ]:           0 :         if (!close_io && !background)
    1522                 :           0 :                 badusage("--no-close is only relevant with --background");
    1523   [ #  #  #  # ]:           0 :         if (output_io && !background)
    1524                 :           0 :                 badusage("--output is only relevant with --background");
    1525                 :             : 
    1526   [ #  #  #  # ]:           0 :         if (close_io && output_io == NULL)
    1527                 :           0 :                 output_io = "/dev/null";
    1528                 :           0 : }
    1529                 :             : 
    1530                 :             : static void
    1531                 :           0 : setup_options(void)
    1532                 :             : {
    1533         [ #  # ]:           0 :         if (execname) {
    1534                 :             :                 char *fullexecname;
    1535                 :             : 
    1536                 :             :                 /* If it's a relative path, normalize it. */
    1537         [ #  # ]:           0 :                 if (execname[0] != '/')
    1538                 :           0 :                         execname = newpath(changedir, execname);
    1539                 :             : 
    1540         [ #  # ]:           0 :                 if (changeroot)
    1541                 :           0 :                         fullexecname = newpath(changeroot, execname);
    1542                 :             :                 else
    1543                 :           0 :                         fullexecname = execname;
    1544                 :             : 
    1545         [ #  # ]:           0 :                 if (stat(fullexecname, &exec_stat))
    1546                 :           0 :                         fatale("unable to stat %s", fullexecname);
    1547                 :             : 
    1548         [ #  # ]:           0 :                 if (fullexecname != execname)
    1549                 :           0 :                         free(fullexecname);
    1550                 :             :         }
    1551                 :             : 
    1552   [ #  #  #  # ]:           0 :         if (userspec && parse_unsigned(userspec, 10, &user_id) < 0) {
    1553                 :             :                 struct passwd *pw;
    1554                 :             : 
    1555                 :           0 :                 pw = getpwnam(userspec);
    1556         [ #  # ]:           0 :                 if (!pw)
    1557                 :           0 :                         fatale("user '%s' not found", userspec);
    1558                 :             : 
    1559                 :           0 :                 user_id = pw->pw_uid;
    1560                 :             :         }
    1561                 :             : 
    1562   [ #  #  #  # ]:           0 :         if (changegroup && parse_unsigned(changegroup, 10, &runas_gid) < 0) {
    1563                 :             :                 struct group *gr;
    1564                 :             : 
    1565                 :           0 :                 gr = getgrnam(changegroup);
    1566         [ #  # ]:           0 :                 if (!gr)
    1567                 :           0 :                         fatale("group '%s' not found", changegroup);
    1568                 :           0 :                 changegroup = gr->gr_name;
    1569                 :           0 :                 runas_gid = gr->gr_gid;
    1570                 :             :         }
    1571         [ #  # ]:           0 :         if (changeuser) {
    1572                 :             :                 struct passwd *pw;
    1573                 :             :                 struct stat st;
    1574                 :             : 
    1575         [ #  # ]:           0 :                 if (parse_unsigned(changeuser, 10, &runas_uid) == 0)
    1576                 :           0 :                         pw = getpwuid(runas_uid);
    1577                 :             :                 else
    1578                 :           0 :                         pw = getpwnam(changeuser);
    1579         [ #  # ]:           0 :                 if (!pw)
    1580                 :           0 :                         fatale("user '%s' not found", changeuser);
    1581                 :           0 :                 changeuser = pw->pw_name;
    1582                 :           0 :                 runas_uid = pw->pw_uid;
    1583         [ #  # ]:           0 :                 if (changegroup == NULL) {
    1584                 :             :                         /* Pass the default group of this user. */
    1585                 :           0 :                         changegroup = ""; /* Just empty. */
    1586                 :           0 :                         runas_gid = pw->pw_gid;
    1587                 :             :                 }
    1588         [ #  # ]:           0 :                 if (stat(pw->pw_dir, &st) == 0)
    1589                 :           0 :                         setenv("HOME", pw->pw_dir, 1);
    1590                 :             :         }
    1591                 :           0 : }
    1592                 :             : 
    1593                 :             : #if defined(OS_Linux)
    1594                 :             : static const char *
    1595                 :           0 : proc_status_field(pid_t pid, const char *field)
    1596                 :             : {
    1597                 :             :         static char *line = NULL;
    1598                 :             :         static size_t line_size = 0;
    1599                 :             : 
    1600                 :             :         FILE *fp;
    1601                 :             :         char filename[32];
    1602                 :           0 :         char *value = NULL;
    1603                 :             :         ssize_t line_len;
    1604                 :           0 :         size_t field_len = strlen(field);
    1605                 :             : 
    1606                 :           0 :         sprintf(filename, "/proc/%d/status", pid);
    1607                 :           0 :         fp = fopen(filename, "r");
    1608         [ #  # ]:           0 :         if (!fp)
    1609                 :           0 :                 return NULL;
    1610         [ #  # ]:           0 :         while ((line_len = getline(&line, &line_size, fp)) >= 0) {
    1611         [ #  # ]:           0 :                 if (strncasecmp(line, field, field_len) == 0) {
    1612                 :           0 :                         line[line_len - 1] = '\0';
    1613                 :             : 
    1614                 :           0 :                         value = line + field_len;
    1615         [ #  # ]:           0 :                         while (isspace(*value))
    1616                 :           0 :                                 value++;
    1617                 :             : 
    1618                 :           0 :                         break;
    1619                 :             :                 }
    1620                 :             :         }
    1621                 :           0 :         fclose(fp);
    1622                 :             : 
    1623                 :           0 :         return value;
    1624                 :             : }
    1625                 :             : #elif (defined(OS_Solaris) || defined(OS_AIX)) && defined(HAVE_STRUCT_PSINFO)
    1626                 :             : static bool
    1627                 :             : proc_get_psinfo(pid_t pid, struct psinfo *psinfo)
    1628                 :             : {
    1629                 :             :         char filename[64];
    1630                 :             :         FILE *fp;
    1631                 :             : 
    1632                 :             :         sprintf(filename, "/proc/%d/psinfo", pid);
    1633                 :             :         fp = fopen(filename, "r");
    1634                 :             :         if (!fp)
    1635                 :             :                 return false;
    1636                 :             :         if (fread(psinfo, sizeof(*psinfo), 1, fp) == 0) {
    1637                 :             :                 fclose(fp);
    1638                 :             :                 return false;
    1639                 :             :         }
    1640                 :             :         if (ferror(fp)) {
    1641                 :             :                 fclose(fp);
    1642                 :             :                 return false;
    1643                 :             :         }
    1644                 :             : 
    1645                 :             :         fclose(fp);
    1646                 :             : 
    1647                 :             :         return true;
    1648                 :             : }
    1649                 :             : #elif defined(OS_Hurd)
    1650                 :             : static void
    1651                 :             : init_procset(void)
    1652                 :             : {
    1653                 :             :         struct ps_context *context;
    1654                 :             :         error_t err;
    1655                 :             : 
    1656                 :             :         err = ps_context_create(getproc(), &context);
    1657                 :             :         if (err)
    1658                 :             :                 error(1, err, "ps_context_create");
    1659                 :             : 
    1660                 :             :         err = proc_stat_list_create(context, &procset);
    1661                 :             :         if (err)
    1662                 :             :                 error(1, err, "proc_stat_list_create");
    1663                 :             : 
    1664                 :             :         err = proc_stat_list_add_all(procset, 0, 0);
    1665                 :             :         if (err)
    1666                 :             :                 error(1, err, "proc_stat_list_add_all");
    1667                 :             : }
    1668                 :             : 
    1669                 :             : static struct proc_stat *
    1670                 :             : get_proc_stat(pid_t pid, ps_flags_t flags)
    1671                 :             : {
    1672                 :             :         struct proc_stat *ps;
    1673                 :             :         ps_flags_t wanted_flags = PSTAT_PID | flags;
    1674                 :             : 
    1675                 :             :         if (!procset)
    1676                 :             :                 init_procset();
    1677                 :             : 
    1678                 :             :         ps = proc_stat_list_pid_proc_stat(procset, pid);
    1679                 :             :         if (!ps)
    1680                 :             :                 return NULL;
    1681                 :             :         if (proc_stat_set_flags(ps, wanted_flags))
    1682                 :             :                 return NULL;
    1683                 :             :         if ((proc_stat_flags(ps) & wanted_flags) != wanted_flags)
    1684                 :             :                 return NULL;
    1685                 :             : 
    1686                 :             :         return ps;
    1687                 :             : }
    1688                 :             : #elif defined(HAVE_KVM_H)
    1689                 :             : static kvm_t *
    1690                 :             : ssd_kvm_open(void)
    1691                 :             : {
    1692                 :             :         kvm_t *kd;
    1693                 :             :         char errbuf[_POSIX2_LINE_MAX];
    1694                 :             : 
    1695                 :             :         kd = kvm_openfiles(NULL, KVM_MEMFILE, NULL, O_RDONLY, errbuf);
    1696                 :             :         if (kd == NULL)
    1697                 :             :                 errx(1, "%s", errbuf);
    1698                 :             : 
    1699                 :             :         return kd;
    1700                 :             : }
    1701                 :             : 
    1702                 :             : static struct kinfo_proc *
    1703                 :             : ssd_kvm_get_procs(kvm_t *kd, int op, int arg, int *count)
    1704                 :             : {
    1705                 :             :         struct kinfo_proc *kp;
    1706                 :             :         int lcount;
    1707                 :             : 
    1708                 :             :         if (count == NULL)
    1709                 :             :                 count = &lcount;
    1710                 :             :         *count = 0;
    1711                 :             : 
    1712                 :             : #if defined(OS_OpenBSD)
    1713                 :             :         kp = kvm_getprocs(kd, op, arg, sizeof(*kp), count);
    1714                 :             : #else
    1715                 :             :         kp = kvm_getprocs(kd, op, arg, count);
    1716                 :             : #endif
    1717                 :             :         if (kp == NULL && errno != ESRCH)
    1718                 :             :                 errx(1, "%s", kvm_geterr(kd));
    1719                 :             : 
    1720                 :             :         return kp;
    1721                 :             : }
    1722                 :             : #endif
    1723                 :             : 
    1724                 :             : #if defined(OS_Linux)
    1725                 :             : static bool
    1726                 :           0 : pid_is_exec(pid_t pid, const struct stat *esb)
    1727                 :             : {
    1728                 :             :         char lname[32];
    1729                 :             :         char lcontents[_POSIX_PATH_MAX + 1];
    1730                 :             :         char *filename;
    1731                 :           0 :         const char deleted[] = " (deleted)";
    1732                 :             :         int nread;
    1733                 :             :         struct stat sb;
    1734                 :             : 
    1735                 :           0 :         sprintf(lname, "/proc/%d/exe", pid);
    1736                 :           0 :         nread = readlink(lname, lcontents, sizeof(lcontents) - 1);
    1737         [ #  # ]:           0 :         if (nread < 0)
    1738                 :           0 :                 return false;
    1739                 :             : 
    1740                 :           0 :         filename = lcontents;
    1741                 :           0 :         filename[nread] = '\0';
    1742                 :             : 
    1743                 :             :         /* OpenVZ kernels contain a bogus patch that instead of appending,
    1744                 :             :          * prepends the deleted marker. Workaround those. Otherwise handle
    1745                 :             :          * the normal appended marker. */
    1746         [ #  # ]:           0 :         if (strncmp(filename, deleted, strlen(deleted)) == 0)
    1747                 :           0 :                 filename += strlen(deleted);
    1748         [ #  # ]:           0 :         else if (strcmp(filename + nread - strlen(deleted), deleted) == 0)
    1749                 :           0 :                 filename[nread - strlen(deleted)] = '\0';
    1750                 :             : 
    1751         [ #  # ]:           0 :         if (stat(filename, &sb) != 0)
    1752                 :           0 :                 return false;
    1753                 :             : 
    1754   [ #  #  #  # ]:           0 :         return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
    1755                 :             : }
    1756                 :             : #elif (defined(OS_Solaris) || defined(OS_AIX)) && defined(HAVE_STRUCT_PSINFO)
    1757                 :             : static bool
    1758                 :             : pid_is_exec(pid_t pid, const struct stat *esb)
    1759                 :             : {
    1760                 :             :         struct stat sb;
    1761                 :             :         char filename[64];
    1762                 :             : 
    1763                 :             :         sprintf(filename, "/proc/%d/object/a.out", pid);
    1764                 :             : 
    1765                 :             :         if (stat(filename, &sb) != 0)
    1766                 :             :                 return false;
    1767                 :             : 
    1768                 :             :         return sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino;
    1769                 :             : }
    1770                 :             : #elif defined(OS_Hurd)
    1771                 :             : static bool
    1772                 :             : pid_is_exec(pid_t pid, const struct stat *esb)
    1773                 :             : {
    1774                 :             :         struct proc_stat *ps;
    1775                 :             :         struct stat sb;
    1776                 :             :         const char *filename;
    1777                 :             : 
    1778                 :             :         ps = get_proc_stat(pid, PSTAT_ARGS);
    1779                 :             :         if (ps == NULL)
    1780                 :             :                 return false;
    1781                 :             : 
    1782                 :             :         /* On old Hurd systems we have to use the argv[0] value, because
    1783                 :             :          * there is nothing better. */
    1784                 :             :         filename = proc_stat_args(ps);
    1785                 :             : #ifdef PSTAT_EXE
    1786                 :             :         /* On new Hurd systems we can use the correct value, as long
    1787                 :             :          * as it's not NULL nor empty, as it was the case on the first
    1788                 :             :          * implementation. */
    1789                 :             :         if (proc_stat_set_flags(ps, PSTAT_EXE) == 0 &&
    1790                 :             :             proc_stat_flags(ps) & PSTAT_EXE &&
    1791                 :             :             proc_stat_exe(ps) != NULL &&
    1792                 :             :             proc_stat_exe(ps)[0] != '\0')
    1793                 :             :                 filename = proc_stat_exe(ps);
    1794                 :             : #endif
    1795                 :             : 
    1796                 :             :         if (stat(filename, &sb) != 0)
    1797                 :             :                 return false;
    1798                 :             : 
    1799                 :             :         return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
    1800                 :             : }
    1801                 :             : #elif defined(OS_Darwin)
    1802                 :             : static bool
    1803                 :             : pid_is_exec(pid_t pid, const struct stat *esb)
    1804                 :             : {
    1805                 :             :         struct stat sb;
    1806                 :             :         char pathname[_POSIX_PATH_MAX];
    1807                 :             : 
    1808                 :             :         if (proc_pidpath(pid, pathname, sizeof(pathname)) < 0)
    1809                 :             :                 return false;
    1810                 :             : 
    1811                 :             :         if (stat(pathname, &sb) != 0)
    1812                 :             :                 return false;
    1813                 :             : 
    1814                 :             :         return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
    1815                 :             : }
    1816                 :             : #elif defined(OS_HPUX)
    1817                 :             : static bool
    1818                 :             : pid_is_exec(pid_t pid, const struct stat *esb)
    1819                 :             : {
    1820                 :             :         struct pst_status pst;
    1821                 :             : 
    1822                 :             :         if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
    1823                 :             :                 return false;
    1824                 :             :         return ((dev_t)pst.pst_text.psf_fsid.psfs_id == esb->st_dev &&
    1825                 :             :                 (ino_t)pst.pst_text.psf_fileid == esb->st_ino);
    1826                 :             : }
    1827                 :             : #elif defined(OS_FreeBSD)
    1828                 :             : static bool
    1829                 :             : pid_is_exec(pid_t pid, const struct stat *esb)
    1830                 :             : {
    1831                 :             :         struct stat sb;
    1832                 :             :         int error, mib[4];
    1833                 :             :         size_t len;
    1834                 :             :         char pathname[PATH_MAX];
    1835                 :             : 
    1836                 :             :         mib[0] = CTL_KERN;
    1837                 :             :         mib[1] = KERN_PROC;
    1838                 :             :         mib[2] = KERN_PROC_PATHNAME;
    1839                 :             :         mib[3] = pid;
    1840                 :             :         len = sizeof(pathname);
    1841                 :             : 
    1842                 :             :         error = sysctl(mib, 4, pathname, &len, NULL, 0);
    1843                 :             :         if (error != 0 && errno != ESRCH)
    1844                 :             :                 return false;
    1845                 :             :         if (len == 0)
    1846                 :             :                 pathname[0] = '\0';
    1847                 :             : 
    1848                 :             :         if (stat(pathname, &sb) != 0)
    1849                 :             :                 return false;
    1850                 :             : 
    1851                 :             :         return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
    1852                 :             : }
    1853                 :             : #elif defined(HAVE_KVM_H)
    1854                 :             : static bool
    1855                 :             : pid_is_exec(pid_t pid, const struct stat *esb)
    1856                 :             : {
    1857                 :             :         kvm_t *kd;
    1858                 :             :         int argv_len = 0;
    1859                 :             :         struct kinfo_proc *kp;
    1860                 :             :         struct stat sb;
    1861                 :             :         char buf[_POSIX2_LINE_MAX];
    1862                 :             :         char **pid_argv_p;
    1863                 :             :         char *start_argv_0_p, *end_argv_0_p;
    1864                 :             :         bool res = false;
    1865                 :             : 
    1866                 :             :         kd = ssd_kvm_open();
    1867                 :             :         kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
    1868                 :             :         if (kp == NULL)
    1869                 :             :                 goto cleanup;
    1870                 :             : 
    1871                 :             :         pid_argv_p = kvm_getargv(kd, kp, argv_len);
    1872                 :             :         if (pid_argv_p == NULL)
    1873                 :             :                 errx(1, "%s", kvm_geterr(kd));
    1874                 :             : 
    1875                 :             :         /* Find and compare string. */
    1876                 :             :         start_argv_0_p = *pid_argv_p;
    1877                 :             : 
    1878                 :             :         /* Find end of argv[0] then copy and cut off str there. */
    1879                 :             :         end_argv_0_p = strchr(*pid_argv_p, ' ');
    1880                 :             :         if (end_argv_0_p == NULL)
    1881                 :             :                 /* There seems to be no space, so we have the command
    1882                 :             :                  * already in its desired form. */
    1883                 :             :                 start_argv_0_p = *pid_argv_p;
    1884                 :             :         else {
    1885                 :             :                 /* Tests indicate that this never happens, since
    1886                 :             :                  * kvm_getargv itself cuts off tailing stuff. This is
    1887                 :             :                  * not what the manual page says, however. */
    1888                 :             :                 strncpy(buf, *pid_argv_p, (end_argv_0_p - start_argv_0_p));
    1889                 :             :                 buf[(end_argv_0_p - start_argv_0_p) + 1] = '\0';
    1890                 :             :                 start_argv_0_p = buf;
    1891                 :             :         }
    1892                 :             : 
    1893                 :             :         if (stat(start_argv_0_p, &sb) != 0)
    1894                 :             :                 goto cleanup;
    1895                 :             : 
    1896                 :             :         res = (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);
    1897                 :             : 
    1898                 :             : cleanup:
    1899                 :             :         kvm_close(kd);
    1900                 :             : 
    1901                 :             :         return res;
    1902                 :             : }
    1903                 :             : #endif
    1904                 :             : 
    1905                 :             : #if defined(OS_Linux)
    1906                 :             : static bool
    1907                 :           0 : pid_is_child(pid_t pid, pid_t ppid)
    1908                 :             : {
    1909                 :             :         const char *ppid_str;
    1910                 :             :         pid_t proc_ppid;
    1911                 :             :         int rc;
    1912                 :             : 
    1913                 :           0 :         ppid_str = proc_status_field(pid, "PPid:");
    1914         [ #  # ]:           0 :         if (ppid_str == NULL)
    1915                 :           0 :                 return false;
    1916                 :             : 
    1917                 :           0 :         rc = parse_pid(ppid_str, &proc_ppid);
    1918         [ #  # ]:           0 :         if (rc < 0)
    1919                 :           0 :                 return false;
    1920                 :             : 
    1921                 :           0 :         return proc_ppid == ppid;
    1922                 :             : }
    1923                 :             : #elif defined(OS_Hurd)
    1924                 :             : static bool
    1925                 :             : pid_is_child(pid_t pid, pid_t ppid)
    1926                 :             : {
    1927                 :             :         struct proc_stat *ps;
    1928                 :             :         struct procinfo *pi;
    1929                 :             : 
    1930                 :             :         ps = get_proc_stat(pid, PSTAT_PROC_INFO);
    1931                 :             :         if (ps == NULL)
    1932                 :             :                 return false;
    1933                 :             : 
    1934                 :             :         pi = proc_stat_proc_info(ps);
    1935                 :             : 
    1936                 :             :         return pi->ppid == ppid;
    1937                 :             : }
    1938                 :             : #elif defined(OS_Darwin)
    1939                 :             : static bool
    1940                 :             : pid_is_child(pid_t pid, pid_t ppid)
    1941                 :             : {
    1942                 :             :         struct proc_bsdinfo pbi;
    1943                 :             : 
    1944                 :             :         if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &pbi, sizeof(pbi)) < 0)
    1945                 :             :                 return false;
    1946                 :             : 
    1947                 :             :         return (pid_t)pbi.pbi_ppid == ppid;
    1948                 :             : }
    1949                 :             : #elif (defined(OS_Solaris) || defined(OS_AIX)) && defined(HAVE_STRUCT_PSINFO)
    1950                 :             : static bool
    1951                 :             : pid_is_child(pid_t pid, pid_t ppid)
    1952                 :             : {
    1953                 :             :         struct psinfo psi;
    1954                 :             : 
    1955                 :             :         if (!proc_get_psinfo(pid, &psi))
    1956                 :             :                 return false;
    1957                 :             : 
    1958                 :             :         return (pid_t)psi.pr_ppid == ppid;
    1959                 :             : }
    1960                 :             : #elif defined(OS_HPUX)
    1961                 :             : static bool
    1962                 :             : pid_is_child(pid_t pid, pid_t ppid)
    1963                 :             : {
    1964                 :             :         struct pst_status pst;
    1965                 :             : 
    1966                 :             :         if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
    1967                 :             :                 return false;
    1968                 :             : 
    1969                 :             :         return pst.pst_ppid == ppid;
    1970                 :             : }
    1971                 :             : #elif defined(OS_FreeBSD)
    1972                 :             : static bool
    1973                 :             : pid_is_child(pid_t pid, pid_t ppid)
    1974                 :             : {
    1975                 :             :         struct kinfo_proc kp;
    1976                 :             :         int rc, mib[4];
    1977                 :             :         size_t len;
    1978                 :             : 
    1979                 :             :         mib[0] = CTL_KERN;
    1980                 :             :         mib[1] = KERN_PROC;
    1981                 :             :         mib[2] = KERN_PROC_PID;
    1982                 :             :         mib[3] = pid;
    1983                 :             :         len = sizeof(kp);
    1984                 :             : 
    1985                 :             :         rc = sysctl(mib, 4, &kp, &len, NULL, 0);
    1986                 :             :         if (rc != 0 && errno != ESRCH)
    1987                 :             :                 return false;
    1988                 :             :         if (len == 0 || len != sizeof(kp))
    1989                 :             :                 return false;
    1990                 :             : 
    1991                 :             :         return kp.ki_ppid == ppid;
    1992                 :             : }
    1993                 :             : #elif defined(HAVE_KVM_H)
    1994                 :             : static bool
    1995                 :             : pid_is_child(pid_t pid, pid_t ppid)
    1996                 :             : {
    1997                 :             :         kvm_t *kd;
    1998                 :             :         struct kinfo_proc *kp;
    1999                 :             :         pid_t proc_ppid;
    2000                 :             :         bool res = false;
    2001                 :             : 
    2002                 :             :         kd = ssd_kvm_open();
    2003                 :             :         kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
    2004                 :             :         if (kp == NULL)
    2005                 :             :                 goto cleanup;
    2006                 :             : 
    2007                 :             : #if defined(OS_FreeBSD)
    2008                 :             :         proc_ppid = kp->ki_ppid;
    2009                 :             : #elif defined(OS_OpenBSD)
    2010                 :             :         proc_ppid = kp->p_ppid;
    2011                 :             : #elif defined(OS_DragonFlyBSD)
    2012                 :             :         proc_ppid = kp->kp_ppid;
    2013                 :             : #else
    2014                 :             :         proc_ppid = kp->kp_proc.p_ppid;
    2015                 :             : #endif
    2016                 :             : 
    2017                 :             :         res = (proc_ppid == ppid);
    2018                 :             : 
    2019                 :             : cleanup:
    2020                 :             :         kvm_close(kd);
    2021                 :             : 
    2022                 :             :         return res;
    2023                 :             : }
    2024                 :             : #endif
    2025                 :             : 
    2026                 :             : #if defined(OS_Linux)
    2027                 :             : static bool
    2028                 :           0 : pid_is_user(pid_t pid, uid_t uid)
    2029                 :             : {
    2030                 :             :         struct stat sb;
    2031                 :             :         char buf[32];
    2032                 :             : 
    2033                 :           0 :         sprintf(buf, "/proc/%d", pid);
    2034         [ #  # ]:           0 :         if (stat(buf, &sb) != 0)
    2035                 :           0 :                 return false;
    2036                 :           0 :         return (sb.st_uid == uid);
    2037                 :             : }
    2038                 :             : #elif defined(OS_Hurd)
    2039                 :             : static bool
    2040                 :             : pid_is_user(pid_t pid, uid_t uid)
    2041                 :             : {
    2042                 :             :         struct proc_stat *ps;
    2043                 :             : 
    2044                 :             :         ps = get_proc_stat(pid, PSTAT_OWNER_UID);
    2045                 :             :         return ps && (uid_t)proc_stat_owner_uid(ps) == uid;
    2046                 :             : }
    2047                 :             : #elif defined(OS_Darwin)
    2048                 :             : static bool
    2049                 :             : pid_is_user(pid_t pid, uid_t uid)
    2050                 :             : {
    2051                 :             :         struct proc_bsdinfo pbi;
    2052                 :             : 
    2053                 :             :         if (proc_pidinfo(pid, PROC_PIDTBSDINFO, 0, &pbi, sizeof(pbi)) < 0)
    2054                 :             :                 return false;
    2055                 :             : 
    2056                 :             :         return pbi.pbi_ruid == uid;
    2057                 :             : }
    2058                 :             : #elif (defined(OS_Solaris) || defined(OS_AIX)) && defined(HAVE_STRUCT_PSINFO)
    2059                 :             : static bool
    2060                 :             : pid_is_user(pid_t pid, uid_t uid)
    2061                 :             : {
    2062                 :             :         struct psinfo psi;
    2063                 :             : 
    2064                 :             :         if (!proc_get_psinfo(pid, &psi))
    2065                 :             :                 return false;
    2066                 :             : 
    2067                 :             :         return psi.pr_uid == uid;
    2068                 :             : }
    2069                 :             : #elif defined(OS_HPUX)
    2070                 :             : static bool
    2071                 :             : pid_is_user(pid_t pid, uid_t uid)
    2072                 :             : {
    2073                 :             :         struct pst_status pst;
    2074                 :             : 
    2075                 :             :         if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
    2076                 :             :                 return false;
    2077                 :             :         return ((uid_t)pst.pst_uid == uid);
    2078                 :             : }
    2079                 :             : #elif defined(OS_FreeBSD)
    2080                 :             : static bool
    2081                 :             : pid_is_user(pid_t pid, uid_t uid)
    2082                 :             : {
    2083                 :             :         struct kinfo_proc kp;
    2084                 :             :         int rc, mib[4];
    2085                 :             :         size_t len;
    2086                 :             : 
    2087                 :             :         mib[0] = CTL_KERN;
    2088                 :             :         mib[1] = KERN_PROC;
    2089                 :             :         mib[2] = KERN_PROC_PID;
    2090                 :             :         mib[3] = pid;
    2091                 :             :         len = sizeof(kp);
    2092                 :             : 
    2093                 :             :         rc = sysctl(mib, 4, &kp, &len, NULL, 0);
    2094                 :             :         if (rc != 0 && errno != ESRCH)
    2095                 :             :                 return false;
    2096                 :             :         if (len == 0 || len != sizeof(kp))
    2097                 :             :                 return false;
    2098                 :             : 
    2099                 :             :         return kp.ki_ruid == uid;
    2100                 :             : }
    2101                 :             : #elif defined(HAVE_KVM_H)
    2102                 :             : static bool
    2103                 :             : pid_is_user(pid_t pid, uid_t uid)
    2104                 :             : {
    2105                 :             :         kvm_t *kd;
    2106                 :             :         uid_t proc_uid;
    2107                 :             :         struct kinfo_proc *kp;
    2108                 :             :         bool res = false;
    2109                 :             : 
    2110                 :             :         kd = ssd_kvm_open();
    2111                 :             :         kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
    2112                 :             :         if (kp == NULL)
    2113                 :             :                 goto cleanup;
    2114                 :             : 
    2115                 :             : #if defined(OS_FreeBSD)
    2116                 :             :         proc_uid = kp->ki_ruid;
    2117                 :             : #elif defined(OS_OpenBSD)
    2118                 :             :         proc_uid = kp->p_ruid;
    2119                 :             : #elif defined(OS_DragonFlyBSD)
    2120                 :             :         proc_uid = kp->kp_ruid;
    2121                 :             : #elif defined(OS_NetBSD)
    2122                 :             :         proc_uid = kp->kp_eproc.e_pcred.p_ruid;
    2123                 :             : #else
    2124                 :             :         if (kp->kp_proc.p_cred)
    2125                 :             :                 kvm_read(kd, (u_long)&(kp->kp_proc.p_cred->p_ruid),
    2126                 :             :                          &proc_uid, sizeof(uid_t));
    2127                 :             :         else
    2128                 :             :                 goto cleanup;
    2129                 :             : #endif
    2130                 :             : 
    2131                 :             :         res = (proc_uid == (uid_t)uid);
    2132                 :             : 
    2133                 :             : cleanup:
    2134                 :             :         kvm_close(kd);
    2135                 :             : 
    2136                 :             :         return res;
    2137                 :             : }
    2138                 :             : #endif
    2139                 :             : 
    2140                 :             : #if defined(OS_Linux)
    2141                 :             : static bool
    2142                 :           0 : pid_is_cmd(pid_t pid, const char *name)
    2143                 :             : {
    2144                 :             :         const char *comm;
    2145                 :             : 
    2146                 :           0 :         comm = proc_status_field(pid, "Name:");
    2147         [ #  # ]:           0 :         if (comm == NULL)
    2148                 :           0 :                 return false;
    2149                 :             : 
    2150                 :           0 :         return strcmp(comm, name) == 0;
    2151                 :             : }
    2152                 :             : #elif defined(OS_Hurd)
    2153                 :             : static bool
    2154                 :             : pid_is_cmd(pid_t pid, const char *name)
    2155                 :             : {
    2156                 :             :         struct proc_stat *ps;
    2157                 :             :         size_t argv0_len;
    2158                 :             :         const char *argv0;
    2159                 :             :         const char *binary_name;
    2160                 :             : 
    2161                 :             :         ps = get_proc_stat(pid, PSTAT_ARGS);
    2162                 :             :         if (ps == NULL)
    2163                 :             :                 return false;
    2164                 :             : 
    2165                 :             :         argv0 = proc_stat_args(ps);
    2166                 :             :         argv0_len = strlen(argv0) + 1;
    2167                 :             : 
    2168                 :             :         binary_name = basename(argv0);
    2169                 :             :         if (strcmp(binary_name, name) == 0)
    2170                 :             :                 return true;
    2171                 :             : 
    2172                 :             :         /* XXX: This is all kinds of ugly, but on the Hurd there's no way to
    2173                 :             :          * know the command name of a process, so we have to try to match
    2174                 :             :          * also on argv[1] for the case of an interpreted script. */
    2175                 :             :         if (proc_stat_args_len(ps) > argv0_len) {
    2176                 :             :                 const char *script_name = basename(argv0 + argv0_len);
    2177                 :             : 
    2178                 :             :                 return strcmp(script_name, name) == 0;
    2179                 :             :         }
    2180                 :             : 
    2181                 :             :         return false;
    2182                 :             : }
    2183                 :             : #elif (defined(OS_Solaris) || defined(OS_AIX)) && defined(HAVE_STRUCT_PSINFO)
    2184                 :             : static bool
    2185                 :             : pid_is_cmd(pid_t pid, const char *name)
    2186                 :             : {
    2187                 :             :         struct psinfo psi;
    2188                 :             : 
    2189                 :             :         if (!proc_get_psinfo(pid, &psi))
    2190                 :             :                 return false;
    2191                 :             : 
    2192                 :             :         return strcmp(psi.pr_fname, name) == 0;
    2193                 :             : }
    2194                 :             : #elif defined(OS_HPUX)
    2195                 :             : static bool
    2196                 :             : pid_is_cmd(pid_t pid, const char *name)
    2197                 :             : {
    2198                 :             :         struct pst_status pst;
    2199                 :             : 
    2200                 :             :         if (pstat_getproc(&pst, sizeof(pst), (size_t)0, (int)pid) < 0)
    2201                 :             :                 return false;
    2202                 :             :         return (strcmp(pst.pst_ucomm, name) == 0);
    2203                 :             : }
    2204                 :             : #elif defined(OS_Darwin)
    2205                 :             : static bool
    2206                 :             : pid_is_cmd(pid_t pid, const char *name)
    2207                 :             : {
    2208                 :             :         char pathname[_POSIX_PATH_MAX];
    2209                 :             : 
    2210                 :             :         if (proc_pidpath(pid, pathname, sizeof(pathname)) < 0)
    2211                 :             :                 return false;
    2212                 :             : 
    2213                 :             :         return strcmp(pathname, name) == 0;
    2214                 :             : }
    2215                 :             : #elif defined(OS_FreeBSD)
    2216                 :             : static bool
    2217                 :             : pid_is_cmd(pid_t pid, const char *name)
    2218                 :             : {
    2219                 :             :         struct kinfo_proc kp;
    2220                 :             :         int rc, mib[4];
    2221                 :             :         size_t len;
    2222                 :             : 
    2223                 :             :         mib[0] = CTL_KERN;
    2224                 :             :         mib[1] = KERN_PROC;
    2225                 :             :         mib[2] = KERN_PROC_PID;
    2226                 :             :         mib[3] = pid;
    2227                 :             :         len = sizeof(kp);
    2228                 :             : 
    2229                 :             :         rc = sysctl(mib, 4, &kp, &len, NULL, 0);
    2230                 :             :         if (rc != 0 && errno != ESRCH)
    2231                 :             :                 return false;
    2232                 :             :         if (len == 0 || len != sizeof(kp))
    2233                 :             :                 return false;
    2234                 :             : 
    2235                 :             :         return strcmp(kp.ki_comm, name) == 0;
    2236                 :             : }
    2237                 :             : #elif defined(HAVE_KVM_H)
    2238                 :             : static bool
    2239                 :             : pid_is_cmd(pid_t pid, const char *name)
    2240                 :             : {
    2241                 :             :         kvm_t *kd;
    2242                 :             :         struct kinfo_proc *kp;
    2243                 :             :         char *process_name;
    2244                 :             :         bool res = false;
    2245                 :             : 
    2246                 :             :         kd = ssd_kvm_open();
    2247                 :             :         kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
    2248                 :             :         if (kp == NULL)
    2249                 :             :                 goto cleanup;
    2250                 :             : 
    2251                 :             : #if defined(OS_FreeBSD)
    2252                 :             :         process_name = kp->ki_comm;
    2253                 :             : #elif defined(OS_OpenBSD)
    2254                 :             :         process_name = kp->p_comm;
    2255                 :             : #elif defined(OS_DragonFlyBSD)
    2256                 :             :         process_name = kp->kp_comm;
    2257                 :             : #else
    2258                 :             :         process_name = kp->kp_proc.p_comm;
    2259                 :             : #endif
    2260                 :             : 
    2261                 :             :         res = (strcmp(name, process_name) == 0);
    2262                 :             : 
    2263                 :             : cleanup:
    2264                 :             :         kvm_close(kd);
    2265                 :             : 
    2266                 :             :         return res;
    2267                 :             : }
    2268                 :             : #endif
    2269                 :             : 
    2270                 :             : #if defined(OS_Hurd)
    2271                 :             : static bool
    2272                 :             : pid_is_running(pid_t pid)
    2273                 :             : {
    2274                 :             :         return get_proc_stat(pid, 0) != NULL;
    2275                 :             : }
    2276                 :             : #else /* !OS_Hurd */
    2277                 :             : static bool
    2278                 :           0 : pid_is_running(pid_t pid)
    2279                 :             : {
    2280   [ #  #  #  # ]:           0 :         if (kill(pid, 0) == 0 || errno == EPERM)
    2281                 :           0 :                 return true;
    2282         [ #  # ]:           0 :         else if (errno == ESRCH)
    2283                 :           0 :                 return false;
    2284                 :             :         else
    2285                 :           0 :                 fatale("error checking pid %u status", pid);
    2286                 :             : }
    2287                 :             : #endif
    2288                 :             : 
    2289                 :             : static enum status_code
    2290                 :           0 : pid_check(pid_t pid)
    2291                 :             : {
    2292   [ #  #  #  # ]:           0 :         if (execname && !pid_is_exec(pid, &exec_stat))
    2293                 :           0 :                 return STATUS_DEAD;
    2294   [ #  #  #  # ]:           0 :         if (match_ppid > 0 && !pid_is_child(pid, match_ppid))
    2295                 :           0 :                 return STATUS_DEAD;
    2296   [ #  #  #  # ]:           0 :         if (userspec && !pid_is_user(pid, user_id))
    2297                 :           0 :                 return STATUS_DEAD;
    2298   [ #  #  #  # ]:           0 :         if (cmdname && !pid_is_cmd(pid, cmdname))
    2299                 :           0 :                 return STATUS_DEAD;
    2300   [ #  #  #  # ]:           0 :         if (action != ACTION_STOP && !pid_is_running(pid))
    2301                 :           0 :                 return STATUS_DEAD;
    2302                 :             : 
    2303                 :           0 :         pid_list_push(&found, pid);
    2304                 :             : 
    2305                 :           0 :         return STATUS_OK;
    2306                 :             : }
    2307                 :             : 
    2308                 :             : static enum status_code
    2309                 :           0 : do_pidfile(const char *name)
    2310                 :             : {
    2311                 :             :         FILE *f;
    2312                 :             :         static pid_t pid = 0;
    2313                 :             : 
    2314         [ #  # ]:           0 :         if (pid)
    2315                 :           0 :                 return pid_check(pid);
    2316                 :             : 
    2317                 :           0 :         f = fopen(name, "r");
    2318         [ #  # ]:           0 :         if (f) {
    2319                 :             :                 enum status_code pid_status;
    2320                 :             : 
    2321                 :             :                 /* If we are only matching on the pidfile, and it is owned by
    2322                 :             :                  * a non-root user, then this is a security risk, and the
    2323                 :             :                  * contents cannot be trusted, because the daemon might have
    2324                 :             :                  * been compromised.
    2325                 :             :                  *
    2326                 :             :                  * If the pidfile is world-writable we refuse to parse it.
    2327                 :             :                  *
    2328                 :             :                  * If we got /dev/null specified as the pidfile, we ignore the
    2329                 :             :                  * checks, as this is being used to run processes no matter
    2330                 :             :                  * what. */
    2331         [ #  # ]:           0 :                 if (strcmp(name, "/dev/null") != 0) {
    2332                 :             :                         struct stat st;
    2333                 :           0 :                         int fd = fileno(f);
    2334                 :             : 
    2335         [ #  # ]:           0 :                         if (fstat(fd, &st) < 0)
    2336                 :           0 :                                 fatale("cannot stat pidfile %s", name);
    2337                 :             : 
    2338   [ #  #  #  # ]:           0 :                         if (match_mode == MATCH_PIDFILE &&
    2339   [ #  #  #  # ]:           0 :                             ((st.st_uid != getuid() && st.st_uid != 0) ||
    2340         [ #  # ]:           0 :                              (st.st_gid != getgid() && st.st_gid != 0)))
    2341                 :           0 :                                 fatal("matching only on non-root pidfile %s is insecure", name);
    2342         [ #  # ]:           0 :                         if (st.st_mode & 0002)
    2343                 :           0 :                                 fatal("matching on world-writable pidfile %s is insecure", name);
    2344                 :             :                 }
    2345                 :             : 
    2346         [ #  # ]:           0 :                 if (fscanf(f, "%d", &pid) == 1)
    2347                 :           0 :                         pid_status = pid_check(pid);
    2348                 :             :                 else
    2349                 :           0 :                         pid_status = STATUS_UNKNOWN;
    2350                 :           0 :                 fclose(f);
    2351                 :             : 
    2352         [ #  # ]:           0 :                 if (pid_status == STATUS_DEAD)
    2353                 :           0 :                         return STATUS_DEAD_PIDFILE;
    2354                 :             :                 else
    2355                 :           0 :                         return pid_status;
    2356         [ #  # ]:           0 :         } else if (errno == ENOENT)
    2357                 :           0 :                 return STATUS_DEAD;
    2358                 :             :         else
    2359                 :           0 :                 fatale("unable to open pidfile %s", name);
    2360                 :             : }
    2361                 :             : 
    2362                 :             : #if defined(OS_Linux) || defined(OS_Solaris) || defined(OS_AIX)
    2363                 :             : static enum status_code
    2364                 :           0 : do_procinit(void)
    2365                 :             : {
    2366                 :             :         DIR *procdir;
    2367                 :             :         struct dirent *entry;
    2368                 :             :         int foundany;
    2369                 :             :         pid_t pid;
    2370                 :           0 :         enum status_code prog_status = STATUS_DEAD;
    2371                 :             : 
    2372                 :           0 :         procdir = opendir("/proc");
    2373         [ #  # ]:           0 :         if (!procdir)
    2374                 :           0 :                 fatale("unable to opendir /proc");
    2375                 :             : 
    2376                 :           0 :         foundany = 0;
    2377         [ #  # ]:           0 :         while ((entry = readdir(procdir)) != NULL) {
    2378                 :             :                 enum status_code pid_status;
    2379                 :             : 
    2380         [ #  # ]:           0 :                 if (sscanf(entry->d_name, "%d", &pid) != 1)
    2381                 :           0 :                         continue;
    2382                 :           0 :                 foundany++;
    2383                 :             : 
    2384                 :           0 :                 pid_status = pid_check(pid);
    2385         [ #  # ]:           0 :                 if (pid_status < prog_status)
    2386                 :           0 :                         prog_status = pid_status;
    2387                 :             :         }
    2388                 :           0 :         closedir(procdir);
    2389         [ #  # ]:           0 :         if (foundany == 0)
    2390                 :           0 :                 fatal("nothing in /proc - not mounted?");
    2391                 :             : 
    2392                 :           0 :         return prog_status;
    2393                 :             : }
    2394                 :             : #elif defined(OS_Hurd)
    2395                 :             : static int
    2396                 :             : check_proc_stat(struct proc_stat *ps)
    2397                 :             : {
    2398                 :             :         pid_check(proc_stat_pid(ps));
    2399                 :             :         return 0;
    2400                 :             : }
    2401                 :             : 
    2402                 :             : static enum status_code
    2403                 :             : do_procinit(void)
    2404                 :             : {
    2405                 :             :         if (!procset)
    2406                 :             :                 init_procset();
    2407                 :             : 
    2408                 :             :         proc_stat_list_for_each(procset, check_proc_stat);
    2409                 :             : 
    2410                 :             :         if (found)
    2411                 :             :                 return STATUS_OK;
    2412                 :             :         else
    2413                 :             :                 return STATUS_DEAD;
    2414                 :             : }
    2415                 :             : #elif defined(OS_Darwin)
    2416                 :             : static enum status_code
    2417                 :             : do_procinit(void)
    2418                 :             : {
    2419                 :             :         pid_t *pid_buf;
    2420                 :             :         int i, npids, pid_bufsize;
    2421                 :             :         enum status_code prog_status = STATUS_DEAD;
    2422                 :             : 
    2423                 :             :         npids = proc_listallpids(NULL, 0);
    2424                 :             :         if (npids == 0)
    2425                 :             :                 return STATUS_UNKNOWN;
    2426                 :             : 
    2427                 :             :         /* Try to avoid sudden changes in number of PIDs. */
    2428                 :             :         npids += 4096;
    2429                 :             :         pid_bufsize = sizeof(pid_t) * npids;
    2430                 :             :         pid_buf = xmalloc(pid_bufsize);
    2431                 :             : 
    2432                 :             :         npids = proc_listallpids(pid_buf, pid_bufsize);
    2433                 :             :         if (npids == 0)
    2434                 :             :                 return STATUS_UNKNOWN;
    2435                 :             : 
    2436                 :             :         for (i = 0; i < npids; i++) {
    2437                 :             :                 enum status_code pid_status;
    2438                 :             : 
    2439                 :             :                 pid_status = pid_check(pid_buf[i]);
    2440                 :             :                 if (pid_status < prog_status)
    2441                 :             :                         prog_status = pid_status;
    2442                 :             :         }
    2443                 :             : 
    2444                 :             :         free(pid_buf);
    2445                 :             : 
    2446                 :             :         return prog_status;
    2447                 :             : }
    2448                 :             : #elif defined(OS_HPUX)
    2449                 :             : static enum status_code
    2450                 :             : do_procinit(void)
    2451                 :             : {
    2452                 :             :         struct pst_status pst[10];
    2453                 :             :         int i, count;
    2454                 :             :         int idx = 0;
    2455                 :             :         enum status_code prog_status = STATUS_DEAD;
    2456                 :             : 
    2457                 :             :         while ((count = pstat_getproc(pst, sizeof(pst[0]), 10, idx)) > 0) {
    2458                 :             :                 for (i = 0; i < count; i++) {
    2459                 :             :                         enum status_code pid_status;
    2460                 :             : 
    2461                 :             :                         pid_status = pid_check(pst[i].pst_pid);
    2462                 :             :                         if (pid_status < prog_status)
    2463                 :             :                                 prog_status = pid_status;
    2464                 :             :                 }
    2465                 :             :                 idx = pst[count - 1].pst_idx + 1;
    2466                 :             :         }
    2467                 :             : 
    2468                 :             :         return prog_status;
    2469                 :             : }
    2470                 :             : #elif defined(OS_FreeBSD)
    2471                 :             : static enum status_code
    2472                 :             : do_procinit(void)
    2473                 :             : {
    2474                 :             :         struct kinfo_proc *kp;
    2475                 :             :         int rc, mib[3];
    2476                 :             :         size_t len = 0;
    2477                 :             :         int nentries, i;
    2478                 :             :         enum status_code prog_status = STATUS_DEAD;
    2479                 :             : 
    2480                 :             :         mib[0] = CTL_KERN;
    2481                 :             :         mib[1] = KERN_PROC;
    2482                 :             :         mib[2] = KERN_PROC_PROC;
    2483                 :             : 
    2484                 :             :         rc = sysctl(mib, 3, NULL, &len, NULL, 0);
    2485                 :             :         if (rc != 0 && errno != ESRCH)
    2486                 :             :                 return STATUS_UNKNOWN;
    2487                 :             :         if (len == 0)
    2488                 :             :                 return STATUS_UNKNOWN;
    2489                 :             : 
    2490                 :             :         kp = xmalloc(len);
    2491                 :             :         rc = sysctl(mib, 3, kp, &len, NULL, 0);
    2492                 :             :         if (rc != 0 && errno != ESRCH)
    2493                 :             :                 return STATUS_UNKNOWN;
    2494                 :             :         if (len == 0)
    2495                 :             :                 return STATUS_UNKNOWN;
    2496                 :             :         nentries = len / sizeof(*kp);
    2497                 :             : 
    2498                 :             :         for (i = 0; i < nentries; i++) {
    2499                 :             :                 enum status_code pid_status;
    2500                 :             : 
    2501                 :             :                 pid_status = pid_check(kp[i].ki_pid);
    2502                 :             :                 if (pid_status < prog_status)
    2503                 :             :                         prog_status = pid_status;
    2504                 :             :         }
    2505                 :             : 
    2506                 :             :         free(kp);
    2507                 :             : 
    2508                 :             :         return prog_status;
    2509                 :             : }
    2510                 :             : #elif defined(HAVE_KVM_H)
    2511                 :             : static enum status_code
    2512                 :             : do_procinit(void)
    2513                 :             : {
    2514                 :             :         kvm_t *kd;
    2515                 :             :         int nentries, i;
    2516                 :             :         struct kinfo_proc *kp;
    2517                 :             :         enum status_code prog_status = STATUS_DEAD;
    2518                 :             : 
    2519                 :             :         kd = ssd_kvm_open();
    2520                 :             :         kp = ssd_kvm_get_procs(kd, KERN_PROC_ALL, 0, &nentries);
    2521                 :             : 
    2522                 :             :         for (i = 0; i < nentries; i++) {
    2523                 :             :                 enum status_code pid_status;
    2524                 :             :                 pid_t pid;
    2525                 :             : 
    2526                 :             : #if defined(OS_FreeBSD)
    2527                 :             :                 pid = kp[i].ki_pid;
    2528                 :             : #elif defined(OS_OpenBSD)
    2529                 :             :                 pid = kp[i].p_pid;
    2530                 :             : #elif defined(OS_DragonFlyBSD)
    2531                 :             :                 pid = kp[i].kp_pid;
    2532                 :             : #else
    2533                 :             :                 pid = kp[i].kp_proc.p_pid;
    2534                 :             : #endif
    2535                 :             : 
    2536                 :             :                 pid_status = pid_check(pid);
    2537                 :             :                 if (pid_status < prog_status)
    2538                 :             :                         prog_status = pid_status;
    2539                 :             :         }
    2540                 :             : 
    2541                 :             :         kvm_close(kd);
    2542                 :             : 
    2543                 :             :         return prog_status;
    2544                 :             : }
    2545                 :             : #endif
    2546                 :             : 
    2547                 :             : static enum status_code
    2548                 :           0 : do_findprocs(void)
    2549                 :             : {
    2550                 :           0 :         pid_list_free(&found);
    2551                 :             : 
    2552         [ #  # ]:           0 :         if (match_pid > 0)
    2553                 :           0 :                 return pid_check(match_pid);
    2554         [ #  # ]:           0 :         else if (pidfile)
    2555                 :           0 :                 return do_pidfile(pidfile);
    2556                 :             :         else
    2557                 :           0 :                 return do_procinit();
    2558                 :             : }
    2559                 :             : 
    2560                 :             : static int
    2561                 :           0 : do_start(int argc, char **argv)
    2562                 :             : {
    2563                 :           0 :         int devnull_fd = -1;
    2564                 :           0 :         int output_fd = -1;
    2565                 :             :         gid_t rgid;
    2566                 :             :         uid_t ruid;
    2567                 :             : 
    2568                 :           0 :         do_findprocs();
    2569                 :             : 
    2570         [ #  # ]:           0 :         if (found) {
    2571         [ #  # ]:           0 :                 info("%s already running.\n", execname ? execname : "process");
    2572                 :           0 :                 return exitnodo;
    2573                 :             :         }
    2574   [ #  #  #  # ]:           0 :         if (testmode && quietmode <= 0) {
    2575                 :           0 :                 printf("Would start %s ", startas);
    2576         [ #  # ]:           0 :                 while (argc-- > 0)
    2577                 :           0 :                         printf("%s ", *argv++);
    2578         [ #  # ]:           0 :                 if (changeuser != NULL) {
    2579                 :           0 :                         printf(" (as user %s[%d]", changeuser, runas_uid);
    2580         [ #  # ]:           0 :                         if (changegroup != NULL)
    2581                 :           0 :                                 printf(", and group %s[%d])", changegroup, runas_gid);
    2582                 :             :                         else
    2583                 :           0 :                                 printf(")");
    2584                 :             :                 }
    2585         [ #  # ]:           0 :                 if (changeroot != NULL)
    2586                 :           0 :                         printf(" in directory %s", changeroot);
    2587         [ #  # ]:           0 :                 if (nicelevel)
    2588                 :           0 :                         printf(", and add %i to the priority", nicelevel);
    2589         [ #  # ]:           0 :                 if (proc_sched)
    2590                 :           0 :                         printf(", with scheduling policy %s with priority %i",
    2591                 :           0 :                                proc_sched->policy_name, proc_sched->priority);
    2592         [ #  # ]:           0 :                 if (io_sched)
    2593                 :           0 :                         printf(", with IO scheduling class %s with priority %i",
    2594                 :           0 :                                io_sched->policy_name, io_sched->priority);
    2595                 :           0 :                 printf(".\n");
    2596                 :             :         }
    2597         [ #  # ]:           0 :         if (testmode)
    2598                 :           0 :                 return 0;
    2599                 :           0 :         debug("Starting %s...\n", startas);
    2600                 :           0 :         *--argv = startas;
    2601         [ #  # ]:           0 :         if (umask_value >= 0)
    2602                 :           0 :                 umask(umask_value);
    2603         [ #  # ]:           0 :         if (background)
    2604                 :             :                 /* Ok, we need to detach this process. */
    2605                 :           0 :                 daemonize();
    2606   [ #  #  #  # ]:           0 :         else if (mpidfile && pidfile != NULL)
    2607                 :             :                 /* User wants _us_ to make the pidfile, but detach themself! */
    2608                 :           0 :                 write_pidfile(pidfile, getpid());
    2609   [ #  #  #  # ]:           0 :         if (background && close_io) {
    2610                 :           0 :                 devnull_fd = open("/dev/null", O_RDONLY);
    2611         [ #  # ]:           0 :                 if (devnull_fd < 0)
    2612                 :           0 :                         fatale("unable to open '%s'", "/dev/null");
    2613                 :             :         }
    2614   [ #  #  #  # ]:           0 :         if (background && output_io) {
    2615                 :           0 :                 output_fd = open(output_io, O_CREAT | O_WRONLY | O_APPEND, 0664);
    2616         [ #  # ]:           0 :                 if (output_fd < 0)
    2617                 :           0 :                         fatale("unable to open '%s'", output_io);
    2618                 :             :         }
    2619         [ #  # ]:           0 :         if (nicelevel) {
    2620                 :           0 :                 errno = 0;
    2621   [ #  #  #  # ]:           0 :                 if ((nice(nicelevel) == -1) && (errno != 0))
    2622                 :           0 :                         fatale("unable to alter nice level by %i", nicelevel);
    2623                 :             :         }
    2624         [ #  # ]:           0 :         if (proc_sched)
    2625                 :           0 :                 set_proc_schedule(proc_sched);
    2626         [ #  # ]:           0 :         if (io_sched)
    2627                 :           0 :                 set_io_schedule(io_sched);
    2628         [ #  # ]:           0 :         if (changeroot != NULL) {
    2629         [ #  # ]:           0 :                 if (chdir(changeroot) < 0)
    2630                 :           0 :                         fatale("unable to chdir() to %s", changeroot);
    2631         [ #  # ]:           0 :                 if (chroot(changeroot) < 0)
    2632                 :           0 :                         fatale("unable to chroot() to %s", changeroot);
    2633                 :             :         }
    2634         [ #  # ]:           0 :         if (chdir(changedir) < 0)
    2635                 :           0 :                 fatale("unable to chdir() to %s", changedir);
    2636                 :             : 
    2637                 :           0 :         rgid = getgid();
    2638                 :           0 :         ruid = getuid();
    2639         [ #  # ]:           0 :         if (changegroup != NULL) {
    2640         [ #  # ]:           0 :                 if (rgid != (gid_t)runas_gid)
    2641         [ #  # ]:           0 :                         if (setgid(runas_gid))
    2642                 :           0 :                                 fatale("unable to set gid to %d", runas_gid);
    2643                 :             :         }
    2644         [ #  # ]:           0 :         if (changeuser != NULL) {
    2645                 :             :                 /* We assume that if our real user and group are the same as
    2646                 :             :                  * the ones we should switch to, the supplementary groups
    2647                 :             :                  * will be already in place. */
    2648   [ #  #  #  # ]:           0 :                 if (rgid != (gid_t)runas_gid || ruid != (uid_t)runas_uid)
    2649         [ #  # ]:           0 :                         if (initgroups(changeuser, runas_gid))
    2650                 :           0 :                                 fatale("unable to set initgroups() with gid %d",
    2651                 :             :                                       runas_gid);
    2652                 :             : 
    2653         [ #  # ]:           0 :                 if (ruid != (uid_t)runas_uid)
    2654         [ #  # ]:           0 :                         if (setuid(runas_uid))
    2655                 :           0 :                                 fatale("unable to set uid to %s", changeuser);
    2656                 :             :         }
    2657                 :             : 
    2658   [ #  #  #  # ]:           0 :         if (background && output_fd >= 0) {
    2659                 :           0 :                 dup2(output_fd, 1); /* stdout */
    2660                 :           0 :                 dup2(output_fd, 2); /* stderr */
    2661                 :             :         }
    2662   [ #  #  #  # ]:           0 :         if (background && close_io) {
    2663                 :             :                 int i;
    2664                 :             : 
    2665                 :           0 :                 dup2(devnull_fd, 0); /* stdin */
    2666                 :             : 
    2667                 :             :                  /* Now close all extra fds. */
    2668         [ #  # ]:           0 :                 for (i = get_open_fd_max() - 1; i >= 3; --i)
    2669                 :           0 :                         close(i);
    2670                 :             :         }
    2671                 :           0 :         execv(startas, argv);
    2672                 :           0 :         fatale("unable to start %s", startas);
    2673                 :             : }
    2674                 :             : 
    2675                 :             : static void
    2676                 :           0 : do_stop(int sig_num, int *n_killed, int *n_notkilled)
    2677                 :             : {
    2678                 :             :         struct pid_list *p;
    2679                 :             : 
    2680                 :           0 :         do_findprocs();
    2681                 :             : 
    2682                 :           0 :         *n_killed = 0;
    2683                 :           0 :         *n_notkilled = 0;
    2684                 :             : 
    2685         [ #  # ]:           0 :         if (!found)
    2686                 :           0 :                 return;
    2687                 :             : 
    2688                 :           0 :         pid_list_free(&killed);
    2689                 :             : 
    2690         [ #  # ]:           0 :         for (p = found; p; p = p->next) {
    2691         [ #  # ]:           0 :                 if (testmode) {
    2692                 :           0 :                         info("Would send signal %d to %d.\n", sig_num, p->pid);
    2693                 :           0 :                         (*n_killed)++;
    2694         [ #  # ]:           0 :                 } else if (kill(p->pid, sig_num) == 0) {
    2695                 :           0 :                         pid_list_push(&killed, p->pid);
    2696                 :           0 :                         (*n_killed)++;
    2697                 :             :                 } else {
    2698         [ #  # ]:           0 :                         if (sig_num)
    2699                 :           0 :                                 warning("failed to kill %d: %s\n",
    2700                 :           0 :                                         p->pid, strerror(errno));
    2701                 :           0 :                         (*n_notkilled)++;
    2702                 :             :                 }
    2703                 :             :         }
    2704                 :             : }
    2705                 :             : 
    2706                 :             : static void
    2707                 :           0 : do_stop_summary(int retry_nr)
    2708                 :             : {
    2709                 :             :         struct pid_list *p;
    2710                 :             : 
    2711   [ #  #  #  # ]:           0 :         if (quietmode >= 0 || !killed)
    2712                 :           0 :                 return;
    2713                 :             : 
    2714                 :           0 :         printf("Stopped %s (pid", what_stop);
    2715         [ #  # ]:           0 :         for (p = killed; p; p = p->next)
    2716                 :           0 :                 printf(" %d", p->pid);
    2717                 :           0 :         putchar(')');
    2718         [ #  # ]:           0 :         if (retry_nr > 0)
    2719                 :           0 :                 printf(", retry #%d", retry_nr);
    2720                 :           0 :         printf(".\n");
    2721                 :             : }
    2722                 :             : 
    2723                 :             : static void LIBCOMPAT_ATTR_PRINTF(1)
    2724                 :           0 : set_what_stop(const char *format, ...)
    2725                 :             : {
    2726                 :             :         va_list arglist;
    2727                 :             :         int rc;
    2728                 :             : 
    2729                 :           0 :         va_start(arglist, format);
    2730                 :           0 :         rc = vasprintf(&what_stop, format, arglist);
    2731                 :           0 :         va_end(arglist);
    2732                 :             : 
    2733         [ #  # ]:           0 :         if (rc < 0)
    2734                 :           0 :                 fatale("cannot allocate formatted string");
    2735                 :           0 : }
    2736                 :             : 
    2737                 :             : /*
    2738                 :             :  * We want to keep polling for the processes, to see if they've exited, or
    2739                 :             :  * until the timeout expires.
    2740                 :             :  *
    2741                 :             :  * This is a somewhat complicated algorithm to try to ensure that we notice
    2742                 :             :  * reasonably quickly when all the processes have exited, but don't spend
    2743                 :             :  * too much CPU time polling. In particular, on a fast machine with
    2744                 :             :  * quick-exiting daemons we don't want to delay system shutdown too much,
    2745                 :             :  * whereas on a slow one, or where processes are taking some time to exit,
    2746                 :             :  * we want to increase the polling interval.
    2747                 :             :  *
    2748                 :             :  * The algorithm is as follows: we measure the elapsed time it takes to do
    2749                 :             :  * one poll(), and wait a multiple of this time for the next poll. However,
    2750                 :             :  * if that would put us past the end of the timeout period we wait only as
    2751                 :             :  * long as the timeout period, but in any case we always wait at least
    2752                 :             :  * MIN_POLL_INTERVAL (20ms). The multiple (‘ratio’) starts out as 2, and
    2753                 :             :  * increases by 1 for each poll to a maximum of 10; so we use up to between
    2754                 :             :  * 30% and 10% of the machine's resources (assuming a few reasonable things
    2755                 :             :  * about system performance).
    2756                 :             :  */
    2757                 :             : static bool
    2758                 :           0 : do_stop_timeout(int timeout, int *n_killed, int *n_notkilled)
    2759                 :             : {
    2760                 :             :         struct timespec stopat, before, after, interval, maxinterval;
    2761                 :             :         int ratio;
    2762                 :             : 
    2763                 :           0 :         timespec_gettime(&stopat);
    2764                 :           0 :         stopat.tv_sec += timeout;
    2765                 :           0 :         ratio = 1;
    2766                 :           0 :         for (;;) {
    2767                 :             :                 int rc;
    2768                 :             : 
    2769                 :           0 :                 timespec_gettime(&before);
    2770   [ #  #  #  # ]:           0 :                 if (timespec_cmp(&before, &stopat, >))
    2771                 :           0 :                         return false;
    2772                 :             : 
    2773                 :           0 :                 do_stop(0, n_killed, n_notkilled);
    2774         [ #  # ]:           0 :                 if (!*n_killed)
    2775                 :           0 :                         return true;
    2776                 :             : 
    2777                 :           0 :                 timespec_gettime(&after);
    2778                 :             : 
    2779   [ #  #  #  # ]:           0 :                 if (!timespec_cmp(&after, &stopat, <))
    2780                 :           0 :                         return false;
    2781                 :             : 
    2782         [ #  # ]:           0 :                 if (ratio < 10)
    2783                 :           0 :                         ratio++;
    2784                 :             : 
    2785                 :           0 :                 timespec_sub(&stopat, &after, &maxinterval);
    2786                 :           0 :                 timespec_sub(&after, &before, &interval);
    2787                 :           0 :                 timespec_mul(&interval, ratio);
    2788                 :             : 
    2789   [ #  #  #  # ]:           0 :                 if (interval.tv_sec < 0 || interval.tv_nsec < 0)
    2790                 :           0 :                         interval.tv_sec = interval.tv_nsec = 0;
    2791                 :             : 
    2792   [ #  #  #  # ]:           0 :                 if (timespec_cmp(&interval, &maxinterval, >))
    2793                 :           0 :                         interval = maxinterval;
    2794                 :             : 
    2795         [ #  # ]:           0 :                 if (interval.tv_sec == 0 &&
    2796         [ #  # ]:           0 :                     interval.tv_nsec <= MIN_POLL_INTERVAL)
    2797                 :           0 :                         interval.tv_nsec = MIN_POLL_INTERVAL;
    2798                 :             : 
    2799                 :           0 :                 rc = pselect(0, NULL, NULL, NULL, &interval, NULL);
    2800   [ #  #  #  # ]:           0 :                 if (rc < 0 && errno != EINTR)
    2801                 :           0 :                         fatale("select() failed for pause");
    2802                 :             :         }
    2803                 :             : }
    2804                 :             : 
    2805                 :             : static int
    2806                 :           0 : finish_stop_schedule(bool anykilled)
    2807                 :             : {
    2808   [ #  #  #  #  :           0 :         if (rpidfile && pidfile && !testmode)
                   #  # ]
    2809                 :           0 :                 remove_pidfile(pidfile);
    2810                 :             : 
    2811         [ #  # ]:           0 :         if (anykilled)
    2812                 :           0 :                 return 0;
    2813                 :             : 
    2814                 :           0 :         info("No %s found running; none killed.\n", what_stop);
    2815                 :             : 
    2816                 :           0 :         return exitnodo;
    2817                 :             : }
    2818                 :             : 
    2819                 :             : static int
    2820                 :           0 : run_stop_schedule(void)
    2821                 :             : {
    2822                 :             :         int position, n_killed, n_notkilled, value, retry_nr;
    2823                 :             :         bool anykilled;
    2824                 :             : 
    2825         [ #  # ]:           0 :         if (testmode) {
    2826         [ #  # ]:           0 :                 if (schedule != NULL) {
    2827                 :           0 :                         info("Ignoring --retry in test mode\n");
    2828                 :           0 :                         schedule = NULL;
    2829                 :             :                 }
    2830                 :             :         }
    2831                 :             : 
    2832         [ #  # ]:           0 :         if (cmdname)
    2833                 :           0 :                 set_what_stop("%s", cmdname);
    2834         [ #  # ]:           0 :         else if (execname)
    2835                 :           0 :                 set_what_stop("%s", execname);
    2836         [ #  # ]:           0 :         else if (pidfile)
    2837                 :           0 :                 set_what_stop("process in pidfile '%s'", pidfile);
    2838         [ #  # ]:           0 :         else if (match_pid > 0)
    2839                 :           0 :                 set_what_stop("process with pid %d", match_pid);
    2840         [ #  # ]:           0 :         else if (match_ppid > 0)
    2841                 :           0 :                 set_what_stop("process(es) with parent pid %d", match_ppid);
    2842         [ #  # ]:           0 :         else if (userspec)
    2843                 :           0 :                 set_what_stop("process(es) owned by '%s'", userspec);
    2844                 :             :         else
    2845                 :           0 :                 BUG("no match option, please report");
    2846                 :             : 
    2847                 :           0 :         anykilled = false;
    2848                 :           0 :         retry_nr = 0;
    2849                 :           0 :         n_killed = 0;
    2850                 :           0 :         n_notkilled = 0;
    2851                 :             : 
    2852         [ #  # ]:           0 :         if (schedule == NULL) {
    2853                 :           0 :                 do_stop(signal_nr, &n_killed, &n_notkilled);
    2854                 :           0 :                 do_stop_summary(0);
    2855         [ #  # ]:           0 :                 if (n_notkilled > 0)
    2856                 :           0 :                         info("%d pids were not killed\n", n_notkilled);
    2857         [ #  # ]:           0 :                 if (n_killed)
    2858                 :           0 :                         anykilled = true;
    2859                 :           0 :                 return finish_stop_schedule(anykilled);
    2860                 :             :         }
    2861                 :             : 
    2862         [ #  # ]:           0 :         for (position = 0; position < schedule_length; position++) {
    2863                 :           0 :         reposition:
    2864                 :           0 :                 value = schedule[position].value;
    2865                 :           0 :                 n_notkilled = 0;
    2866                 :             : 
    2867   [ #  #  #  # ]:           0 :                 switch (schedule[position].type) {
    2868                 :           0 :                 case sched_goto:
    2869                 :           0 :                         position = value;
    2870                 :           0 :                         goto reposition;
    2871                 :           0 :                 case sched_signal:
    2872                 :           0 :                         do_stop(value, &n_killed, &n_notkilled);
    2873                 :           0 :                         do_stop_summary(retry_nr++);
    2874         [ #  # ]:           0 :                         if (!n_killed)
    2875                 :           0 :                                 return finish_stop_schedule(anykilled);
    2876                 :             :                         else
    2877                 :           0 :                                 anykilled = true;
    2878                 :           0 :                         continue;
    2879                 :           0 :                 case sched_timeout:
    2880         [ #  # ]:           0 :                         if (do_stop_timeout(value, &n_killed, &n_notkilled))
    2881                 :           0 :                                 return finish_stop_schedule(anykilled);
    2882                 :             :                         else
    2883                 :           0 :                                 continue;
    2884                 :           0 :                 default:
    2885                 :           0 :                         BUG("schedule[%d].type value %d is not valid",
    2886                 :             :                             position, schedule[position].type);
    2887                 :             :                 }
    2888                 :             :         }
    2889                 :             : 
    2890                 :           0 :         info("Program %s, %d process(es), refused to die.\n",
    2891                 :             :              what_stop, n_killed);
    2892                 :             : 
    2893                 :           0 :         return 2;
    2894                 :             : }
    2895                 :             : 
    2896                 :             : int
    2897                 :           0 : main(int argc, char **argv)
    2898                 :             : {
    2899                 :           0 :         progname = argv[0];
    2900                 :             : 
    2901                 :           0 :         parse_options(argc, argv);
    2902                 :           0 :         setup_options();
    2903                 :             : 
    2904                 :           0 :         argc -= optind;
    2905                 :           0 :         argv += optind;
    2906                 :             : 
    2907         [ #  # ]:           0 :         if (action == ACTION_START)
    2908                 :           0 :                 return do_start(argc, argv);
    2909         [ #  # ]:           0 :         else if (action == ACTION_STOP)
    2910                 :           0 :                 return run_stop_schedule();
    2911         [ #  # ]:           0 :         else if (action == ACTION_STATUS)
    2912                 :           0 :                 return do_findprocs();
    2913                 :             : 
    2914                 :           0 :         return 0;
    2915                 :             : }
        

Generated by: LCOV version 2.0-1