1 |
#include <stdio.h> |
2 |
#include <stdlib.h> |
3 |
#include <unistd.h> |
4 |
#include <errno.h> |
5 |
#include <string.h> |
6 |
#include <sys/times.h> |
7 |
#include <sys/types.h> |
8 |
#include <sys/wait.h> |
9 |
#include <grp.h> |
10 |
|
11 |
#define UNOBODY 99 |
12 |
#define GNOBODY 99 |
13 |
|
14 |
#define SRCUID 500 |
15 |
#define TGTUID UNOBODY |
16 |
#define TGTGID GNOBODY |
17 |
|
18 |
static const char sccsid[] = "@(#)$Id$"; |
19 |
|
20 |
extern int optind; |
21 |
extern char *optarg; |
22 |
|
23 |
/* The GNU C library cannot parse options correctly unless "+" is used */ |
24 |
#if defined __GNUC__ |
25 |
#define OPTSTRING "+q" |
26 |
#else |
27 |
#define OPTSTRING "q" |
28 |
#endif |
29 |
|
30 |
int main(argc,argv) |
31 |
int argc; |
32 |
char **argv; |
33 |
{ |
34 |
|
35 |
struct tms tms_start,tms_stop; |
36 |
clock_t t_start,t_end; |
37 |
clock_t clock_ticks = 0; |
38 |
|
39 |
pid_t pid_child,wpid; |
40 |
int rc; |
41 |
int c; |
42 |
int opt_quiet = 0; |
43 |
|
44 |
while ( (c = getopt(argc,argv,OPTSTRING)) > 0 ) { |
45 |
switch (c) { |
46 |
case 'q': opt_quiet++; break; |
47 |
default: |
48 |
fprintf(stderr,"Invalid options: exiting.\n"); |
49 |
exit(EXIT_FAILURE); |
50 |
break; |
51 |
} |
52 |
} |
53 |
|
54 |
if (optind >= argc ) { |
55 |
fprintf(stderr,"Usage: %s [-q] command [arguments]\n", |
56 |
argv[0]); |
57 |
exit(EXIT_FAILURE); |
58 |
} |
59 |
|
60 |
if ( getuid() != SRCUID ) { |
61 |
fprintf(stderr, |
62 |
"You are not allowed to experiment with %s:\n" |
63 |
"your uid %d is not a valid source uid\n", |
64 |
argv[0],getuid()); |
65 |
exit(EXIT_FAILURE); |
66 |
} |
67 |
|
68 |
rc=setgroups(0,NULL); |
69 |
if (rc) { |
70 |
printf("Could not clear supplementary groups (error %d): %s\n", |
71 |
errno,strerror(errno)); |
72 |
exit(EXIT_FAILURE); |
73 |
} |
74 |
|
75 |
rc=setgid(TGTGID); |
76 |
if (rc) { |
77 |
printf("Could not set primary group to %d (error %d): %s\n", |
78 |
TGTGID,errno,strerror(errno)); |
79 |
exit(EXIT_FAILURE); |
80 |
} |
81 |
|
82 |
rc=setuid(TGTUID); |
83 |
if (rc) { |
84 |
printf("Could not change identity to uid %d (error %d): %s\n", |
85 |
TGTUID,errno,strerror(errno)); |
86 |
exit(EXIT_FAILURE); |
87 |
} |
88 |
|
89 |
if ( ! opt_quiet ) |
90 |
printf("Notice: identity changed to uid %d\n",geteuid()); |
91 |
|
92 |
clock_ticks = sysconf(_SC_CLK_TCK); |
93 |
|
94 |
t_start = times(&tms_start); |
95 |
|
96 |
pid_child = fork(); |
97 |
|
98 |
switch(pid_child) { |
99 |
case 0: /* we are the child */ |
100 |
rc=execvp(argv[optind],argv+optind); |
101 |
printf("Child execvp of %s failed (error %d): %s\n", |
102 |
argv[optind],errno,strerror(errno)); |
103 |
exit(EXIT_FAILURE); |
104 |
break ;; |
105 |
case -1: |
106 |
fprintf(stderr,"Cannot fork (error %d); %s\n", |
107 |
errno,strerror(errno)); |
108 |
exit(EXIT_FAILURE); |
109 |
default: |
110 |
wpid = waitpid(pid_child, &rc, 0); |
111 |
t_end = times(&tms_stop); |
112 |
|
113 |
if ( ! opt_quiet ) { |
114 |
printf("times utime/stime: real/user/sys (%f/%f/%f)\n", |
115 |
(double)(t_end - t_start)/clock_ticks, |
116 |
(double)(tms_stop.tms_utime - |
117 |
tms_start.tms_utime)/clock_ticks, |
118 |
(double)(tms_stop.tms_stime - |
119 |
tms_start.tms_stime)/clock_ticks); |
120 |
printf("times cutime/cstime: real/user/sys (%f/%f/%f)\n", |
121 |
(double)(t_end - t_start)/clock_ticks, |
122 |
(double)(tms_stop.tms_cutime - |
123 |
tms_start.tms_cutime)/clock_ticks, |
124 |
(double)(tms_stop.tms_cstime - |
125 |
tms_start.tms_cstime)/clock_ticks); |
126 |
printf("Child return code: %d\n",rc); |
127 |
} |
128 |
break ; |
129 |
} |
130 |
|
131 |
return (EXIT_SUCCESS); |
132 |
} |