Skip to content

Commit de8aed6

Browse files
author
olevole
committed
playing with pexec
1 parent ae7ea47 commit de8aed6

File tree

4 files changed

+162
-0
lines changed

4 files changed

+162
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ misc/exec_jail
1010
misc/src/cbsd_md5/cbsd_md5
1111
misc/cbsdlogtail
1212
misc/cbsdtee
13+
misc/pexec
1314
misc/chk_arp_byip
1415
misc/conv2human
1516
misc/daemon

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ distclean:
4141
${RM} -f misc/chk_arp_byip
4242
${RM} -f misc/cbsdtee
4343
${RM} -f misc/daemonize
44+
${RM} -f misc/pexec
4445
${RM} -f bin/cbsdsftp
4546
${RM} -f bin/cbsdsftp6
4647
${RM} -f bin/cfetch
@@ -119,6 +120,7 @@ cbsd: pkg-config-check
119120
${CC} misc/src/pwcrypt.c -lcrypt -o misc/pwcrypt && ${STRIP} misc/pwcrypt
120121
${CC} misc/src/chk_arp_byip.c -o misc/chk_arp_byip && ${STRIP} misc/chk_arp_byip
121122
${CC} misc/src/cbsdtee.c -o misc/cbsdtee && ${STRIP} misc/cbsdtee
123+
${CC} misc/src/pexec.c -o misc/pexec && ${STRIP} misc/pexec
122124
${CC} misc/src/elf_tables.c -I/usr/local/include -I/usr/local/include/libelf -L/usr/local/lib -lelf -o misc/elf_tables && ${STRIP} misc/elf_tables
123125
${CC} misc/src/fmagic.c -lmagic -o misc/fmagic && ${STRIP} misc/fmagic
124126
${CC} misc/src/getshell.c -o misc/getshell && ${STRIP} misc/getshell

