%%% Part 4 - Standalone application generation %%%

% A few simple support predicates to make standalone cgi-bin applications
save_cgi_bin(Name,EntryPoint) :-
        save_cgi_bin(Name,EntryPoint,n).

%% Savetype "p" if for parallel systems...
save_cgi_bin(Name,EntryPoint,Savetype) :-
        cgi_bin_dir(BinDir),
        atom_concat(BinDir,Name,FullName),
        (Savetype == p -> psave(FullName,Return) ; save(FullName,Return)),
        boot_form(Return,FullName,EntryPoint).

boot_form(0,FullName,_) :- 
        atom_concat('chmod ugo+rx ',FullName,Command),
        unix(system(Command)).

boot_form(1,_,EntryPoint) :- 
        html_protect(EntryPoint),
        halt.

html_protect(Goal) :-
        on_exception(E,Goal,html_report_error(E)).
html_protect(_) :-
        html_report_error('Sorry, html_pl application failed.').

%% Save active module in cgi directory, store address as file 
%% (i.e. does not use name server yet)

save_cgi_active_module(ExecName) :- 
        cgi_bin_dir(BinDir),
        atom_concat(BinDir,ExecName,FullName),
        atom_concat(FullName,'_address',AddressFile),
        atom_concat('rm -f ',AddressFile,RmCommand),
        atom_concat('chmod ugo+r ',AddressFile,AdChmodCommand),
        atom_concat('chmod ugo+rx ',FullName,ChmodCommand),
        atom_concat(FullName,'_log',LogFile),
        ReportAddressAction = 
        (
            unix(system(RmCommand)),
            tell(AddressFile),
            user:get_pid(Pid),
            write_canonical(Address), write('.'), nl, flush_output,
            write_canonical(my_pid(Pid)), write('.'), nl, flush_output,
            told,
            unix(system(AdChmodCommand))
        ),
        tell(LogFile),
        save_active_module(FullName, Address, ReportAddressAction),
        unix(system(ChmodCommand)).

%%% Support predicates %%%

%% Concatenates two atoms
atom_concat(A,B,AB) :-
        name(A,AS),
        name(B,BS),
        append(AS,BS,ABS),
        name(AB,ABS).

append([],X,X).
append([H|T1],L,[H|T2]) :- append(T1,L,T2).

%% Get Unix environment variable
getenv(Var,Val) :-
        name(Var,VS),
        append("echo $",VS,SCommand),
        name(Command,SCommand),
        unix(popen(Command,read,S)),
        read_command_output(S,SInput),
        SInput = [_|_], % not null
        atom_chars(Val,SInput).

%% For reading output from a unix command
read_command_output(S,List) :- 
        get0(S,Char),
        check_char(Char,S,List).

check_char(-1,_S,[]) :- !. % EOF
check_char(10,_S,[]) :- !. % Newline
check_char(Ch,S,[Ch|Rest]) :- 
        get0(S,Ch1),
        check_char(Ch1,S,Rest).
