Mercurial > hg
annotate contrib/chg/chg.c @ 45095:8e04607023e5
procutil: ensure that procutil.std{out,err}.write() writes all bytes
Python 3 offers different kind of streams and it’s not guaranteed for all of
them that calling write() writes all bytes.
When Python is started in unbuffered mode, sys.std{out,err}.buffer are
instances of io.FileIO, whose write() can write less bytes for
platform-specific reasons (e.g. Linux has a 0x7ffff000 bytes maximum and could
write less if interrupted by a signal; when writing to Windows consoles, it’s
limited to 32767 bytes to avoid the "not enough space" error). This can lead to
silent loss of data, both when using sys.std{out,err}.buffer (which may in fact
not be a buffered stream) and when using the text streams sys.std{out,err}
(I’ve created a CPython bug report for that:
https://bugs.python.org/issue41221).
Python may fix the problem at some point. For now, we implement our own wrapper
for procutil.std{out,err} that calls the raw stream’s write() method until all
bytes have been written. We don’t use sys.std{out,err} for larger writes, so I
think it’s not worth the effort to patch them.
author | Manuel Jacob <me@manueljacob.de> |
---|---|
date | Fri, 10 Jul 2020 12:27:58 +0200 |
parents | 2c920c4dbb31 |
children | 5eee6f4f3d0d |
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> | |
11 #include <errno.h> | |
12 #include <fcntl.h> | |
13 #include <signal.h> | |
14 #include <stdio.h> | |
15 #include <stdlib.h> | |
16 #include <string.h> | |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
17 #include <sys/file.h> |
28060 | 18 #include <sys/stat.h> |
19 #include <sys/types.h> | |
20 #include <sys/un.h> | |
21 #include <sys/wait.h> | |
22 #include <time.h> | |
23 #include <unistd.h> | |
24 | |
25 #include "hgclient.h" | |
30693 | 26 #include "procutil.h" |
28060 | 27 #include "util.h" |
28 | |
30677 | 29 #ifndef PATH_MAX |
30 #define PATH_MAX 4096 | |
28060 | 31 #endif |
32 | |
33 struct cmdserveropts { | |
30677 | 34 char sockname[PATH_MAX]; |
35 char initsockname[PATH_MAX]; | |
36 char redirectsockname[PATH_MAX]; | |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
37 size_t argsize; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
38 const char **args; |
28060 | 39 }; |
40 | |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
41 static void initcmdserveropts(struct cmdserveropts *opts) |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
42 { |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
43 memset(opts, 0, sizeof(struct cmdserveropts)); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
44 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
45 |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
46 static void freecmdserveropts(struct cmdserveropts *opts) |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
47 { |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
48 free(opts->args); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
49 opts->args = NULL; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
50 opts->argsize = 0; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
51 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
52 |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
53 /* |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
54 * Test if an argument is a sensitive flag that should be passed to the server. |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
55 * Return 0 if not, otherwise the number of arguments starting from the current |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
56 * one that should be passed to the server. |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
57 */ |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
58 static size_t testsensitiveflag(const char *arg) |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
59 { |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
60 static const struct { |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
61 const char *name; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
62 size_t narg; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
63 } flags[] = { |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
64 {"--config", 1}, {"--cwd", 1}, {"--repo", 1}, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
65 {"--repository", 1}, {"--traceback", 0}, {"-R", 1}, |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
66 }; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
67 size_t i; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
68 for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) { |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
69 size_t len = strlen(flags[i].name); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
70 size_t narg = flags[i].narg; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
71 if (memcmp(arg, flags[i].name, len) == 0) { |
28790 | 72 if (arg[len] == '\0') { |
73 /* --flag (value) */ | |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
74 return narg + 1; |
28790 | 75 } else if (arg[len] == '=' && narg > 0) { |
76 /* --flag=value */ | |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
77 return 1; |
28790 | 78 } else if (flags[i].name[1] != '-') { |
79 /* short flag */ | |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
80 return 1; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
81 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
82 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
83 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
84 return 0; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
85 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
86 |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
87 /* |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
88 * Parse argv[] and put sensitive flags to opts->args |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
89 */ |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
90 static void setcmdserverargs(struct cmdserveropts *opts, int argc, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
91 const char *argv[]) |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
92 { |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
93 size_t i, step; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
94 opts->argsize = 0; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
95 for (i = 0, step = 1; i < (size_t)argc; i += step, step = 1) { |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
96 if (!argv[i]) |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
97 continue; /* pass clang-analyse */ |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
98 if (strcmp(argv[i], "--") == 0) |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
99 break; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
100 size_t n = testsensitiveflag(argv[i]); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
101 if (n == 0 || i + n > (size_t)argc) |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
102 continue; |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
103 opts->args = |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
104 reallocx(opts->args, (n + opts->argsize) * sizeof(char *)); |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
105 memcpy(opts->args + opts->argsize, argv + i, |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
106 sizeof(char *) * n); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
107 opts->argsize += n; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
108 step = n; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
109 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
110 } |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
111 |
28060 | 112 static void preparesockdir(const char *sockdir) |
113 { | |
114 int r; | |
115 r = mkdir(sockdir, 0700); | |
116 if (r < 0 && errno != EEXIST) | |
28789
7f6e0a15189b
chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
117 abortmsgerrno("cannot create sockdir %s", sockdir); |
28060 | 118 |
119 struct stat st; | |
120 r = lstat(sockdir, &st); | |
121 if (r < 0) | |
28789
7f6e0a15189b
chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
122 abortmsgerrno("cannot stat %s", sockdir); |
28060 | 123 if (!S_ISDIR(st.st_mode)) |
124 abortmsg("cannot create sockdir %s (file exists)", sockdir); | |
125 if (st.st_uid != geteuid() || st.st_mode & 0077) | |
126 abortmsg("insecure sockdir %s", sockdir); | |
127 } | |
128 | |
30884 | 129 /* |
130 * Check if a socket directory exists and is only owned by the current user. | |
131 * Return 1 if so, 0 if not. This is used to check if XDG_RUNTIME_DIR can be | |
132 * used or not. According to the specification [1], XDG_RUNTIME_DIR should be | |
133 * ignored if the directory is not owned by the user with mode 0700. | |
134 * [1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html | |
135 */ | |
136 static int checkruntimedir(const char *sockdir) | |
137 { | |
138 struct stat st; | |
139 int r = lstat(sockdir, &st); | |
140 if (r < 0) /* ex. does not exist */ | |
141 return 0; | |
142 if (!S_ISDIR(st.st_mode)) /* ex. is a file, not a directory */ | |
143 return 0; | |
144 return st.st_uid == geteuid() && (st.st_mode & 0777) == 0700; | |
145 } | |
146 | |
30680
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
147 static void getdefaultsockdir(char sockdir[], size_t size) |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
148 { |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
149 /* by default, put socket file in secure directory |
30681 | 150 * (${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
|
151 * (permission of socket file may be ignored on some Unices) */ |
30681 | 152 const char *runtimedir = getenv("XDG_RUNTIME_DIR"); |
153 int r; | |
30884 | 154 if (runtimedir && checkruntimedir(runtimedir)) { |
30681 | 155 r = snprintf(sockdir, size, "%s/chg", runtimedir); |
156 } else { | |
157 const char *tmpdir = getenv("TMPDIR"); | |
158 if (!tmpdir) | |
159 tmpdir = "/tmp"; | |
160 r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid()); | |
161 } | |
30680
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
162 if (r < 0 || (size_t)r >= size) |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
163 abortmsg("too long TMPDIR (r = %d)", r); |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
164 } |
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
165 |
28060 | 166 static void setcmdserveropts(struct cmdserveropts *opts) |
167 { | |
168 int r; | |
30677 | 169 char sockdir[PATH_MAX]; |
28060 | 170 const char *envsockname = getenv("CHGSOCKNAME"); |
171 if (!envsockname) { | |
30680
4677df6b449a
chg: make "get default sockdir" a separate method
Jun Wu <quark@fb.com>
parents:
30677
diff
changeset
|
172 getdefaultsockdir(sockdir, sizeof(sockdir)); |
28060 | 173 preparesockdir(sockdir); |
174 } | |
175 | |
176 const char *basename = (envsockname) ? envsockname : sockdir; | |
177 const char *sockfmt = (envsockname) ? "%s" : "%s/server"; | |
178 r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename); | |
179 if (r < 0 || (size_t)r >= sizeof(opts->sockname)) | |
180 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
|
181 r = snprintf(opts->initsockname, sizeof(opts->initsockname), "%s.%u", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
182 opts->sockname, (unsigned)getpid()); |
30620
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
183 if (r < 0 || (size_t)r >= sizeof(opts->initsockname)) |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
184 abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); |
28060 | 185 } |
186 | |
28237
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
187 static const char *gethgcmd(void) |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
188 { |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
189 static const char *hgcmd = NULL; |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
190 if (!hgcmd) { |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
191 hgcmd = getenv("CHGHG"); |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
192 if (!hgcmd || hgcmd[0] == '\0') |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
193 hgcmd = getenv("HG"); |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
194 if (!hgcmd || hgcmd[0] == '\0') |
28605
baa073200ba2
chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents:
28555
diff
changeset
|
195 #ifdef HGPATH |
baa073200ba2
chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents:
28555
diff
changeset
|
196 hgcmd = (HGPATH); |
baa073200ba2
chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents:
28555
diff
changeset
|
197 #else |
28237
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
198 hgcmd = "hg"; |
28605
baa073200ba2
chg: allows default hg path to be overridden
Jun Wu <quark@fb.com>
parents:
28555
diff
changeset
|
199 #endif |
28237
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
200 } |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
201 return hgcmd; |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
202 } |
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
203 |
28060 | 204 static void execcmdserver(const struct cmdserveropts *opts) |
205 { | |
28237
a3d73e069f8d
chg: extract gethgcmd logic to a function
Jun Wu <quark@fb.com>
parents:
28196
diff
changeset
|
206 const char *hgcmd = gethgcmd(); |
28060 | 207 |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
208 const char *baseargv[] = { |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
209 hgcmd, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
210 "serve", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
211 "--cmdserver", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
212 "chgunix", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
213 "--address", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
214 opts->initsockname, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
215 "--daemon-postexec", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
216 "chdir:/", |
28060 | 217 }; |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
218 size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
219 size_t argsize = baseargvsize + opts->argsize + 1; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
220 |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
221 const char **argv = mallocx(sizeof(char *) * argsize); |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
222 memcpy(argv, baseargv, sizeof(baseargv)); |
38198
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35959
diff
changeset
|
223 if (opts->args) { |
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35959
diff
changeset
|
224 size_t size = sizeof(char *) * opts->argsize; |
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35959
diff
changeset
|
225 memcpy(argv + baseargvsize, opts->args, size); |
3c84493556db
chg: fix an undefined behavior about memcpy
Jun Wu <quark@fb.com>
parents:
35959
diff
changeset
|
226 } |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
227 argv[argsize - 1] = NULL; |
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
228 |
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
|
229 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
|
230 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
|
231 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
|
232 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
|
233 } 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
|
234 if (setenv("CHGORIG_LC_CTYPE", lc_ctype_env, 1) != 0) { |
44995 | 235 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
|
236 } |
04a3ae7aba14
chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents:
38198
diff
changeset
|
237 } |
04a3ae7aba14
chg: force-set LC_CTYPE on server start to actual value from the environment
Kyle Lippincott <spectral@google.com>
parents:
38198
diff
changeset
|
238 |
28261 | 239 if (putenv("CHGINTERNALMARK=") != 0) |
28789
7f6e0a15189b
chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
240 abortmsgerrno("failed to putenv"); |
28060 | 241 if (execvp(hgcmd, (char **)argv) < 0) |
28789
7f6e0a15189b
chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
242 abortmsgerrno("failed to exec cmdserver"); |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
243 free(argv); |
28060 | 244 } |
245 | |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
246 /* 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
|
247 static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid) |
28060 | 248 { |
249 static const struct timespec sleepreq = {0, 10 * 1000000}; | |
250 int pst = 0; | |
251 | |
30620
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
252 debugmsg("try connect to %s repeatedly", opts->initsockname); |
29345 | 253 |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
254 unsigned int timeoutsec = 60; /* default: 60 seconds */ |
29345 | 255 const char *timeoutenv = getenv("CHGTIMEOUT"); |
256 if (timeoutenv) | |
257 sscanf(timeoutenv, "%u", &timeoutsec); | |
258 | |
259 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
|
260 hgclient_t *hgc = hgc_open(opts->initsockname); |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
261 if (hgc) { |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
262 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
|
263 opts->sockname); |
30620
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
264 int r = rename(opts->initsockname, opts->sockname); |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
265 if (r != 0) |
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
266 abortmsgerrno("cannot rename"); |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
267 return hgc; |
30620
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
268 } |
28060 | 269 |
270 if (pid > 0) { | |
271 /* 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
|
272 int r = waitpid(pid, &pst, WNOHANG); |
28060 | 273 if (r != 0) |
274 goto cleanup; | |
275 } | |
276 | |
277 nanosleep(&sleepreq, NULL); | |
278 } | |
279 | |
30620
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
280 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
|
281 return NULL; |
28060 | 282 |
283 cleanup: | |
284 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
|
285 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
|
286 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
|
287 "(exited with status 0)"); |
28477
194a6cd873cd
chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents:
28455
diff
changeset
|
288 debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst)); |
194a6cd873cd
chg: silently inherit server exit code
Jun Wu <quark@fb.com>
parents:
28455
diff
changeset
|
289 exit(WEXITSTATUS(pst)); |
28060 | 290 } else if (WIFSIGNALED(pst)) { |
291 abortmsg("cmdserver killed by signal %d", WTERMSIG(pst)); | |
292 } else { | |
28851
584e0716c7af
chg: fix spelling in the error message about error waiting for cmdserver
Jun Wu <quark@fb.com>
parents:
28790
diff
changeset
|
293 abortmsg("error while waiting for cmdserver"); |
28060 | 294 } |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
295 return NULL; |
28060 | 296 } |
297 | |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
298 /* 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
|
299 static hgclient_t *connectcmdserver(struct cmdserveropts *opts) |
28060 | 300 { |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
301 const char *sockname = |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
302 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
|
303 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
|
304 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
|
305 if (hgc) |
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
306 return hgc; |
28060 | 307 |
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
308 /* 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
|
309 * 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
|
310 * 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
|
311 * 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
|
312 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
|
313 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
|
314 |
30620
937c52f06709
chg: start server at a unique address
Jun Wu <quark@fb.com>
parents:
30513
diff
changeset
|
315 debugmsg("start cmdserver at %s", opts->initsockname); |
28060 | 316 |
317 pid_t pid = fork(); | |
318 if (pid < 0) | |
319 abortmsg("failed to fork cmdserver process"); | |
320 if (pid == 0) { | |
321 execcmdserver(opts); | |
322 } else { | |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
323 hgc = retryconnectcmdserver(opts, pid); |
28060 | 324 } |
28196
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
325 |
87de4a22e8c2
chg: hold a lock file before connected to server
Jun Wu <quark@fb.com>
parents:
28194
diff
changeset
|
326 return hgc; |
28060 | 327 } |
328 | |
28455 | 329 static void killcmdserver(const struct cmdserveropts *opts) |
28060 | 330 { |
28455 | 331 /* resolve config hash */ |
332 char *resolvedpath = realpath(opts->sockname, NULL); | |
333 if (resolvedpath) { | |
334 unlink(resolvedpath); | |
335 free(resolvedpath); | |
28060 | 336 } |
337 } | |
338 | |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
339 /* 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
|
340 * 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
|
341 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
|
342 { |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
343 int needreconnect = 0; |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
344 if (!insts) |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
345 return needreconnect; |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
346 |
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
347 assert(insts); |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
348 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
|
349 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
|
350 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
|
351 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
|
352 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
|
353 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
|
354 } 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
|
355 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
|
356 sizeof(opts->redirectsockname), "%s", |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
357 *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
|
358 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
|
359 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
|
360 needreconnect = 1; |
28516
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
361 } else if (strncmp(*pinst, "exit ", 5) == 0) { |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
362 int n = 0; |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
363 if (sscanf(*pinst + 5, "%d", &n) != 1) |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
364 abortmsg("cannot read the exit code"); |
3bf2892f685f
chgserver: handle ParseError during validate
Jun Wu <quark@fb.com>
parents:
28477
diff
changeset
|
365 exit(n); |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
366 } else if (strcmp(*pinst, "reconnect") == 0) { |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
367 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
|
368 } else { |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
369 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
|
370 } |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
371 } |
28535
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
372 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
|
373 } |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
374 |
28260
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
375 /* |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
376 * Test whether the command is unsupported or not. This is not designed to |
44617
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44261
diff
changeset
|
377 * cover all cases. But it's fast, does 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
|
378 */ |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
379 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
|
380 { |
35959
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
381 enum { SERVE = 1, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
382 DAEMON = 2, |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
383 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
|
384 }; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
385 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
|
386 int i; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
387 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
|
388 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
|
389 break; |
44617
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44261
diff
changeset
|
390 /* |
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44261
diff
changeset
|
391 * 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
|
392 * 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
|
393 * 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
|
394 */ |
1e459ac4cb48
chg: be stricter about checking invocation of `serve` command
Pulkit Goyal <7895pulkit@gmail.com>
parents:
44261
diff
changeset
|
395 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
|
396 state |= SERVE; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
397 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
|
398 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
|
399 state |= DAEMON; |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
400 } |
34531
50788d1ae6cc
chg: just forward --time to command server
Yuya Nishihara <yuya@tcha.org>
parents:
31890
diff
changeset
|
401 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
|
402 } |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
403 |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
404 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
|
405 { |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
406 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
|
407 if (execvp(gethgcmd(), (char **)argv) < 0) |
28789
7f6e0a15189b
chg: replace abortmsg showing errno with abortmsgerrno
Jun Wu <quark@fb.com>
parents:
28787
diff
changeset
|
408 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
|
409 } |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
410 |
28060 | 411 int main(int argc, const char *argv[], const char *envp[]) |
412 { | |
413 if (getenv("CHGDEBUG")) | |
414 enabledebugmsg(); | |
415 | |
28787
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28769
diff
changeset
|
416 if (!getenv("HGPLAIN") && isatty(fileno(stderr))) |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28769
diff
changeset
|
417 enablecolor(); |
ea86cdcd9b50
chg: use color in debug/error messages conditionally
Jun Wu <quark@fb.com>
parents:
28769
diff
changeset
|
418 |
28261 | 419 if (getenv("CHGINTERNALMARK")) |
420 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
|
421 "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
|
422 "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
|
423 "path of real hg."); |
28261 | 424 |
28260
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
425 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
|
426 execoriginalhg(argv); |
0a17cfbe5429
chg: fallback to original hg for some unsupported commands or flags
Jun Wu <quark@fb.com>
parents:
28237
diff
changeset
|
427 |
28060 | 428 struct cmdserveropts opts; |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
429 initcmdserveropts(&opts); |
28060 | 430 setcmdserveropts(&opts); |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
431 setcmdserverargs(&opts, argc, argv); |
28060 | 432 |
433 if (argc == 2) { | |
28455 | 434 if (strcmp(argv[1], "--kill-chg-daemon") == 0) { |
435 killcmdserver(&opts); | |
28060 | 436 return 0; |
437 } | |
438 } | |
439 | |
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
440 hgclient_t *hgc; |
28358 | 441 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
|
442 while (1) { |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
443 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
|
444 if (!hgc) |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
445 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
|
446 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
|
447 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
|
448 int needreconnect = runinstructions(&opts, insts); |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
449 free(insts); |
aa082a8125da
chgserver: add an explicit "reconnect" instruction to validate
Jun Wu <quark@fb.com>
parents:
28516
diff
changeset
|
450 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
|
451 break; |
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
452 hgc_close(hgc); |
28358 | 453 if (++retry > 10) |
454 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
|
455 "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
|
456 "changes sensitive environment variables " |
9724f54923ec
chg: enable clang-format on all .c and .h files
Augie Fackler <augie@google.com>
parents:
34531
diff
changeset
|
457 "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
|
458 "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
|
459 gethgcmd()); |
28357
2f0f352d4196
chg: use validate to make sure the server is up to date
Jun Wu <quark@fb.com>
parents:
28327
diff
changeset
|
460 } |
28060 | 461 |
30690
e9ec42634ec8
chg: decouple hgclient from setupsignalhandler
Jun Wu <quark@fb.com>
parents:
30689
diff
changeset
|
462 setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc)); |
31890 | 463 atexit(waitpager); |
28060 | 464 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
|
465 restoresignalhandler(); |
28060 | 466 hgc_close(hgc); |
28167
66f6dad20c19
chg: pass sensitive command line flags to server
Jun Wu <quark@fb.com>
parents:
28086
diff
changeset
|
467 freecmdserveropts(&opts); |
29344 | 468 |
28060 | 469 return exitcode; |
470 } |