## posix-process.pkg
#
# Posix-specific process support.
# This is a subpackage of the POSIX 1003.1 based
# 'Posix' package
#
#
src/lib/std/src/psx/posixlib.pkg#
#
# An alternative higher-level unix 'spawn' interface
# is defined and implemented (respectively) in:
#
#
src/lib/std/src/posix/spawn--premicrothread.api#
src/lib/std/src/posix/spawn--premicrothread.pkg#
#
# A portable (cross-platform) process interface
# is defined and implemented (respectively) in:
#
#
src/lib/std/src/winix/winix-process--premicrothread.api#
src/lib/std/src/posix/winix-process--premicrothread.pkg# Compiled by:
#
src/lib/std/src/standard-core.sublib### "I wanted to separate data from programs,
### because data and instructions are very different."
###
### -- Ken Thompson
### "The Hobbits named it the Shire, as the region
### of the authority of their Thain, and a district
### of well-ordered business; and there in that
### pleasant corner of the world they plied their
### well-ordered business of living, and they heeded
### less and less the world outside where dark things
### moved, until they came to think that peace and
### plenty were the rule in Middle-earth and the right
### of all sensible folk.
###
### "They forgot or ignored what little they had
### ever known of the Guardians, and of the labours of
### those that made possible the long peace of the Shire.
### They were, in fact, sheltered, but they had ceased
### to remember it."
###
### -- J R R Tolkien
stipulate
package hi = host_int; # host_int is from
src/lib/std/src/psx/host-int.pkg package hu = host_unt_guts; # host_unt_guts is from
src/lib/std/src/bind-sysword-32.pkg package u1b = one_byte_unt_guts; # one_byte_unt_guts is from
src/lib/std/src/one-byte-unt-guts.pkg package tim = time_guts; # time_guts is from
src/lib/std/src/time-guts.pkg package ig = int_guts; # int_guts is from
src/lib/std/src/int-guts.pkg package sig = interprocess_signals; # interprocess_signals is from
src/lib/std/src/nj/interprocess-signals.pkg package ci = mythryl_callable_c_library_interface; # mythryl_callable_c_library_interface is from
src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg #
fun cfun fun_name = ci::find_c_function { lib_name => "posix_process", fun_name }; # "posix_process" def in src/c/lib/posix-process/cfun-list.h
fun cfun' fun_name = ci::find_c_function'' { lib_name => "posix_process", fun_name }; # "posix_process" def in src/c/lib/posix-process/cfun-list.h
#
#
###############################################################
# The functions in this package -- fork(), exec() etc -- are
# mostly not the sort where latency is a concern or where
# execution in another posix thread is appropriate.
#
# Consequently I've not taken the time and effort to switch them
# over from using find_c_function() to using find_c_function'().
#
# The exceptions are sysconf, osval, kill and waitpid.
# These I have switched over to find_c_function'.
#
# (waitpid might be a mistake; I'm presuming it is only used
# to harvest the status of children in response to SIGCHLF.)
#
# -- 2012-04-21 CrT
Signal = sig::Signal;
herein
package posix_process { # Posix_Process is from
src/lib/std/src/psx/posix-process.api #
Unt = hu::Unt;
Sy_Int = hi::Int;
Process_Id = PID Sy_Int;
fun pid_to_unt (PID i)
=
hu::from_int i;
fun unt_to_pid w
=
PID (hu::to_int w);
(cfun' "osval") # osval def in src/c/lib/posix-process/osval.c
->
( osval__syscall: String -> Sy_Int,
osval__ref,
set__osval__ref
);
fun osval string
=
*osval__ref string;
w_osval = hu::from_int o osval;
stipulate
fun cfun' fun_name
=
ci::find_c_function'' { lib_name => "posix_process_environment", fun_name }; # "posix_process_environment" def in src/c/lib/posix-process-environment/cfun-list.h
herein
(cfun' "sysconf") # sysconf def in src/c/lib/posix-process-environment/sysconf.c
->
( sysconf__syscall: String -> hu::Unt,
sysconf__ref,
set__sysconf__ref
);
fun sysconf string
=
*sysconf__ref string;
end;
fork' = cfun "fork" : Void -> Sy_Int; # fork def in src/c/lib/posix-process/fork.c
fun fork ()
=
case (fork' ())
#
0 => NULL;
child_pid => THE (PID child_pid);
esac;
#
# This is essentially the unix-level fork().
# For a higher-level fork() see fork_process() in
#
#
src/lib/std/src/posix/spawn--premicrothread.api #
src/lib/std/src/posix/spawn--premicrothread.pkg fun exec (x: (String, List( String )) ) : X = cfun "exec" x; # exec def in src/c/lib/posix-process/exec.c
fun exece (x: (String, List( String ), List( String )) ) : X = cfun "exece" x; # exece def in src/c/lib/posix-process/exece.c
fun execp (x: (String, List( String )) ): X = cfun "execp" x; # execp def in src/c/lib/posix-process/execp.c
Waitpid_Arg
#
= W_ANY_CHILD
| W_CHILD Process_Id
| W_GROUP Process_Id
| W_SAME_GROUP
;
Killpid_Arg
#
= K_PROC Process_Id
| K_GROUP Process_Id
| K_SAME_GROUP
;
Exit_Status
#
= W_EXITED
| W_EXITSTATUS u1b::Unt
| W_SIGNALED Signal
| W_STOPPED Signal
;
# (pid', status, status_val) = waitpid' (pid, options)
(cfun' "waitpid") # waitpid def in src/c/lib/posix-process/waitpid.c
->
( waitpid__syscall: (hi::Int, Unt) -> (hi::Int, hi::Int, hi::Int),
waitpid__ref,
set__waitpid__ref
);
fun arg_to_int W_ANY_CHILD => -1;
arg_to_int (W_CHILD (PID pid)) => pid;
arg_to_int (W_SAME_GROUP) => 0;
arg_to_int (W_GROUP (PID pid)) => -pid;
end;
# The exit status from wait is encoded as a pair of integers.
# If the first integer is 0, the child exited normally, and
# the second integer gives its exit value.
# If the first integer is 1, the child exited due to an uncaught
# signal, and the second integer gives the signal value.
# Otherwise, the child is stopped and the second integer
# gives the signal value that caused the child to stop.
fun make_exit_status (0, 0) => W_EXITED;
make_exit_status (0, v) => W_EXITSTATUS (u1b::from_int v);
make_exit_status (1, s) => W_SIGNALED (sig::int_to_signal s);
make_exit_status (_, s) => W_STOPPED (sig::int_to_signal s);
end;
package w {
#
stipulate
package w0 = bit_flags_g ();
herein
include package w0;
end;
untraced = from_unt ( { *sysconf__ref "JOB_CONTROL";
w_osval "WUNTRACED";
}
except _ = 0u0
);
};
fun waitpid (arg, flags)
=
{ (*waitpid__ref (arg_to_int arg, w::to_unt (w::flags flags)))
->
(pid, status, exit_value);
(PID pid, make_exit_status (status, exit_value));
};
stipulate
wnohang = w::from_unt (w_osval "WNOHANG");
herein
fun waitpid_without_blocking (arg, flags)
=
case (*waitpid__ref (arg_to_int arg, w::to_unt (w::flags (wnohang ! flags))))
#
(0, _, _) => NULL;
(pid, status, exit_value) => THE (PID pid, make_exit_status (status, exit_value));
esac;
end;
fun wait ()
=
waitpid (W_ANY_CHILD,[]);
fun exit (x: u1b::Unt) : X
=
{
cfun "exit" x; # exit def in src/c/lib/posix-process/exit.c
};
(cfun' "kill") # kill def in src/c/lib/posix-process/kill.c
->
( kill__syscall: (Sy_Int, Sy_Int) -> Void,
kill__ref,
set__kill__ref
);
fun kill (K_PROC (PID pid), s) => *kill__ref (pid, sig::signal_to_int s); # "Kill me to-morrow; let me live to-night!" -- William Shakespeare, "Othello"
kill (K_SAME_GROUP, s) => *kill__ref (-1, sig::signal_to_int s);
kill (K_GROUP (PID pid), s) => *kill__ref (-pid, sig::signal_to_int s);
end;
stipulate
fun wrap f t
=
tim::from_seconds (ig::to_multiword_int (f (ig::from_multiword_int (tim::to_seconds t))));
alarm' = cfun "alarm" : Int -> Int;
sleep' = cfun "sleep" : Int -> Int; # sleep def in src/c/lib/posix-process/sleep.c
#
# From the manpage:
#
# BUGS
# sleep() may be implemented using SIGALRM; mixing calls to alarm(2) and
# sleep() is a bad idea.
herein
alarm = wrap alarm';
sleep = wrap sleep';
#
# Note that you can sleep with sub-second resolution
# via winix__premicrothread::process::sleep or winix__premicrothread::io::poll.
end;
pause = cfun "pause": Void -> Void; # pause def in src/c/lib/posix-process/pause.c
}; # package posix_process
end;