author | Martin von Zweigbergk <martinvonz@google.com> |
Wed, 16 Dec 2020 22:30:07 -0800 | |
changeset 46133 | dfe2760db2a6 |
parent 45771 | 81da6feb5000 |
child 46177 | 0c320e6032f1 |
permissions | -rw-r--r-- |
28060 | 1 |
/* |
2 |
* A fast client for Mercurial command server |
|
3 |
* |
|
4 |
* Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> |
|
5 |
* |
|
6 |
* This software may be used and distributed according to the terms of the |
|
7 |
* GNU General Public License version 2 or any later version. |
|
8 |
*/ |
|
9 |
||
10 |
#include <assert.h> |
|
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
11 |
#include <dirent.h> |
28060 | 12 |
#include <errno.h> |
13 |
#include <fcntl.h> |
|
14 |
#include <signal.h> |
|
15 |
#include <stdio.h> |
|
16 |
#include <stdlib.h> |
|
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 | 19 |
#include <sys/stat.h> |
20 |
#include <sys/types.h> |
|
21 |
#include <sys/un.h> |
|
22 |
#include <sys/wait.h> |
|
23 |
#include <time.h> |
|
24 |
#include <unistd.h> |
|
25 |
||
26 |
#include "hgclient.h" |
|
30693 | 27 |
#include "procutil.h" |
28060 | 28 |
#include "util.h" |
29 |
||
30680 | 30 |
#ifndef PATH_MAX |
31 |
#define PATH_MAX 4096 |
|
28060 | 32 |
#endif |
33 |
||
34 |
struct cmdserveropts { |
|
30680 | 35 |
char sockname[PATH_MAX]; |
36 |
char initsockname[PATH_MAX]; |
|
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 | 40 |
}; |
41 |
||
35998
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 |
|
35998
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[] = { |
35998
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 | 73 |
if (arg[len] == '\0') { |
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 | 76 |
} else if (arg[len] == '=' && narg > 0) { |
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 | 79 |
} else if (flags[i].name[1] != '-') { |
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 |
*/ |
35998
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]) |
35998
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; |
35998
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 | 113 |
static void preparesockdir(const char *sockdir) |
114 |
{ |
|
115 |
int r; |
|
116 |
r = mkdir(sockdir, 0700); |
|
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 | 119 |
|
120 |
struct stat st; |
|
121 |
r = lstat(sockdir, &st); |
|
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 | 124 |
if (!S_ISDIR(st.st_mode)) |
125 |
abortmsg("cannot create sockdir %s (file exists)", sockdir); |
|
126 |
if (st.st_uid != geteuid() || st.st_mode & 0077) |
|
127 |
abortmsg("insecure sockdir %s", sockdir); |
|
128 |
} |
|
129 |
||
30916 | 130 |
/* |
131 |
* Check if a socket directory exists and is only owned by the current user. |
|
132 |
* Return 1 if so, 0 if not. This is used to check if XDG_RUNTIME_DIR can be |
|
133 |
* used or not. According to the specification [1], XDG_RUNTIME_DIR should be |
|
134 |
* ignored if the directory is not owned by the user with mode 0700. |
|
135 |
* [1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html |
|
136 |
*/ |
|
137 |
static int checkruntimedir(const char *sockdir) |
|
138 |
{ |
|
139 |
struct stat st; |
|
140 |
int r = lstat(sockdir, &st); |
|
141 |
if (r < 0) /* ex. does not exist */ |
|
142 |
return 0; |
|
143 |
if (!S_ISDIR(st.st_mode)) /* ex. is a file, not a directory */ |
|
144 |
return 0; |
|
145 |
return st.st_uid == geteuid() && (st.st_mode & 0777) == 0700; |
|
146 |
} |
|
147 |
||
30683
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30680
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:
30680
diff
changeset
|
149 |
{ |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30680
diff
changeset
|
150 |
/* by default, put socket file in secure directory |
30684 | 151 |
* (${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
|
152 |
* (permission of socket file may be ignored on some Unices) */ |
30684 | 153 |
const char *runtimedir = getenv("XDG_RUNTIME_DIR"); |
154 |
int r; |
|
30916 | 155 |
if (runtimedir && checkruntimedir(runtimedir)) { |
30684 | 156 |
r = snprintf(sockdir, size, "%s/chg", runtimedir); |
157 |
} else { |
|
158 |
const char *tmpdir = getenv("TMPDIR"); |
|
159 |
if (!tmpdir) |
|
160 |
tmpdir = "/tmp"; |
|
161 |
r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid()); |
|
162 |
} |
|
30683
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30680
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:
30680
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:
30680
diff
changeset
|
165 |
} |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30680
diff
changeset
|
166 |
|
28060 | 167 |
static void setcmdserveropts(struct cmdserveropts *opts) |
168 |
{ |
|
169 |
int r; |
|
30680 | 170 |
char sockdir[PATH_MAX]; |
28060 | 171 |
const char *envsockname = getenv("CHGSOCKNAME"); |
172 |
if (!envsockname) { |
|
30683
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30680
diff
changeset
|
173 |
getdefaultsockdir(sockdir, sizeof(sockdir)); |
28060 | 174 |
preparesockdir(sockdir); |
175 |
} |
|
176 |
||
177 |
const char *basename = (envsockname) ? envsockname : sockdir; |
|
178 |
const char *sockfmt = (envsockname) ? "%s" : "%s/server"; |
|
179 |
r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename); |
|
180 |
if (r < 0 || (size_t)r >= sizeof(opts->sockname)) |
|
181 |
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
|
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()); |
30625
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
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:
30522
diff
changeset
|
185 |
abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); |
28060 | 186 |
} |
187 |
||
45557
4c8d9b53b1c7
chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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; |
45557
4c8d9b53b1c7
chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents:
45528
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:
45528
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:
45528
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:
45528
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:
45528
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"); |
45557
4c8d9b53b1c7
chg: make is possible to call by default an hg binary located next to chg
Valentin Gatien-Baron <vgatien-baron@janestreet.com>
parents:
45528
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:
45528
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 |
} |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
235 |
return hgcmd; |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
236 |
} |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
237 |
|
28060 | 238 |
static void execcmdserver(const struct cmdserveropts *opts) |
239 |
{ |
|
28237
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
240 |
const char *hgcmd = gethgcmd(); |
28060 | 241 |
|
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
242 |
const char *baseargv[] = { |
35998
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
243 |
hgcmd, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
244 |
"serve", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
245 |
"--cmdserver", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
246 |
"chgunix", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
247 |
"--address", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
248 |
opts->initsockname, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
249 |
"--daemon-postexec", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
250 |
"chdir:/", |
28060 | 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)); |
37871
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35998
diff
changeset
|
257 |
if (opts->args) { |
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35998
diff
changeset
|
258 |
size_t size = sizeof(char *) * opts->argsize; |
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35998
diff
changeset
|
259 |
memcpy(argv + baseargvsize, opts->args, size); |
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35998
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 |
|
44308
04a3ae7aba14
chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents:
37871
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:
37871
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:
37871
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:
37871
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:
37871
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:
37871
diff
changeset
|
268 |
if (setenv("CHGORIG_LC_CTYPE", lc_ctype_env, 1) != 0) { |
45015 | 269 |
abortmsgerrno("failed to setenv CHGORIG_LC_CTYPE"); |
44308
04a3ae7aba14
chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents:
37871
diff
changeset
|
270 |
} |
04a3ae7aba14
chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents:
37871
diff
changeset
|
271 |
} |
04a3ae7aba14
chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents:
37871
diff
changeset
|
272 |
|
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
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:
45557
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:
45557
diff
changeset
|
275 |
if (dp != NULL) { |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
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:
45557
diff
changeset
|
277 |
struct dirent *de; |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
278 |
while ((de = readdir(dp))) { |
45771
81da6feb5000
chg: reset errno prior to calling strtol()
Yuya Nishihara <yuya@tcha.org>
parents:
45770
diff
changeset
|
279 |
errno = 0; |
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
280 |
char *end; |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
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:
45557
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:
45557
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:
45557
diff
changeset
|
284 |
continue; |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
285 |
} |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
286 |
if (errno == ERANGE) { |
45768 | 287 |
debugmsg("tried to parse %s, but range error " |
288 |
"occurred", |
|
289 |
de->d_name); |
|
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
290 |
continue; |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
291 |
} |
45770
9534de20358f
chg: do not close dir fd while iterating
Yuya Nishihara <yuya@tcha.org>
parents:
45769
diff
changeset
|
292 |
if (fd_value > STDERR_FILENO && fd_value != dirfd(dp)) { |
45769
731ea8fa1f11
chg: show debug message for each fd to be closed
Yuya Nishihara <yuya@tcha.org>
parents:
45768
diff
changeset
|
293 |
debugmsg("closing fd %ld", fd_value); |
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
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:
45557
diff
changeset
|
295 |
if (res) { |
45768 | 296 |
debugmsg("tried to close fd %ld: %d " |
297 |
"(errno: %d)", |
|
298 |
fd_value, res, errno); |
|
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
299 |
} |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
300 |
} |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
301 |
} |
45770
9534de20358f
chg: do not close dir fd while iterating
Yuya Nishihara <yuya@tcha.org>
parents:
45769
diff
changeset
|
302 |
closedir(dp); |
45767
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
303 |
} |
8711dc13474c
chg: close file descriptors when starting the daemon
Mathias De Mare <mathias.de_mare@nokia.com>
parents:
45557
diff
changeset
|
304 |
|
28261 | 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 | 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 | 310 |
} |
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 | 314 |
{ |
315 |
static const struct timespec sleepreq = {0, 10 * 1000000}; |
|
316 |
int pst = 0; |
|
317 |
||
30625
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
318 |
debugmsg("try connect to %s repeatedly", opts->initsockname); |
29345 | 319 |
|
35998
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 | 321 |
const char *timeoutenv = getenv("CHGTIMEOUT"); |
322 |
if (timeoutenv) |
|
323 |
sscanf(timeoutenv, "%u", &timeoutsec); |
|
324 |
||
325 |
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
|
326 |
hgclient_t *hgc = hgc_open(opts->initsockname); |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
327 |
if (hgc) { |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
328 |
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
|
329 |
opts->sockname); |
30625
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
330 |
int r = rename(opts->initsockname, opts->sockname); |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
331 |
if (r != 0) |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
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; |
30625
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
334 |
} |
28060 | 335 |
|
336 |
if (pid > 0) { |
|
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 | 339 |
if (r != 0) |
340 |
goto cleanup; |
|
341 |
} |
|
342 |
||
343 |
nanosleep(&sleepreq, NULL); |
|
344 |
} |
|
345 |
||
30625
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
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 | 348 |
|
349 |
cleanup: |
|
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 " |
35998
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 | 356 |
} else if (WIFSIGNALED(pst)) { |
357 |
abortmsg("cmdserver killed by signal %d", WTERMSIG(pst)); |
|
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 | 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 | 362 |
} |
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 | 366 |
{ |
35998
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 | 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 |
|
30625
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30522
diff
changeset
|
381 |
debugmsg("start cmdserver at %s", opts->initsockname); |
28060 | 382 |
|
383 |
pid_t pid = fork(); |
|
384 |
if (pid < 0) |
|
385 |
abortmsg("failed to fork cmdserver process"); |
|
386 |
if (pid == 0) { |
|
387 |
execcmdserver(opts); |
|
388 |
} else { |
|
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
389 |
hgc = retryconnectcmdserver(opts, pid); |
28060 | 390 |
} |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
391 |
|
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
392 |
return hgc; |
28060 | 393 |
} |
394 |
||
28455 | 395 |
static void killcmdserver(const struct cmdserveropts *opts) |
28060 | 396 |
{ |
28455 | 397 |
/* resolve config hash */ |
398 |
char *resolvedpath = realpath(opts->sockname, NULL); |
|
399 |
if (resolvedpath) { |
|
400 |
unlink(resolvedpath); |
|
401 |
free(resolvedpath); |
|
28060 | 402 |
} |
403 |
} |
|
404 |
||
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
405 |
/* 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
|
406 |
* 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
|
407 |
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
|
408 |
{ |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
409 |
int needreconnect = 0; |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
410 |
if (!insts) |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
411 |
return needreconnect; |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
412 |
|
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
413 |
assert(insts); |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
414 |
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
|
415 |
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
|
416 |
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
|
417 |
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
|
418 |
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
|
419 |
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
|
420 |
} 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
|
421 |
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
|
422 |
sizeof(opts->redirectsockname), "%s", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
423 |
*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
|
424 |
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
|
425 |
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
|
426 |
needreconnect = 1; |
28516
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
427 |
} else if (strncmp(*pinst, "exit ", 5) == 0) { |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
428 |
int n = 0; |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
429 |
if (sscanf(*pinst + 5, "%d", &n) != 1) |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
430 |
abortmsg("cannot read the exit code"); |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
431 |
exit(n); |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
432 |
} else if (strcmp(*pinst, "reconnect") == 0) { |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
433 |
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
|
434 |
} else { |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
435 |
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
|
436 |
} |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
437 |
} |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
438 |
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
|
439 |
} |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
440 |
|
28260
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
441 |
/* |
45528
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
442 |
* 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:
45015
diff
changeset
|
443 |
* |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
444 |
* 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:
45015
diff
changeset
|
445 |
* 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:
45015
diff
changeset
|
446 |
* 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:
45015
diff
changeset
|
447 |
* correctly. |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
448 |
* |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
449 |
* 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:
45015
diff
changeset
|
450 |
* 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
|
451 |
*/ |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
452 |
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
|
453 |
{ |
35998
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
454 |
enum { SERVE = 1, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
455 |
DAEMON = 2, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
456 |
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
|
457 |
}; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
458 |
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
|
459 |
int i; |
45528
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
460 |
/* use fcntl to test missing stdio fds */ |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
461 |
if (fcntl(STDIN_FILENO, F_GETFD) == -1 || |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
462 |
fcntl(STDOUT_FILENO, F_GETFD) == -1 || |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
463 |
fcntl(STDERR_FILENO, F_GETFD) == -1) { |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
464 |
debugmsg("stdio fds are missing"); |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
465 |
return 1; |
5eee6f4f3d0d
chg: fallback to original hg if stdio fds are missing
Jun Wu <quark@fb.com>
parents:
45015
diff
changeset
|
466 |
} |
28260
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
467 |
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
|
468 |
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
|
469 |
break; |
44621
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44308
diff
changeset
|
470 |
/* |
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44308
diff
changeset
|
471 |
* 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:
44308
diff
changeset
|
472 |
* 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:
44308
diff
changeset
|
473 |
* 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:
44308
diff
changeset
|
474 |
*/ |
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44308
diff
changeset
|
475 |
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
|
476 |
state |= SERVE; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
477 |
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
|
478 |
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
|
479 |
state |= DAEMON; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
480 |
} |
34531
50788d1ae6cc
chg: just forward --time to command server
Yuya Nishihara <yuya@tcha.org>
parents:
31890
diff
changeset
|
481 |
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
|
482 |
} |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
483 |
|
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
484 |
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
|
485 |
{ |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
486 |
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
|
487 |
if (execvp(gethgcmd(), (char **)argv) < 0) |
28789
7f6e0a15189b
chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
488 |
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
|
489 |
} |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
490 |
|
28060 | 491 |
int main(int argc, const char *argv[], const char *envp[]) |
492 |
{ |
|
493 |
if (getenv("CHGDEBUG")) |
|
494 |
enabledebugmsg(); |
|
495 |
||
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28769
diff
changeset
|
496 |
if (!getenv("HGPLAIN") && isatty(fileno(stderr))) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28769
diff
changeset
|
497 |
enablecolor(); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28769
diff
changeset
|
498 |
|
28261 | 499 |
if (getenv("CHGINTERNALMARK")) |
500 |
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
|
501 |
"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
|
502 |
"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
|
503 |
"path of real hg."); |
28261 | 504 |
|
28260
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
505 |
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
|
506 |
execoriginalhg(argv); |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
507 |
|
28060 | 508 |
struct cmdserveropts opts; |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
509 |
initcmdserveropts(&opts); |
28060 | 510 |
setcmdserveropts(&opts); |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
511 |
setcmdserverargs(&opts, argc, argv); |
28060 | 512 |
|
513 |
if (argc == 2) { |
|
28455 | 514 |
if (strcmp(argv[1], "--kill-chg-daemon") == 0) { |
515 |
killcmdserver(&opts); |
|
28060 | 516 |
return 0; |
517 |
} |
|
518 |
} |
|
519 |
||
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
520 |
hgclient_t *hgc; |
28358 | 521 |
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
|
522 |
while (1) { |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
523 |
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
|
524 |
if (!hgc) |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
525 |
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
|
526 |
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
|
527 |
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
|
528 |
int needreconnect = runinstructions(&opts, insts); |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
529 |
free(insts); |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
530 |
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
|
531 |
break; |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
532 |
hgc_close(hgc); |
28358 | 533 |
if (++retry > 10) |
534 |
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
|
535 |
"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
|
536 |
"changes sensitive environment variables " |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
537 |
"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
|
538 |
"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
|
539 |
gethgcmd()); |
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
540 |
} |
28060 | 541 |
|
30690
e9ec42634ec8
chg: decouple hgclient from setupsignalhandler
Jun Wu <quark@fb.com>
parents:
30689
diff
changeset
|
542 |
setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc)); |
31890 | 543 |
atexit(waitpager); |
28060 | 544 |
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
|
545 |
restoresignalhandler(); |
28060 | 546 |
hgc_close(hgc); |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
547 |
freecmdserveropts(&opts); |
29344 | 548 |
|
28060 | 549 |
return exitcode; |
550 |
} |