static void decode_execve(struct tcb *tcp, const unsigned int index) { printpath(tcp, tcp->u_arg[index + 0]); tprints(", "); if (!tcp->u_arg[index + 1] || !verbose(tcp)) printaddr(tcp->u_arg[index + 1]); else { tprints("["); printargv(tcp, tcp->u_arg[index + 1]); tprints("]"); } tprints(", "); if (!tcp->u_arg[index + 2] || !verbose(tcp)) printaddr(tcp->u_arg[index + 2]); else if (abbrev(tcp)) printargc("[/* %d var%s */]", tcp, tcp->u_arg[index + 2]); else { tprints("["); printargv(tcp, tcp->u_arg[index + 2]); tprints("]"); } }
int main() { char buf[1024]; s2argv_getvar=getenv; while (1) { char **myargv; if (fgets(buf,1024,stdin) == NULL) return 0; buf[strlen(buf)-1]=0; myargv=s2argv(buf); printargv(myargv); printf("len %zd argc %zd\n", s2argvlen(myargv), s2argc(myargv)); s2argv_free(myargv); s2multiargv(buf, print1argv, NULL); if (fork()==0) { eexecsp(buf); exit(-1); } else { int status; wait(&status); } } }
static void summarize(const char *fmt, char **command, resource_t *resp) { unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ unsigned cpu_ticks; /* Same, in "CPU ticks" */ unsigned pagesize = getpagesize(); /* Impossible: we do not use WUNTRACED flag in wait()... if (WIFSTOPPED(resp->waitstatus)) printf("Command stopped by signal %u\n", WSTOPSIG(resp->waitstatus)); else */ if (WIFSIGNALED(resp->waitstatus)) printf("Command terminated by signal %u\n", WTERMSIG(resp->waitstatus)); else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) printf("Command exited with non-zero status %u\n", WEXITSTATUS(resp->waitstatus)); vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; #if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000 /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */ cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC); #else cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; #endif if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */ while (*fmt) { /* Handle leading literal part */ int n = strcspn(fmt, "%\\"); if (n) { printf("%.*s", n, fmt); fmt += n; continue; } switch (*fmt) { #ifdef NOT_NEEDED /* Handle literal char */ /* Usually we optimize for size, but there is a limit * for everything. With this we do a lot of 1-byte writes */ default: bb_putchar(*fmt); break; #endif case '%': switch (*++fmt) { #ifdef NOT_NEEDED_YET /* Our format strings do not have these */ /* and we do not take format str from user */ default: bb_putchar('%'); /*FALLTHROUGH*/ case '%': if (!*fmt) goto ret; bb_putchar(*fmt); break; #endif case 'C': /* The command that got timed. */ printargv(command); break; case 'D': /* Average unshared data size. */ printf("%lu", (ptok(pagesize, (UL) resp->ru.ru_idrss) + ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks); break; case 'E': { /* Elapsed real (wall clock) time. */ unsigned seconds = resp->elapsed_ms / 1000; if (seconds >= 3600) /* One hour -> h:m:s. */ printf("%uh %um %02us", seconds / 3600, (seconds % 3600) / 60, seconds % 60); else printf("%um %u.%02us", /* -> m:s. */ seconds / 60, seconds % 60, (unsigned)(resp->elapsed_ms / 10) % 100); break; } case 'F': /* Major page faults. */ printf("%lu", resp->ru.ru_majflt); break; case 'I': /* Inputs. */ printf("%lu", resp->ru.ru_inblock); break; case 'K': /* Average mem usage == data+stack+text. */ printf("%lu", (ptok(pagesize, (UL) resp->ru.ru_idrss) + ptok(pagesize, (UL) resp->ru.ru_isrss) + ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks); break; case 'M': /* Maximum resident set size. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss)); break; case 'O': /* Outputs. */ printf("%lu", resp->ru.ru_oublock); break; case 'P': /* Percent of CPU this job got. */ /* % cpu is (total cpu time)/(elapsed time). */ if (resp->elapsed_ms > 0) printf("%u%%", (unsigned)(vv_ms * 100 / resp->elapsed_ms)); else printf("?%%"); break; case 'R': /* Minor page faults (reclaims). */ printf("%lu", resp->ru.ru_minflt); break; case 'S': /* System time. */ printf("%u.%02u", (unsigned)resp->ru.ru_stime.tv_sec, (unsigned)(resp->ru.ru_stime.tv_usec / 10000)); break; case 'T': /* System time. */ if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%uh %um %02us", (unsigned)(resp->ru.ru_stime.tv_sec / 3600), (unsigned)(resp->ru.ru_stime.tv_sec % 3600) / 60, (unsigned)(resp->ru.ru_stime.tv_sec % 60)); else printf("%um %u.%02us", /* -> m:s. */ (unsigned)(resp->ru.ru_stime.tv_sec / 60), (unsigned)(resp->ru.ru_stime.tv_sec % 60), (unsigned)(resp->ru.ru_stime.tv_usec / 10000)); break; case 'U': /* User time. */ printf("%u.%02u", (unsigned)resp->ru.ru_utime.tv_sec, (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); break; case 'u': /* User time. */ if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%uh %um %02us", (unsigned)(resp->ru.ru_utime.tv_sec / 3600), (unsigned)(resp->ru.ru_utime.tv_sec % 3600) / 60, (unsigned)(resp->ru.ru_utime.tv_sec % 60)); else printf("%um %u.%02us", /* -> m:s. */ (unsigned)(resp->ru.ru_utime.tv_sec / 60), (unsigned)(resp->ru.ru_utime.tv_sec % 60), (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); break; case 'W': /* Times swapped out. */ printf("%lu", resp->ru.ru_nswap); break; case 'X': /* Average shared text size. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks); break; case 'Z': /* Page size. */ printf("%u", pagesize); break; case 'c': /* Involuntary context switches. */ printf("%lu", resp->ru.ru_nivcsw); break; case 'e': /* Elapsed real time in seconds. */ printf("%u.%02u", (unsigned)resp->elapsed_ms / 1000, (unsigned)(resp->elapsed_ms / 10) % 100); break; case 'k': /* Signals delivered. */ printf("%lu", resp->ru.ru_nsignals); break; case 'p': /* Average stack segment. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks); break; case 'r': /* Incoming socket messages received. */ printf("%lu", resp->ru.ru_msgrcv); break; case 's': /* Outgoing socket messages sent. */ printf("%lu", resp->ru.ru_msgsnd); break; case 't': /* Average resident set size. */ printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks); break; case 'w': /* Voluntary context switches. */ printf("%lu", resp->ru.ru_nvcsw); break; case 'x': /* Exit status. */ printf("%u", WEXITSTATUS(resp->waitstatus)); break; } break; #ifdef NOT_NEEDED_YET case '\\': /* Format escape. */ switch (*++fmt) { default: bb_putchar('\\'); /*FALLTHROUGH*/ case '\\': if (!*fmt) goto ret; bb_putchar(*fmt); break; case 't': bb_putchar('\t'); break; case 'n': bb_putchar('\n'); break; } break; #endif } ++fmt; } /* ret: */ bb_putchar('\n'); }
static void summarize(const char *fmt, char **command, resource_t * resp) { unsigned long r; /* Elapsed real milliseconds. */ unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ if (WIFSTOPPED(resp->waitstatus)) printf("Command stopped by signal %d\n", WSTOPSIG(resp->waitstatus)); else if (WIFSIGNALED(resp->waitstatus)) printf("Command terminated by signal %d\n", WTERMSIG(resp->waitstatus)); else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) printf("Command exited with non-zero status %d\n", WEXITSTATUS(resp->waitstatus)); /* Convert all times to milliseconds. Occasionally, one of these values comes out as zero. Dividing by zero causes problems, so we first check the time value. If it is zero, then we take `evasive action' instead of calculating a value. */ r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000; v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC + resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC; /* putchar() != putc(stdout) in glibc! */ while (*fmt) { /* Handle leading literal part */ int n = strcspn(fmt, "%\\"); if (n) { printf("%.*s", n, fmt); fmt += n; continue; } switch (*fmt) { #ifdef NOT_NEEDED /* Handle literal char */ /* Usually we optimize for size, but there is a limit * for everything. With this we do a lot of 1-byte writes */ default: putc(*fmt, stdout); break; #endif case '%': switch (*++fmt) { #ifdef NOT_NEEDED_YET /* Our format strings do not have these */ /* and we do not take format str from user */ default: putc('%', stdout); /*FALLTHROUGH*/ case '%': if (!*fmt) goto ret; putc(*fmt, stdout); break; #endif case 'C': /* The command that got timed. */ printargv(command, " "); break; case 'D': /* Average unshared data size. */ printf("%lu", MSEC_TO_TICKS(v) == 0 ? 0 : ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v)); break; case 'E': /* Elapsed real (wall clock) time. */ if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%ldh %ldm %02lds", resp->elapsed.tv_sec / 3600, (resp->elapsed.tv_sec % 3600) / 60, resp->elapsed.tv_sec % 60); else printf("%ldm %ld.%02lds", /* -> m:s. */ resp->elapsed.tv_sec / 60, resp->elapsed.tv_sec % 60, resp->elapsed.tv_usec / 10000); break; case 'F': /* Major page faults. */ printf("%ld", resp->ru.ru_majflt); break; case 'I': /* Inputs. */ printf("%ld", resp->ru.ru_inblock); break; case 'K': /* Average mem usage == data+stack+text. */ printf("%lu", MSEC_TO_TICKS(v) == 0 ? 0 : ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) + ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v)); break; case 'M': /* Maximum resident set size. */ printf("%lu", ptok((UL) resp->ru.ru_maxrss)); break; case 'O': /* Outputs. */ printf("%ld", resp->ru.ru_oublock); break; case 'P': /* Percent of CPU this job got. */ /* % cpu is (total cpu time)/(elapsed time). */ if (r > 0) printf("%lu%%", (v * 100 / r)); else printf("?%%"); break; case 'R': /* Minor page faults (reclaims). */ printf("%ld", resp->ru.ru_minflt); break; case 'S': /* System time. */ printf("%ld.%02ld", resp->ru.ru_stime.tv_sec, resp->ru.ru_stime.TV_MSEC / 10); break; case 'T': /* System time. */ if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%ldh %ldm %02lds", resp->ru.ru_stime.tv_sec / 3600, (resp->ru.ru_stime.tv_sec % 3600) / 60, resp->ru.ru_stime.tv_sec % 60); else printf("%ldm %ld.%02lds", /* -> m:s. */ resp->ru.ru_stime.tv_sec / 60, resp->ru.ru_stime.tv_sec % 60, resp->ru.ru_stime.tv_usec / 10000); break; case 'U': /* User time. */ printf("%ld.%02ld", resp->ru.ru_utime.tv_sec, resp->ru.ru_utime.TV_MSEC / 10); break; case 'u': /* User time. */ if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ printf("%ldh %ldm %02lds", resp->ru.ru_utime.tv_sec / 3600, (resp->ru.ru_utime.tv_sec % 3600) / 60, resp->ru.ru_utime.tv_sec % 60); else printf("%ldm %ld.%02lds", /* -> m:s. */ resp->ru.ru_utime.tv_sec / 60, resp->ru.ru_utime.tv_sec % 60, resp->ru.ru_utime.tv_usec / 10000); break; case 'W': /* Times swapped out. */ printf("%ld", resp->ru.ru_nswap); break; case 'X': /* Average shared text size. */ printf("%lu", MSEC_TO_TICKS(v) == 0 ? 0 : ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v)); break; case 'Z': /* Page size. */ printf("%d", getpagesize()); break; case 'c': /* Involuntary context switches. */ printf("%ld", resp->ru.ru_nivcsw); break; case 'e': /* Elapsed real time in seconds. */ printf("%ld.%02ld", resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000); break; case 'k': /* Signals delivered. */ printf("%ld", resp->ru.ru_nsignals); break; case 'p': /* Average stack segment. */ printf("%lu", MSEC_TO_TICKS(v) == 0 ? 0 : ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v)); break; case 'r': /* Incoming socket messages received. */ printf("%ld", resp->ru.ru_msgrcv); break; case 's': /* Outgoing socket messages sent. */ printf("%ld", resp->ru.ru_msgsnd); break; case 't': /* Average resident set size. */ printf("%lu", MSEC_TO_TICKS(v) == 0 ? 0 : ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v)); break; case 'w': /* Voluntary context switches. */ printf("%ld", resp->ru.ru_nvcsw); break; case 'x': /* Exit status. */ printf("%d", WEXITSTATUS(resp->waitstatus)); break; } break; #ifdef NOT_NEEDED_YET case '\\': /* Format escape. */ switch (*++fmt) { default: putc('\\', stdout); /*FALLTHROUGH*/ case '\\': if (!*fmt) goto ret; putc(*fmt, stdout); break; case 't': putc('\t', stdout); break; case 'n': putc('\n', stdout); break; } break; #endif } ++fmt; } /* ret: */ putc('\n', stdout); }