示例#1
0
文件: rerere.c 项目: basilgor/git
/*
 * Find the conflict identified by "id"; the change between its
 * "preimage" (i.e. a previous contents with conflict markers) and its
 * "postimage" (i.e. the corresponding contents with conflicts
 * resolved) may apply cleanly to the contents stored in "path", i.e.
 * the conflict this time around.
 *
 * Returns 0 for successful replay of recorded resolution, or non-zero
 * for failure.
 */
static int merge(const struct rerere_id *id, const char *path)
{
	FILE *f;
	int ret;
	mmfile_t cur = {NULL, 0};
	mmbuffer_t result = {NULL, 0};

	/*
	 * Normalize the conflicts in path and write it out to
	 * "thisimage" temporary file.
	 */
	if ((handle_file(path, NULL, rerere_path(id, "thisimage")) < 0) ||
	    read_mmfile(&cur, rerere_path(id, "thisimage"))) {
		ret = 1;
		goto out;
	}

	ret = try_merge(id, path, &cur, &result);
	if (ret)
		goto out;

	/*
	 * A successful replay of recorded resolution.
	 * Mark that "postimage" was used to help gc.
	 */
	if (utime(rerere_path(id, "postimage"), NULL) < 0)
		warning_errno("failed utime() on %s",
			      rerere_path(id, "postimage"));

	/* Update "path" with the resolution */
	f = fopen(path, "w");
	if (!f)
		return error_errno("Could not open %s", path);
	if (fwrite(result.ptr, result.size, 1, f) != 1)
		error_errno("Could not write %s", path);
	if (fclose(f))
		return error_errno("Writing %s failed", path);

out:
	free(cur.ptr);
	free(result.ptr);

	return ret;
}
示例#2
0
文件: tv_attach.c 项目: hocks/TSCC
/*
 * This does not play well with MPI_Comm_spawn.  Probably Totalview does
 * not support such a usage model anyway.
 */
int tv_startup(int ntasks)
{
    int rc;
    growstr_t *g;
    struct sockaddr_in tv_sockaddr;
    socklen_t tv_sockaddr_len = sizeof(tv_sockaddr);
    struct timespec ts = { 0, 20L * 1000 * 1000 };  /* 20 ms */

    MPIR_proctable = Malloc(ntasks * sizeof(*MPIR_proctable));

    /* Creating socket for pid exchange of remote processes */
    tv_socket = socket(PF_INET, SOCK_STREAM, 0);
    if (tv_socket < 0)
	error_errno("%s: socket ", __func__);

    memset(&tv_sockaddr, 0, sizeof(tv_sockaddr));
    tv_sockaddr.sin_family = AF_INET;
    tv_sockaddr.sin_addr = myaddr.sin_addr;

    rc = bind(tv_socket, (struct sockaddr *) &tv_sockaddr, tv_sockaddr_len);
    if (rc)
	error_errno("%s: bind", __func__);
    rc = getsockname(tv_socket, (struct sockaddr *) &tv_sockaddr,
		     &tv_sockaddr_len);
    if (rc)
	error_errno("%s: getsockname", __func__);
    rc = listen(tv_socket, 32767);
    if (rc)
	error_errno("%s: listen", __func__);

    /* start totalview and tell it to attach to this mpiexec process */
    g = growstr_init();
    growstr_printf(g, "%s -e \"dattach mpiexec %d; dgo; "
		      "dassign MPIR_being_debugged 1\" &", tvname, getpid());
    system(g->s);
    growstr_free(g);

    /* wait for totalview to find us */
    while (!MPIR_being_debugged)
	nanosleep(&ts, NULL);

    return ntohs(tv_sockaddr.sin_port);
}
示例#3
0
文件: gc.c 项目: MichaelBlume/git
/*
 * Returns 0 if there was no previous error and gc can proceed, 1 if
 * gc should not proceed due to an error in the last run. Prints a
 * message and returns -1 if an error occured while reading gc.log
 */
