contrib/chg/chg.c
author Arun Kulshreshtha <akulshreshtha@janestreet.com>
Mon, 27 Mar 2023 17:30:14 -0400
branchstable
changeset 50383 cf4d2f31660d
parent 47024 8fcc0a829f3d
child 50430 d06e43cd393f
permissions -rw-r--r--
chg: populate CHGHG if not set Normally, chg determines which `hg` executable to use by first consulting the `$CHGHG` and `$HG` environment variables, and if neither are present defaults to the `hg` found in the user's `$PATH`. If built with the `HGPATHREL` compiler flag, chg will instead assume that there exists an `hg` executable in the same directory as the `chg` binary and attempt to use that. This can cause problems in situations where there are multiple actively-used Mercurial installations on the same system. When a `chg` client connects to a running command server, the server process performs some basic validation to determine whether a new command server needs to be spawned. These checks include things like checking certain "sensitive" environment variables and config sections, as well as checking whether the mtime of the extensions, hg's `__version__.py` module, and the Python interpreter have changed. Crucially, the command server doesn't explicitly check whether the executable it is running from matches the executable that the `chg` client would have otherwise invoked had there been no existing command server process. Without `HGPATHREL`, this still gets implicitly checked during the validation step, because the only way to specify an alternate hg executable (apart from `$PATH`) is via the `$CHGHG` and `$HG` environment variables, both of which are checked. With `HGPATHREL`, however, the command server has no way of knowing which hg executable the client would have run. This means that a client located at `/version_B/bin/chg` will happily connect to a command server running `/version_A/bin/hg` instead of `/version_B/bin/hg` as expected. A simple solution is to have the client set `$CHGHG` itself, which then allows the command server's environment validation to work as intended. I have tested this manually using two locally built hg installations and it seems to work with no ill effects. That said, I'm not sure how to write an automated test for this since the `chg` available to the tests isn't even built with the `HGPATHREL` compiler flag to begin with.
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>
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
    11
#include <dirent.h>
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    12
#include <errno.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    13
#include <fcntl.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    14
#include <signal.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    15
#include <stdio.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    16
#include <stdlib.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    17
#include <string.h>
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
    18
#include <sys/file.h>
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    19
#include <sys/stat.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    20
#include <sys/types.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    21
#include <sys/un.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    22
#include <sys/wait.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    23
#include <time.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    24
#include <unistd.h>
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    25
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    26
#include "hgclient.h"
30693
baee0f47b533 chg: add procutil.h
Jun Wu <quark@fb.com>
parents: 30692
diff changeset
    27
#include "procutil.h"
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    28
#include "util.h"
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    29
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    30
#ifndef PATH_MAX
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    31
#define PATH_MAX 4096
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    32
#endif
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    33
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    34
struct cmdserveropts {
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    35
	char sockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    36
	char initsockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
    37
	char redirectsockname[PATH_MAX];
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    38
	size_t argsize;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    39
	const char **args;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    40
};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
    41
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    42
static void initcmdserveropts(struct cmdserveropts *opts)
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    43
{
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    44
	memset(opts, 0, sizeof(struct cmdserveropts));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    45
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    46
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    47
static void freecmdserveropts(struct cmdserveropts *opts)
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    48
{
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    49
	free(opts->args);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    50
	opts->args = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    51
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    52
}
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    53
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
 * 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
    56
 * 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
    57
 * 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
    58
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    59
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
    60
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    61
	static const struct {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    62
		const char *name;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    63
		size_t narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    64
	} flags[] = {
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    65
	    {"--config", 1},     {"--cwd", 1},       {"--repo", 1},
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    66
	    {"--repository", 1}, {"--traceback", 0}, {"-R", 1},
28167
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
 */
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    91
static void setcmdserverargs(struct cmdserveropts *opts, int argc,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    92
                             const char *argv[])
28167
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])
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    98
			continue; /* pass clang-analyse */
