I'm writing a major mode to interface with a popular but clunky Monte Carlo program. I've also written a script that makes the interface a little more tolerable, and have written the following simple Lisp function to run that script within Emacs:

(defun run-phits ()
  "Run phits-command on the current buffer asynchronously, displaying output in a new buffer and placing output files in the same directory as the current buffer's file."
  (let ((default-directory (file-name-directory buffer-file-name)))
    (async-shell-command (concat phits-command buffer-file-name))))

Whenever I run the value of phits-command (the name of the script plus a space) on a file in a regular terminal buffer, it works fine.

Whenever I hit M-x run-phits in a buffer of the same file, I get an internal error from the program I'm invoking that seems to be related to path-setting:

 Fission_barrier_table_PhysRevC_91_024310.dat is  missing in data folder

 Error : input data file for multiplier does not exist.
 file name = c:/phits/data/multiplier/m211.inp

The file it's talking about very much does exist. Evidently, c:/ is somehow internally aliased to the install directory of the program in a way that doesn't work with Emacs (I'm on Linux, to be clear; this must be happening because the same program works from the terminal). It doesn't work typing the command into M-! either; I copied-and-pasted the command name from the line of *Messages* that mentioned the error to the terminal and it worked flawlessly.

Removing the complexity of the script and using the default calling method of redirecting the file to the executable doesn't work either; here's the script in any case:



while getopts ":MOh" option; do
    case $option in
    \?) echo -n "phits: unrecognized argument "
        echo -n ${OPTARG}
        echo "; see phits -h for help."

    M)  # borrowed from calandoa on SO
        if [[ $nextopt != -* && $nextopt != ${@: -1} ]] ; then
        OPTIND=$((OPTIND + 1))
        np=$(nproc --all)
        echo "file = $(readlink -f ${@: -1})" > ${phitsin_path}
        mpirun -np ${np} ${phits_MPI}

    O) ${phits_OMP} < ${@: -1}

    h) echo "phits: nicer command-line interface to JAEA's Particle Heavy Ion Transport code System"
       echo "Usage: phits -[MOh] [file]"
       echo "Options:"
       echo "    none: run the standard PHITS single-core binary on [file]"
       echo "    -M [proc]: copy the path of [file] to phits.in and run a PHITS MPI binary on all cores of the current machine. If specified, use [proc] processes; otherwise, use every core."
       echo "    -O: run a PHITS OpenMP binary on [file]."
       echo "    -h: display this message."

# no option given; use single-thread binary

if [[ -n $1 ]] ; then
    ${phits_single} < $1
    echo "Error: no input file specified."

(Just checked that it's not the redirection by getting the MPI switch working; same error)

What subtle internal differences are there between Emacs spinning up a shell and running a script and my doing the same in M-x term? The program in question is a million lines of FORTRAN in a style straight out of 1965, very much "real programmer" stuff, so there's little chance of me chasing down what the program is doing internally.

  • If you are on Linux, where is the c:/ stuff coming from? You say: "Evidently, c:/ is somehow internally aliased to the install directory of the program in a way that doesn't work with Emacs " - that is not at all evident to me. On what do you base that statement? And which program are you referring to in the sentence above? You are talking about a command that you cut-and-pasted from the *Messages* buffer: what command is that? Please edit your question and add all that information.
    – NickD
    Jan 29, 2022 at 4:55
  • PHITS was originally developed for Windows, and I suppose they didn't change their internal representation of the installation directory of the program. Since the program works whenever I run it from the command line, it must be readjusting something internally. I wrote the command I pasted from the Messages buffer; I can paste the script here, but the point of the script was to take the absurd calling syntax of PHITS and make it look like an actual Linux program from the user's perspective. I'm just posting to determine why the same program works one way on the terminal and another in Emacs
    – Duncan W
    Jan 29, 2022 at 6:35
  • ...because I know very little about how Emacs internally handles shell creation, path variables, working directories, and all that.
    – Duncan W
    Jan 29, 2022 at 6:37

1 Answer 1


Found it. A nuance with how Emacs inherits environment variables from the shell: By diffing printenv output from my script when on the command line versus in Emacs, I noticed there was a PHITSPATH variable missing in Emacs.

This variable was exported in my .zshrc, so I presumed exec-path-from-shell-intitialize from the exec-path-from-shell package would have picked it up. It didn't; the function only loads the environment variables from the list exec-path-from-shell-variables.

The correct use-package invocation, if anyone is interested, is

(use-package exec-path-from-shell
    (setq exec-path-from-shell-variables '("PATH" "MANPATH" "PHITSPATH"))
    ;; ^ defaults to ("PATH" "MANPATH"); the program requires the additional one
    (when (memq window-system '(mac ns x))

  • Or just start Emacs via a shell and it'll inherit the environment generated by your shell config without the need for any additional helpers.
    – phils
    Jan 30, 2022 at 3:51
  • Interesting. I use dmenu to launch all programs, so I wonder how it handles environment variables?
    – Duncan W
    Jan 30, 2022 at 5:13
  • Everything inherits the environment from which it was started. I doubt that dmenu is doing anything particular with environment variables.
    – phils
    Jan 30, 2022 at 8:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.