static int report_last_gc_error(void)
{
	struct strbuf sb = STRBUF_INIT;
	int ret = 0;
	ssize_t len;
	struct stat st;
	char *gc_log_path = git_pathdup("gc.log");

	if (stat(gc_log_path, &st)) {
		if (errno == ENOENT)
			goto done;

		ret = error_errno(_("cannot stat '%s'"), gc_log_path);
		goto done;
	}

	if (st.st_mtime < gc_log_expire_time)
		goto done;

	len = strbuf_read_file(&sb, gc_log_path, 0);
	if (len < 0)
		ret = error_errno(_("cannot read '%s'"), gc_log_path);
	else if (len > 0) {
		/*
		 * A previous gc failed.  Report the error, and don't
		 * bother with an automatic gc run since it is likely
		 * to fail in the same way.
		 */
		warning(_("The last gc run reported the following. "
			       "Please correct the root cause\n"
			       "and remove %s.\n"
			       "Automatic cleanup will not be performed "
			       "until the file is removed.\n\n"
			       "%s"),
			    gc_log_path, sb.buf);
		ret = 1;
	}
	strbuf_release(&sb);
done:
	free(gc_log_path);
	return ret;
}
示例#4
0
int verify_signed_buffer(const char *payload, size_t payload_size,
			 const char *signature, size_t signature_size,
			 struct strbuf *gpg_output, struct strbuf *gpg_status)
{
	struct child_process gpg = CHILD_PROCESS_INIT;
	struct tempfile *temp;
	int ret;
	struct strbuf buf = STRBUF_INIT;

	temp = mks_tempfile_t(".git_vtag_tmpXXXXXX");
	if (!temp)
		return error_errno(_("could not create temporary file"));
	if (write_in_full(temp->fd, signature, signature_size) < 0 ||
	    close_tempfile_gently(temp) < 0) {
		error_errno(_("failed writing detached signature to '%s'"),
			    temp->filename.buf);
		delete_tempfile(&temp);
		return -1;
	}

	argv_array_pushl(&gpg.args,
			 gpg_program,
			 "--status-fd=1",
			 "--keyid-format=long",
			 "--verify", temp->filename.buf, "-",
			 NULL);

	if (!gpg_status)
		gpg_status = &buf;

	sigchain_push(SIGPIPE, SIG_IGN);
	ret = pipe_command(&gpg, payload, payload_size,
			   gpg_status, 0, gpg_output, 0);
	sigchain_pop(SIGPIPE);

	delete_tempfile(&temp);

	ret |= !strstr(gpg_status->buf, "\n[GNUPG:] GOODSIG ");
	strbuf_release(&buf); /* no matter it was used or not */

	return ret;
}
示例#5
0
文件: socket.c 项目: dpw/molerat
static struct sockaddr *get_socket_peer_address(int fd, struct error *err)
{
	struct sockaddr_storage ss;
	socklen_t len = sizeof ss;

	if (getpeername(fd, (struct sockaddr *)&ss, &len) >= 0)
		return copy_sockaddr(&ss, len, err);

	error_errno(err, "getpeername");
	return NULL;
}
示例#6
0
int read_mmfile(mmfile_t *ptr, const char *filename)
{
	struct stat st;
	FILE *f;
	size_t sz;

	if (stat(filename, &st))
		return error_errno("Could not stat %s", filename);
	if ((f = fopen(filename, "rb")) == NULL)
		return error_errno("Could not open %s", filename);
	sz = xsize_t(st.st_size);
	ptr->ptr = xmalloc(sz ? sz : 1);
	if (sz && fread(ptr->ptr, sz, 1, f) != 1) {
		fclose(f);
		return error("Could not read %s", filename);
	}
	fclose(f);
	ptr->size = sz;
	return 0;
}
示例#7
0
文件: rerere.c 项目: Noffica/git
/*
 * Scan the path for conflicts, do the "handle_path()" thing above, and
 * return the number of conflict hunks found.
 */
