PreviousUpNext

15.4.1125  src/lib/std/src/posix-1003.1b/posix-process.pkg

## posix-process.pkg

# Compiled by:
#     src/lib/std/src/standard-core.sublib

# Posix-specific process support.
# This is a subpackage of the POSIX 1003.1 based
# 'Posix' package
#
#     src/lib/std/src/posix-1003.1b/posix-1003-1b.pkg


# An alternative higher-level unix 'spawn' interface
# is defined and implemented (respectively) in:
#
#     src/lib/std/src/posix/spawn.api
#     src/lib/std/src/posix/spawn.pkg


# A portable (cross-platform) process interface
# is defined and implemented (respectively) in:
#
#     src/lib/std/src/winix/winix-process.api
#     src/lib/std/src/posix/winix-process.pkg



###             "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 host_unt=  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 time    =      time_guts;                                   # time_guts                             is from   src/lib/std/src/time-guts.pkg
    package int     =       int_guts;                                   # int_guts                              is from   src/lib/std/src/bind-int-32.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
herein

    package posix_process {
        #
        package sig = posix_signal;                                                                     # posix_signal                  is from   src/lib/std/src/posix-1003.1b/posix-signal.pkg

        Unt    = host_unt::Unt;
        Sy_Int = host_int::Int;

        Signal = sig::Signal;

        Process_Id = PID  Sy_Int;


        fun pid_to_unt (PID i)
            =
            host_unt::from_int i;


        fun unt_to_pid w
            =
            PID (host_unt::to_int w);


        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


        my osval:  String -> Sy_Int
            =
            cfun "osval";                                                                               # osval                         def in    src/c/lib/posix-process/osval.c


        w_osval = host_unt::from_int o osval;


        my sysconf:  String -> host_unt::Unt
            =                                                                                           # "posix_process_environment"   def in    src/c/lib/posix-process-environment/cfun-list.h
            ci::find_c_function { lib_name => "posix_process_environment", fun_name => "sysconf" };     # sysconf                       def in    src/c/lib/posix-process-environment/sysconf.c


        my fork' : Void -> Sy_Int
            =
            cfun "fork";                                                                                # 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.api
            #     src/lib/std/src/posix/spawn.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)  

        my waitpid' : (Sy_Int, Unt) -> (Sy_Int, Sy_Int, Sy_Int)
            =
            cfun "waitpid";                                                                             # waidpid                       def in    src/c/lib/posix-process/waitpid.c

        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::SIGNAL s);
            make_exit_status (_, s) =>  W_STOPPED (sig::SIGNAL s);
        end;

        fun from_status s
            =
            make_exit_status (int::quot (s, 256), int::rem (s, 256));

        package w {

            stipulate
                package w0 = bit_flags_g ();
            herein
                include w0;
            end;

            untraced
                =
                from_unt ({ sysconf "JOB_CONTROL"; w_osval "WUNTRACED";}
                          except _ = 0u0);
        };

        wnohang =  w::from_unt (w_osval "WNOHANG");

        fun waitpid (arg, flags)
            =
            {   (waitpid' (arg_to_int arg, w::to_unt (w::flags flags)))
                    ->
                    (pid, status, sv);

                (PID pid,  make_exit_status (status, sv));
            };

        fun waitpid_nh (arg, flags)                                                     # "_nh" == "nohang"
            =
            case (waitpid' (arg_to_int arg, w::to_unt (w::flags (wnohang ! flags))))
                #
                (0, _, _)         =>  NULL;
                (pid, status, sv) =>  THE (PID pid, make_exit_status (status, sv));
            esac;


        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


        my  kill' : (Sy_Int, Sy_Int) -> Void
            =
            cfun "kill";                                                        # kill          def in    src/c/lib/posix-process/kill.c


        fun kill (K_PROC (PID pid),  sig::SIGNAL s) => kill' (pid,  s);         # "Kill me to-morrow; let me live to-night!"    -- William Shakespeare, "Othello"
            kill (K_SAME_GROUP,      sig::SIGNAL s) => kill' (-1,   s);
            kill (K_GROUP (PID pid), sig::SIGNAL s) => kill' (-pid, s);
        end;


        stipulate
            fun wrap f t
                =
                time::from_seconds (int::to_multiword_int (f(int::from_multiword_int (time::to_seconds t))));

            my alarm' :   Int -> Int =   cfun "alarm";
            my sleep' :   Int -> Int =   cfun "sleep";                          # 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::process::sleep or winix::io::poll.

        end;

        my pause:  Void -> Void
            =
            cfun "pause";                                                       # pause         def in    src/c/lib/posix-process/pause.c


    }; #  package posix_process 
end;



Comments and suggestions to: bugs@mythryl.org

PreviousUpNext