contrib/chg/chg.c
branchstable
changeset 50336 cf4d2f31660d
parent 47024 8fcc0a829f3d
child 50352 d06e43cd393f
equal deleted inserted replaced
50335:787e7caf887a 50336:cf4d2f31660d
   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;