static int handle_file(struct index_state *istate,
		       const char *path, unsigned char *hash, const char *output)
{
	int has_conflicts = 0;
	struct rerere_io_file io;
	int marker_size = ll_merge_marker_size(istate, path);

	memset(&io, 0, sizeof(io));
	io.io.getline = rerere_file_getline;
	io.input = fopen(path, "r");
	io.io.wrerror = 0;
	if (!io.input)
		return error_errno(_("could not open '%s'"), path);

	if (output) {
		io.io.output = fopen(output, "w");
		if (!io.io.output) {
			error_errno(_("could not write '%s'"), output);
			fclose(io.input);
			return -1;
		}
	}

	has_conflicts = handle_path(hash, (struct rerere_io *)&io, marker_size);

	fclose(io.input);
	if (io.io.wrerror)
		error(_("there were errors while writing '%s' (%s)"),
		      path, strerror(io.io.wrerror));
	if (io.io.output && fclose(io.io.output))
		io.io.wrerror = error_errno(_("failed to flush '%s'"), path);

	if (has_conflicts < 0) {
		if (output)
			unlink_or_warn(output);
		return error(_("could not parse conflict hunks in '%s'"), path);
	}
	if (io.io.wrerror)
		return -1;
	return has_conflicts;
}
示例#8
0
文件: sequencer.c 项目: dindinw/git
static int create_seq_dir(void)
{
	if (file_exists(git_path_seq_dir())) {
		error(_("a cherry-pick or revert is already in progress"));
		advise(_("try \"git cherry-pick (--continue | --quit | --abort)\""));
		return -1;
	}
	else if (mkdir(git_path_seq_dir(), 0777) < 0)
		return error_errno(_("could not create sequencer directory '%s'"),
				   git_path_seq_dir());
	return 0;
}
示例#9
0
文件: upload-archive.c 项目: 9b/git
int cmd_upload_archive(int argc, const char **argv, const char *prefix)
{
	struct child_process writer = { argv };

	/*
	 * Set up sideband subprocess.
	 *
	 * We (parent) monitor and read from child, sending its fd#1 and fd#2
	 * multiplexed out to our fd#1.  If the child dies, we tell the other
	 * end over channel #3.
	 */
	argv[0] = "upload-archive--writer";
	writer.out = writer.err = -1;
	writer.git_cmd = 1;
	if (start_command(&writer)) {
		int err = errno;
		packet_write_fmt(1, "NACK unable to spawn subprocess\n");
		die("upload-archive: %s", strerror(err));
	}

	packet_write_fmt(1, "ACK\n");
	packet_flush(1);

	while (1) {
		struct pollfd pfd[2];

		pfd[0].fd = writer.out;
		pfd[0].events = POLLIN;
		pfd[1].fd = writer.err;
		pfd[1].events = POLLIN;
		if (poll(pfd, 2, -1) < 0) {
			if (errno != EINTR) {
				error_errno("poll failed resuming");
				sleep(1);
			}
			continue;
		}
		if (pfd[1].revents & POLLIN)
			/* Status stream ready */
			if (process_input(pfd[1].fd, 2))
				continue;
		if (pfd[0].revents & POLLIN)
			/* Data stream ready */
			if (process_input(pfd[0].fd, 1))
				continue;

		if (finish_command(&writer))
			error_clnt("%s", deadchild);
		packet_flush(1);
		break;
	}
	return 0;
}
示例#10
0
static int file_skip(struct output_file *out, int64_t cnt)
{
	off64_t ret;
	struct output_file_normal *outn = to_output_file_normal(out);

	ret = lseek64(outn->fd, cnt, SEEK_CUR);
	if (ret < 0) {
		error_errno("lseek64");
		return -1;
	}
	return 0;
}
示例#11
0
static int gz_file_open(struct output_file *out, int fd)
{
	struct output_file_gz *outgz = to_output_file_gz(out);

	outgz->gz_fd = gzdopen(fd, "wb9");
	if (!outgz->gz_fd) {
		error_errno("gzopen");
		return -errno;
	}

	return 0;
}
示例#12
0
文件: socket.c 项目: dpw/molerat
static int make_listening_socket(int family, int socktype, struct error *err)
{
	int fd = make_socket(family, socktype, err);

	if (fd >= 0 && listen(fd, SOMAXCONN) < 0) {
		error_errno(err, "listen");
		close(fd);
		fd = -1;
	}

	return fd;
}
示例#13
0
static int gz_file_skip(struct output_file *out, int64_t cnt)
{
	off64_t ret;
	struct output_file_gz *outgz = to_output_file_gz(out);

	ret = gzseek(outgz->gz_fd, cnt, SEEK_CUR);
	if (ret < 0) {
		error_errno("gzseek");
		return -1;
	}
	return 0;
}
示例#14
0
/* this runs in the parent process */
static void child_err_spew(struct child_process *cmd, struct child_err *cerr)
{
	static void (*old_errfn)(const char *err, va_list params);

	old_errfn = get_error_routine();
	set_error_routine(fake_fatal);
	errno = cerr->syserr;

	switch (cerr->err) {
	case CHILD_ERR_CHDIR:
		error_errno("exec '%s': cd to '%s' failed",
			    cmd->argv[0], cmd->dir);
		break;
	case CHILD_ERR_DUP2:
		error_errno("dup2() in child failed");
		break;
	case CHILD_ERR_CLOSE:
		error_errno("close() in child failed");
		break;
	case CHILD_ERR_SIGPROCMASK:
		error_errno("sigprocmask failed restoring signals");
		break;
	case CHILD_ERR_ENOENT:
		error_errno("cannot run %s", cmd->argv[0]);
		break;
	case CHILD_ERR_SILENT:
		break;
	case CHILD_ERR_ERRNO:
		error_errno("cannot exec '%s'", cmd->argv[0]);
		break;
	}
	set_error_routine(old_errfn);
}
示例#15
0
文件: rerere.c 项目: basilgor/git
/*
 * Scan the path for conflicts, do the "handle_path()" thing above, and
 * return the number of conflict hunks found.
 */
