1#include <stdlib.h>
2#include <stdio.h>
3#include <errno.h>
4#include <sys/stat.h>
5#include <pwd.h>
6#include <unistd.h>
7#include <err.h>
8
9#include "dumpemacs.h"
10
11int decreasepriv(int debugflag);
12
13int runit(const char * const argv[], int dropprivs)
14{
15  pid_t child;
16  int ret;
17
18  child = fork();
19  if(child == 0) {
20    if(dropprivs && geteuid() == 0) {
21      ret = decreasepriv(0);
22      if(ret)
23	err(1, "failed to decrease privileges");
24
25    }
26
27    ret = execve(argv[0], (char * const *) argv, 0);
28    if(ret)
29      err(1, "execve(%s) failed", argv[0]);
30  } else {
31    do {
32      int status = 0;
33      pid_t rch = waitpid(child, &status, 0);
34      if(rch == -1)
35	err(1, "waitpid(%d)", child);
36
37      if(WIFSTOPPED(status))
38	continue;
39
40      if(WIFSIGNALED(status))
41	errx(1, "child exited on signal %d", WTERMSIG(status));
42
43      if(WIFEXITED(status)) {
44	if(WEXITSTATUS(status) == 0)
45	  break; // success
46	else
47	  errx(1, "child exited with status %d", WEXITSTATUS(status));
48      }
49
50    } while(1);
51  }
52
53  return 0;
54}
55
56
57int decreasepriv(int debugflag)
58{
59  struct passwd *nobody = NULL;
60  int ret;
61
62  nobody = getpwnam("nobody");
63  if(nobody == NULL)
64    err(1, "getpwnam(nobody) failed");
65
66
67  ret = initgroups(nobody->pw_name, nobody->pw_gid);
68  if(ret)
69    err(1, "initgroups() failed");
70
71  ret = setgid(nobody->pw_gid);
72  if(ret)
73    err(1, "setgid() failed");
74
75  ret = setuid(nobody->pw_uid);
76  if(ret)
77    err(1, "setuid() failed");
78
79
80  // system("id");
81
82  return 0;
83}
84