static int run_applet_l(const char *arg, ...) { int (*applet)(int, char **); va_list ap; int ret, optind_saved, argc; char **argv; const char *argv0_saved; optind_saved = optind; argv0_saved = argv0; applet = lookup_applet(arg); if (!applet) return -1; /* This doesn't NULL terminate argv, but you should be using argc */ va_start(ap, arg); argc = 0; argv = NULL; while (arg) { argv = xrealloc(argv, sizeof(*argv) * ++argc); argv[argc - 1] = xstrdup(arg); arg = va_arg(ap, const char *); } va_end(ap); optind = 0; argv0 = argv[0]; ret = applet(argc, argv); while (argc--) free(argv[argc]); free(argv); optind = optind_saved; argv0 = argv0_saved; return ret; }
int q_main(int argc, char **argv) { int i, install; const char *p; APPLET func; if (argc == 0) return 1; argv0 = p = basename(argv[0]); if ((func = lookup_applet(p)) == NULL) return 1; if (strcmp("q", p) != 0) return (func)(argc, argv); if (argc == 1) q_usage(EXIT_FAILURE); install = 0; while ((i = GETOPT_LONG(Q, q, "+")) != -1) { switch (i) { COMMON_GETOPTS_CASES(q) case 'M': modpath = optarg; break; case 'i': install = 1; break; } } if (install) { char buf[_Q_PATH_MAX]; const char *prog, *dir; ssize_t rret; int fd, ret; if (!quiet) printf("Installing symlinks:\n"); #if defined(__MACH__) rret = proc_pidpath(getpid(), buf, sizeof(buf)); if (rret != -1) rret = strlen(buf); #elif defined(__sun) && defined(__SVR4) prog = getexecname(); rret = strlen(prog); if ((size_t)rret > sizeof(buf) - 1) { rret = -1; } else { snprintf(buf, sizeof(buf), "%s", prog); } #else rret = readlink("/proc/self/exe", buf, sizeof(buf) - 1); #endif if (rret == -1) { warnfp("haha no symlink love for you"); return 1; } buf[rret] = '\0'; prog = basename(buf); dir = dirname(buf); fd = open(dir, O_RDONLY|O_CLOEXEC|O_PATH); if (fd < 0) { warnfp("open(%s) failed", dir); return 1; } ret = 0; for (i = 1; applets[i].desc; ++i) { int r = symlinkat(prog, fd, applets[i].name); if (!quiet) printf(" %s ...\t[%s]\n", applets[i].name, r ? strerror(errno) : "OK"); if (r && errno != EEXIST) ret = 1; } close(fd); return ret; } if (argc == optind) q_usage(EXIT_FAILURE); if ((func = lookup_applet(argv[optind])) == NULL) return 1; /* In case of "q --option ... appletname ...", remove appletname from the * applet's args. */ if (optind > 1) { argv[0] = argv[optind]; for (i = optind; i < argc; ++i) argv[i] = argv[i + 1]; } else ++argv; optind = 0; /* reset so the applets can call getopt */ return (func)(argc - 1, argv); }