equal
deleted
inserted
replaced
230 hgcmd = (HGPATH); |
230 hgcmd = (HGPATH); |
231 #else |
231 #else |
232 hgcmd = "hg"; |
232 hgcmd = "hg"; |
233 #endif |
233 #endif |
234 } |
234 } |
|
235 /* Set $CHGHG to the path to the seleted hg executable if it wasn't |
|
236 * already set. This has the effect of ensuring that a new command |
|
237 * server will be spawned if the existing command server is running from |
|
238 * an executable at a different path. */ |
|
239 if (setenv("CHGHG", hgcmd, 1) != 0) |
|
240 abortmsgerrno("failed to setenv"); |
235 return hgcmd; |
241 return hgcmd; |
236 } |
242 } |
237 |
243 |
238 static void execcmdserver(const struct cmdserveropts *opts) |
244 static void execcmdserver(const char *hgcmd, const struct cmdserveropts *opts) |
239 { |
245 { |
240 const char *hgcmd = gethgcmd(); |
|
241 |
246 |
242 const char *baseargv[] = { |
247 const char *baseargv[] = { |
243 hgcmd, "serve", "--no-profile", "--cmdserver", |
248 hgcmd, "serve", "--no-profile", "--cmdserver", |
244 "chgunix", "--address", opts->initsockname, "--daemon-postexec", |
249 "chgunix", "--address", opts->initsockname, "--daemon-postexec", |
245 "chdir:/", |
250 "chdir:/", |
373 if (sockname == opts->redirectsockname) |
378 if (sockname == opts->redirectsockname) |
374 unlink(opts->sockname); |
379 unlink(opts->sockname); |
375 |
380 |
376 debugmsg("start cmdserver at %s", opts->initsockname); |
381 debugmsg("start cmdserver at %s", opts->initsockname); |
377 |
382 |
|
383 /* Get the path to the hg executable before we fork because this |
|
384 * function might update the environment, and we want this to be |
|
385 * reflected in both the parent and child processes. */ |
|
386 const char *hgcmd = gethgcmd(); |
|
387 |
378 pid_t pid = fork(); |
388 pid_t pid = fork(); |
379 if (pid < 0) |
389 if (pid < 0) |
380 abortmsg("failed to fork cmdserver process"); |
390 abortmsg("failed to fork cmdserver process"); |
381 if (pid == 0) { |
391 if (pid == 0) { |
382 execcmdserver(opts); |
392 execcmdserver(hgcmd, opts); |
383 } else { |
393 } else { |
384 hgc = retryconnectcmdserver(opts, pid); |
394 hgc = retryconnectcmdserver(opts, pid); |
385 } |
395 } |
386 |
396 |
387 return hgc; |
397 return hgc; |
482 debugmsg("execute original hg"); |
492 debugmsg("execute original hg"); |
483 if (execvp(gethgcmd(), (char **)argv) < 0) |
493 if (execvp(gethgcmd(), (char **)argv) < 0) |
484 abortmsgerrno("failed to exec original hg"); |
494 abortmsgerrno("failed to exec original hg"); |
485 } |
495 } |
486 |
496 |
487 int main(int argc, const char *argv[], const char *envp[]) |
497 int main(int argc, const char *argv[]) |
488 { |
498 { |
489 if (getenv("CHGDEBUG")) |
499 if (getenv("CHGDEBUG")) |
490 enabledebugmsg(); |
500 enabledebugmsg(); |
491 |
501 |
492 if (!getenv("HGPLAIN") && isatty(fileno(stderr))) |
502 if (!getenv("HGPLAIN") && isatty(fileno(stderr))) |
517 size_t retry = 0; |
527 size_t retry = 0; |
518 while (1) { |
528 while (1) { |
519 hgc = connectcmdserver(&opts); |
529 hgc = connectcmdserver(&opts); |
520 if (!hgc) |
530 if (!hgc) |
521 abortmsg("cannot open hg client"); |
531 abortmsg("cannot open hg client"); |
522 hgc_setenv(hgc, envp); |
532 /* Use `environ(7)` instead of the optional `envp` argument to |
|
533 * `main` because `envp` does not update when the environment |
|
534 * changes, but `environ` does. */ |
|
535 hgc_setenv(hgc, (const char *const *)environ); |
523 const char **insts = hgc_validate(hgc, argv + 1, argc - 1); |
536 const char **insts = hgc_validate(hgc, argv + 1, argc - 1); |
524 int needreconnect = runinstructions(&opts, insts); |
537 int needreconnect = runinstructions(&opts, insts); |
525 free(insts); |
538 free(insts); |
526 if (!needreconnect) |
539 if (!needreconnect) |
527 break; |
540 break; |