Show More
@@ -31,6 +31,7 b'' | |||||
31 |
|
31 | |||
32 | struct cmdserveropts { |
|
32 | struct cmdserveropts { | |
33 | char sockname[UNIX_PATH_MAX]; |
|
33 | char sockname[UNIX_PATH_MAX]; | |
|
34 | char redirectsockname[UNIX_PATH_MAX]; | |||
34 | char lockfile[UNIX_PATH_MAX]; |
|
35 | char lockfile[UNIX_PATH_MAX]; | |
35 | char pidfile[UNIX_PATH_MAX]; |
|
36 | char pidfile[UNIX_PATH_MAX]; | |
36 | size_t argsize; |
|
37 | size_t argsize; | |
@@ -270,18 +271,27 b' cleanup:' | |||||
270 | /* Connect to a cmdserver. Will start a new server on demand. */ |
|
271 | /* Connect to a cmdserver. Will start a new server on demand. */ | |
271 | static hgclient_t *connectcmdserver(struct cmdserveropts *opts) |
|
272 | static hgclient_t *connectcmdserver(struct cmdserveropts *opts) | |
272 | { |
|
273 | { | |
273 | hgclient_t *hgc = hgc_open(opts->sockname); |
|
274 | const char *sockname = opts->redirectsockname[0] ? | |
|
275 | opts->redirectsockname : opts->sockname; | |||
|
276 | hgclient_t *hgc = hgc_open(sockname); | |||
274 | if (hgc) |
|
277 | if (hgc) | |
275 | return hgc; |
|
278 | return hgc; | |
276 |
|
279 | |||
277 | lockcmdserver(opts); |
|
280 | lockcmdserver(opts); | |
278 |
hgc = hgc_open( |
|
281 | hgc = hgc_open(sockname); | |
279 | if (hgc) { |
|
282 | if (hgc) { | |
280 | unlockcmdserver(opts); |
|
283 | unlockcmdserver(opts); | |
281 | debugmsg("cmdserver is started by another process"); |
|
284 | debugmsg("cmdserver is started by another process"); | |
282 | return hgc; |
|
285 | return hgc; | |
283 | } |
|
286 | } | |
284 |
|
287 | |||
|
288 | /* prevent us from being connected to an outdated server: we were | |||
|
289 | * told by a server to redirect to opts->redirectsockname and that | |||
|
290 | * address does not work. we do not want to connect to the server | |||
|
291 | * again because it will probably tell us the same thing. */ | |||
|
292 | if (sockname == opts->redirectsockname) | |||
|
293 | unlink(opts->sockname); | |||
|
294 | ||||
285 | debugmsg("start cmdserver at %s", opts->sockname); |
|
295 | debugmsg("start cmdserver at %s", opts->sockname); | |
286 |
|
296 | |||
287 | pid_t pid = fork(); |
|
297 | pid_t pid = fork(); | |
@@ -448,6 +458,28 b' error:' | |||||
448 | abortmsg("failed to prepare pager (errno = %d)", errno); |
|
458 | abortmsg("failed to prepare pager (errno = %d)", errno); | |
449 | } |
|
459 | } | |
450 |
|
460 | |||
|
461 | /* Run instructions sent from the server like unlink and set redirect path */ | |||
|
462 | static void runinstructions(struct cmdserveropts *opts, const char **insts) | |||
|
463 | { | |||
|
464 | assert(insts); | |||
|
465 | opts->redirectsockname[0] = '\0'; | |||
|
466 | const char **pinst; | |||
|
467 | for (pinst = insts; *pinst; pinst++) { | |||
|
468 | debugmsg("instruction: %s", *pinst); | |||
|
469 | if (strncmp(*pinst, "unlink ", 7) == 0) { | |||
|
470 | unlink(*pinst + 7); | |||
|
471 | } else if (strncmp(*pinst, "redirect ", 9) == 0) { | |||
|
472 | int r = snprintf(opts->redirectsockname, | |||
|
473 | sizeof(opts->redirectsockname), | |||
|
474 | "%s", *pinst + 9); | |||
|
475 | if (r < 0 || r >= (int)sizeof(opts->redirectsockname)) | |||
|
476 | abortmsg("redirect path is too long (%d)", r); | |||
|
477 | } else { | |||
|
478 | abortmsg("unknown instruction: %s", *pinst); | |||
|
479 | } | |||
|
480 | } | |||
|
481 | } | |||
|
482 | ||||
451 | /* |
|
483 | /* | |
452 | * Test whether the command is unsupported or not. This is not designed to |
|
484 | * Test whether the command is unsupported or not. This is not designed to | |
453 | * cover all cases. But it's fast, does not depend on the server and does |
|
485 | * cover all cases. But it's fast, does not depend on the server and does | |
@@ -516,12 +548,21 b' int main(int argc, const char *argv[], c' | |||||
516 | } |
|
548 | } | |
517 | } |
|
549 | } | |
518 |
|
550 | |||
519 | hgclient_t *hgc = connectcmdserver(&opts); |
|
551 | hgclient_t *hgc; | |
520 | if (!hgc) |
|
552 | while (1) { | |
521 | abortmsg("cannot open hg client"); |
|
553 | hgc = connectcmdserver(&opts); | |
|
554 | if (!hgc) | |||
|
555 | abortmsg("cannot open hg client"); | |||
|
556 | hgc_setenv(hgc, envp); | |||
|
557 | const char **insts = hgc_validate(hgc, argv + 1, argc - 1); | |||
|
558 | if (insts == NULL) | |||
|
559 | break; | |||
|
560 | runinstructions(&opts, insts); | |||
|
561 | free(insts); | |||
|
562 | hgc_close(hgc); | |||
|
563 | } | |||
522 |
|
564 | |||
523 | setupsignalhandler(hgc_peerpid(hgc)); |
|
565 | setupsignalhandler(hgc_peerpid(hgc)); | |
524 | hgc_setenv(hgc, envp); |
|
|||
525 | setuppager(hgc, argv + 1, argc - 1); |
|
566 | setuppager(hgc, argv + 1, argc - 1); | |
526 | int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); |
|
567 | int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); | |
527 | hgc_close(hgc); |
|
568 | hgc_close(hgc); |
General Comments 0
You need to be logged in to leave comments.
Login now