static int handle_file(const char *path, unsigned char *sha1, const char *output)
{
	int hunk_no = 0;
	struct rerere_io_file io;
	int marker_size = ll_merge_marker_size(path);

	memset(&io, 0, sizeof(io));
	io.io.getline = rerere_file_getline;
	io.input = fopen(path, "r");
	io.io.wrerror = 0;
	if (!io.input)
		return error_errno("Could not open %s", path);

	if (output) {
		io.io.output = fopen(output, "w");
		if (!io.io.output) {
			error_errno("Could not write %s", output);
			fclose(io.input);
			return -1;
		}
	}

	hunk_no = handle_path(sha1, (struct rerere_io *)&io, marker_size);

	fclose(io.input);
	if (io.io.wrerror)
		error("There were errors while writing %s (%s)",
		      path, strerror(io.io.wrerror));
	if (io.io.output && fclose(io.io.output))
		io.io.wrerror = error_errno("Failed to flush %s", path);

	if (hunk_no < 0) {
		if (output)
			unlink_or_warn(output);
		return error("Could not parse conflict hunks in %s", path);
	}
	if (io.io.wrerror)
		return -1;
	return hunk_no;
}
示例#16
0
文件: worktree.c 项目: ayanmw/git
static int delete_git_dir(struct worktree *wt)
{
	struct strbuf sb = STRBUF_INIT;
	int ret = 0;

	strbuf_addstr(&sb, git_common_path("worktrees/%s", wt->id));
	if (remove_dir_recursively(&sb, 0)) {
		error_errno(_("failed to delete '%s'"), sb.buf);
		ret = -1;
	}
	strbuf_release(&sb);
	return ret;
}
示例#17
0
文件: sequencer.c 项目: dindinw/git
static int save_head(const char *head)
{
	static struct lock_file head_lock;
	struct strbuf buf = STRBUF_INIT;
	int fd;

	fd = hold_lock_file_for_update(&head_lock, git_path_head_file(), 0);
	if (fd < 0) {
		rollback_lock_file(&head_lock);
		return error_errno(_("could not lock HEAD"));
	}
	strbuf_addf(&buf, "%s\n", head);
	if (write_in_full(fd, buf.buf, buf.len) < 0) {
		rollback_lock_file(&head_lock);
		return error_errno(_("could not write to '%s'"),
				   git_path_head_file());
	}
	if (commit_lock_file(&head_lock) < 0) {
		rollback_lock_file(&head_lock);
		return error(_("failed to finalize '%s'."), git_path_head_file());
	}
	return 0;
}
示例#18
0
文件: sequencer.c 项目: dindinw/git
static int write_message(const void *buf, size_t len, const char *filename,
			 int append_eol)
{
	static struct lock_file msg_file;

	int msg_fd = hold_lock_file_for_update(&msg_file, filename, 0);
	if (msg_fd < 0)
		return error_errno(_("could not lock '%s'"), filename);
	if (write_in_full(msg_fd, buf, len) < 0) {
		rollback_lock_file(&msg_file);
		return error_errno(_("could not write to '%s'"), filename);
	}
	if (append_eol && write(msg_fd, "\n", 1) < 0) {
		rollback_lock_file(&msg_file);
		return error_errno(_("could not write eol to '%s'"), filename);
	}
	if (commit_lock_file(&msg_file) < 0) {
		rollback_lock_file(&msg_file);
		return error(_("failed to finalize '%s'."), filename);
	}

	return 0;
}
示例#19
0
文件: socket.c 项目: dpw/molerat
static enum stream_result simple_socket_close_locked(struct simple_socket *s,
						     struct error *e)
{
	if (s->fd >= 0) {
		watched_fd_destroy(s->watched_fd);
		if (close(s->fd) < 0 && e) {
			error_errno(e, "close");
			return STREAM_ERROR;
		}

		s->fd = -1;
	}

