442 close(pipefds[0]); |
442 close(pipefds[0]); |
443 close(pipefds[1]); |
443 close(pipefds[1]); |
444 abortmsg("failed to prepare pager (errno = %d)", errno); |
444 abortmsg("failed to prepare pager (errno = %d)", errno); |
445 } |
445 } |
446 |
446 |
447 /* Run instructions sent from the server like unlink and set redirect path */ |
447 /* Run instructions sent from the server like unlink and set redirect path |
448 static void runinstructions(struct cmdserveropts *opts, const char **insts) |
448 * Return 1 if reconnect is needed, otherwise 0 */ |
449 { |
449 static int runinstructions(struct cmdserveropts *opts, const char **insts) |
|
450 { |
|
451 int needreconnect = 0; |
|
452 if (!insts) |
|
453 return needreconnect; |
|
454 |
450 assert(insts); |
455 assert(insts); |
451 opts->redirectsockname[0] = '\0'; |
456 opts->redirectsockname[0] = '\0'; |
452 const char **pinst; |
457 const char **pinst; |
453 for (pinst = insts; *pinst; pinst++) { |
458 for (pinst = insts; *pinst; pinst++) { |
454 debugmsg("instruction: %s", *pinst); |
459 debugmsg("instruction: %s", *pinst); |
458 int r = snprintf(opts->redirectsockname, |
463 int r = snprintf(opts->redirectsockname, |
459 sizeof(opts->redirectsockname), |
464 sizeof(opts->redirectsockname), |
460 "%s", *pinst + 9); |
465 "%s", *pinst + 9); |
461 if (r < 0 || r >= (int)sizeof(opts->redirectsockname)) |
466 if (r < 0 || r >= (int)sizeof(opts->redirectsockname)) |
462 abortmsg("redirect path is too long (%d)", r); |
467 abortmsg("redirect path is too long (%d)", r); |
|
468 needreconnect = 1; |
463 } else if (strncmp(*pinst, "exit ", 5) == 0) { |
469 } else if (strncmp(*pinst, "exit ", 5) == 0) { |
464 int n = 0; |
470 int n = 0; |
465 if (sscanf(*pinst + 5, "%d", &n) != 1) |
471 if (sscanf(*pinst + 5, "%d", &n) != 1) |
466 abortmsg("cannot read the exit code"); |
472 abortmsg("cannot read the exit code"); |
467 exit(n); |
473 exit(n); |
|
474 } else if (strcmp(*pinst, "reconnect") == 0) { |
|
475 needreconnect = 1; |
468 } else { |
476 } else { |
469 abortmsg("unknown instruction: %s", *pinst); |
477 abortmsg("unknown instruction: %s", *pinst); |
470 } |
478 } |
471 } |
479 } |
|
480 return needreconnect; |
472 } |
481 } |
473 |
482 |
474 /* |
483 /* |
475 * 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 |
476 * 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 |
540 hgc = connectcmdserver(&opts); |
549 hgc = connectcmdserver(&opts); |
541 if (!hgc) |
550 if (!hgc) |
542 abortmsg("cannot open hg client"); |
551 abortmsg("cannot open hg client"); |
543 hgc_setenv(hgc, envp); |
552 hgc_setenv(hgc, envp); |
544 const char **insts = hgc_validate(hgc, argv + 1, argc - 1); |
553 const char **insts = hgc_validate(hgc, argv + 1, argc - 1); |
545 if (insts == NULL) |
554 int needreconnect = runinstructions(&opts, insts); |
|
555 free(insts); |
|
556 if (!needreconnect) |
546 break; |
557 break; |
547 runinstructions(&opts, insts); |
|
548 free(insts); |
|
549 hgc_close(hgc); |
558 hgc_close(hgc); |
550 if (++retry > 10) |
559 if (++retry > 10) |
551 abortmsg("too many redirections.\n" |
560 abortmsg("too many redirections.\n" |
552 "Please make sure %s is not a wrapper which " |
561 "Please make sure %s is not a wrapper which " |
553 "changes sensitive environment variables " |
562 "changes sensitive environment variables " |