xref: /src/tests/sys/capsicum/capsicum-test.cc (revision fba81b33aabff74ad03d5f9f9663c176cf060fa6)
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 
TmpFile(const char * p)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 
ProcessState(int pid)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