	return STREAM_OK;
}
示例#20
0
static int populate_from_stdin(struct diff_filespec *s)
{
	struct strbuf buf = STRBUF_INIT;
	size_t size = 0;

	if (strbuf_read(&buf, 0, 0) < 0)
		return error_errno("error while reading from stdin");

	s->should_munmap = 0;
	s->data = strbuf_detach(&buf, &size);
	s->size = size;
	s->should_free = 1;
	s->is_stdin = 1;
	return 0;
}
示例#21
0
static int gz_file_write(struct output_file *out, void *data, int len)
{
	int ret;
	struct output_file_gz *outgz = to_output_file_gz(out);

	ret = gzwrite(outgz->gz_fd, data, len);
	if (ret < 0) {
		error_errno("gzwrite");
		return -1;
	} else if (ret < len) {
		error("incomplete gzwrite");
		return -1;
	}

	return 0;
}
示例#22
0
static int file_write(struct output_file *out, void *data, int len)
{
	int ret;
	struct output_file_normal *outn = to_output_file_normal(out);

	ret = write(outn->fd, data, len);
	if (ret < 0) {
		error_errno("write");
		return -1;
	} else if (ret < len) {
		error("incomplete write");
		return -1;
	}

	return 0;
}
示例#23
0
文件: sequencer.c 项目: dindinw/git
int sequencer_rollback(struct replay_opts *opts)
{
	FILE *f;
	unsigned char sha1[20];
	struct strbuf buf = STRBUF_INIT;

	f = fopen(git_path_head_file(), "r");
	if (!f && errno == ENOENT) {
		/*
		 * There is no multiple-cherry-pick in progress.
		 * If CHERRY_PICK_HEAD or REVERT_HEAD indicates
		 * a single-cherry-pick in progress, abort that.
		 */
		return rollback_single_pick();
	}
	if (!f)
		return error_errno(_("cannot open '%s'"), git_path_head_file());
	if (strbuf_getline_lf(&buf, f)) {
		error(_("cannot read '%s': %s"), git_path_head_file(),
		      ferror(f) ?  strerror(errno) : _("unexpected end of file"));
		fclose(f);
		goto fail;
	}
	fclose(f);
	if (get_sha1_hex(buf.buf, sha1) || buf.buf[40] != '\0') {
		error(_("stored pre-cherry-pick HEAD file '%s' is corrupt"),
			git_path_head_file());
		goto fail;
	}
	if (is_null_sha1(sha1)) {
		error(_("cannot abort from a branch yet to be born"));
		goto fail;
	}

	if (!rollback_is_safe()) {
		/* Do not error, just do not rollback */
		warning(_("You seem to have moved HEAD. "
			  "Not rewinding, check your HEAD!"));
	} else
	if (reset_for_rollback(sha1))
		goto fail;
	strbuf_release(&buf);
	return sequencer_remove_state(opts);
fail:
	strbuf_release(&buf);
	return -1;
}
示例#24
0
static int bisect_write(const char *state, const char *rev,
			const struct bisect_terms *terms, int nolog)
{
	struct strbuf tag = STRBUF_INIT;
	struct object_id oid;
	struct commit *commit;
	FILE *fp = NULL;
	int retval = 0;

	if (!strcmp(state, terms->term_bad)) {
		strbuf_addf(&tag, "refs/bisect/%s", state);
	} else if (one_of(state, terms->term_good, "skip", NULL)) {
		strbuf_addf(&tag, "refs/bisect/%s-%s", state, rev);
	} else {
		retval = error(_("Bad bisect_write argument: %s"), state);
		goto finish;
	}

	if (get_oid(rev, &oid)) {
		retval = error(_("couldn't get the oid of the rev '%s'"), rev);
		goto finish;
	}

	if (update_ref(NULL, tag.buf, &oid, NULL, 0,
		       UPDATE_REFS_MSG_ON_ERR)) {
		retval = -1;
		goto finish;
	}

	fp = fopen(git_path_bisect_log(), "a");
	if (!fp) {
		retval = error_errno(_("couldn't open the file '%s'"), git_path_bisect_log());
		goto finish;
	}

	commit = lookup_commit_reference(the_repository, &oid);
	log_commit(fp, "%s", state, commit);

	if (!nolog)
		fprintf(fp, "git bisect %s %s\n", state, rev);

finish:
	if (fp)
		fclose(fp);
	strbuf_release(&tag);
	return retval;
}
示例#25
0
文件: socket.c 项目: dpw/molerat
static void simple_server_socket_close_locked(struct simple_server_socket *s,
					      struct error *e)
{
	int i;

