contrib/chg/chg.c
author Gregory Szorc <gregory.szorc@gmail.com>
Fri, 06 Apr 2018 17:21:16 -0700
changeset 37536 2003da12f49b
parent 35998 9724f54923ec
child 37871 3c84493556db
permissions -rw-r--r--
wireproto: only expose "clonebundles" to version 1 transports This may make a comeback in wire protocol version 2. The feature definitely needs to be carried forward. But at this juncture, I'm flirting with the idea of implementing this via a "redirect" mechanism at the command response level itself rather than something that requires one-off client support for querying and handling. i.e. I want to make it so servers can say "fetch this first and then come back" and clients handle that automatically. This would not only support clone bundles, but would also support piece-meal "pull bundles." Whatever happens, we can deal with it down the road. Differential Revision: https://phab.mercurial-scm.org/D3203
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
30680
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30679
diff changeset
    29
#ifndef PATH_MAX
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30679
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 {
30680
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30679
diff changeset
    34
	char sockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30679
diff changeset
    35
	char initsockname[PATH_MAX];
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30679
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
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    41
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
    42
{
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    43
	memset(opts, 0, sizeof(struct cmdserveropts));
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
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    46
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
    47
{
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    48
	free(opts->args);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    49
	opts->args = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    50
	opts->argsize = 0;
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
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
 * 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
    55
 * 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
    56
 * 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
    57
 */
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    58
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
    59
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    60
	static const struct {
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    61
		const char *name;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    62
		size_t narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    63
	} flags[] = {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    64
	    {"--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
    65
	    {"--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
    66
	};
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    67
	size_t i;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    68
	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
    69
		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
    70
		size_t narg = flags[i].narg;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    71
		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
    72
			if (arg[len] == '\0') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    73
				/* --flag (value) */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    74
				return narg + 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    75
			} else if (arg[len] == '=' && narg > 0) {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    76
				/* --flag=value */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    77
				return 1;
28790
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    78
			} else if (flags[i].name[1] != '-') {
b0cc9652e8dc chg: wrap line at 80 chars
Jun Wu <quark@fb.com>
parents: 28789
diff changeset
    79
				/* short flag */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    80
				return 1;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    81
			}
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
	return 0;
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
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
 * 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
    89
 */
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    90
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
    91
                             const char *argv[])
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    92
{
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    93
	size_t i, step;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    94
	opts->argsize = 0;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    95
	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
    96
		if (!argv[i])
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
    97
			continue; /* pass clang-analyse */
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    98
		if (strcmp(argv[i], "--") == 0)
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
    99
			break;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   100
		size_t n = testsensitiveflag(argv[i]);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   101
		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
   102
			continue;
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   103
		opts->args =
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   104
		    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
   105
		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
   106
		       sizeof(char *) * n);
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   107
		opts->argsize += n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   108
		step = n;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   109
	}
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
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   112
static void preparesockdir(const char *sockdir)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   113
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   114
	int r;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   115
	r = mkdir(sockdir, 0700);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   116
	if (r < 0 && errno != EEXIST)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   117
		abortmsgerrno("cannot create sockdir %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   118
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   119
	struct stat st;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   120
	r = lstat(sockdir, &st);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   121
	if (r < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   122
		abortmsgerrno("cannot stat %s", sockdir);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   123
	if (!S_ISDIR(st.st_mode))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   124
		abortmsg("cannot create sockdir %s (file exists)", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   125
	if (st.st_uid != geteuid() || st.st_mode & 0077)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   126
		abortmsg("insecure sockdir %s", sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   127
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   128
30916
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   129
/*
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   130
 * 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
   131
 * 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
   132
 * 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
   133
 * 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
   134
 * [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
   135
 */
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   136
static int checkruntimedir(const char *sockdir)
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   137
{
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   138
	struct stat st;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   139
	int r = lstat(sockdir, &st);
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   140
	if (r < 0) /* ex. does not exist */
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   141
		return 0;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   142
	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
   143
		return 0;
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   144
	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
   145
}
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   146
30683
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   147
static void getdefaultsockdir(char sockdir[], size_t size)
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   148
{
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   149
	/* by default, put socket file in secure directory
30684
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   150
	 * (${XDG_RUNTIME_DIR}/chg, or /${TMPDIR:-tmp}/chg$UID)
30683
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   151
	 * (permission of socket file may be ignored on some Unices) */
30684
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   152
	const char *runtimedir = getenv("XDG_RUNTIME_DIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   153
	int r;
30916
a68510b69f41 chg: verify XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30741
diff changeset
   154
	if (runtimedir && checkruntimedir(runtimedir)) {
30684
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   155
		r = snprintf(sockdir, size, "%s/chg", runtimedir);
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   156
	} else {
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   157
		const char *tmpdir = getenv("TMPDIR");
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   158
		if (!tmpdir)
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   159
			tmpdir = "/tmp";
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   160
		r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid());
0064a1eb28e2 chg: respect XDG_RUNTIME_DIR
Jun Wu <quark@fb.com>
parents: 30683
diff changeset
   161
	}
30683
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   162
	if (r < 0 || (size_t)r >= size)
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   163
		abortmsg("too long TMPDIR (r = %d)", r);
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   164
}
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   165
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   166
static void setcmdserveropts(struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   167
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   168
	int r;
30680
c80c16a8a0b0 chg: support long socket path
Jun Wu <quark@fb.com>
parents: 30679
diff changeset
   169
	char sockdir[PATH_MAX];
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   170
	const char *envsockname = getenv("CHGSOCKNAME");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   171
	if (!envsockname) {
30683
4677df6b449a chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents: 30680
diff changeset
   172
		getdefaultsockdir(sockdir, sizeof(sockdir));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   173
		preparesockdir(sockdir);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   174
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   175
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   176
	const char *basename = (envsockname) ? envsockname : sockdir;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   177
	const char *sockfmt = (envsockname) ? "%s" : "%s/server";
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   178
	r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   179
	if (r < 0 || (size_t)r >= sizeof(opts->sockname))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   180
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   181
	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
   182
	             opts->sockname, (unsigned)getpid());
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   183
	if (r < 0 || (size_t)r >= sizeof(opts->initsockname))
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   184
		abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   185
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   186
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   187
static const char *gethgcmd(void)
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   188
{
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   189
	static const char *hgcmd = NULL;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   190
	if (!hgcmd) {
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   191
		hgcmd = getenv("CHGHG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   192
		if (!hgcmd || hgcmd[0] == '\0')
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   193
			hgcmd = getenv("HG");
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   194
		if (!hgcmd || hgcmd[0] == '\0')
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   195
#ifdef HGPATH
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   196
			hgcmd = (HGPATH);
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   197
#else
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   198
			hgcmd = "hg";
28605
baa073200ba2 chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents: 28555
diff changeset
   199
#endif
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   200
	}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   201
	return hgcmd;
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   202
}
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   203
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   204
static void execcmdserver(const struct cmdserveropts *opts)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   205
{
28237
a3d73e069f8d chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents: 28196
diff changeset
   206
	const char *hgcmd = gethgcmd();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   207
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   208
	const char *baseargv[] = {
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   209
	    hgcmd,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   210
	    "serve",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   211
	    "--cmdserver",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   212
	    "chgunix",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   213
	    "--address",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   214
	    opts->initsockname,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   215
	    "--daemon-postexec",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   216
	    "chdir:/",
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   217
	};
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   218
	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
   219
	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
   220
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   221
	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
   222
	memcpy(argv, baseargv, sizeof(baseargv));
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   223
	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
   224
	argv[argsize - 1] = NULL;
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   225
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   226
	if (putenv("CHGINTERNALMARK=") != 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   227
		abortmsgerrno("failed to putenv");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   228
	if (execvp(hgcmd, (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   229
		abortmsgerrno("failed to exec cmdserver");
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   230
	free(argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   231
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   232
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   233
/* 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
   234
static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   235
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   236
	static const struct timespec sleepreq = {0, 10 * 1000000};
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   237
	int pst = 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   238
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   239
	debugmsg("try connect to %s repeatedly", opts->initsockname);
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   240
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   241
	unsigned int timeoutsec = 60; /* default: 60 seconds */
29345
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   242
	const char *timeoutenv = getenv("CHGTIMEOUT");
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   243
	if (timeoutenv)
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   244
		sscanf(timeoutenv, "%u", &timeoutsec);
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   245
62b890496de5 chg: make timeout adjustable
Jun Wu <quark@fb.com>
parents: 29344
diff changeset
   246
	for (unsigned int i = 0; !timeoutsec || i < timeoutsec * 100; i++) {
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   247
		hgclient_t *hgc = hgc_open(opts->initsockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   248
		if (hgc) {
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   249
			debugmsg("rename %s to %s", opts->initsockname,
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   250
			         opts->sockname);
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   251
			int r = rename(opts->initsockname, opts->sockname);
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   252
			if (r != 0)
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   253
				abortmsgerrno("cannot rename");
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   254
			return hgc;
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   255
		}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   256
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   257
		if (pid > 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   258
			/* 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
   259
			int r = waitpid(pid, &pst, WNOHANG);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   260
			if (r != 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   261
				goto cleanup;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   262
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   263
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   264
		nanosleep(&sleepreq, NULL);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   265
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   266
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   267
	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
   268
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   269
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   270
cleanup:
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   271
	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
   272
		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
   273
			abortmsg("could not connect to cmdserver "
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   274
			         "(exited with status 0)");
28477
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   275
		debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst));
194a6cd873cd chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents: 28455
diff changeset
   276
		exit(WEXITSTATUS(pst));
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   277
	} else if (WIFSIGNALED(pst)) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   278
		abortmsg("cmdserver killed by signal %d", WTERMSIG(pst));
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   279
	} else {
28851
584e0716c7af chg: fix spelling in the error message about error waiting for cmdserver
Jun Wu <quark@fb.com>
parents: 28790
diff changeset
   280
		abortmsg("error while waiting for cmdserver");
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   281
	}
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   282
	return NULL;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   283
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   284
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   285
/* 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
   286
static hgclient_t *connectcmdserver(struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   287
{
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   288
	const char *sockname =
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   289
	    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
   290
	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
   291
	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
   292
	if (hgc)
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   293
		return hgc;
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   294
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   295
	/* 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
   296
	 * 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
   297
	 * 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
   298
	 * 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
   299
	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
   300
		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
   301
30625
937c52f06709 chg: start server at a unique address
Jun Wu <quark@fb.com>
parents: 30522
diff changeset
   302
	debugmsg("start cmdserver at %s", opts->initsockname);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   303
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   304
	pid_t pid = fork();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   305
	if (pid < 0)
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   306
		abortmsg("failed to fork cmdserver process");
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   307
	if (pid == 0) {
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   308
		execcmdserver(opts);
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   309
	} else {
28196
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   310
		hgc = retryconnectcmdserver(opts, pid);
28060
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
87de4a22e8c2 chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents: 28194
diff changeset
   313
	return hgc;
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
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   316
static void killcmdserver(const struct cmdserveropts *opts)
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   317
{
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   318
	/* resolve config hash */
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   319
	char *resolvedpath = realpath(opts->sockname, NULL);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   320
	if (resolvedpath) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   321
		unlink(resolvedpath);
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   322
		free(resolvedpath);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   323
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   324
}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   325
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   326
/* 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
   327
 * 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
   328
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
   329
{
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   330
	int needreconnect = 0;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   331
	if (!insts)
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   332
		return needreconnect;
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   333
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   334
	assert(insts);
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   335
	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
   336
	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
   337
	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
   338
		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
   339
		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
   340
			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
   341
		} 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
   342
			int r = snprintf(opts->redirectsockname,
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   343
			                 sizeof(opts->redirectsockname), "%s",
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   344
			                 *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
   345
			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
   346
				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
   347
			needreconnect = 1;
28516
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   348
		} else if (strncmp(*pinst, "exit ", 5) == 0) {
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   349
			int n = 0;
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   350
			if (sscanf(*pinst + 5, "%d", &n) != 1)
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   351
				abortmsg("cannot read the exit code");
3bf2892f685f chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents: 28477
diff changeset
   352
			exit(n);
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   353
		} else if (strcmp(*pinst, "reconnect") == 0) {
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   354
			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
   355
		} else {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   356
			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
   357
		}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   358
	}
28535
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   359
	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
   360
}
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   361
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   362
/*
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   363
 * 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
   364
 * 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
   365
 * 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
   366
 */
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   367
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
   368
{
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   369
	enum { SERVE = 1,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   370
	       DAEMON = 2,
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   371
	       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
   372
	};
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   373
	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
   374
	int i;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   375
	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
   376
		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
   377
			break;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   378
		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
   379
			state |= SERVE;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   380
		else if (strcmp("-d", argv[i]) == 0 ||
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   381
		         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
   382
			state |= DAEMON;
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   383
	}
34531
50788d1ae6cc chg: just forward --time to command server
Yuya Nishihara <yuya@tcha.org>
parents: 31890
diff changeset
   384
	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
   385
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   386
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   387
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
   388
{
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   389
	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
   390
	if (execvp(gethgcmd(), (char **)argv) < 0)
28789
7f6e0a15189b chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents: 28787
diff changeset
   391
		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
   392
}
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   393
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   394
int main(int argc, const char *argv[], const char *envp[])
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   395
{
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   396
	if (getenv("CHGDEBUG"))
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   397
		enabledebugmsg();
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   398
28787
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   399
	if (!getenv("HGPLAIN") && isatty(fileno(stderr)))
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   400
		enablecolor();
ea86cdcd9b50 chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents: 28769
diff changeset
   401
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   402
	if (getenv("CHGINTERNALMARK"))
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   403
		abortmsg("chg started by chg detected.\n"
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   404
		         "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
   405
		         "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
   406
		         "path of real hg.");
28261
2ab59ac06b76 chg: detect chg started by chg
Jun Wu <quark@fb.com>
parents: 28260
diff changeset
   407
28260
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   408
	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
   409
		execoriginalhg(argv);
0a17cfbe5429 chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents: 28237
diff changeset
   410
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   411
	struct cmdserveropts opts;
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   412
	initcmdserveropts(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   413
	setcmdserveropts(&opts);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   414
	setcmdserverargs(&opts, argc, argv);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   415
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   416
	if (argc == 2) {
28455
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   417
		if (strcmp(argv[1], "--kill-chg-daemon") == 0) {
412ee35a8005 chg: do not write pidfile
Jun Wu <quark@fb.com>
parents: 28454
diff changeset
   418
			killcmdserver(&opts);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   419
			return 0;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   420
		}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   421
	}
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   422
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   423
	hgclient_t *hgc;
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   424
	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
   425
	while (1) {
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   426
		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
   427
		if (!hgc)
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   428
			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
   429
		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
   430
		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
   431
		int needreconnect = runinstructions(&opts, insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   432
		free(insts);
aa082a8125da chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents: 28516
diff changeset
   433
		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
   434
			break;
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   435
		hgc_close(hgc);
28358
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   436
		if (++retry > 10)
ffd3ac07b1d7 chg: limit reconnect attempts
Jun Wu <quark@fb.com>
parents: 28357
diff changeset
   437
			abortmsg("too many redirections.\n"
35998
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   438
			         "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
   439
			         "changes sensitive environment variables "
9724f54923ec chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents: 34531
diff changeset
   440
			         "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
   441
			         "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
   442
			         gethgcmd());
28357
2f0f352d4196 chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents: 28327
diff changeset
   443
	}
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   444
30690
e9ec42634ec8 chg: decouple hgclient from setupsignalhandler
Jun Wu <quark@fb.com>
parents: 30689
diff changeset
   445
	setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc));
31890
ca7af5d15b21 chg: always wait for pager
Jun Wu <quark@fb.com>
parents: 30916
diff changeset
   446
	atexit(waitpager);
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   447
	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
   448
	restoresignalhandler();
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   449
	hgc_close(hgc);
28167
66f6dad20c19 chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents: 28086
diff changeset
   450
	freecmdserveropts(&opts);
29344
bb3d5c20eaf6 chg: exec pager in child process
Jun Wu <quark@fb.com>
parents: 29016
diff changeset
   451
28060
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   452
	return exitcode;
726f8d6cc324 chg: import frontend sources
Yuya Nishihara <yuya@tcha.org>
parents:
diff changeset
   453
}