You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
2.0 KiB
76 lines
2.0 KiB
/* logwrapper.c - Record commands called out of $PATH to a log
|
|
*
|
|
* Copyright 2019 Rob Landley <rob@landley.net>
|
|
*
|
|
* I made it up. Must be built standalone to work. (Is its own multiplexer.)
|
|
|
|
USE_LOGWRAPPER(NEWTOY(logwrapper, 0, TOYFLAG_NOHELP|TOYFLAG_USR|TOYFLAG_BIN))
|
|
|
|
config LOGWRAPPER
|
|
bool "logwrapper"
|
|
default n
|
|
help
|
|
usage: logwrapper ...
|
|
|
|
Append command line to $WRAPLOG, then call second instance
|
|
of command in $PATH.
|
|
*/
|
|
|
|
#define FOR_logwrapper
|
|
#include "toys.h"
|
|
|
|
void logwrapper_main(void)
|
|
{
|
|
char *log = getenv("WRAPLOG"), *omnom = basename(*toys.argv),
|
|
*s, *ss, *sss;
|
|
struct string_list *list;
|
|
int i, len;
|
|
|
|
// Log the command line
|
|
if (!log) error_exit("no $WRAPLOG");
|
|
len = strlen(omnom)+2;
|
|
for (i = 0; i<toys.optc; i++) len += 2*strlen(toys.optargs[i])+3;
|
|
ss = stpcpy(s = xmalloc(len), omnom);
|
|
|
|
// Copy arguments surrounded by quotes with \ escapes for " \ or \n
|
|
for (i = 0; i<toys.optc; i++) {
|
|
*(ss++) = ' ';
|
|
*(ss++) = '"';
|
|
for (sss = toys.optargs[i]; *sss; sss++) {
|
|
if (-1 == (len = stridx("\n\\\"", *sss))) *(ss++) = *sss;
|
|
else {
|
|
*(ss++) = '\\';
|
|
*(ss++) = "n\\\""[len];
|
|
}
|
|
}
|
|
*(ss++) = '"';
|
|
}
|
|
*(ss++) = '\n';
|
|
|
|
// Atomically append to log and free buffer
|
|
i = xcreate(log, O_RDWR|O_CREAT|O_APPEND, 0644);
|
|
xwrite(i, s, ss-s);
|
|
close(i);
|
|
free(s);
|
|
|
|
// Run next instance in $PATH after this one. If we were called via absolute
|
|
// path search for this instance, otherwise assume we're first instance
|
|
list = find_in_path(getenv("PATH"), omnom);
|
|
if (**toys.argv == '/') {
|
|
while (list) {
|
|
if (!strcmp(list->str, *toys.argv)) break;
|
|
free(llist_pop(&list));
|
|
}
|
|
}
|
|
|
|
// Skip first instance and try to run next one, until out of instances.
|
|
for (;;) {
|
|
if (list) free(llist_pop(&list));
|
|
if (!list)
|
|
error_exit("no %s after %s in $PATH=%s", omnom,
|
|
**toys.argv == '/' ? *toys.argv : "logwrapper", getenv("PATH"));
|
|
*toys.argv = list->str;
|
|
execve(list->str, toys.argv, environ);
|
|
}
|
|
}
|