26639


素の emacs を実行しても (`emacs -q`)、 TERM 環境変数はもともとが何に設定されていても、結果として `dumb` になります。
`M-x getenv <RET> TERM <RET>` で確認しました。

普段 emacs を環境として使っていて、意図しない環境変数の書き換えがあると、無駄な罠に将来はまると思っています。

質問:

  * 端末上の emacs が、親のシェルから引き継がない環境変数は、 `TERM` 以外にありますか?


CC BY-SA 3.0
2016-06-10T07:53:29.473
26620
2016-06-16T05:22:44.977
754
question
emacs
端末上の emacs が、シェルから書き換える環境変数は何？


emacs process の環境変数は `process-environment` 変数に保持されています。

> **process-environment**  
>  List of overridden environment variables for subprocesses to inherit.
[code]

    (require 'cl)
    (find-if #'(lambda (e) (string-match "^TERM=" e)) process-environment)
    => "TERM=dumb"
    
[/code]

ただし、一つだけ例外があって、それは `DISPLAY` 環境変数です。

[code]

    (find-if #'(lambda (e) (string-match "^DISPLAY=" e)) process-environment)
    => nil
    
    (getenv "DISPLAY")
    => ":0.0"
    (let (process-environment) (getenv "DISPLAY"))
    => ":0.0"
    (let (process-environment) (start-process "env" (current-buffer) "env"))
    => DISPLAY=:0.0
    
[/code]

`process-environment` 変数を `nil`(empty list)に bind しても `DISPLAY`
環境変数がセットされています。

ソースコードを確認してみると、`process-environment` に `DISPLAY` 環境変数が存在しない場合は `initial-
environment` から取り出しています。

**emacs/src/callproc.c**

[code]

    static bool
    getenv_internal (const char *var, ptrdiff_t varlen, char **value, ...)
    {
      /* Try to find VAR in Vprocess_environment first.  */
      if (getenv_internal_1 (var, varlen, value, valuelen, Vprocess_environment))
        return *value ? 1 : 0;
    
      /* For DISPLAY try to get the values from the frame or the initial env. */
      if (strcmp (var, "DISPLAY") == 0)
        {
                    :
          /* If still not found, Look for DISPLAY in Vinitial_environment.  */
          if (getenv_internal_1 (var, varlen, value, valuelen, Vinitial_environment))
            return *value ? 1 : 0;
        }
                :
    
    int
    child_setup (int in, ...)
    {
               :
      for (tem = Vprocess_environment;
           CONSP (tem) && STRINGP (XCAR (tem));
           tem = XCDR (tem))
        {
          if (strncmp (SSDATA (XCAR (tem)), "DISPLAY", 7) == 0
              && (SDATA (XCAR (tem)) [7] == '\0'
                  || SDATA (XCAR (tem)) [7] == '='))
             /* DISPLAY is specified in process-environment.  */
               :
        }
    
      /* If not provided yet, use the frame's DISPLAY.  */
      if (NILP (display))
        {
          Lisp_Object tmp = Fframe_parameter (selected_frame, Qdisplay);
          if (!STRINGP (tmp) && CONSP (Vinitial_environment))
            /* If still not found, Look for DISPLAY in Vinitial_environment.  */
            tmp = Fgetenv_internal (build_string ("DISPLAY"),
                                    Vinitial_environment);
               :
    
    
    /* If we have a PWD envvar, pass one down,
       but with corrected value.  */
    if (egetenv ("PWD"))
      *new_env++ = pwd_var;
    
[/code]

> **initial-environment**  
>  List of environment variables inherited from the parent process.

この parent process は emacs を起動したプロセス(例えばシェルプロセス)です。

それから、先のソースコードに `PWD` 環境変数を再設定している部分があります。

[code]

    (let ((default-directory "/tmp"))
       (start-process "pwd" (current-buffer) "printenv" "PWD"))
    => /tmp
    
[/code]

なお、`process-environment` はユーザ側で変更することが可能です。

[code]

    (let ((process-environment
           (cons "TERM=xterm" process-environment)))
      (list
       (mapcan #'(lambda (e) (and (string-match "^TERM=" e) (list e)))
               process-environment)
       (getenv "TERM")))
    => (("TERM=xterm" "TERM=dumb") "xterm")
    
[/code]

同じ環境変数が存在する場合は、先に設定された値が有効になります。

**追記**

`term-mode` での環境変数の追加(`process-
environment`へのpush)は以下の部分で行われています。端末制御に必要な環境変数なのだと思います。

**emacs/25.1.50/lisp/term.el**

[code]

    (let ((process-environment
           (nconc
            (list
             (format "TERM=%s" term-term-name)
             (format "TERMINFO=%s" data-directory)
             (format term-termcap-format "TERMCAP="
                     term-term-name term-height term-width)
    
             ;; This is for backwards compatibility with Bash 4.3 and earlier.
             ;; Remove this hack once Bash 4.4-or-later is common, because
             ;; it breaks './configure' of some packages that expect it to
             ;; say where to find EMACS.
             (format "EMACS=%s (term:%s)" emacs-version term-protocol-version)
    
             (format "INSIDE_EMACS=%s,term:%s" emacs-version term-protocol-version)
             (format "LINES=%d" term-height)
             (format "COLUMNS=%d" term-width))
            process-environment))
    
[/code]


CC BY-SA 3.0
2016-06-10T10:10:03.330
26624
2016-06-10T19:54:31.747
2016-06-10T19:54:31.747
26620
answer


「Emacs起動時に親プロセスから継承された環境変数の一覧」と「現在の環境変数の一覧」は[initial-
environment](https://www.gnu.org/software/emacs/manual/html_node/elisp/System-
Environment.html#index-initial_002denvironment)と[process-
environment](https://www.gnu.org/software/emacs/manual/html_node/elisp/System-
Environment.html#index-process_002denvironment)で参照できます。中身はどちらも文字列のリスト
`("PATH=/bin:/usr/bin..." "SHELL=/bin/bash" ...)` です。

この2つのリストの差分をとってみると環境変数`TERM`だけが更新されているようです。

[code]

    (require 'cl-lib)
    (cl-set-difference initial-environment process-environment)
    ;;=> ("TERM=dumb")
    
[/code]

また[ソースコードを検索](https://github.com/emacs-
mirror/emacs/search?l=c&q=xputenv&utf8=%E2%9C%93)してみると`EMACS_HEAP_EXEC=true`,
`GDK_CORE_DEVICE_EVENTS=1`などが環境によっては更新されるようです。

* * *

これとは別に、`M-x
shell`でシェルを起動すると以下の2つの環境変数が上書きされます。(おそらく通常のシェルと区別する目的があると思うのですが、詳しくはわかりません)

  * `EMACS=t`
  * `INSIDE_EMACS=24.5.1,comint` (数字はEmacsのバージョン番号)


CC BY-SA 3.0
2016-06-10T18:03:04.320
26639
2016-06-10T18:27:10.013
2016-06-10T18:27:10.013
2391
2391
26620
answer


`process-environment` で emacs-24.1 ソース内部を `grep` してみました。  
外部プロセスを起動する系の `elisp` はかなりのものが環境変数を上書きしているようです。  
一部のみ抜粋してみましょう。

`emacs-24.1/lisp/man.el`  
`COLUMNS=999`  
`man` コマンドのカラム数を 999 に設定し emacs 内部で整形させるためのもののようです。

`emacs-24.1/lisp/progmodes/grep.el`  
`TERM=emacs-grep GREP_OPTIONS+=--color=auto GREP_COLORS=...`  
GNU grep のときに色指定を行っている様子

`emacs-24.1/lisp/vc/vc-dispatcher.el`  
`LC_MESSAGES=C`

`emacs-24.1/lisp/vc/vc-hg.el`  
`TERM=dumb LANGUAGE=C`

`emacs-24.1/lisp/vc/vc-git.el`  
`PAGER=`

最初から NLS 対応な vcs ツールは英語モードで起動している様子  
PAGER 対応なツールは PAGER なしで起動している様子

`term.el` はもう指摘があるの省略

この辺を気にするかしないかは人それぞれでしょうか・・・


CC BY-SA 3.0
2016-06-16T05:22:44.977
26779
2016-06-16T05:22:44.977
8589
26620
answer