Git init
[external/ltrace.git] / execute_program.c
1 #include "config.h"
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <string.h>
10 #include <pwd.h>
11 #include <grp.h>
12
13 #include "common.h"
14
15 static void
16 change_uid(Process *proc) {
17         uid_t run_uid, run_euid;
18         gid_t run_gid, run_egid;
19
20         if (options.user) {
21                 struct passwd *pent;
22
23                 if (getuid() != 0 || geteuid() != 0) {
24                         fprintf(stderr,
25                                 "you must be root to use the -u option\n");
26                         exit(1);
27                 }
28                 if ((pent = getpwnam(options.user)) == NULL) {
29                         fprintf(stderr, "cannot find user `%s'\n", options.user);
30                         exit(1);
31                 }
32                 run_uid = pent->pw_uid;
33                 run_gid = pent->pw_gid;
34
35                 if (initgroups(options.user, run_gid) < 0) {
36                         perror("ltrace: initgroups");
37                         exit(1);
38                 }
39         } else {
40                 run_uid = getuid();
41                 run_gid = getgid();
42         }
43         if (options.user || !geteuid()) {
44                 struct stat statbuf;
45                 run_euid = run_uid;
46                 run_egid = run_gid;
47
48                 if (!stat(proc->filename, &statbuf)) {
49                         if (statbuf.st_mode & S_ISUID) {
50                                 run_euid = statbuf.st_uid;
51                         }
52                         if (statbuf.st_mode & S_ISGID) {
53                                 run_egid = statbuf.st_gid;
54                         }
55                 }
56                 if (setregid(run_gid, run_egid) < 0) {
57                         perror("ltrace: setregid");
58                         exit(1);
59                 }
60                 if (setreuid(run_uid, run_euid) < 0) {
61                         perror("ltrace: setreuid");
62                         exit(1);
63                 }
64         }
65 }
66
67 void
68 execute_program(Process *sp, char **argv) {
69         pid_t pid;
70
71         debug(1, "Executing `%s'...", sp->filename);
72
73         pid = fork();
74         if (pid < 0) {
75                 perror("ltrace: fork");
76                 exit(1);
77         } else if (!pid) {      /* child */
78                 change_uid(sp);
79                 trace_me();
80                 execvp(sp->filename, argv);
81                 fprintf(stderr, "Can't execute `%s': %s\n", sp->filename,
82                         strerror(errno));
83                 _exit(1);
84         }
85
86         debug(1, "PID=%d", pid);
87
88         sp->pid = pid;
89
90         return;
91 }