contrib/chg/util.c
author Pierre-Yves David <pierre-yves.david@octobus.net>
Fri, 28 Feb 2020 11:22:47 +0100
branchstable
changeset 44403 fca7caeaa6e7
parent 41336 763b45bc4483
permissions -rw-r--r--
remotefilelog-test: glob some flaky output line This is similar to ee0959e7d435. The affected line is flaky underload, yet the final result is correct. The command involves background pre-check of output, these are not stable probably because they run in parallel in multiple process. If it become useful to start testing precise internal details of the, they will have to be tested in a more appropriate framework than `.t` tests. Differential Revision: https://phab.mercurial-scm.org/D8179
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>
34309
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
{
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
    28
	if (!colorenabled) {
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    29
		return;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
    30
	}
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    31
	fprintf(fp, "\033[%sm", code);
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    32
}
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    33
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    34
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
    35
{
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    36
	fsetcolor(stderr, "1;31");
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    37
	fputs("chg: abort: ", stderr);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    38
	vfprintf(stderr, fmt, args);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
    39
	if (no != 0) {
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    40
		fprintf(stderr, " (errno = %d, %s)", no, strerror(no));
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
    41
	}
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    42
	fsetcolor(stderr, "");
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    43
	fputc('\n', stderr);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    44
	exit(255);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    45
}
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    46
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    47
void abortmsg(const char *fmt, ...)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    48
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    49
	va_list args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    50
	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
    51
	vabortmsgerrno(0, fmt, args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    52
	va_end(args);
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    53
}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    54
28788
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    55
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
    56
{
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    57
	int no = errno;
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    58
	va_list args;
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    59
	va_start(args, fmt);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    60
	vabortmsgerrno(no, fmt, args);
57a78a64de44 chg: add util function abortmsgerrno to print error with errno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
    61
	va_end(args);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    62
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    63
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    64
static int debugmsgenabled = 0;
34309
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    65
static double debugstart = 0;
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    66
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34309
diff changeset
    67
static double now()
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34309
diff changeset
    68
{
34309
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    69
	struct timeval t;
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    70
	gettimeofday(&t, NULL);
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    71
	return t.tv_usec / 1e6 + t.tv_sec;
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    72
}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    73
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    74
void enablecolor(void)
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
	colorenabled = 1;
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    77
}
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    78
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    79
void enabledebugmsg(void)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    80
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    81
	debugmsgenabled = 1;
34309
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    82
	debugstart = now();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    83
}
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
void debugmsg(const char *fmt, ...)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    86
{
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
    87
	if (!debugmsgenabled) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    88
		return;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
    89
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    90
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    91
	va_list args;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    92
	va_start(args, fmt);
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    93
	fsetcolor(stderr, "1;30");
34309
b94db1780365 chg: show timestamp with debug messages
Jun Wu <quark@fb.com>
parents: 28855
diff changeset
    94
	fprintf(stderr, "chg: debug: %4.6f ", now() - debugstart);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    95
	vfprintf(stderr, fmt, args);
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    96
	fsetcolor(stderr, "");
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28165
diff changeset
    97
	fputc('\n', stderr);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    98
	va_end(args);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    99
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   100
28854
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   101
void fchdirx(int dirfd)
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   102
{
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   103
	int r = fchdir(dirfd);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   104
	if (r == -1) {
28854
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   105
		abortmsgerrno("failed to fchdir");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   106
	}
28854
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   107
}
ddef14468952 chg: add fchdirx as a utility function
Jun Wu <quark@fb.com>
parents: 28788
diff changeset
   108
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   109
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
   110
{
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   111
	int flags = fcntl(fd, F_GETFD);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   112
	if (flags < 0) {
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   113
		abortmsgerrno("cannot get flags of fd %d", fd);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   114
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   115
	if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   116
		abortmsgerrno("cannot set flags of fd %d", fd);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   117
	}
28855
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   118
}
f5764e177bbe chg: extract the logic of setting FD_CLOEXEC to a utility function
Jun Wu <quark@fb.com>
parents: 28854
diff changeset
   119
28165
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   120
void *mallocx(size_t size)
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 *result = malloc(size);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   123
	if (!result) {
28165
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   124
		abortmsg("failed to malloc");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   125
	}
28165
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   126
	return result;
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   127
}
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
void *reallocx(void *ptr, size_t size)
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   130
{
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   131
	void *result = realloc(ptr, size);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   132
	if (!result) {
28165
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   133
		abortmsg("failed to realloc");
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   134
	}
28165
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   135
	return result;
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   136
}
c6705c6303dd chg: add utility functions mallocx, reallocx
Jun Wu <quark@fb.com>
parents: 28084
diff changeset
   137
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   138
/*
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   139
 * 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
   140
 * 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
   141
 * code compatible with the Python subprocess module.
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
int runshellcmd(const char *cmd, const char *envp[], const char *cwd)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   144
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   145
	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
   146
	unsigned int doneflags = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   147
	int status = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   148
	struct sigaction newsa, oldsaint, oldsaquit;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
	sigset_t oldmask;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   150
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   151
	/* 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
   152
	memset(&newsa, 0, sizeof(newsa));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   153
	newsa.sa_handler = SIG_IGN;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   154
	newsa.sa_flags = 0;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   155
	if (sigemptyset(&newsa.sa_mask) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   156
		goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   157
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   158
	if (sigaction(SIGINT, &newsa, &oldsaint) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   159
		goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   160
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
	doneflags |= F_SIGINT;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   162
	if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
		goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   164
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   165
	doneflags |= F_SIGQUIT;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   166
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   167
	if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
		goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   169
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   170
	if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   171
		goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   172
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   173
	doneflags |= F_SIGMASK;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
	pid_t pid = fork();
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   176
	if (pid < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
		goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   178
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   179
	if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
		sigaction(SIGINT, &oldsaint, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
		sigaction(SIGQUIT, &oldsaquit, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   182
		sigprocmask(SIG_SETMASK, &oldmask, NULL);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   183
		if (cwd && chdir(cwd) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   184
			_exit(127);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   185
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
		const char *argv[] = {"sh", "-c", cmd, NULL};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
		if (envp) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
			execve("/bin/sh", (char **)argv, (char **)envp);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
		} else {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
			execv("/bin/sh", (char **)argv);
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
		_exit(127);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
	} else {
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   194
		if (waitpid(pid, &status, 0) < 0) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
			goto done;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   196
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
		doneflags |= F_WAITPID;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   199
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   200
done:
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   201
	if (doneflags & F_SIGINT) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   202
		sigaction(SIGINT, &oldsaint, NULL);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   203
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   204
	if (doneflags & F_SIGQUIT) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
		sigaction(SIGQUIT, &oldsaquit, NULL);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   206
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   207
	if (doneflags & F_SIGMASK) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
		sigprocmask(SIG_SETMASK, &oldmask, NULL);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   209
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   210
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
	/* no way to report other errors, use 127 (= shell termination) */
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   212
	if (!(doneflags & F_WAITPID)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   213
		return 127;
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   214
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   215
	if (WIFEXITED(status)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
		return WEXITSTATUS(status);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   217
	}
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   218
	if (WIFSIGNALED(status)) {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   219
		return -WTERMSIG(status);
41336
763b45bc4483 cleanup: use clang-tidy to add missing {} around one-line statements
Augie Fackler <augie@google.com>
parents: 35959
diff changeset
   220
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   221
	return 127;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   222
}