X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=udev_utils_run.c;h=1315154c2678c27d9c869fe3fdc2100b0aad6764;hp=50b31781e7f31d6d3f1dfa6ff8f8962cc346ca1c;hb=f1ff8d7b4ad1f95385d42c3fa1b2a997b9e6d5f5;hpb=27f877e60f1c1793d6fafdd888e7e367c44b2eb9 diff --git a/udev_utils_run.c b/udev_utils_run.c index 50b31781e..1315154c2 100644 --- a/udev_utils_run.c +++ b/udev_utils_run.c @@ -46,7 +46,8 @@ int pass_env_to_socket(const char *sockname, const char *devpath, const char *ac char buf[2048]; size_t bufpos = 0; int i; - int retval; + ssize_t count; + int retval = 0; dbg("pass environment to socket '%s'", sockname); sock = socket(AF_LOCAL, SOCK_DGRAM, 0); @@ -63,23 +64,23 @@ int pass_env_to_socket(const char *sockname, const char *devpath, const char *ac bufpos++; } - retval = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, addrlen); - if (retval != -1) - retval = 0; + count = sendto(sock, &buf, bufpos, 0, (struct sockaddr *)&saddr, addrlen); + if (count < 0) + retval = -1; + info("passed %zi bytes to socket '%s', ", count, sockname); close(sock); return retval; } int run_program(const char *command, const char *subsystem, - char *result, size_t ressize, size_t *reslen, int dbg) + char *result, size_t ressize, size_t *reslen, int log) { int retval = 0; int status; int outpipe[2] = {-1, -1}; int errpipe[2] = {-1, -1}; pid_t pid; - char *pos; char arg[PATH_SIZE]; char *argv[(sizeof(arg) / 2) + 1]; int devnull; @@ -88,7 +89,7 @@ int run_program(const char *command, const char *subsystem, strlcpy(arg, command, sizeof(arg)); i = 0; if (strchr(arg, ' ')) { - pos = arg; + char *pos = arg; while (pos != NULL) { if (pos[0] == '\'') { /* don't separate if in apostrophes */ @@ -103,22 +104,22 @@ int run_program(const char *command, const char *subsystem, i++; } argv[i] = NULL; - dbg("execute '%s' with parsed arguments", arg); + info("'%s'", command); } else { argv[0] = arg; argv[1] = (char *) subsystem; argv[2] = NULL; - dbg("execute '%s' with subsystem '%s' argument", arg, argv[1]); + info("'%s' '%s'", arg, argv[1]); } /* prepare pipes from child to parent */ - if (result || dbg) { + if (result || log) { if (pipe(outpipe) != 0) { err("pipe failed"); return -1; } } - if (dbg) { + if (log) { if (pipe(errpipe) != 0) { err("pipe failed"); return -1; @@ -129,61 +130,57 @@ int run_program(const char *command, const char *subsystem, switch(pid) { case 0: /* child closes parent ends of pipes */ - if (outpipe[0] > 0) - close(outpipe[0]); - if (errpipe[0] > 0) - close(errpipe[0]); + if (outpipe[READ_END] > 0) + close(outpipe[READ_END]); + if (errpipe[READ_END] > 0) + close(errpipe[READ_END]); /* discard child output or connect to pipe */ devnull = open("/dev/null", O_RDWR); - if (devnull < 0) { + if (devnull > 0) { + dup2(devnull, STDIN_FILENO); + if (outpipe[WRITE_END] < 0) + dup2(devnull, STDOUT_FILENO); + if (errpipe[WRITE_END] < 0) + dup2(devnull, STDERR_FILENO); + close(devnull); + } else err("open /dev/null failed"); - exit(1); - } - dup2(devnull, STDIN_FILENO); - - if (outpipe[1] > 0) - dup2(outpipe[1], STDOUT_FILENO); - else - dup2(devnull, STDOUT_FILENO); - - if (errpipe[1] > 0) - dup2(errpipe[1], STDERR_FILENO); - else - dup2(devnull, STDERR_FILENO); - - close(devnull); - execv(arg, argv); + if (outpipe[WRITE_END] > 0) + dup2(outpipe[WRITE_END], STDOUT_FILENO); + if (errpipe[WRITE_END] > 0) + dup2(errpipe[WRITE_END], STDERR_FILENO); + execv(argv[0], argv); /* we should never reach this */ - err("exec of program failed"); + err("exec of program '%s' failed", argv[0]); _exit(1); case -1: - err("fork of '%s' failed", arg); + err("fork of '%s' failed", argv[0]); return -1; default: /* read from child if requested */ - if (outpipe[0] > 0 || errpipe[0] > 0) { - size_t count; + if (outpipe[READ_END] > 0 || errpipe[READ_END] > 0) { + ssize_t count; size_t respos = 0; /* parent closes child ends of pipes */ - if (outpipe[1] > 0) - close(outpipe[1]); - if (errpipe[1] > 0) - close(errpipe[1]); + if (outpipe[WRITE_END] > 0) + close(outpipe[WRITE_END]); + if (errpipe[WRITE_END] > 0) + close(errpipe[WRITE_END]); /* read child output */ - while (outpipe[0] > 0 || errpipe[0] > 0) { + while (outpipe[READ_END] > 0 || errpipe[READ_END] > 0) { int fdcount; fd_set readfds; FD_ZERO(&readfds); - if (outpipe[0] > 0) - FD_SET(outpipe[0], &readfds); - if (errpipe[0] > 0) - FD_SET(errpipe[0], &readfds); - fdcount = select(UDEV_MAX(outpipe[0], errpipe[0])+1, &readfds, NULL, NULL, NULL); + if (outpipe[READ_END] > 0) + FD_SET(outpipe[READ_END], &readfds); + if (errpipe[READ_END] > 0) + FD_SET(errpipe[READ_END], &readfds); + fdcount = select(UDEV_MAX(outpipe[READ_END], errpipe[READ_END])+1, &readfds, NULL, NULL, NULL); if (fdcount < 0) { if (errno == EINTR) continue; @@ -192,13 +189,15 @@ int run_program(const char *command, const char *subsystem, } /* get stdout */ - if (outpipe[0] > 0 && FD_ISSET(outpipe[0], &readfds)) { + if (outpipe[READ_END] > 0 && FD_ISSET(outpipe[READ_END], &readfds)) { char inbuf[1024]; + char *pos; + char *line; - count = read(outpipe[0], inbuf, sizeof(inbuf)-1); + count = read(outpipe[READ_END], inbuf, sizeof(inbuf)-1); if (count <= 0) { - close(outpipe[0]); - outpipe[0] = -1; + close(outpipe[READ_END]); + outpipe[READ_END] = -1; if (count < 0) { err("stdin read failed with '%s'", strerror(errno)); retval = -1; @@ -206,39 +205,48 @@ int run_program(const char *command, const char *subsystem, continue; } inbuf[count] = '\0'; - dbg("stdout: '%s'", inbuf); + /* store result for rule processing */ if (result) { - if (respos + count >= ressize) { + if (respos + count < ressize) { + memcpy(&result[respos], inbuf, count); + respos += count; + } else { err("ressize %ld too short", (long)ressize); retval = -1; - continue; } - memcpy(&result[respos], inbuf, count); - respos += count; } + pos = inbuf; + while ((line = strsep(&pos, "\n"))) + if (pos || line[0] != '\0') + info("'%s' (stdout) '%s'", argv[0], line); } /* get stderr */ - if (errpipe[0] > 0 && FD_ISSET(errpipe[0], &readfds)) { + if (errpipe[READ_END] > 0 && FD_ISSET(errpipe[READ_END], &readfds)) { char errbuf[1024]; + char *pos; + char *line; - count = read(errpipe[0], errbuf, sizeof(errbuf)-1); + count = read(errpipe[READ_END], errbuf, sizeof(errbuf)-1); if (count <= 0) { - close(errpipe[0]); - errpipe[0] = -1; + close(errpipe[READ_END]); + errpipe[READ_END] = -1; if (count < 0) err("stderr read failed with '%s'", strerror(errno)); continue; } errbuf[count] = '\0'; - dbg("stderr: '%s'", errbuf); + pos = errbuf; + while ((line = strsep(&pos, "\n"))) + if (pos || line[0] != '\0') + info("'%s' (stderr) '%s'", argv[0], line); } } - if (outpipe[0] > 0) - close(outpipe[0]); - if (errpipe[0] > 0) - close(errpipe[0]); + if (outpipe[READ_END] > 0) + close(outpipe[READ_END]); + if (errpipe[READ_END] > 0) + close(errpipe[READ_END]); /* return the childs stdout string */ if (result) { @@ -249,8 +257,12 @@ int run_program(const char *command, const char *subsystem, } } waitpid(pid, &status, 0); - if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { - dbg("exec program status 0x%x", status); + if (WIFEXITED(status)) { + info("'%s' returned with status %i", argv[0], WEXITSTATUS(status)); + if (WEXITSTATUS(status) != 0) + retval = -1; + } else { + err("'%s' abnormal exit", argv[0]); retval = -1; } }