contrib/chg/chg.c
author Jun Wu <quark@fb.com>
Mon, 02 Jan 2017 14:02:47 +0000
changeset 30689 9fa7255d4abd
parent 30681 0064a1eb28e2
child 30690 e9ec42634ec8
permissions -rw-r--r--
chg: move signal and pager handling to a separate file In the future hgclient will deal with pager directly inside runcommand, so related signal handling stuff needs to be decoupled from chg.c. The signal handling and pager logic are coupled because we need to forward SIGPIPE when pager exits. So they are moved together, otherwise a global variable (pagerpid) is inevitable. This patch moves related functions from chg.c to procutil.c, which was marked as copied to maintain annotate history. The move is done without code modification for easy review, therefore `#include "procutil.c"` was introduced temporarily.
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
 * A fast client for Mercurial command server
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    10
#include <assert.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    11
#include <errno.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
#include <fcntl.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
#include <signal.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>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
#include <string.h>
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
    17
#include <sys/file.h>
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    18
#include <sys/stat.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
#include <sys/types.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
#include <sys/un.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
#include <sys/wait.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
#include <time.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
#include <unistd.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
#include "hgclient.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
#include "util.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    28
#ifndef PATH_MAX
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    29
#define PATH_MAX 4096
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    30
#endif
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    31
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
struct cmdserveropts {
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    33
	char sockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    34
	char initsockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    35
	char redirectsockname[PATH_MAX];
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    36
	size_t argsize;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    37
	const char **args;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    38
};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    40
static void initcmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    41
	memset(opts, 0, sizeof(struct cmdserveropts));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    42
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    43
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    44
static void freecmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    45
	free(opts->args);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    46
	opts->args = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    47
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    48
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    49
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    50
/*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    51
 * Test if an argument is a sensitive flag that should be passed to the server.
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    52
 * Return 0 if not, otherwise the number of arguments starting from the current
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    53
 * one that should be passed to the server.
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    54
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    55
static size_t testsensitiveflag(const char *arg)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    56
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    57
	static const struct {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    58
		const char *name;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    59
		size_t narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    60
	} flags[] = {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    61
		{"--config", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    62
		{"--cwd", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    63
		{"--repo", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    64
		{"--repository", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    65
		{"--traceback", 0},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    66
		{"-R", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    67
	};
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    68
	size_t i;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    69
	for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    70
		size_t len = strlen(flags[i].name);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    71
		size_t narg = flags[i].narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    72
		if (memcmp(arg, flags[i].name, len) == 0) {
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    73
			if (arg[len] == '\0') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    74
				/* --flag (value) */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    75
				return narg + 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    76
			} else if (arg[len] == '=' && narg > 0) {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    77
				/* --flag=value */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    78
				return 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    79
			} else if (flags[i].name[1] != '-') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    80
				/* short flag */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    81
				return 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    82
			}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    83
		}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    84
	}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    85
	return 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    86
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    87
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    88
/*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    89
 * Parse argv[] and put sensitive flags to opts->args
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    90
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    91
static void setcmdserverargs(struct cmdserveropts *opts,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    92
			     int argc, const char *argv[])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    93
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    94
	size_t i, step;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    95
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    96
	for (i = 0, step = 1; i < (size_t)argc; i += step, step = 1) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    97
		if (!argv[i])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    98
			continue;  /* pass clang-analyse */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    99
		if (strcmp(argv[i], "--") == 0)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   100
			break;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   101
		size_t n = testsensitiveflag(argv[i]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   102
		if (n == 0 || i + n > (size_t)argc)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   103
			continue;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   104
		opts->args = reallocx(opts->args,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   105
				      (n + opts->argsize) * sizeof(char *));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   106
		memcpy(opts->args + opts->argsize, argv + i,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   107
		       sizeof(char *) * n);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   108
		opts->argsize += n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   109
		step = n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   110
	}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   111
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   112
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   113
static void preparesockdir(const char *sockdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   114
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   115
	int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   116
	r = mkdir(sockdir, 0700);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   117
	if (r < 0 && errno != EEXIST)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   118
		abortmsgerrno("cannot create sockdir %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   119
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
	struct stat st;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
	r = lstat(sockdir, &st);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   122
	if (r < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   123
		abortmsgerrno("cannot stat %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   124
	if (!S_ISDIR(st.st_mode))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
		abortmsg("cannot create sockdir %s (file exists)", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
	if (st.st_uid != geteuid() || st.st_mode & 0077)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
		abortmsg("insecure sockdir %s", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   129
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   130
static void getdefaultsockdir(char sockdir[], size_t size)
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   131
{
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   132
	/* by default, put socket file in secure directory
30681
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   133
	 * (${XDG_RUNTIME_DIR}/chg, or /${TMPDIR:-tmp}/chg$UID)
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   134
	 * (permission of socket file may be ignored on some Unices) */
30681
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   135
	const char *runtimedir = getenv("XDG_RUNTIME_DIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   136
	int r;
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   137
	if (runtimedir) {
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   138
		r = snprintf(sockdir, size, "%s/chg", runtimedir);
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   139
	} else {
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   140
		const char *tmpdir = getenv("TMPDIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   141
		if (!tmpdir)
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   142
			tmpdir = "/tmp";
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   143
		r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid());
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   144
	}
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   145
	if (r < 0 || (size_t)r >= size)
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   146
		abortmsg("too long TMPDIR (r = %d)", r);
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   147
}
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   148
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   149
static void setcmdserveropts(struct cmdserveropts *opts)
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
	int r;
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
   152
	char sockdir[PATH_MAX];
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   153
	const char *envsockname = getenv("CHGSOCKNAME");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   154
	if (!envsockname) {
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   155
		getdefaultsockdir(sockdir, sizeof(sockdir));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   156
		preparesockdir(sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   157
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   158
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   159
	const char *basename = (envsockname) ? envsockname : sockdir;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   160
	const char *sockfmt = (envsockname) ? "%s" : "%s/server";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
	r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   162
	if (r < 0 || (size_t)r >= sizeof(opts->sockname))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   164
	r = snprintf(opts->initsockname, sizeof(opts->initsockname),
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   165
			"%s.%u", opts->sockname, (unsigned)getpid());
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   166
	if (r < 0 || (size_t)r >= sizeof(opts->initsockname))
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   167
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   170
static const char *gethgcmd(void)
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   171
{
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   172
	static const char *hgcmd = NULL;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   173
	if (!hgcmd) {
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   174
		hgcmd = getenv("CHGHG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   175
		if (!hgcmd || hgcmd[0] == '\0')
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   176
			hgcmd = getenv("HG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   177
		if (!hgcmd || hgcmd[0] == '\0')
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   178
#ifdef HGPATH
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   179
			hgcmd = (HGPATH);
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   180
#else
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   181
			hgcmd = "hg";
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   182
#endif
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   183
	}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   184
	return hgcmd;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   185
}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   186
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
static void execcmdserver(const struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
{
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   189
	const char *hgcmd = gethgcmd();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   190
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   191
	const char *baseargv[] = {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   192
		hgcmd,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
		"serve",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
		"--cmdserver", "chgunix",
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   195
		"--address", opts->initsockname,
28453
8a7110e351ec chg: use --daemon-postexec chdir:/ instead of --cwd /
Jun Wu <quark@fb.com>
parents: 28358
diff changeset
   196
		"--daemon-postexec", "chdir:/",
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   197
	};
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   198
	size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   199
	size_t argsize = baseargvsize + opts->argsize + 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   200
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   201
	const char **argv = mallocx(sizeof(char *) * argsize);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   202
	memcpy(argv, baseargv, sizeof(baseargv));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   203
	memcpy(argv + baseargvsize, opts->args, sizeof(char *) * opts->argsize);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   204
	argv[argsize - 1] = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   205
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   206
	if (putenv("CHGINTERNALMARK=") != 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   207
		abortmsgerrno("failed to putenv");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   208
	if (execvp(hgcmd, (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   209
		abortmsgerrno("failed to exec cmdserver");
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   210
	free(argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   211
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   213
/* Retry until we can connect to the server. Give up after some time. */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   214
static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   215
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
	static const struct timespec sleepreq = {0, 10 * 1000000};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
	int pst = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   219
	debugmsg("try connect to %s repeatedly", opts->initsockname);
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   220
29357
66d41c9e9222 chg: change default connect timeout to 60 seconds
Jun Wu <quark@fb.com>
parents: 29345
diff changeset
   221
	unsigned int timeoutsec = 60;  /* default: 60 seconds */
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   222
	const char *timeoutenv = getenv("CHGTIMEOUT");
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   223
	if (timeoutenv)
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   224
		sscanf(timeoutenv, "%u", &timeoutsec);
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   225
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   226
	for (unsigned int i = 0; !timeoutsec || i < timeoutsec * 100; i++) {
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   227
		hgclient_t *hgc = hgc_open(opts->initsockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   228
		if (hgc) {
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   229
			debugmsg("rename %s to %s", opts->initsockname,
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   230
					opts->sockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   231
			int r = rename(opts->initsockname, opts->sockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   232
			if (r != 0)
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   233
				abortmsgerrno("cannot rename");
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   234
			return hgc;
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   235
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   236
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
		if (pid > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
			/* collect zombie if child process fails to start */
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   239
			int r = waitpid(pid, &pst, WNOHANG);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   240
			if (r != 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   241
				goto cleanup;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   242
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   243
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   244
		nanosleep(&sleepreq, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   245
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   246
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   247
	abortmsg("timed out waiting for cmdserver %s", opts->initsockname);
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   248
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   249
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   250
cleanup:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   251
	if (WIFEXITED(pst)) {
28863
6e06fbee9244 chg: server exited with code 0 without being connectable is an error
Jun Wu <quark@fb.com>
parents: 28856
diff changeset
   252
		if (WEXITSTATUS(pst) == 0)
6e06fbee9244 chg: server exited with code 0 without being connectable is an error
Jun Wu <quark@fb.com>
parents: 28856
diff changeset
   253
			abortmsg("could not connect to cmdserver "
6e06fbee9244 chg: server exited with code 0 without being connectable is an error
Jun Wu <quark@fb.com>
parents: 28856
diff changeset
   254
				 "(exited with status 0)");
28477
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   255
		debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   256
		exit(WEXITSTATUS(pst));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   257
	} else if (WIFSIGNALED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   258
		abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   259
	} else {
28851
584e0716c7af chg: fix spelling in the error message about error waiting for cmdserver
Jun Wu <quark@fb.com>
parents: 28790
diff changeset
   260
		abortmsg("error while waiting for cmdserver");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   261
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   262
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   263
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   264
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   265
/* Connect to a cmdserver. Will start a new server on demand. */
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   266
static hgclient_t *connectcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   267
{
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   268
	const char *sockname = opts->redirectsockname[0] ?
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   269
		opts->redirectsockname : opts->sockname;
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28605
diff changeset
   270
	debugmsg("try connect to %s", sockname);
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   271
	hgclient_t *hgc = hgc_open(sockname);
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   272
	if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   273
		return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   274
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   275
	/* prevent us from being connected to an outdated server: we were
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   276
	 * told by a server to redirect to opts->redirectsockname and that
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   277
	 * address does not work. we do not want to connect to the server
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   278
	 * again because it will probably tell us the same thing. */
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   279
	if (sockname == opts->redirectsockname)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   280
		unlink(opts->sockname);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   281
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   282
	debugmsg("start cmdserver at %s", opts->initsockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   283
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
		abortmsg("failed to fork cmdserver process");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
	if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
		execcmdserver(opts);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
	} else {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   290
		hgc = retryconnectcmdserver(opts, pid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   291
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   292
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   293
	return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   294
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   295
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   296
static void killcmdserver(const struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   297
{
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   298
	/* resolve config hash */
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   299
	char *resolvedpath = realpath(opts->sockname, NULL);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   300
	if (resolvedpath) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   301
		unlink(resolvedpath);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   302
		free(resolvedpath);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
30689
9fa7255d4abd chg: move signal and pager handling to a separate file
Jun Wu <quark@fb.com>
parents: 30681
diff changeset
   306
#include "procutil.c"
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   308
/* Run instructions sent from the server like unlink and set redirect path
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   309
 * Return 1 if reconnect is needed, otherwise 0 */
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   310
static int runinstructions(struct cmdserveropts *opts, const char **insts)
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   311
{
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   312
	int needreconnect = 0;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   313
	if (!insts)
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   314
		return needreconnect;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   315
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   316
	assert(insts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   317
	opts->redirectsockname[0] = '\0';
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   318
	const char **pinst;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   319
	for (pinst = insts; *pinst; pinst++) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   320
		debugmsg("instruction: %s", *pinst);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   321
		if (strncmp(*pinst, "unlink ", 7) == 0) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   322
			unlink(*pinst + 7);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   323
		} else if (strncmp(*pinst, "redirect ", 9) == 0) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   324
			int r = snprintf(opts->redirectsockname,
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   325
					 sizeof(opts->redirectsockname),
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   326
					 "%s", *pinst + 9);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   327
			if (r < 0 || r >= (int)sizeof(opts->redirectsockname))
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   328
				abortmsg("redirect path is too long (%d)", r);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   329
			needreconnect = 1;
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   330
		} else if (strncmp(*pinst, "exit ", 5) == 0) {
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   331
			int n = 0;
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   332
			if (sscanf(*pinst + 5, "%d", &n) != 1)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   333
				abortmsg("cannot read the exit code");
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   334
			exit(n);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   335
		} else if (strcmp(*pinst, "reconnect") == 0) {
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   336
			needreconnect = 1;
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   337
		} else {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   338
			abortmsg("unknown instruction: %s", *pinst);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   339
		}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   340
	}
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   341
	return needreconnect;
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   342
}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   343
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   344
/*
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   345
 * Test whether the command is unsupported or not. This is not designed to
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   346
 * cover all cases. But it's fast, does not depend on the server and does
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   347
 * not return false positives.
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   348
 */
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   349
static int isunsupported(int argc, const char *argv[])
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   350
{
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   351
	enum {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   352
		SERVE = 1,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   353
		DAEMON = 2,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   354
		SERVEDAEMON = SERVE | DAEMON,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   355
		TIME = 4,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   356
	};
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   357
	unsigned int state = 0;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   358
	int i;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   359
	for (i = 0; i < argc; ++i) {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   360
		if (strcmp(argv[i], "--") == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   361
			break;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   362
		if (i == 0 && strcmp("serve", argv[i]) == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   363
			state |= SERVE;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   364
		else if (strcmp("-d", argv[i]) == 0 ||
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   365
			 strcmp("--daemon", argv[i]) == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   366
			state |= DAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   367
		else if (strcmp("--time", argv[i]) == 0)
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   368
			state |= TIME;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   369
	}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   370
	return (state & TIME) == TIME ||
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   371
	       (state & SERVEDAEMON) == SERVEDAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   372
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   373
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   374
static void execoriginalhg(const char *argv[])
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   375
{
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   376
	debugmsg("execute original hg");
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   377
	if (execvp(gethgcmd(), (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   378
		abortmsgerrno("failed to exec original hg");
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   379
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   380
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   381
int main(int argc, const char *argv[], const char *envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   382
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   383
	if (getenv("CHGDEBUG"))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   384
		enabledebugmsg();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   385
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   386
	if (!getenv("HGPLAIN") && isatty(fileno(stderr)))
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   387
		enablecolor();
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   388
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   389
	if (getenv("CHGINTERNALMARK"))
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   390
		abortmsg("chg started by chg detected.\n"
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   391
			 "Please make sure ${HG:-hg} is not a symlink or "
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   392
			 "wrapper to chg. Alternatively, set $CHGHG to the "
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   393
			 "path of real hg.");
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   394
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   395
	if (isunsupported(argc - 1, argv + 1))
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   396
		execoriginalhg(argv);
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   397
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
	struct cmdserveropts opts;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   399
	initcmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   400
	setcmdserveropts(&opts);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   401
	setcmdserverargs(&opts, argc, argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   403
	if (argc == 2) {
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   404
		if (strcmp(argv[1], "--kill-chg-daemon") == 0) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   405
			killcmdserver(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   406
			return 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   407
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   408
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   409
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   410
	hgclient_t *hgc;
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   411
	size_t retry = 0;
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   412
	while (1) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   413
		hgc = connectcmdserver(&opts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   414
		if (!hgc)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   415
			abortmsg("cannot open hg client");
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   416
		hgc_setenv(hgc, envp);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   417
		const char **insts = hgc_validate(hgc, argv + 1, argc - 1);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   418
		int needreconnect = runinstructions(&opts, insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   419
		free(insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   420
		if (!needreconnect)
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   421
			break;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   422
		hgc_close(hgc);
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   423
		if (++retry > 10)
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   424
			abortmsg("too many redirections.\n"
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   425
				 "Please make sure %s is not a wrapper which "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   426
				 "changes sensitive environment variables "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   427
				 "before executing hg. If you have to use a "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   428
				 "wrapper, wrap chg instead of hg.",
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   429
				 gethgcmd());
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   430
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   431
29608
681fe090d82e chg: forward SIGINT, SIGHUP to process group
Jun Wu <quark@fb.com>
parents: 29440
diff changeset
   432
	setupsignalhandler(hgc);
29429
cf99de051385 chg: send SIGPIPE to server immediately when pager exits (issue5278)
Jun Wu <quark@fb.com>
parents: 29370
diff changeset
   433
	pagerpid = setuppager(hgc, argv + 1, argc - 1);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   434
	int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1);
29369
85a18f3c0bdd chg: reset signal handlers to default before waiting pager
Yuya Nishihara <yuya@tcha.org>
parents: 29357
diff changeset
   435
	restoresignalhandler();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   436
	hgc_close(hgc);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   437
	freecmdserveropts(&opts);
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   438
	if (pagerpid)
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   439
		waitpager(pagerpid);
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   440
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   441
	return exitcode;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   442
}