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