28167
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;
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   104
		opts->args =
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   105
		    reallocx(opts->args, (n + opts->argsize) * sizeof(char *));
28167
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
30884
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   130
/*
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   131
 * Check if a socket directory exists and is only owned by the current user.
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   132
 * Return 1 if so, 0 if not. This is used to check if XDG_RUNTIME_DIR can be
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   133
 * used or not. According to the specification [1], XDG_RUNTIME_DIR should be
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   134
 * ignored if the directory is not owned by the user with mode 0700.
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   135
 * [1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   136
 */
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   137
static int checkruntimedir(const char *sockdir)
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   138
{
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   139
	struct stat st;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   140
	int r = lstat(sockdir, &st);
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   141
	if (r < 0) /* ex. does not exist */
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   142
		return 0;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   143
	if (!S_ISDIR(st.st_mode)) /* ex. is a file, not a directory */
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   144
		return 0;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   145
	return st.st_uid == geteuid() && (st.st_mode & 0777) == 0700;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   146
}
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   147
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   148
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
   149
{
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   150
	/* by default, put socket file in secure directory
30681
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   151
	 * (${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
   152
	 * (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
   153
	const char *runtimedir = getenv("XDG_RUNTIME_DIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   154
	int r;
30884
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   155
	if (runtimedir && checkruntimedir(runtimedir)) {
30681
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   156
		r = snprintf(sockdir, size, "%s/chg", runtimedir);
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   157
	} else {
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   158
		const char *tmpdir = getenv("TMPDIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   159
		if (!tmpdir)
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   160
			tmpdir = "/tmp";
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   161
		r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid());
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   162
	}
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   163
	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
   164
		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
   165
}
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   166
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   167
static void setcmdserveropts(struct cmdserveropts *opts)
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
	int r;
30677
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30676
diff changeset
   170
	char sockdir[PATH_MAX];
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   171
	const char *envsockname = getenv("CHGSOCKNAME");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   172
	if (!envsockname) {
30680
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30677
diff changeset
   173
		getdefaultsockdir(sockdir, sizeof(sockdir));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
		preparesockdir(sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
	const char *basename = (envsockname) ? envsockname : sockdir;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   178
	const char *sockfmt = (envsockname) ? "%s" : "%s/server";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   179
	r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
	if (r < 0 || (size_t)r >= sizeof(opts->sockname))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   181
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   182
	r = snprintf(opts->initsockname, sizeof(opts->initsockname), "%s.%u",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   183
	             opts->sockname, (unsigned)getpid());
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   184
	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
   185
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   187
45551
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   188
/* If the current program is, say, /a/b/c/chg, returns /a/b/c/hg. */
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   189
static char *getrelhgcmd(void)
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   190
{
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   191
	ssize_t n;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   192
	char *res, *slash;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   193
	int maxsize = 4096;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   194
	res = malloc(maxsize);
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   195
	if (res == NULL)
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   196
		goto cleanup;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   197
	n = readlink("/proc/self/exe", res, maxsize);
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   198
	if (n < 0 || n >= maxsize)
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   199
		goto cleanup;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   200
	res[n] = '\0';
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   201
	slash = strrchr(res, '/');
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   202
	if (slash == NULL)
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   203
		goto cleanup;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   204
	/* 4 is strlen("/hg") + nul byte */
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   205
	if (slash + 4 >= res + maxsize)
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   206
		goto cleanup;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   207
	memcpy(slash, "/hg", 4);
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   208
	return res;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   209
cleanup:
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   210
	free(res);
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   211
	return NULL;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   212
}
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   213
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   214
static const char *gethgcmd(void)
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   215
{
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   216
	static const char *hgcmd = NULL;
45551
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   217
#ifdef HGPATHREL
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   218
	int tryrelhgcmd = 1;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   219
#else
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   220
	int tryrelhgcmd = 0;
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   221
#endif
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   222
	if (!hgcmd) {
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   223
		hgcmd = getenv("CHGHG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   224
		if (!hgcmd || hgcmd[0] == '\0')
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   225
			hgcmd = getenv("HG");
45551
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   226
		if (tryrelhgcmd && (!hgcmd || hgcmd[0] == '\0'))
4c8d9b53b1c7 chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents: 45520
diff changeset
   227
			hgcmd = getrelhgcmd();
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   228
		if (!hgcmd || hgcmd[0] == '\0')
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   229
#ifdef HGPATH
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   230
			hgcmd = (HGPATH);
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   231
#else
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   232
			hgcmd = "hg";
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   233
#endif
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   234
	}
50383
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   235
	/* Set $CHGHG to the path to the seleted hg executable if it wasn't
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   236
	 * already set. This has the effect of ensuring that a new command
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   237
	 * server will be spawned if the existing command server is running from
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   238
	 * an executable at a different path. */
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   239
	if (setenv("CHGHG", hgcmd, 1) != 0)
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   240
		abortmsgerrno("failed to setenv");
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   241
	return hgcmd;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   242
}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   243
50383
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   244
static void execcmdserver(const char *hgcmd, const struct cmdserveropts *opts)
28060
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
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   247
	const char *baseargv[] = {
47024
8fcc0a829f3d chg: pass --no-profile to disable profiling when starting hg serve
Kyle Lippincott <spectral@google.com>
parents: 46177
diff changeset
   248
	    hgcmd,     "serve",     "--no-profile",     "--cmdserver",
8fcc0a829f3d chg: pass --no-profile to disable profiling when starting hg serve
Kyle Lippincott <spectral@google.com>
parents: 46177
diff changeset
   249
	    "chgunix", "--address", opts->initsockname, "--daemon-postexec",
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   250
	    "chdir:/",
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   251
	};
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   252
	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
   253
	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
   254
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   255
	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
   256
	memcpy(argv, baseargv, sizeof(baseargv));
38198
3c84493556db chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents: 35959
diff changeset
   257
	if (opts->args) {
3c84493556db chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents: 35959
diff changeset
   258
		size_t size = sizeof(char *) * opts->argsize;
3c84493556db chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents: 35959
diff changeset
   259
		memcpy(argv + baseargvsize, opts->args, size);
3c84493556db chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents: 35959
diff changeset
   260
	}
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   261
	argv[argsize - 1] = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   262
44261
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   263
	const char *lc_ctype_env = getenv("LC_CTYPE");
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   264
	if (lc_ctype_env == NULL) {
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   265
		if (putenv("CHG_CLEAR_LC_CTYPE=") != 0)
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   266
			abortmsgerrno("failed to putenv CHG_CLEAR_LC_CTYPE");
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   267
	} else {
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   268
		if (setenv("CHGORIG_LC_CTYPE", lc_ctype_env, 1) != 0) {
44995
2c920c4dbb31 chg: fix typo
Manuel Jacob <me@manueljacob.de>
parents: 44617
diff changeset
   269
			abortmsgerrno("failed to setenv CHGORIG_LC_CTYPE");
44261
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   270
		}
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   271
	}
04a3ae7aba14 chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents: 38198
diff changeset
   272
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   273
	/* close any open files to avoid hanging locks */
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   274
	DIR *dp = opendir("/proc/self/fd");
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   275
	if (dp != NULL) {
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   276
		debugmsg("closing files based on /proc contents");
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   277
		struct dirent *de;
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   278
		while ((de = readdir(dp))) {
45851
81da6feb5000 chg: reset errno prior to calling strtol()
Yuya Nishihara <yuya@tcha.org>
parents: 45850
diff changeset
   279
			errno = 0;
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   280
			char *end;
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   281
			long fd_value = strtol(de->d_name, &end, 10);
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   282
			if (end == de->d_name) {
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   283
				/* unable to convert to int (. or ..) */
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   284
				continue;
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   285
			}
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   286
			if (errno == ERANGE) {
45848
41aaf960dc00 chg: apply clang-format
Yuya Nishihara <yuya@tcha.org>
parents: 45802
diff changeset
   287
				debugmsg("tried to parse %s, but range error "
41aaf960dc00 chg: apply clang-format
Yuya Nishihara <yuya@tcha.org>
parents: 45802
diff changeset
   288
				         "occurred",
41aaf960dc00 chg: apply clang-format
Yuya Nishihara <yuya@tcha.org>
parents: 45802
diff changeset
   289
				         de->d_name);
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   290
				continue;
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   291
			}
45850
9534de20358f chg: do not close dir fd while iterating
Yuya Nishihara <yuya@tcha.org>
parents: 45849
diff changeset
   292
			if (fd_value > STDERR_FILENO && fd_value != dirfd(dp)) {
45849
731ea8fa1f11 chg: show debug message for each fd to be closed
Yuya Nishihara <yuya@tcha.org>
parents: 45848
diff changeset
   293
				debugmsg("closing fd %ld", fd_value);
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   294
				int res = close(fd_value);
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   295
				if (res) {
45848
41aaf960dc00 chg: apply clang-format
Yuya Nishihara <yuya@tcha.org>
parents: 45802
diff changeset
   296
					debugmsg("tried to close fd %ld: %d "
41aaf960dc00 chg: apply clang-format
Yuya Nishihara <yuya@tcha.org>
parents: 45802
diff changeset
   297
					         "(errno: %d)",
41aaf960dc00 chg: apply clang-format
Yuya Nishihara <yuya@tcha.org>
parents: 45802
diff changeset
   298
					         fd_value, res, errno);
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   299
				}
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   300
			}
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   301
		}
45850
9534de20358f chg: do not close dir fd while iterating
Yuya Nishihara <yuya@tcha.org>
parents: 45849
diff changeset
   302
		closedir(dp);
45802
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   303
	}
8711dc13474c chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents: 45551
diff changeset
   304
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   305
	if (putenv("CHGINTERNALMARK=") != 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   306
		abortmsgerrno("failed to putenv");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
	if (execvp(hgcmd, (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   308
		abortmsgerrno("failed to exec cmdserver");
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   309
	free(argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   310
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   311
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   312
/* 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
   313
static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   314
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   315
	static const struct timespec sleepreq = {0, 10 * 1000000};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   316
	int pst = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   318
	debugmsg("try connect to %s repeatedly", opts->initsockname);
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   319
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   320
	unsigned int timeoutsec = 60; /* default: 60 seconds */
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   321
	const char *timeoutenv = getenv("CHGTIMEOUT");
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   322
	if (timeoutenv)
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   323
		sscanf(timeoutenv, "%u", &timeoutsec);
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   324
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   325
	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
   326
		hgclient_t *hgc = hgc_open(opts->initsockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   327
		if (hgc) {
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   328
			debugmsg("rename %s to %s", opts->initsockname,
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   329
			         opts->sockname);
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   330
			int r = rename(opts->initsockname, opts->sockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   331
			if (r != 0)
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   332
				abortmsgerrno("cannot rename");
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   333
			return hgc;
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   334
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   335
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   336
		if (pid > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   337
			/* 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
   338
			int r = waitpid(pid, &pst, WNOHANG);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   339
			if (r != 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   340
				goto cleanup;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   341
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   342
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   343
		nanosleep(&sleepreq, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   344
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   345
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   346
	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
   347
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   348
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   349
cleanup:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   350
	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
   351
		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
   352
			abortmsg("could not connect to cmdserver "
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   353
			         "(exited with status 0)");
28477
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   354
		debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   355
		exit(WEXITSTATUS(pst));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   356
	} else if (WIFSIGNALED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   357
		abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   358
	} else {
28851
584e0716c7af chg: fix spelling in the error message about error waiting for cmdserver
Jun Wu <quark@fb.com>
parents: 28790
diff changeset
   359
		abortmsg("error while waiting for cmdserver");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   360
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   361
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   362
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   363
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   364
/* 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
   365
static hgclient_t *connectcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   366
{
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   367
	const char *sockname =
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   368
	    opts->redirectsockname[0] ? opts->redirectsockname : opts->sockname;
28769
222f482930c8 chg: make connect debug message less repetitive
Jun Wu <quark@fb.com>
parents: 28605
diff changeset
   369
	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
   370
	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
   371
	if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   372
		return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   373
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   374
	/* 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
   375
	 * 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
   376
	 * 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
   377
	 * 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
   378
	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
   379
		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
   380
30620
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30513
diff changeset
   381
	debugmsg("start cmdserver at %s", opts->initsockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   382
50383
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   383
	/* Get the path to the hg executable before we fork because this
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   384
	 * function might update the environment, and we want this to be
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   385
	 * reflected in both the parent and child processes. */
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   386
	const char *hgcmd = gethgcmd();
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   387
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   388
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   389
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   390
		abortmsg("failed to fork cmdserver process");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   391
	if (pid == 0) {
50383
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   392
		execcmdserver(hgcmd, opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   393
	} else {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   394
		hgc = retryconnectcmdserver(opts, pid);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   396
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   397
	return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   399
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   400
static void killcmdserver(const struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   401
{
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   402
	/* resolve config hash */
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   403
	char *resolvedpath = realpath(opts->sockname, NULL);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   404
	if (resolvedpath) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   405
		unlink(resolvedpath);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   406
		free(resolvedpath);
28060
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
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   410
/* 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
   411
 * 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
   412
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
   413
{
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   414
	int needreconnect = 0;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   415
	if (!insts)
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   416
		return needreconnect;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   417
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   418
	assert(insts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   419
	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
   420
	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
   421
	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
   422
		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
   423
		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
   424
			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
   425
		} 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
   426
			int r = snprintf(opts->redirectsockname,
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   427
			                 sizeof(opts->redirectsockname), "%s",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   428
			                 *pinst + 9);
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   429
			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
   430
				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
   431
			needreconnect = 1;
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   432
		} else if (strncmp(*pinst, "exit ", 5) == 0) {
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   433
			int n = 0;
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   434
			if (sscanf(*pinst + 5, "%d", &n) != 1)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   435
				abortmsg("cannot read the exit code");
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   436
			exit(n);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   437
		} else if (strcmp(*pinst, "reconnect") == 0) {
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   438
			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
   439
		} else {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   440
			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
   441
		}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   442
	}
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   443
	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
   444
}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   445
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   446
/*
45520
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   447
 * Test whether the command and the environment is unsupported or not.
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   448
 *
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   449
 * If any of the stdio file descriptors are not present (rare, but some tools
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   450
 * might spawn new processes without stdio instead of redirecting them to the
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   451
 * null device), then mark it as not supported because attachio won't work
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   452
 * correctly.
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   453
 *
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   454
 * The command list is not designed to cover all cases. But it's fast, and does
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   455
 * not depend on the server.
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   456
 */
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   457
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
   458
{
46177
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 45851
diff changeset
   459
	enum {
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 45851
diff changeset
   460
		SERVE = 1,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 45851
diff changeset
   461
		DAEMON = 2,
0c320e6032f1 chg: format code by clang-format version 11.0.1-+rc1-1
Yuya Nishihara <yuya@tcha.org>
parents: 45851
diff changeset
   462
		SERVEDAEMON = SERVE | DAEMON,
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   463
	};
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   464
	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
   465
	int i;
45520
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   466
	/* use fcntl to test missing stdio fds */
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   467
	if (fcntl(STDIN_FILENO, F_GETFD) == -1 ||
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   468
	    fcntl(STDOUT_FILENO, F_GETFD) == -1 ||
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   469
	    fcntl(STDERR_FILENO, F_GETFD) == -1) {
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   470
		debugmsg("stdio fds are missing");
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   471
		return 1;
5eee6f4f3d0d chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents: 44995
diff changeset
   472
	}
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   473
	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
   474
		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
   475
			break;
44617
1e459ac4cb48 chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 44261
diff changeset
   476
		/*
1e459ac4cb48 chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 44261
diff changeset
   477
		 * there can be false positives but no false negative
1e459ac4cb48 chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 44261
diff changeset
   478
		 * we cannot assume `serve` will always be first argument
1e459ac4cb48 chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 44261
diff changeset
   479
		 * because global options can be passed before the command name
1e459ac4cb48 chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 44261
diff changeset
   480
		 */
1e459ac4cb48 chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents: 44261
diff changeset
   481
		if (strcmp("serve", argv[i]) == 0)
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   482
			state |= SERVE;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   483
		else if (strcmp("-d", argv[i]) == 0 ||
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   484
		         strcmp("--daemon", argv[i]) == 0)
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   485
			state |= DAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   486
	}
34531
50788d1ae6cc chg: just forward --time to command server
Yuya Nishihara <yuya@tcha.org>
parents: 31890
diff changeset
   487
	return (state & SERVEDAEMON) == SERVEDAEMON;
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   488
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   489
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   490
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
   491
{
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   492
	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
   493
	if (execvp(gethgcmd(), (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   494
		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
   495
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   496
50383
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   497
int main(int argc, const char *argv[])
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   498
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   499
	if (getenv("CHGDEBUG"))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   500
		enabledebugmsg();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   501
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   502
	if (!getenv("HGPLAIN") && isatty(fileno(stderr)))
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   503
		enablecolor();
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   504
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   505
	if (getenv("CHGINTERNALMARK"))
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   506
		abortmsg("chg started by chg detected.\n"
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   507
		         "Please make sure ${HG:-hg} is not a symlink or "
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   508
		         "wrapper to chg. Alternatively, set $CHGHG to the "
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   509
		         "path of real hg.");
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   510
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   511
	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
   512
		execoriginalhg(argv);
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   513
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   514
	struct cmdserveropts opts;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   515
	initcmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   516
	setcmdserveropts(&opts);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   517
	setcmdserverargs(&opts, argc, argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   518
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   519
	if (argc == 2) {
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   520
		if (strcmp(argv[1], "--kill-chg-daemon") == 0) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   521
			killcmdserver(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   522
			return 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   523
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   524
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   525
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   526
	hgclient_t *hgc;
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   527
	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
   528
	while (1) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   529
		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
   530
		if (!hgc)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   531
			abortmsg("cannot open hg client");
50383
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   532
		/* Use `environ(7)` instead of the optional `envp` argument to
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   533
		 * `main` because `envp` does not update when the environment
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   534
		 * changes, but `environ` does. */
cf4d2f31660d chg: populate CHGHG if not set
Arun Kulshreshtha <akulshreshtha@janestreet.com>
parents: 47024
diff changeset
   535
		hgc_setenv(hgc, (const char *const *)environ);
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   536
		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
   537
		int needreconnect = runinstructions(&opts, insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   538
		free(insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   539
		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
   540
			break;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   541
		hgc_close(hgc);
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   542
		if (++retry > 10)
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   543
			abortmsg("too many redirections.\n"
35959
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   544
			         "Please make sure %s is not a wrapper which "
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   545
			         "changes sensitive environment variables "
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   546
			         "before executing hg. If you have to use a "
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   547
			         "wrapper, wrap chg instead of hg.",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   548
			         gethgcmd());
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   549
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   550
30690
e9ec42634ec8 chg: decouple hgclient from setupsignalhandler
Jun Wu <quark@fb.com>
parents: 30689
diff changeset
   551
	setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc));
31890
ca7af5d15b21 chg: always wait for pager
Jun Wu <quark@fb.com>
parents: 30884
diff changeset
   552
	atexit(waitpager);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   553
	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
   554
	restoresignalhandler();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   555
	hgc_close(hgc);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   556
	freecmdserveropts(&opts);
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   557
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   558
	return exitcode;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   559
}