	for (i = 0; i < s->n_fds; i++) {
		int fd = s->fds[i].fd;
		if (fd >= 0) {
			watched_fd_destroy(s->fds[i].watched_fd);
			if (close(fd) < 0 && e)
				error_errno(e, "close");
		}
	}

	free(s->fds);
	s->fds = NULL;
}
示例#26
0
文件: tv_attach.c 项目: hocks/TSCC
/*
 * This is called once for each task startup.  Wait until the started
 * task sends its pid, then enter that into the totalview table.  It
 * might be better to do this in parallel with a service... handler
 * like some other libraries have, but since this is only for the
 * debugging case, maybe it is not too terrible to be slow.
 */
void tv_accept_one(int n)
{
    int pid, ps1;
    char rpid[11];

    ps1 = accept(tv_socket, 0, 0);
    if (ps1 < 0)
	error_errno("%s: accept totalview pid", __func__);
    read_full(ps1, rpid, 10);
    close(ps1);
    rpid[10] = '\0';
    pid = atoi(rpid);
    MPIR_proctable[n].host_name = nodes[tasks[n].node].name;
    MPIR_proctable[n].executable_name = tasks[n].conf->exe;
    MPIR_proctable[n].pid = pid;
    MPIR_proctable_size++;
}
示例#27
0
文件: socket.c 项目: dpw/molerat
static bool_t simple_socket_partial_close(struct socket *gs,
					  bool_t read_else_write,
					  struct error *e)
{
	struct simple_socket *s = (struct simple_socket *)gs;
	bool_t res = TRUE;

