contrib/chg/chg.c
author Jun Wu <quark@fb.com>
Fri, 06 Jan 2017 16:11:03 +0000
changeset 30726 dd897eb1699e
parent 30693 baee0f47b533
child 30741 fde9692a02c0
permissions -rw-r--r--
chg: send type information via S channel (BC) Previously S channel is only used to send system commands. It will also be used to send pager commands. So add a type parameter. This breaks older chg clients. But chg and hg should always come from a single commit and be packed into a single package. Supporting running inconsistent versions of chg and hg seems to be unnecessarily complicated with little benefit. So just make the change and assume people won't use inconsistent chg with hg.
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"
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    26
#include "procutil.h"
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    27
#include "util.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    29
#ifndef PATH_MAX
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    30
#define PATH_MAX 4096
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    31
#endif
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    33
struct cmdserveropts {
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    34
	char sockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    35
	char initsockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    36
	char redirectsockname[PATH_MAX];
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    37
	size_t argsize;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    38
	const char **args;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    39
};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    41
static void initcmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    42
	memset(opts, 0, sizeof(struct cmdserveropts));
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
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    45
static void freecmdserveropts(struct cmdserveropts *opts) {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    46
	free(opts->args);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    47
	opts->args = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    48
	opts->argsize = 0;
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
/*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    52
 * 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
    53
 * 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
    54
 * 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
    55
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    56
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
    57
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    58
	static const struct {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    59
		const char *name;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    60
		size_t narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    61
	} flags[] = {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    62
		{"--config", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    63
		{"--cwd", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    64
		{"--repo", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    65
		{"--repository", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    66
		{"--traceback", 0},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    67
		{"-R", 1},
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    68
	};
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    69
	size_t i;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    70
	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
    71
		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
    72
		size_t narg = flags[i].narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    73
		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
    74
			if (arg[len] == '\0') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    75
				/* --flag (value) */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    76
				return narg + 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    77
			} else if (arg[len] == '=' && narg > 0) {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    78
				/* --flag=value */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    79
				return 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    80
			} else if (flags[i].name[1] != '-') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    81
				/* short flag */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    82
				return 1;
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
	}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    86
	return 0;
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
/*
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    90
 * 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
    91
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    92
static void setcmdserverargs(struct cmdserveropts *opts,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    93
			     int argc, const char *argv[])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    94
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    95
	size_t i, step;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    96
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    97
	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
    98
		if (!argv[i])
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    99
			continue;  /* pass clang-analyse */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   100
		if (strcmp(argv[i], "--") == 0)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   101
			break;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   102
		size_t n = testsensitiveflag(argv[i]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   103
		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
   104
			continue;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   105
		opts->args = reallocx(opts->args,
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   106
				      (n + opts->argsize) * sizeof(char *));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   107
		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
   108
		       sizeof(char *) * n);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   109
		opts->argsize += n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   110
		step = n;
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
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   113
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   114
static void preparesockdir(const char *sockdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   115
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   116
	int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   117
	r = mkdir(sockdir, 0700);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   118
	if (r < 0 && errno != EEXIST)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   119
		abortmsgerrno("cannot create sockdir %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
	struct stat st;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   122
	r = lstat(sockdir, &st);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   123
	if (r < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   124
		abortmsgerrno("cannot stat %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
	if (!S_ISDIR(st.st_mode))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
		abortmsg("cannot create sockdir %s (file exists)", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
	if (st.st_uid != geteuid() || st.st_mode & 0077)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
		abortmsg("insecure sockdir %s", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   129
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   130
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   131
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
   132
{
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   133
	/* by default, put socket file in secure directory
30681
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   134
	 * (${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
   135
	 * (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
   136
	const char *runtimedir = getenv("XDG_RUNTIME_DIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   137
	int r;
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   138
	if (runtimedir) {
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   139
		r = snprintf(sockdir, size, "%s/chg", runtimedir);
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   140
	} else {
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   141
		const char *tmpdir = getenv("TMPDIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   142
		if (!tmpdir)
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   143
			tmpdir = "/tmp";
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   144
		r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid());
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   145
	}
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   146
	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
   147
		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
   148
}
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   149
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   150
static void setcmdserveropts(struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   151
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   152
	int r;
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
   153
	char sockdir[PATH_MAX];
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   154
	const char *envsockname = getenv("CHGSOCKNAME");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   155
	if (!envsockname) {
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   156
		getdefaultsockdir(sockdir, sizeof(sockdir));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   157
		preparesockdir(sockdir);
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   160
	const char *basename = (envsockname) ? envsockname : sockdir;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   161
	const char *sockfmt = (envsockname) ? "%s" : "%s/server";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   162
	r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   163
	if (r < 0 || (size_t)r >= sizeof(opts->sockname))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   164
		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
   165
	r = snprintf(opts->initsockname, sizeof(opts->initsockname),
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   166
			"%s.%u", opts->sockname, (unsigned)getpid());
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   167
	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
   168
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   169
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   170
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   171
static const char *gethgcmd(void)
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   172
{
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   173
	static const char *hgcmd = NULL;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   174
	if (!hgcmd) {
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   175
		hgcmd = getenv("CHGHG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   176
		if (!hgcmd || hgcmd[0] == '\0')
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   177
			hgcmd = getenv("HG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   178
		if (!hgcmd || hgcmd[0] == '\0')
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   179
#ifdef HGPATH
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   180
			hgcmd = (HGPATH);
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   181
#else
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   182
			hgcmd = "hg";
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   183
#endif
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   184
	}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   185
	return hgcmd;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   186
}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   187
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   188
static void execcmdserver(const struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   189
{
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   190
	const char *hgcmd = gethgcmd();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   191
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   192
	const char *baseargv[] = {
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   193
		hgcmd,
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   194
		"serve",
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   195
		"--cmdserver", "chgunix",
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   196
		"--address", opts->initsockname,
28453
8a7110e351ec chg: use --daemon-postexec chdir:/ instead of --cwd /
Jun Wu <quark@fb.com>
parents: 28358
diff changeset
   197
		"--daemon-postexec", "chdir:/",
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   198
	};
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   199
	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
   200
	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
   201
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   202
	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
   203
	memcpy(argv, baseargv, sizeof(baseargv));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   204
	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
   205
	argv[argsize - 1] = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   206
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   207
	if (putenv("CHGINTERNALMARK=") != 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   208
		abortmsgerrno("failed to putenv");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   209
	if (execvp(hgcmd, (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   210
		abortmsgerrno("failed to exec cmdserver");
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   211
	free(argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   212
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   213
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   214
/* 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
   215
static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   216
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
	static const struct timespec sleepreq = {0, 10 * 1000000};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   218
	int pst = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   219
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   220
	debugmsg("try connect to %s repeatedly", opts->initsockname);
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   221
29357
66d41c9e9222 chg: change default connect timeout to 60 seconds
Jun Wu <quark@fb.com>
parents: 29345
diff changeset
   222
	unsigned int timeoutsec = 60;  /* default: 60 seconds */
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   223
	const char *timeoutenv = getenv("CHGTIMEOUT");
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   224
	if (timeoutenv)
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   225
		sscanf(timeoutenv, "%u", &timeoutsec);
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   226
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   227
	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
   228
		hgclient_t *hgc = hgc_open(opts->initsockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   229
		if (hgc) {
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   230
			debugmsg("rename %s to %s", opts->initsockname,
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   231
					opts->sockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   232
			int r = rename(opts->initsockname, opts->sockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   233
			if (r != 0)
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   234
				abortmsgerrno("cannot rename");
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   235
			return hgc;
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   236
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
		if (pid > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   239
			/* 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
   240
			int r = waitpid(pid, &pst, WNOHANG);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   241
			if (r != 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   242
				goto cleanup;
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
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   245
		nanosleep(&sleepreq, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   246
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   247
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   248
	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
   249
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   250
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   251
cleanup:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   252
	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
   253
		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
   254
			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
   255
				 "(exited with status 0)");
28477
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   256
		debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   257
		exit(WEXITSTATUS(pst));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   258
	} else if (WIFSIGNALED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   259
		abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   260
	} else {
28851
584e0716c7af chg: fix spelling in the error message about error waiting for cmdserver
Jun Wu <quark@fb.com>
parents: 28790
diff changeset
   261
		abortmsg("error while waiting for cmdserver");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   262
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   263
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   264
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   265
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   266
/* 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
   267
static hgclient_t *connectcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   268
{
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   269
	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
   270
		opts->redirectsockname : opts->sockname;
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28605
diff changeset
   271
	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
   272
	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
   273
	if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   274
		return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   275
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   276
	/* 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
   277
	 * 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
   278
	 * 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
   279
	 * 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
   280
	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
   281
		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
   282
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   283
	debugmsg("start cmdserver at %s", opts->initsockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   285
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   286
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
		abortmsg("failed to fork cmdserver process");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   288
	if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   289
		execcmdserver(opts);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   290
	} else {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   291
		hgc = retryconnectcmdserver(opts, pid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   292
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   293
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   294
	return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   295
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   296
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   297
static void killcmdserver(const struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   298
{
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   299
	/* resolve config hash */
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   300
	char *resolvedpath = realpath(opts->sockname, NULL);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   301
	if (resolvedpath) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   302
		unlink(resolvedpath);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   303
		free(resolvedpath);
28060
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
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   307
/* 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
   308
 * 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
   309
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
   310
{
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   311
	int needreconnect = 0;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   312
	if (!insts)
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   313
		return needreconnect;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   314
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   315
	assert(insts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   316
	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
   317
	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
   318
	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
   319
		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
   320
		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
   321
			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
   322
		} 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
   323
			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
   324
					 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
   325
					 "%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
   326
			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
   327
				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
   328
			needreconnect = 1;
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   329
		} else if (strncmp(*pinst, "exit ", 5) == 0) {
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   330
			int n = 0;
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   331
			if (sscanf(*pinst + 5, "%d", &n) != 1)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   332
				abortmsg("cannot read the exit code");
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   333
			exit(n);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   334
		} else if (strcmp(*pinst, "reconnect") == 0) {
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   335
			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
   336
		} else {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   337
			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
   338
		}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   339
	}
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   340
	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
   341
}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   342
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   343
/*
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   344
 * 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
   345
 * 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
   346
 * 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
   347
 */
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   348
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
   349
{
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   350
	enum {
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   351
		SERVE = 1,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   352
		DAEMON = 2,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   353
		SERVEDAEMON = SERVE | DAEMON,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   354
		TIME = 4,
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   355
	};
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   356
	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
   357
	int i;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   358
	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
   359
		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
   360
			break;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   361
		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
   362
			state |= SERVE;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   363
		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
   364
			 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
   365
			state |= DAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   366
		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
   367
			state |= TIME;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   368
	}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   369
	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
   370
	       (state & SERVEDAEMON) == SERVEDAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   371
}
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
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
   374
{
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   375
	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
   376
	if (execvp(gethgcmd(), (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   377
		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
   378
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   379
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   380
int main(int argc, const char *argv[], const char *envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   381
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   382
	if (getenv("CHGDEBUG"))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   383
		enabledebugmsg();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   384
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   385
	if (!getenv("HGPLAIN") && isatty(fileno(stderr)))
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   386
		enablecolor();
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   387
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   388
	if (getenv("CHGINTERNALMARK"))
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   389
		abortmsg("chg started by chg detected.\n"
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   390
			 "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
   391
			 "wrapper to chg. Alternatively, set $CHGHG to the "
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   392
			 "path of real hg.");
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   393
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   394
	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
   395
		execoriginalhg(argv);
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   396
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
	struct cmdserveropts opts;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   398
	initcmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
	setcmdserveropts(&opts);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   400
	setcmdserverargs(&opts, argc, argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   402
	if (argc == 2) {
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   403
		if (strcmp(argv[1], "--kill-chg-daemon") == 0) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   404
			killcmdserver(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   405
			return 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   406
		}
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
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   409
	hgclient_t *hgc;
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   410
	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
   411
	while (1) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   412
		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
   413
		if (!hgc)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   414
			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
   415
		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
   416
		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
   417
		int needreconnect = runinstructions(&opts, insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   418
		free(insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   419
		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
   420
			break;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   421
		hgc_close(hgc);
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   422
		if (++retry > 10)
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   423
			abortmsg("too many redirections.\n"
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   424
				 "Please make sure %s is not a wrapper which "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   425
				 "changes sensitive environment variables "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   426
				 "before executing hg. If you have to use a "
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   427
				 "wrapper, wrap chg instead of hg.",
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   428
				 gethgcmd());
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   429
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   430
30690
e9ec42634ec8 chg: decouple hgclient from setupsignalhandler
Jun Wu <quark@fb.com>
parents: 30689
diff changeset
   431
	setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc));
30691
7adb60660496 chg: decouple hgclient from setuppager
Jun Wu <quark@fb.com>
parents: 30690
diff changeset
   432
	const char *pagercmd = hgc_getpager(hgc, argv + 1, argc - 1);
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   433
	pid_t pagerpid = setuppager(pagercmd);
30691
7adb60660496 chg: decouple hgclient from setuppager
Jun Wu <quark@fb.com>
parents: 30690
diff changeset
   434
	if (pagerpid)
7adb60660496 chg: decouple hgclient from setuppager
Jun Wu <quark@fb.com>
parents: 30690
diff changeset
   435
		hgc_attachio(hgc);  /* reattach to pager */
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   436
	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
   437
	restoresignalhandler();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   438
	hgc_close(hgc);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   439
	freecmdserveropts(&opts);
30692
23ddd43ba866 chg: let procutil maintain its own pagerpid
Jun Wu <quark@fb.com>
parents: 30691
diff changeset
   440
	waitpager();
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   441
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   442
	return exitcode;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   443
}