Get more help from gcc, add -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2...
[sysvinit.git] / src / killall5.c
index 3d35364c1d01cec1c286bc24ba440e4d4e0cae1f..187255598df3030a7fce410788d6aa6e30ecf5e4 100644 (file)
@@ -376,6 +376,20 @@ out:
        return 0;
 }
 
+/*
+ * Get the maximal number of symlinks to follow.  Use sysconf() on
+ * Hurd where the hardcoded value MAXSYMLINKS is not available.
+ */
+static int maxsymlinks(void)
+{
+       int v = sysconf(_SC_SYMLOOP_MAX);
+#ifdef MAXSYMLINKS
+       if (v == -1)
+               return MAXSYMLINKS;
+#endif
+       return v;
+}
+
 /*
  *     Check path is located on a network based partition.
  */
@@ -383,7 +397,7 @@ int check4nfs(const char * path, char * real)
 {
        char buf[PATH_MAX+1];
        const char *curr;
-       int deep = MAXSYMLINKS;
+       int deep = maxsymlinks();
 
        if (!nlist) return 0;
 
@@ -469,6 +483,7 @@ int readproc(int do_stat)
        char            *s, *q;
        unsigned long   startcode, endcode;
        int             pid, f;
+       ssize_t         len;
 
        /* Open the /proc directory. */
        if (chdir("/proc") == -1) {
@@ -507,8 +522,10 @@ int readproc(int do_stat)
 
                /* Read SID & statname from it. */
                if ((fp = fopen(path, "r")) != NULL) {
-                       if (!fgets(buf, sizeof(buf), fp))
-                               buf[0] = '\0';
+                       size_t len;
+
+                       len = fread(buf, sizeof(char), sizeof(buf)-1, fp);
+                       buf[len] = '\0';
 
                        if (buf[0] == '\0') {
                                nsyslog(LOG_ERR,
@@ -635,23 +652,46 @@ int readproc(int do_stat)
                switch (do_stat) {
                case DO_NETFS:
                        if ((p->nfs = check4nfs(path, buf)))
-                               break;
+                               goto link;
                case DO_STAT:
-                       if (stat(path, &st) != 0)
+                       if (stat(path, &st) != 0) {
+                               char * ptr;
+
+                               len = readlink(path, buf, PATH_MAX);
+                               if (len <= 0)
+                                       break;
+                               buf[len] = '\0';
+
+                               ptr = strstr(buf, " (deleted)");
+                               if (!ptr)
+                                       break;
+                               *ptr = '\0';
+                               len -= strlen(" (deleted)");
+
+                               if (stat(buf, &st) != 0)
+                                       break;
+                               p->dev = st.st_dev;
+                               p->ino = st.st_ino;
+                               p->pathname = (char *)xmalloc(len + 1);
+                               memcpy(p->pathname, buf, len);
+                               p->pathname[len] = '\0';
+
+                               /* All done */
                                break;
-                       else {
-                               char buf[PATH_MAX];
-
-                               f = readlink(path, buf, sizeof buf);
-                               if (f > 0) {
-                                       p->pathname = (char *)xmalloc(f + 1);
-                                       memcpy(p->pathname, buf, f);
-                                       p->pathname[f] = '\0';
-                               }
                        }
+
                        p->dev = st.st_dev;
                        p->ino = st.st_ino;
+
+                       /* Fall through */
                default:
+               link:
+                       len = readlink(path, buf, PATH_MAX);
+                       if (len > 0) {
+                               p->pathname = (char *)xmalloc(len + 1);
+                               memcpy(p->pathname, buf, len);
+                               p->pathname[len] = '\0';
+                       }
                        break;
                }
 
@@ -722,6 +762,7 @@ PIDQ_HEAD *pidof(char *prog)
        int             dostat = 0;
        int             foundone = 0;
        int             ok = 0;
+       const int       root = (getuid() == 0);
        char            real[PATH_MAX+1];
 
        if (! prog)
@@ -769,16 +810,11 @@ PIDQ_HEAD *pidof(char *prog)
         * network FS located binaries */
        if (!foundone && nfs) {
                for (p = plist; p; p = p->next) {
-                       char exe [PATH_MAX+1];
-                       char path[PATH_MAX+1];
-                       int len;
+                       if (!p->pathname)
+                               continue;
                        if (!p->nfs)
                                continue;
-                       snprintf(exe, sizeof(exe), "/proc/%d/exe", p->pid);
-                       if ((len = readlink(exe, path, PATH_MAX)) < 0)
-                                   continue;
-                       path[len] = '\0';
-                       if (strcmp(prog, path) != 0)
+                       if (strcmp(prog, p->pathname) != 0)
                                continue;
                        add_pid_to_q(q, p);
                        foundone++;
@@ -788,19 +824,31 @@ PIDQ_HEAD *pidof(char *prog)
        /* If we didn't find a match based on dev/ino, try the name. */
        if (!foundone) for (p = plist; p; p = p->next) {
                if (prog[0] == '/') {
-                       if (!p->pathname)
-                               continue;
+                       if (!p->pathname) {
+                               if (root)
+                                       continue;
+                               goto fallback; 
+                       }
                        if (strcmp(prog, p->pathname)) {
                                int len = strlen(prog);
                                if (strncmp(prog, p->pathname, len))
+                               {
+                                       if (scripts_too)
+                                               goto fallback;
                                        continue;
+                               }
                                if (strcmp(" (deleted)", p->pathname + len))
+                               {
+                                       if (scripts_too)
+                                               goto fallback;
                                        continue;
+                               }
                        }
                        add_pid_to_q(q, p);
                        continue;
                }
 
+       fallback:
                ok = 0;
 
                /*             matching        nonmatching