1 #include "capsicum-test.h" 2 3 #ifdef __FreeBSD__ 4 #include <sys/param.h> 5 #include <sys/proc.h> 6 #include <sys/queue.h> 7 #include <sys/socket.h> 8 #include <sys/sysctl.h> 9 #include <sys/user.h> 10 #include <libprocstat.h> 11 #endif 12 13 #include <stdio.h> 14 #include <string.h> 15 #include <signal.h> 16 17 #include <map> 18 #include <vector> 19 #include <string> 20 21 bool verbose = false; 22 bool tmpdir_on_tmpfs = false; 23 bool force_mt = false; 24 bool force_nofork = false; 25 uid_t other_uid = 0; 26 27 namespace { 28 std::map<std::string, std::string> tmp_paths; 29 } 30 31 const char *TmpFile(const char *p) { 32 std::string pathname(p); 33 if (tmp_paths.find(pathname) == tmp_paths.end()) { 34 std::string fullname = tmpdir + "/" + pathname; 35 tmp_paths[pathname] = fullname; 36 } 37 return tmp_paths[pathname].c_str(); 38 } 39 40 char ProcessState(int pid) { 41 #ifdef __linux__ 42 // Open the process status file. 43 char s[1024]; 44 snprintf(s, sizeof(s), "/proc/%d/status", pid); 45 FILE *f = fopen(s, "r"); 46 if (f == NULL) return '\0'; 47 48 // Read the file line by line looking for the state line. 49 const char *prompt = "State:\t"; 50 while (!feof(f)) { 51 fgets(s, sizeof(s), f); 52 if (!strncmp(s, prompt, strlen(prompt))) { 53 fclose(f); 54 return s[strlen(prompt)]; 55 } 56 } 57 fclose(f); 58 return '?'; 59 #endif 60 #ifdef __FreeBSD__ 61 // First check if the process exists/we have permission to see it. This 62 // Avoids warning messages being printed to stderr by libprocstat. 63 size_t len = 0; 64 int name[4]; 65 name[0] = CTL_KERN; 66 name[1] = KERN_PROC; 67 name[2] = KERN_PROC_PID; 68 name[3] = pid; 69 if (sysctl(name, nitems(name), NULL, &len, NULL, 0) < 0 && errno == ESRCH) { 70 if (verbose) fprintf(stderr, "Process %d does not exist\n", pid); 71 return '\0'; // No such process. 72 } 73 unsigned int count = 0; 74 struct procstat *prstat = procstat_open_sysctl(); 75 EXPECT_NE(nullptr, prstat) << "procstat_open_sysctl failed."; 76 errno = 0; 77 struct kinfo_proc *p = procstat_getprocs(prstat, KERN_PROC_PID, pid, &count); 78 if (p == NULL || count == 0) { 79 if (verbose) { 80 fprintf(stderr, "procstat_getprocs failed with %p/%d: %s\n", (void *)p, 81 count, strerror(errno)); 82 } 83 procstat_close(prstat); 84 return '\0'; 85 } 86 char result = '\0'; 87 // See state() in bin/ps/print.c 88 switch (p->ki_stat) { 89 case SSTOP: 90 result = 'T'; 91 break; 92 case SSLEEP: 93 if (p->ki_tdflags & TDF_SINTR) /* interruptable (long) */ 94 result = 'S'; 95 else 96 result = 'D'; 97 break; 98 case SRUN: 99 case SIDL: 100 result = 'R'; 101 break; 102 case SWAIT: 103 case SLOCK: 104 // We treat SWAIT/SLOCK as 'S' here (instead of 'W'/'L'). 105 result = 'S'; 106 break; 107 case SZOMB: 108 result = 'Z'; 109 break; 110 default: 111 result = '?'; 112 break; 113 } 114 procstat_freeprocs(prstat, p); 115 procstat_close(prstat); 116 if (verbose) fprintf(stderr, "Process %d in state '%c'\n", pid, result); 117 return result; 118 #endif 119 } 120