Esempio n. 1
0
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);
	}
}
Esempio n. 2
0
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;
}