diff --git a/contrib/chg/chg.c b/contrib/chg/chg.c --- a/contrib/chg/chg.c +++ b/contrib/chg/chg.c @@ -201,6 +201,36 @@ return hgcmd; } +static void putsidechannelenv(const char *envname) +{ + char *namebuf, *valbuf; + const char *existing_val = getenv(envname); + size_t existing_val_len = 0, namebuf_len = 0, valbuf_len = 0; + size_t envname_len = strlen(envname); + + if (existing_val != NULL) { + existing_val_len = strlen(existing_val); + } + + namebuf_len = envname_len + 9; + namebuf = mallocx(namebuf_len); + memcpy(namebuf, "CHGORIG_", 8); + memcpy(namebuf + 8, envname, envname_len + 1); + + valbuf_len = existing_val_len + 2; + valbuf = mallocx(valbuf_len); + valbuf[0] = (existing_val == NULL) ? '0' : '1'; + if (existing_val != NULL && existing_val_len > 0) { + memcpy(valbuf + 1, existing_val, existing_val_len); + } + valbuf[valbuf_len - 1] = '\0'; + if (setenv(namebuf, valbuf, 1) != 0) { + abortmsgerrno("failed to setenv for stored vars"); + } + free(valbuf); + free(namebuf); +} + static void execcmdserver(const struct cmdserveropts *opts) { const char *hgcmd = gethgcmd(); @@ -226,6 +256,14 @@ } argv[argsize - 1] = NULL; + char *coerce = getenv("PYTHONCOERCECLOCALE"); + if (coerce == NULL || coerce[0] != '0') { + /* Py3 modifies the environment on execution, we need a side + * channel to get an unmodified environment to `hg serve` for + * some variables */ + putsidechannelenv("LC_CTYPE"); + } + if (putenv("CHGINTERNALMARK=") != 0) abortmsgerrno("failed to putenv"); if (execvp(hgcmd, (char **)argv) < 0)