	mutex_lock(&s->mutex);

	if (shutdown(s->fd, read_else_write ? SHUT_RD : SHUT_WR) < 0) {
		error_errno(e, "shutdown");
		res = FALSE;
	}

	mutex_unlock(&s->mutex);
	return res;
}
示例#28
0
文件: socket.c 项目: dpw/molerat
static void start_connecting(struct connector *c)
{
	for (;;) {
		struct addrinfo *ai = c->next_addrinfo;
		if (!ai)
			break;

		/* If we have an existing connecting socket, dispose of it. */
		connector_close(c);

		c->next_addrinfo = ai->ai_next;
		error_reset(&c->err);
		c->fd = make_socket(ai->ai_family, ai->ai_socktype, &c->err);
		if (c->fd < 0)
			continue;

		c->watched_fd
			= watched_fd_create(c->fd, connector_handle_events, c);
		if (connect(c->fd, ai->ai_addr, ai->ai_addrlen) >= 0) {
			/* Immediately connected.  Not sure this can
			   actually happen. */
			wait_list_up(&c->connecting, 1);
			return;
		}
		else if (would_block()) {
			/* Writeability will indicate that the connection has
			 * been established. */
			if (!watched_fd_set_interest(c->watched_fd,
						     WATCHED_FD_OUT, &c->err))
				/* Give up and propagate the error */
				break;

			return;
		}
		else {
			error_errno(&c->err, "connect");
		}
	}

	/* Ran out of addresses to try, so we are done. We should have
	   an error to report. */
	assert(!error_ok(&c->err));
	simple_socket_wake_all(&c->socket->base);
}
示例#29
0
static int wait_or_whine(pid_t pid, const char *argv0, int in_signal)
{
	int status, code = -1;
	pid_t waiting;
	int failed_errno = 0;

	while ((waiting = waitpid(pid, &status, 0)) < 0 && errno == EINTR)
		;	/* nothing */
	if (in_signal)
		return 0;

	if (waiting < 0) {
		failed_errno = errno;
		error_errno("waitpid for %s failed", argv0);
	} else if (waiting != pid) {
		error("waitpid is confused (%s)", argv0);
	} else if (WIFSIGNALED(status)) {
		code = WTERMSIG(status);
		if (code != SIGINT && code != SIGQUIT && code != SIGPIPE)
			error("%s died of signal %d", argv0, code);
		/*
		 * This return value is chosen so that code & 0xff
		 * mimics the exit code that a POSIX shell would report for
		 * a program that died from this signal.
		 */
		code += 128;
	} else if (WIFEXITED(status)) {
		code = WEXITSTATUS(status);
		/*
		 * Convert special exit code when execvp failed.
		 */
		if (code == 127) {
			code = -1;
			failed_errno = ENOENT;
		}
	} else {
		error("waitpid is confused (%s)", argv0);
	}

	clear_child_for_cleanup(pid);

	errno = failed_errno;
	return code;
}
示例#30
0
static int write_terms(const char *bad, const char *good)
{
	FILE *fp = NULL;
	int res;

	if (!strcmp(bad, good))
		return error(_("please use two different terms"));

	if (check_term_format(bad, "bad") || check_term_format(good, "good"))
		return -1;

	fp = fopen(git_path_bisect_terms(), "w");
	if (!fp)
		return error_errno(_("could not open the file BISECT_TERMS"));

	res = fprintf(fp, "%s\n%s\n", bad, good);
	res |= fclose(fp);
	return (res < 0) ? -1 : 0;
}