contrib/chg/util.c
author Joerg Sonnenberger <joerg@bec.de>
Thu, 16 Aug 2018 05:50:49 +0200
changeset 39237 1af95139e5ec
parent 35998 9724f54923ec
child 41361 763b45bc4483
permissions -rw-r--r--
util: improve handling of truncated compressed streams If the compressed stream is over as marked by the reader providing nothing new and the compression engine is not providing data, bail out. This can happen in practise when the server misbehaves and would result in an infinite loop otherwise. Differential Revision: https://phab.mercurial-scm.org/D4297
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     1
/*
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     2
 * Utility functions
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     3
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     4
 * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     5
 *
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     6
 * This software may be used and distributed according to the terms of the
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     7
 * GNU General Public License version 2 or any later version.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     8
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
     9
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    10
#include <errno.h>
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
    11
#include <fcntl.h>
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
#include <signal.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
#include <stdarg.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
#include <stdio.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
#include <stdlib.h>
28084
3fc45956c978 chg: initialize sigaction fields more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 28060
diff changeset
    16
#include <string.h>
34316
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    17
#include <sys/time.h>
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
#include <sys/types.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
#include <sys/wait.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
#include <unistd.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
#include "util.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    24
static int colorenabled = 0;
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    25
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    26
static inline void fsetcolor(FILE *fp, const char *code)
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    27
{
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    28
	if (!colorenabled)
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    29
		return;
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    30
	fprintf(fp, "\033[%sm", code);
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    31
}
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    32
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    33
static void vabortmsgerrno(int no, const char *fmt, va_list args)
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    34
{
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    35
	fsetcolor(stderr, "1;31");
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    36
	fputs("chg: abort: ", stderr);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    37
	vfprintf(stderr, fmt, args);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    38
	if (no != 0)
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    39
		fprintf(stderr, " (errno = %d, %s)", no, strerror(no));
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    40
	fsetcolor(stderr, "");
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    41
	fputc('\n', stderr);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    42
	exit(255);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    43
}
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    44
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    45
void abortmsg(const char *fmt, ...)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    46
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    47
	va_list args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    48
	va_start(args, fmt);
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    49
	vabortmsgerrno(0, fmt, args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    50
	va_end(args);
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    51
}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    52
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    53
void abortmsgerrno(const char *fmt, ...)
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    54
{
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    55
	int no = errno;
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    56
	va_list args;
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    57
	va_start(args, fmt);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    58
	vabortmsgerrno(no, fmt, args);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    59
	va_end(args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    60
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    61
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
static int debugmsgenabled = 0;
34316
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    63
static double debugstart = 0;
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    64
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34316
diff changeset
    65
static double now()
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34316
diff changeset
    66
{
34316
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    67
	struct timeval t;
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    68
	gettimeofday(&t, NULL);
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    69
	return t.tv_usec / 1e6 + t.tv_sec;
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    70
}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    71
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    72
void enablecolor(void)
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    73
{
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    74
	colorenabled = 1;
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    75
}
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    76
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    77
void enabledebugmsg(void)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    78
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    79
	debugmsgenabled = 1;
34316
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    80
	debugstart = now();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    81
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    82
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    83
void debugmsg(const char *fmt, ...)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    84
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    85
	if (!debugmsgenabled)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
		return;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    87
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    88
	va_list args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    89
	va_start(args, fmt);
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    90
	fsetcolor(stderr, "1;30");
34316
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    91
	fprintf(stderr, "chg: debug: %4.6f ", now() - debugstart);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    92
	vfprintf(stderr, fmt, args);
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    93
	fsetcolor(stderr, "");
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    94
	fputc('\n', stderr);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    95
	va_end(args);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    96
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    97
28854
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
    98
void fchdirx(int dirfd)
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
    99
{
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   100
	int r = fchdir(dirfd);
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   101
	if (r == -1)
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   102
		abortmsgerrno("failed to fchdir");
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   103
}
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   104
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   105
void fsetcloexec(int fd)
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   106
{
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   107
	int flags = fcntl(fd, F_GETFD);
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   108
	if (flags < 0)
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   109
		abortmsgerrno("cannot get flags of fd %d", fd);
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   110
	if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0)
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   111
		abortmsgerrno("cannot set flags of fd %d", fd);
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   112
}
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   113
28165
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   114
void *mallocx(size_t size)
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   115
{
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   116
	void *result = malloc(size);
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   117
	if (!result)
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   118
		abortmsg("failed to malloc");
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   119
	return result;
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   120
}
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   121
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   122
void *reallocx(void *ptr, size_t size)
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   123
{
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   124
	void *result = realloc(ptr, size);
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   125
	if (!result)
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   126
		abortmsg("failed to realloc");
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   127
	return result;
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   128
}
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   129
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   130
/*
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   131
 * Execute a shell command in mostly the same manner as system(), with the
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   132
 * give environment variables, after chdir to the given cwd. Returns a status
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   133
 * code compatible with the Python subprocess module.
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   134
 */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   135
int runshellcmd(const char *cmd, const char *envp[], const char *cwd)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   136
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   137
	enum { F_SIGINT = 1, F_SIGQUIT = 2, F_SIGMASK = 4, F_WAITPID = 8 };
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   138
	unsigned int doneflags = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   139
	int status = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   140
	struct sigaction newsa, oldsaint, oldsaquit;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   141
	sigset_t oldmask;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   142
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   143
	/* block or mask signals just as system() does */
28084
3fc45956c978 chg: initialize sigaction fields more reliably
Yuya Nishihara <yuya@tcha.org>
parents: 28060
diff changeset
   144
	memset(&newsa, 0, sizeof(newsa));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   145
	newsa.sa_handler = SIG_IGN;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   146
	newsa.sa_flags = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   147
	if (sigemptyset(&newsa.sa_mask) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   148
		goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
	if (sigaction(SIGINT, &newsa, &oldsaint) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   150
		goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   151
	doneflags |= F_SIGINT;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   152
	if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   153
		goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   154
	doneflags |= F_SIGQUIT;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   155
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   156
	if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   157
		goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   158
	if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   159
		goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   160
	doneflags |= F_SIGMASK;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   162
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   164
		goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   165
	if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   166
		sigaction(SIGINT, &oldsaint, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   167
		sigaction(SIGQUIT, &oldsaquit, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
		sigprocmask(SIG_SETMASK, &oldmask, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
		if (cwd && chdir(cwd) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   170
			_exit(127);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   171
		const char *argv[] = {"sh", "-c", cmd, NULL};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   172
		if (envp) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   173
			execve("/bin/sh", (char **)argv, (char **)envp);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
		} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
			execv("/bin/sh", (char **)argv);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
		_exit(127);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   178
	} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   179
		if (waitpid(pid, &status, 0) < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
			goto done;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
		doneflags |= F_WAITPID;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   182
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   183
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   184
done:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
	if (doneflags & F_SIGINT)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
		sigaction(SIGINT, &oldsaint, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
	if (doneflags & F_SIGQUIT)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
		sigaction(SIGQUIT, &oldsaquit, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
	if (doneflags & F_SIGMASK)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
		sigprocmask(SIG_SETMASK, &oldmask, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
	/* no way to report other errors, use 127 (= shell termination) */
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
	if (!(doneflags & F_WAITPID))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
		return 127;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
	if (WIFEXITED(status))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   196
		return WEXITSTATUS(status);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
	if (WIFSIGNALED(status))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
		return -WTERMSIG(status);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
	return 127;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
}