misc/src/pexec.c

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <sys/types.h>
4+
#include <sys/wait.h>
5+
#include <unistd.h>
6+
#include <time.h>
7+
#include <string.h>
8+
#include <sys/resource.h>
9+
10+
11+
int main(int argc, char *argv[]) {
12+
if (argc < 2) {
13+
fprintf(stderr, "Usage: %s \"command1 args\" \"command2 args\" ...\n", argv[0]);
14+
return EXIT_FAILURE;
15+
}
16+
int stats_enabled = 0;
17+
int n = 0;
18+
char **cmd_argv = malloc((argc - 1) * sizeof(char*));
19+
for (int i = 1; i < argc; ++i) {
20+
if (strcmp(argv[i], "-s") == 0) {
21+
stats_enabled = 1;
22+
} else {
23+
cmd_argv[n++] = argv[i];
24+
}
25+
}
26+
if (n < 1) {
27+
fprintf(stderr, "Usage: %s [-s] \"command1 args\" \"command2 args\" ...\n", argv[0]);
28+
free(cmd_argv);
29+
return EXIT_FAILURE;
30+
}
31+
pid_t *pids = malloc(n * sizeof(pid_t));
32+
struct timespec *start_times = stats_enabled ? malloc(n * sizeof(struct timespec)) : NULL;
33+
struct timespec *end_times = stats_enabled ? malloc(n * sizeof(struct timespec)) : NULL;
34+
double *elapsed_times = stats_enabled ? malloc(n * sizeof(double)) : NULL;
35+
double *user_cpus = stats_enabled ? malloc(n * sizeof(double)) : NULL;
36+
double *sys_cpus = stats_enabled ? malloc(n * sizeof(double)) : NULL;
37+
long int *rss_values = stats_enabled ? malloc(n * sizeof(long int)) : NULL;
38+
char ***cmd_args = malloc(n * sizeof(char **));
39+
int error_found = 0;
40+
int status;
41+
42+
for (int i = 0; i < n; i++) {
43+
// max 64 args per command
44+
cmd_args[i] = malloc(65 * sizeof(char*));
45+
int arg_idx = 0;
46+
char *cmd_copy = strdup(cmd_argv[i]);
47+
char *token = strtok(cmd_copy, " ");
48+
while (token && arg_idx < 64) {
49+
cmd_args[i][arg_idx++] = strdup(token);
50+
token = strtok(NULL, " ");
51+
}
52+
cmd_args[i][arg_idx] = NULL;
53+
free(cmd_copy);
54+
}
55+
56+
for (int i = 0; i < n; i++) {
57+
if (stats_enabled) clock_gettime(CLOCK_MONOTONIC, &start_times[i]);
58+
pids[i] = fork();
59+
if (pids[i] < 0) {
60+
perror("fork");
61+
exit(EXIT_FAILURE);
62+
}
63+
if (pids[i] == 0) {
64+
execvp(cmd_args[i][0], cmd_args[i]);
65+
perror("execvp");
66+
exit(127);
67+
}
68+
}
69+
70+
for (int finished = 0; finished < n; finished++) {
71+
struct rusage usage;
72+
pid_t ended_pid = wait4(-1, &status, 0, stats_enabled ? &usage : NULL);
73+
if (ended_pid == -1) {
74+
perror("wait4");
75+
error_found = 1;
76+
continue;
77+
}
78+
int cmd_idx = -1;
79+
for (int j = 0; j < n; j++) {
80+
if (pids[j] == ended_pid) {
81+
cmd_idx = j;
82+
break;
83+
}
84+
}
85+
if (cmd_idx == -1) {
86+
printf("unknown pid: %d\n", ended_pid);
87+
continue;
88+
}
89+
if (stats_enabled) {
90+
clock_gettime(CLOCK_MONOTONIC, &end_times[cmd_idx]);
91+
elapsed_times[cmd_idx] = (end_times[cmd_idx].tv_sec - start_times[cmd_idx].tv_sec) +
92+
(end_times[cmd_idx].tv_nsec - start_times[cmd_idx].tv_nsec) / 1e9;
93+
}
94+
double user_cpu = 0, sys_cpu = 0;
95+
long int ru_maxrss = 0;
96+
if (stats_enabled) {
97+
user_cpu = usage.ru_utime.tv_sec + usage.ru_utime.tv_usec / 1e6;
98+
sys_cpu = usage.ru_stime.tv_sec + usage.ru_stime.tv_usec / 1e6;
99+
ru_maxrss = usage.ru_maxrss;
100+
user_cpus[cmd_idx] = user_cpu;
101+
sys_cpus[cmd_idx] = sys_cpu;
102+
rss_values[cmd_idx] = ru_maxrss;
103+
}
104+
105+
if (WIFEXITED(status)) {
106+
int exit_code = WEXITSTATUS(status);
107+
if (exit_code != 0) {
108+
printf("Process %d (%s) error: %d\n", ended_pid, cmd_args[cmd_idx][0], exit_code);
109+
error_found = 1;
110+
}
111+
} else {
112+
printf("Process %d (%s) error\n", ended_pid, cmd_args[cmd_idx][0]);
113+
error_found = 1;
114+
}
115+
if (stats_enabled) {
116+
printf("command '%s' success in %.3f sec, CPU: user %.3f c, system %.3f c, RSS: %ld\n",
117+
cmd_argv[cmd_idx], elapsed_times[cmd_idx], user_cpu, sys_cpu, ru_maxrss);
118+
} else {
119+
printf("command '%s' complete\n", cmd_argv[cmd_idx]);
120+
}
121+
}
122+
123+
for (int i = 0; i < n; i++) {
124+
for (int j = 0; cmd_args[i][j] != NULL; j++) {
125+
free(cmd_args[i][j]);
126+
}
127+
free(cmd_args[i]);
128+
}
129+
free(cmd_args);
130+
free(pids);
131+
if (stats_enabled) {
132+
free(start_times);
133+
free(end_times);
134+
// sum stats
135+
double total_elapsed = 0, total_user = 0, total_sys = 0;
136+
long int total_rss = 0;
137+
for (int i = 0; i < n; i++) {
138+
total_elapsed += elapsed_times[i];
139+
total_user += user_cpus[i];
140+
total_sys += sys_cpus[i];
141+
total_rss += rss_values[i];
142+
}
143+
printf("\nSum stats: time: %.3f sec, CPU: user %.3f c, system %.3f c, RSS sum: %ld\n",
144+
total_elapsed, total_user, total_sys, total_rss);
145+
free(elapsed_times);
146+
free(user_cpus);
147+
free(sys_cpus);
148+
free(rss_values);
149+
}
150+
free(cmd_argv);
151+
152+
if (error_found) {
153+
printf("some processes terminated with an error.\n");
154+
return EXIT_FAILURE;
155+
}
156+
157+
return EXIT_SUCCESS;
158+
}

sudoexec/initenv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,7 @@ phase2()
581581
fi
582582
[ ! -f "${distdir}/misc/efivar" ] && compile_cc ${distdir}/misc/src/efivar.c -o ${distdir}/misc/efivar
583583
[ ! -f "${distdir}/misc/cbsdtee" ] && compile_cc ${distdir}/misc/src/cbsdtee.c -o ${distdir}/misc/cbsdtee
584+
[ ! -f "${distdir}/misc/pexec" ] && compile_cc ${distdir}/misc/src/pexec.c -o ${distdir}/misc/pexec
584585
[ ! -f "${distdir}/tools/imghelper" ] && compile_cc ${distdir}/tools/src/imghelper.c -o ${distdir}/tools/imghelper
585586
[ ! -f "${distdir}/misc/cbsdlogtail" ] && compile_cc ${distdir}/misc/src/cbsdlogtail.c -o ${distdir}/misc/cbsdlogtail
586587
[ ! -f "${distdir}/misc/daemonize" ] && compile_cc ${distdir}/misc/src/daemonize/daemonize.c ${distdir}/misc/src/daemonize/getopt.c -I${distdir}/misc/src/daemonize -O2 -o ${distdir}/misc/daemonize

0 commit comments

Comments
 (0)