0 | module System.Posix.Process
  1 |
  2 | import System.Posix.File
  3 | import System.Posix.Signal
  4 | import System.Posix.Process.Prim as P
  5 |
  6 | import public Data.C.Ptr
  7 | import public System.Posix.Errno
  8 | import public System.Posix.Process.Flags
  9 | import public System.Posix.Process.ProcStatus
 10 |
 11 | %default total
 12 |
 13 | --------------------------------------------------------------------------------
 14 | -- API
 15 | --------------------------------------------------------------------------------
 16 |
 17 | ||| Returns the process ID of the current process
 18 | export %inline
 19 | getpid : HasIO io => io PidT
 20 | getpid = primIO getpid
 21 |
 22 | ||| Returns the process ID of the current process' parent process
 23 | export %inline
 24 | getppid : HasIO io => io PidT
 25 | getppid = primIO getppid
 26 |
 27 | ||| Returns the real user ID of the current process
 28 | export %inline
 29 | getuid : HasIO io => io UidT
 30 | getuid = primIO getuid
 31 |
 32 | ||| Returns the effective user ID of the current process
 33 | export %inline
 34 | geteuid : HasIO io => io UidT
 35 | geteuid = primIO geteuid
 36 |
 37 | ||| Returns the real group ID of the current process
 38 | export %inline
 39 | getgid : HasIO io => io GidT
 40 | getgid = primIO getgid
 41 |
 42 | ||| Returns the effective group ID of the current process
 43 | export %inline
 44 | getegid : HasIO io => io GidT
 45 | getegid = primIO getegid
 46 |
 47 | ||| Tries to set the real user ID of the current process
 48 | export %inline
 49 | setuid : Has Errno es => EIO1 f => UidT -> f es ()
 50 | setuid u = elift1 (P.setuid u)
 51 |
 52 | ||| Tries to set the effective user ID of the current process
 53 | export %inline
 54 | seteuid : Has Errno es => EIO1 f => UidT -> f es ()
 55 | seteuid u = elift1 (P.seteuid u)
 56 |
 57 | ||| Tries to set the real group ID of the current process
 58 | export %inline
 59 | setgid : Has Errno es => EIO1 f => GidT -> f es ()
 60 | setgid g = elift1 (P.setgid g)
 61 |
 62 | ||| Tries to set the effective group ID of the current process
 63 | export %inline
 64 | setegid : Has Errno es => EIO1 f => GidT -> f es ()
 65 | setegid g = elift1 (P.setegid g)
 66 |
 67 | parameters {auto has : Has Errno es}
 68 |            {auto eoi : EIO1 f}
 69 |
 70 |   ||| Creates a new child process.
 71 |   |||
 72 |   ||| This creates a new process by copying the stack, head, and
 73 |   ||| data memory segment of the parent process. If successful,
 74 |   ||| the functions returns `0` for the child process and
 75 |   ||| the child's process ID for the parent.
 76 |   export %inline
 77 |   fork : f es PidT
 78 |   fork = elift1 P.fork
 79 |
 80 |   ||| Loads a new program into this process's memory.
 81 |   |||
 82 |   ||| `path` : The path of the program to run
 83 |   ||| `args` : Command-line arguments (a `NULL` terminated array of strings)
 84 |   ||| `env ` : Environment (a `NULL` terminated array of strings of the for "a=b")
 85 |   |||
 86 |   ||| This only returns in case of an error.
 87 |   export %inline
 88 |   execve :
 89 |        String
 90 |     -> (args : CArrayIO m (Maybe String))
 91 |     -> (env  : CArrayIO n (Maybe String))
 92 |     -> f es ()
 93 |   execve s a env = elift1 (P.execve s a env)
 94 |
 95 |   ||| Convenience alias of `execve` that uses Idris lists for passing
 96 |   ||| the arguments list and environment.
 97 |   export
 98 |   execle : String -> List String -> List (String,String) -> f es ()
 99 |   execle s a ps = elift1 (P.execle s a ps)
100 |
101 |   ||| Like `execve` but uses the environment of the current process.
102 |   export %inline
103 |   execv : String -> CArrayIO m (Maybe String) -> f es ()
104 |   execv s arr = elift1 (P.execv s arr)
105 |
106 |   ||| Like `execv` but allows us to just use a filename
107 |   ||| and resolve in using the `$PATH` variable.
108 |   export %inline
109 |   execvp : String -> CArrayIO m (Maybe String) -> f es ()
110 |   execvp s arr = elift1 (P.execvp s arr)
111 |
112 |   ||| Convenience alias for `execvp` that uses an Idris list for
113 |   ||| the list of arguments.
114 |   export
115 |   execlp : String -> List String -> f es ()
116 |   execlp s ss = elift1 (P.execlp s ss)
117 |
118 |   ||| Runs the given shell command in a child process.
119 |   |||
120 |   ||| This has a slightly different type signature that the actual
121 |   ||| `system` call in C, which allows us to use the same mechanism
122 |   ||| as with `wait` to get the returned exit status.
123 |   export %inline
124 |   system : (cmd : String) -> f es ProcStatus
125 |   system cmd = elift1 (P.system cmd)
126 |
127 |   ||| Waits for one of the child processes of this process to
128 |   ||| terminate.
129 |   |||
130 |   ||| On success, this returns the process ID of the child process
131 |   ||| that terminated plus its termination status.
132 |   export %inline
133 |   wait : f es (PidT, ProcStatus)
134 |   wait = elift1 P.wait
135 |
136 |   ||| Waits for the given child processes of to terminate.
137 |   |||
138 |   ||| Unlike `wait`, this allows us to wait on a specific child process.
139 |   ||| In addition, it is possible to be notified about child processes that have
140 |   ||| been terminated by a signal.
141 |   export %inline
142 |   waitpid : PidT -> WaitFlags -> f es (PidT, ProcStatus)
143 |   waitpid chld fs = elift1 (P.waitpid chld fs)
144 |
145 |   ||| More powerful version of `waitpid` supporting additional flags and
146 |   ||| waiting on groups of children. Wait results are stored in a `Siginfo`
147 |   ||| record.
148 |   export %inline
149 |   waitid : IdType -> PidT -> WaitFlags -> f es Siginfo
150 |   waitid t chld fs = elift1 (P.waitid t chld fs)
151 |