How to get environment variables HOME and USER in Prolog cgi

How to get environment variables HOME and USER in Prolog cgi ? As getenv/2 does’nt work for this purpose, I used an ad hoc way which uses prolog_load_context/2 hinted by a sample code by Jan somewhere sometime. Now I would like to know more appropriate way to get the two environmental variables. Thanks in advance.

What do you mean by Prolog cgi? I suspect you are referring to some library or example code.
Can you give a reference.

What is wrong with getenv/2? If it is an environment variable it should work. As @EricGT says, a bit more context may help.

The prolog cgi (scipt?) is called from Javascrit like this, which I borrowed
from the net more than 10 years ago without knowing anything about Ajax.
I am afraid it is too old style nowadays, but I would like to keep using this as far as it works. My purpose is to hide home and user from sources which are so far on several host and plat forms.

# shell script calling Prolog code

#! /bin/sh
USER=cantor
HOME=/Users/${USER}

SWIPL=$HOME/bin/swipl
PACLIB=${HOME}/devel/zdd/prolog
PACSETUP=${PACLIB}/pac.pl
SCRIPT=${PACLIB}/util/web.pl
CGI=${PACLIB}/util/cgi.pl
MAIN='web:cgi_main'
${SWIPL} -q -s ${PACSETUP} -s ${CGI} -s ${SCRIPT}  -g ${MAIN} -t halt
# Ajax 

function httpPostRequest(target_url, post_data, functionReference) {
    try {
        if(window.XMLHttpRequest) {
            httpObj = new XMLHttpRequest();
        } else if(window.ActiveXObject) {
            httpObj = new ActiveXObject("Microsoft.XMLHTTP");
        } else {
           httpObj = false;
        }
    } catch(e) { httpObj = false; }
    if(! httpObj) { httpObjGenerateFail(); }
    // タイマーをセット
    if (timerId == null) 
	{ timerId = setInterval('timeoutCheck()', 1000);}
    else 
    { clearInterval(timerId); timerId = null; }
    httpObj.open("POST", target_url, true);
    httpObj.onreadystatechange = function() {
        if (httpObj.readyState == 4) {
            clearInterval(timerId);
            if (httpObj.status == 200) {
                functionReference(httpObj.responseText);
            } else {
                alert(httpObj.status + ' : ' + httpObj.statusText);
                return false;
            }
        }
    }
    timeout_sec = timeout_sec_init; // reset timer counter [2010/02/16]
    httpObj.send(post_data);
}

getenv/2 should work like that; I tried running a shell script like the one you have there around a simple prolog program that just outputs the environment variables and it acted as expected.

What does the Prolog code that’s trying to get the environment variables look like?

Thanks. I will try it later on a linux host to see it works like that. As far as on macOS, I never have seen it works, which has been a mystery for me for a long time.

Shouldn’t this be export USER=cantor, etc.?

I actually just ran it on macos & it worked as expected…

Script + execution
⟣─ ~/tmp
cat foo.sh
#!/bin/sh

USER=cantor
HOME=/Users/${USER}

swipl -q -l foo.pl -g main -t halt
⟣─ ~/tmp
cat foo.pl
:- module(foo, [main/0]).

main :-
    getenv('HOME', Home),
    getenv('USER', User),
    format("Hello; HOME=~w; USER=~w~n", [Home, User]).
⟣─ ~/tmp
./foo.sh
Hello; HOME=/Users/cantor; USER=cantor
⟣─ ~/tmp
uname -a
Darwin bishop.local 21.5.0 Darwin Kernel Version 21.5.0: Tue Apr 26 21:08:37 PDT 2022; root:xnu-8020.121.3~4/RELEASE_ARM64_T6000 arm64

I would have thought so, but it seems like USER and HOME specifically get inherited without having to export.

A little experiment confirmed what I thought: if a variable is already exported and set in the shell the environment is updated. If the variable is newly set in the shell it is not added to the environment.

My suspicion is that @kuniaki.mukai runs the web server as a service and this service does not set USER and HOME.

1 Like

Yes, I issued the command
% brew services restart httpd

I have tested the case for prolog cgi called from Ajax on a LINUX machine.

Prolog getenv(‘HOME’, _) seems also to fail to get the HOME, which is the same as on macOS.

:- getenv(‘HOME’, Home), open(’/home/mukai/Desktop/home_value’, write, S),
write(S, Home), close(S).

It seems a platform independent problem, and perhaps it is just a bug
which lives somewhere in my codes.

If you try changing the script to

export USER="..."
export HOME="..."

does that work?

No, it does not.

Now I am thinking it may be natural in a sense that USER and HOME are undefined in a CGI, because USER may be defined to be www in the httpd.conf on a host. My ad hoc way using ‘prolog_load_context/1’ seems more suitable way to get the CGI owner’s HOME and USER.

Additional information: on linux,
printenv at terminal shows HOME and USER correctly as expected, but
printenv at prolog script under httpd via javascript does not include neither HOME nor USER. So I am giving up hope to get HOME and USER by prolog getenv.

If you’re running as a daemon (or from initd, chron, service, etc), does it make sense to have any environment variables by default? After all, these things are often started by root. (There’s also no attached tty, of course, which is why there’s /var/log.)

The easiest way is to set environment variables in a shell script and then use exec "$@". You can find some suggestions for how to do this by searching stackoverflow for [daemon environment variables], but some of the answers I found are not good code, so you might want to ask again here when you’ve found an answer that seems to fit your situation.

Thank for suggestion, which tells me that things are much more complex than I thought. My purpose is to use the exactly same SWI-Prolog script on macOS also on a linux host machine with a simple local config information at the home directory, on which I am not a root user. For Prolog codes it is simple task provided that only USER and HOME are known. Thank you for preventing me from further efforts who is not good at such investigation.

This is a local configuration for my mac at home. Editing a few lines around commented lines, this configuration works on the remote linux machine with the same prolog script provided HOME and USER are availabe for getenv. I setenved by ‘parsing’ information from prolog_load_context.

~/.config/cgi-config.pl
:- module(config, [cgi_eqns/1, pac_directories/1]).
cgi_eqns([
	home_html	= $(home)  + '/public_html',
	home_cgi_bin = $(home) + '/public_html/cgi-bin',
	host		= 'http://localhost',
%	host		= 'http://webedit.sfc.keio.ac.jp',
	host_user	= $(host) + ':/~' + $(user),
	host_cgi_bin  = $(host_user) + '/cgi-bin',
	dvipdfmx	= '/Library/TeX/texbin/dvipdfmx',
%	dvipdfmx	= '/usr/local/bin/dvipdfmx'
	platex		= '/Library/TeX/texbin/platex',
%	platex		= ' /usr/local/bin/platex',
	pdf2ps		= '/usr/local/bin/pdf2ps',
%	pdf2ps		= '/usr/bin/pdf2ps',
	snapshot	= $(home)+'/Desktop/snapshot',
	exercise_js_name = 'http_request.js'
			]).

pac_directories(
		[	(pac_root : []) -
			 [	test:test,
				:(prolog) -
					[	pac		: pac,
						util	: util,
						zdd		: zdd,
						tmp		: tmp,
						gb		: "util/grobner",
						other	: other
					]]]
			   ).