Show More
@@ -32,8 +32,80 b' struct cmdserveropts {' | |||||
32 | char sockname[UNIX_PATH_MAX]; |
|
32 | char sockname[UNIX_PATH_MAX]; | |
33 | char lockfile[UNIX_PATH_MAX]; |
|
33 | char lockfile[UNIX_PATH_MAX]; | |
34 | char pidfile[UNIX_PATH_MAX]; |
|
34 | char pidfile[UNIX_PATH_MAX]; | |
|
35 | size_t argsize; | |||
|
36 | const char **args; | |||
35 | }; |
|
37 | }; | |
36 |
|
38 | |||
|
39 | static void initcmdserveropts(struct cmdserveropts *opts) { | |||
|
40 | memset(opts, 0, sizeof(struct cmdserveropts)); | |||
|
41 | } | |||
|
42 | ||||
|
43 | static void freecmdserveropts(struct cmdserveropts *opts) { | |||
|
44 | free(opts->args); | |||
|
45 | opts->args = NULL; | |||
|
46 | opts->argsize = 0; | |||
|
47 | } | |||
|
48 | ||||
|
49 | /* | |||
|
50 | * Test if an argument is a sensitive flag that should be passed to the server. | |||
|
51 | * Return 0 if not, otherwise the number of arguments starting from the current | |||
|
52 | * one that should be passed to the server. | |||
|
53 | */ | |||
|
54 | static size_t testsensitiveflag(const char *arg) | |||
|
55 | { | |||
|
56 | static const struct { | |||
|
57 | const char *name; | |||
|
58 | size_t narg; | |||
|
59 | } flags[] = { | |||
|
60 | {"--config", 1}, | |||
|
61 | {"--cwd", 1}, | |||
|
62 | {"--repo", 1}, | |||
|
63 | {"--repository", 1}, | |||
|
64 | {"--traceback", 0}, | |||
|
65 | {"-R", 1}, | |||
|
66 | }; | |||
|
67 | size_t i; | |||
|
68 | for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) { | |||
|
69 | size_t len = strlen(flags[i].name); | |||
|
70 | size_t narg = flags[i].narg; | |||
|
71 | if (memcmp(arg, flags[i].name, len) == 0) { | |||
|
72 | if (arg[len] == '\0') { /* --flag (value) */ | |||
|
73 | return narg + 1; | |||
|
74 | } else if (arg[len] == '=' && narg > 0) { /* --flag=value */ | |||
|
75 | return 1; | |||
|
76 | } else if (flags[i].name[1] != '-') { /* short flag */ | |||
|
77 | return 1; | |||
|
78 | } | |||
|
79 | } | |||
|
80 | } | |||
|
81 | return 0; | |||
|
82 | } | |||
|
83 | ||||
|
84 | /* | |||
|
85 | * Parse argv[] and put sensitive flags to opts->args | |||
|
86 | */ | |||
|
87 | static void setcmdserverargs(struct cmdserveropts *opts, | |||
|
88 | int argc, const char *argv[]) | |||
|
89 | { | |||
|
90 | size_t i, step; | |||
|
91 | opts->argsize = 0; | |||
|
92 | for (i = 0, step = 1; i < (size_t)argc; i += step, step = 1) { | |||
|
93 | if (!argv[i]) | |||
|
94 | continue; /* pass clang-analyse */ | |||
|
95 | if (strcmp(argv[i], "--") == 0) | |||
|
96 | break; | |||
|
97 | size_t n = testsensitiveflag(argv[i]); | |||
|
98 | if (n == 0 || i + n > (size_t)argc) | |||
|
99 | continue; | |||
|
100 | opts->args = reallocx(opts->args, | |||
|
101 | (n + opts->argsize) * sizeof(char *)); | |||
|
102 | memcpy(opts->args + opts->argsize, argv + i, | |||
|
103 | sizeof(char *) * n); | |||
|
104 | opts->argsize += n; | |||
|
105 | step = n; | |||
|
106 | } | |||
|
107 | } | |||
|
108 | ||||
37 | static void preparesockdir(const char *sockdir) |
|
109 | static void preparesockdir(const char *sockdir) | |
38 | { |
|
110 | { | |
39 | int r; |
|
111 | int r; | |
@@ -111,7 +183,7 b' static void execcmdserver(const struct c' | |||||
111 | if (!hgcmd || hgcmd[0] == '\0') |
|
183 | if (!hgcmd || hgcmd[0] == '\0') | |
112 | hgcmd = "hg"; |
|
184 | hgcmd = "hg"; | |
113 |
|
185 | |||
114 | const char *argv[] = { |
|
186 | const char *baseargv[] = { | |
115 | hgcmd, |
|
187 | hgcmd, | |
116 | "serve", |
|
188 | "serve", | |
117 | "--cwd", "/", |
|
189 | "--cwd", "/", | |
@@ -122,10 +194,18 b' static void execcmdserver(const struct c' | |||||
122 | "--config", "extensions.chgserver=", |
|
194 | "--config", "extensions.chgserver=", | |
123 | /* wrap root ui so that it can be disabled/enabled by config */ |
|
195 | /* wrap root ui so that it can be disabled/enabled by config */ | |
124 | "--config", "progress.assume-tty=1", |
|
196 | "--config", "progress.assume-tty=1", | |
125 | NULL, |
|
|||
126 | }; |
|
197 | }; | |
|
198 | size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]); | |||
|
199 | size_t argsize = baseargvsize + opts->argsize + 1; | |||
|
200 | ||||
|
201 | const char **argv = mallocx(sizeof(char *) * argsize); | |||
|
202 | memcpy(argv, baseargv, sizeof(baseargv)); | |||
|
203 | memcpy(argv + baseargvsize, opts->args, sizeof(char *) * opts->argsize); | |||
|
204 | argv[argsize - 1] = NULL; | |||
|
205 | ||||
127 | if (execvp(hgcmd, (char **)argv) < 0) |
|
206 | if (execvp(hgcmd, (char **)argv) < 0) | |
128 | abortmsg("failed to exec cmdserver (errno = %d)", errno); |
|
207 | abortmsg("failed to exec cmdserver (errno = %d)", errno); | |
|
208 | free(argv); | |||
129 | } |
|
209 | } | |
130 |
|
210 | |||
131 | /* |
|
211 | /* | |
@@ -352,7 +432,9 b' int main(int argc, const char *argv[], c' | |||||
352 | enabledebugmsg(); |
|
432 | enabledebugmsg(); | |
353 |
|
433 | |||
354 | struct cmdserveropts opts; |
|
434 | struct cmdserveropts opts; | |
|
435 | initcmdserveropts(&opts); | |||
355 | setcmdserveropts(&opts); |
|
436 | setcmdserveropts(&opts); | |
|
437 | setcmdserverargs(&opts, argc, argv); | |||
356 |
|
438 | |||
357 | if (argc == 2) { |
|
439 | if (argc == 2) { | |
358 | int sig = 0; |
|
440 | int sig = 0; | |
@@ -379,5 +461,6 b' int main(int argc, const char *argv[], c' | |||||
379 | setuppager(hgc, argv + 1, argc - 1); |
|
461 | setuppager(hgc, argv + 1, argc - 1); | |
380 | int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); |
|
462 | int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); | |
381 | hgc_close(hgc); |
|
463 | hgc_close(hgc); | |
|
464 | freecmdserveropts(&opts); | |||
382 | return exitcode; |
|
465 | return exitcode; | |
383 | } |
|
466 | } |
General Comments 0
You need to be logged in to leave comments.
Login now