static void read_answer(void) { char buf[8192]; int got_nl = 0; int len = 0; while (1) { int rc = read(sock, buf, sizeof(buf)); if (rc < 0) { warn_errno("read"); return; } if (!rc) die("unexpected EOF\n"); len += rc; // Last line should be empty (i.e. read "\n" or "...\n\n"). // Write everything but the last \n to stdout. if (got_nl && buf[0] == '\n') return; if (len == 1 && buf[0] == '\n') return; if (rc > 1 && buf[rc - 1] == '\n' && buf[rc - 2] == '\n') { write_all(1, buf, rc - 1); return; } got_nl = buf[rc - 1] == '\n'; write_all(1, buf, rc); } }
static void load_saved_environment(void) { _cleanup_free_ char *env = NULL; env = config_read_string("env"); if (!env) return; for (char *tok = strtok(env, "\n"); tok; tok = strtok(NULL, "\n")) { char *equals = strchr(tok, '='); if (!equals || !*equals) { warn("The environment line '%s' is invalid.", tok); continue; } *equals = '\0'; if (setenv(tok, equals + 1, true)) warn_errno("The environment line '%s' is invalid.", tok); } }
int main(int argc, char *argv[]) { unsigned int login = 0, usage = 0; if (argc > 1) { if (!strcmp(argv[1], "-l")) { login = 1; argv[1] = argv[0]; argv++; argc--; } else if (!strcmp(argv[1], "-v") || !strcmp(argv[1], "--version")) { printf("%s version %s\n Supported OSes: %s\n", argv[0], version, supported_oses); exit(0); } else if (*argv[1] == '-') { warn("unknown option: %s", argv[1]); usage = 2; } } if (argc < 2) usage = 1; if (usage) die(usage, "usage: %s [-l] <program> [args...]\n%s", argv[0], usage_msg); unsigned int os = 0; struct utsname u; if (uname(&u)) { warn_errno("uname failed"); goto reattach_failed; } if (strcmp(u.sysname, "Darwin")) { warn("unsupported OS sysname: %s", u.sysname); goto reattach_failed; } char *rest, *whole = strdup(u.release); if (!whole) { warn_errno("strdup failed"); goto reattach_failed; } rest = whole; strsep(&rest, "."); if (whole && *whole && whole != rest) { int major = atoi(whole); os = 100000; /* 10.1, 10.0 and prior betas/previews */ if (major >= 6) /* 10.2 and newer */ os += (major-4) * 100; } else warn("unparsable major release number: '%s'", u.release); free(whole); /* * change the 'os' variable to represent the "reattach variation" * instead of the major OS release * * older => 100500 with warning * 10.5 => 100500 * 10.6 => 100600 * 10.7 => 100600 * 10.8 => 100600 * 10.9 => 100600 * 10.10=> 101000 * 10.11=> 101000 * 10.12=> 101000 * newer => 101000 with warning */ if (100600 <= os && os <= 100900) os = 100600; else if (101000 <= os && os <= 101200) os = 101000; else if (os < 100500) { warn("%s: unsupported old OS, trying as if it were 10.5", argv[0]); os = 100500; } else if (os > 101200) { warn("%s: unsupported new OS, trying as if it were 10.10", argv[0]); os = 101000; } if (move_to_user_namespace(os) != 0) { reattach_failed: warn("%s: unable to reattach", argv[0]); } char **newargs = NULL; const char *file = argv[1]; if (login) { /* * For their argv[0], take the bit of file after the * last slash (the whole thing if there is no slash * or if that bit would be zero length) and prefix * it with '-'. */ char *arg0 = malloc(strlen(file) + 2); if (!arg0) goto exec_it; *arg0 = '-'; char *slash = strrchr(file, '/'); if (slash && slash[1]) strcpy(arg0+1, slash+1); else strcpy(arg0+1, file); /* use the rest of the args as they are */ newargs = malloc(sizeof(*newargs) * (argc)); if (!newargs) { free(arg0); goto exec_it; } newargs[0] = arg0; int arg = 2; for(; arg < argc; arg++) newargs[arg-1] = argv[arg]; newargs[arg-1] = NULL; } exec_it: if (execvp(file, newargs ? newargs : argv+1) < 0) die_errno(3, "%s: execv failed", argv[0]); if (newargs) { free(newargs[0]); free(newargs); } return 0; }
int main(int argc, char *argv[]) { unsigned int login = 0, usage = 0; if (argc > 1) { if (!strcmp(argv[1], "-l")) { login = 1; argv[1] = argv[0]; argv++; argc--; } else if (*argv[1] == '-') { warn("unkown option: %s", argv[1]); usage = 2; } } if (argc < 2) usage = 1; if (usage) die(usage, "usage: %s [-l] <program> [args...]\n%s", argv[0], usage_msg); unsigned int os = 0; struct utsname u; if (uname(&u)) { warn_errno("uname failed"); goto reattach_failed; } if (strcmp(u.sysname, "Darwin")) { warn("unsupported OS sysname: %s", u.sysname); goto reattach_failed; } char *rest, *whole = strdup(u.release); if (!whole) { warn_errno("strdup failed"); goto reattach_failed; } rest = whole; strsep(&rest, "."); if (whole && *whole && whole != rest) { int major = atoi(whole); if (major >= 6) /* 10.2 and newer */ os = 1000 + (major-4) * 10; else /* 10.1, 10.0 and prior betas/previews */ os = 1000; } else warn("unparsable major release number: '%s'", u.release); free(whole); /* * change the 'os' variable to represent the "reattach variation" * instead of the major OS release * * older => 1050 with warning * 10.5 => 1050 * 10.6 => 1060 * 10.7 => 1060 * 10.8 => 1060 * newer => 1060 with warning */ if (1060 <= os && os <= 1080) os = 1060; else if (os < 1050) { warn("%s: unsupported old OS, trying as if it were 10.5", argv[0]); os = 1050; } else if (os > 1060) { warn("%s: unsupported new OS, trying as if it were 10.6-10.8", argv[0]); os = 1060; } switch(os) { case 1050: case 1060: { static const char fn[] = "_vprocmgr_move_subset_to_user"; void *(*f)(); if (!(f = (void *(*)()) dlsym(RTLD_NEXT, fn))) { warn("unable to find %s: %s", fn, dlerror()); goto reattach_failed; } void *r; static const char bg[] = "Background"; /* * 10.5 has one fewer args. * Since we are probably using a caller-cleans-up * calling convention, we could probably always just * call it with the extra arg, but we might as well * do things properly. */ if (os == 1050) { void *(*func)(uid_t, const char *) = f; r = func(getuid(), bg); } else if (os == 1060) { void *(*func)(uid_t, const char *, uint64_t) = f; r = func(getuid(), bg, 0); } else { warn("BUG: unhandled reattach variation: %u", os); goto reattach_failed; } if (r) { warn("%s failed", fn); goto reattach_failed; } } break; default: reattach_failed: warn("%s: unable to reattach", argv[0]); break; } char **newargs = NULL; const char *file = argv[1]; if (login) { /* * For their argv[0], take the bit of file after the * last slash (the whole thing if there is no slash * or if that bit would be zero length) and prefix * it with '-'. */ char *arg0 = malloc(strlen(file) + 2); if (!arg0) goto exec_it; *arg0 = '-'; char *slash = strrchr(file, '/'); if (slash && slash[1]) strcpy(arg0+1, slash+1); else strcpy(arg0+1, file); /* use the rest of the args as they are */ newargs = malloc(sizeof(*newargs) * (argc)); if (!newargs) { free(arg0); goto exec_it; } newargs[0] = arg0; int arg = 2; for(; arg < argc; arg++) newargs[arg-1] = argv[arg]; newargs[arg-1] = NULL; } exec_it: if (execvp(file, newargs ? newargs : argv+1) < 0) die_errno(3, "%s: execv failed", argv[0]); if (newargs) { free(newargs[0]); free(newargs); } return 0; }