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