Beispiel #1
0
inline static retvalue aptmethod_startup(struct aptmethod *method) {
	pid_t f;
	int mstdin[2];
	int mstdout[2];
	int r;

	/* When there is nothing to get, there is no reason to startup
	 * the method. */
	if (method->tobedone == NULL) {
		return RET_NOTHING;
	}

	/* when we are already running, we are already ready...*/
	if (method->child > 0) {
		return RET_OK;
	}

	method->status = ams_waitforcapabilities;

	r = pipe(mstdin);
	if (r < 0) {
		int e = errno;
		fprintf(stderr, "Error %d creating pipe: %s\n",
				e, strerror(e));
		return RET_ERRNO(e);
	}
	r = pipe(mstdout);
	if (r < 0) {
		int e = errno;
		(void)close(mstdin[0]); (void)close(mstdin[1]);
		fprintf(stderr, "Error %d in pipe syscall: %s\n",
				e, strerror(e));
		return RET_ERRNO(e);
	}

	if (interrupted()) {
		(void)close(mstdin[0]);(void)close(mstdin[1]);
		(void)close(mstdout[0]);(void)close(mstdout[1]);
		return RET_ERROR_INTERRUPTED;
	}
	f = fork();
	if (f < 0) {
		int e = errno;
		(void)close(mstdin[0]); (void)close(mstdin[1]);
		(void)close(mstdout[0]); (void)close(mstdout[1]);
		fprintf(stderr, "Error %d forking: %s\n",
				e, strerror(e));
		return RET_ERRNO(e);
	}
	if (f == 0) {
		char *methodname;
		int e;
		/* child: */
		(void)close(mstdin[1]);
		(void)close(mstdout[0]);
		if (dup2(mstdin[0], 0) < 0) {
			e = errno;
			fprintf(stderr, "Error %d while setting stdin: %s\n",
					e, strerror(e));
			exit(255);
		}
		if (dup2(mstdout[1], 1) < 0) {
			e = errno;
			fprintf(stderr, "Error %d while setting stdout: %s\n",
					e, strerror(e));
			exit(255);
		}
		closefrom(3);

		methodname = calc_dirconcat(global.methoddir, method->name);
		if (FAILEDTOALLOC(methodname))
			exit(255);

		/* not really useful here, unless someone write reprepro
		 * specific modules (which I hope noone will) */
		sethookenvironment(NULL, NULL, NULL, NULL);
		/* actually call the method without any arguments: */
		(void)execl(methodname, methodname, ENDOFARGUMENTS);

		e = errno;
		fprintf(stderr, "Error %d while executing '%s': %s\n",
				e, methodname, strerror(e));
		exit(255);
	}
	/* the main program continues... */
	method->child = f;
	if (verbose > 10)
		fprintf(stderr,
"Method '%s' started as %d\n", method->baseuri, (int)f);
	(void)close(mstdin[0]);
	(void)close(mstdout[1]);
	markcloseonexec(mstdin[1]);
	markcloseonexec(mstdout[0]);
	method->mstdin = mstdin[1];
	method->mstdout = mstdout[0];
	method->inputbuffer = NULL;
	method->input_size = 0;
	method->alreadyread = 0;
	method->command = NULL;
	method->output_length = 0;
	method->alreadywritten = 0;
	return RET_OK;
}
Beispiel #2
0
static retvalue callexporthook(/*@null@*/const char *hook, const char *relfilename, const char *mode, struct release *release) {
    pid_t f, c;
    int status;
    int io[2];
    char buffer[1000];
    int already = 0;

    if (hook == NULL)
        return RET_NOTHING;

    status = pipe(io);
    if (status < 0) {
        int e = errno;
        fprintf(stderr, "Error %d creating pipe: %s!\n",
                e, strerror(e));
        return RET_ERRNO(e);
    }

    f = fork();
    if (f < 0) {
        int e = errno;
        (void)close(io[0]);
        (void)close(io[1]);
        fprintf(stderr, "Error %d while forking for exporthook: %s\n",
                e, strerror(e));
        return RET_ERRNO(e);
    }
    if (f == 0) {
        char *reltmpfilename;
        int e;

        if (dup2(io[1], 3) < 0) {
            e = errno;
            fprintf(stderr, "Error %d dup2'ing fd %d to 3: %s\n",
                    e, io[1], strerror(e));
            exit(255);
        }
        /* "Doppelt haelt besser": */
        if (io[0] != 3)
            (void)close(io[0]);
        if (io[1] != 3)
            (void)close(io[1]);
        closefrom(4);
        /* backward compatibilty */
        reltmpfilename = calc_addsuffix(relfilename, "new");
        if (reltmpfilename == NULL) {
            exit(255);
        }
        setenv("REPREPRO_BASE_DIR", global.basedir, true);
        setenv("REPREPRO_OUT_DIR", global.outdir, true);
        setenv("REPREPRO_CONF_DIR", global.confdir, true);
        setenv("REPREPRO_DIST_DIR", global.distdir, true);
        setenv("REPREPRO_LOG_DIR", global.logdir, true);
        (void)execl(hook, hook, release_dirofdist(release),
                    reltmpfilename, relfilename, mode,
                    ENDOFARGUMENTS);
        e = errno;
        fprintf(stderr, "Error %d while executing '%s': %s\n",
                e, hook, strerror(e));
        exit(255);
    }
    close(io[1]);
    markcloseonexec(io[0]);

    if (verbose > 6)
        printf("Called %s '%s' '%s.new' '%s' '%s'\n",
               hook, release_dirofdist(release),
               relfilename, relfilename, mode);
    /* read what comes from the client */
    while (true) {
        ssize_t r;
        int last, j;

        r = read(io[0], buffer + already, 999 - already);
        if (r < 0) {
            int e = errno;
            fprintf(stderr,
                    "Error %d reading from exporthook: %s!\n",
                    e, strerror(e));
            break;
        }

        already += r;
        if (r == 0) {
            buffer[already] = '\0';
            already++;
        }
        last = 0;
        for (j = 0 ; j < already ; j++) {
            if (buffer[j] == '\n' || buffer[j] == '\0') {
                int next = j+1;
                int e = (j>0)?(j-1):j;
                retvalue ret;

                while (last < j && xisspace(buffer[last]))
                    last++;
                if (last >= j) {
                    last = next;
                    continue;
                }
                while (xisspace(buffer[e])) {
                    e--;
                    assert (e >= last);
                }

                ret = gotfilename(buffer + last, e - last + 1,
                                  release);
                if (RET_WAS_ERROR(ret)) {
                    (void)close(io[0]);
                    return ret;
                }
                last = next;
            }
        }
        if (last > 0) {
            if (already > last)
                memmove(buffer, buffer + last, already - last);
            already -= last;
        }
        if (r == 0)
            break;
    }
    (void)close(io[0]);
    do {
        c = waitpid(f, &status, WUNTRACED);
        if (c < 0) {
            int e = errno;
            fprintf(stderr,
                    "Error %d while waiting for hook '%s' to finish: %s\n", e, hook, strerror(e));
            return RET_ERRNO(e);
        }
    } while (c != f);
    if (WIFEXITED(status)) {
        if (WEXITSTATUS(status) == 0) {
            if (verbose > 6)
                printf("Exporthook successfully returned!\n");
            return RET_OK;
        } else {
            fprintf(stderr,
                    "Exporthook failed with exitcode %d!\n",
                    (int)WEXITSTATUS(status));
            return RET_ERROR;
        }
    } else if (WIFSIGNALED(status)) {
        fprintf(stderr, "Exporthook killed by signal %d!\n",
                (int)(WTERMSIG(status)));
        return RET_ERROR;
    } else {
        fprintf(stderr,
                "Exporthook terminated abnormally. (status is %x)!\n",
                status);
        return RET_ERROR;
    }
}