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