[project @ 1996-12-19 18:35:23 by simonpj]
[ghc-hetmet.git] / ghc / lib / required / System.lhs
1 %
2 % (c) The AQUA Project, Glasgow University, 1994-1996
3 %
4
5 \section[System]{Module @System@}
6
7 \begin{code}
8 module System ( 
9     ExitCode(ExitSuccess,ExitFailure),
10     getArgs, getProgName, getEnv, system, exitWith
11   ) where
12
13 import Foreign          ( Addr )
14 import IOBase           ( IOError(..), thenIO_Prim, constructErrorAndFail )
15 import ArrBase          ( indexAddrOffAddr )
16 import PackedString     ( unpackCString )
17 \end{code}
18
19 %*********************************************************
20 %*                                                      *
21 \subsection{The @ExitCode@ type}
22 %*                                                      *
23 %*********************************************************
24
25 The $ExitCode$ type defines the exit codes that a program
26 can return.  $ExitSuccess$ indicates successful termination;
27 and $ExitFailure code$ indicates program failure
28 with value {\em code}.  The exact interpretation of {\em code}
29 is operating-system dependent.  In particular, some values of 
30 {\em code} may be prohibited (e.g. 0 on a POSIX-compliant system).
31
32 \begin{code}
33 data ExitCode = ExitSuccess | ExitFailure Int 
34                 deriving (Eq, Ord, Read, Show)
35
36 \end{code}
37
38
39 %*********************************************************
40 %*                                                      *
41 \subsection{Other functions}
42 %*                                                      *
43 %*********************************************************
44
45 \begin{code}
46 getArgs                 :: IO [String]
47 getProgName             :: IO String
48 getEnv                  :: String -> IO String
49 system                  :: String -> IO ExitCode
50 exitWith                :: ExitCode -> IO a
51 \end{code}
52
53 Computation $getArgs$ returns a list of the program's command
54 line arguments (not including the program name).
55
56 \begin{code}
57 getArgs = return (unpackArgv ``prog_argv'' (``prog_argc''::Int))
58 \end{code}
59
60 Computation $getProgName$ returns the name of the program
61 as it was invoked.
62
63 \begin{code}
64 getProgName = return (unpackProgName ``prog_argv'')
65 \end{code}
66
67 Computation $getEnv var$ returns the value
68 of the environment variable {\em var}.  
69
70 This computation may fail with
71 \begin{itemize}
72 \item $NoSuchThing$
73 The environment variable does not exist.
74 \end{itemize}
75
76 \begin{code}
77 getEnv name = 
78     _ccall_ getenv name `thenIO_Prim` \ litstring ->
79     if litstring /= ``NULL'' then
80         return (unpackCString litstring)
81     else
82         fail (NoSuchThing ("environment variable: " ++ name))
83 \end{code}
84
85 Computation $system cmd$ returns the exit code
86 produced when the operating system processes the command {\em cmd}.
87
88 This computation may fail with
89 \begin{itemize}
90 \item $PermissionDenied$
91 The process has insufficient privileges to perform the operation.
92 \item $ResourceExhausted$
93 Insufficient resources are available to perform the operation.  
94 \item $UnsupportedOperation$
95 The implementation does not support system calls.
96 \end{itemize}
97
98 \begin{code}
99 system "" = fail (InvalidArgument "null command")
100 system cmd = 
101     _ccall_ systemCmd cmd       `thenIO_Prim` \ status ->
102     case status of
103         0  -> return ExitSuccess
104         -1 -> constructErrorAndFail "system"
105         n  -> return (ExitFailure n)
106
107 \end{code}
108
109 Computation $exitWith code$ terminates the
110 program, returning {\em code} to the program's caller.
111 Before it terminates, any open or semi-closed handles are first closed.
112
113 \begin{code}
114 exitWith ExitSuccess = 
115     _ccall_ EXIT (0::Int)       `thenIO_Prim` \ () ->
116     fail (OtherError "exit should not return")
117
118 exitWith (ExitFailure n) 
119   | n == 0 = fail (InvalidArgument "ExitFailure 0")
120   | otherwise = 
121     _ccall_ EXIT n              `thenIO_Prim` \ () ->
122     fail (OtherError "exit should not return")
123 \end{code}
124
125
126 %*********************************************************
127 %*                                                      *
128 \subsection{Local utilities}
129 %*                                                      *
130 %*********************************************************
131
132 \begin{code}
133 type CHAR_STAR_STAR     = Addr  -- this is all a  HACK
134 type CHAR_STAR          = Addr
135
136 unpackArgv      :: CHAR_STAR_STAR -> Int -> [String] -- argv[1 .. argc-1]
137 unpackProgName  :: CHAR_STAR_STAR        -> String   -- argv[0]
138
139 unpackArgv argv argc = unpack 1
140   where
141     unpack :: Int -> [String]
142     unpack n
143       = if (n >= argc)
144         then ([] :: [String])
145         else case (indexAddrOffAddr argv n) of { item ->
146              unpackCString item : unpack (n + 1) }
147
148 unpackProgName argv
149   = case (indexAddrOffAddr argv 0) of { prog ->
150     de_slash [] (unpackCString prog) }
151   where
152     -- re-start accumulating at every '/'
153     de_slash :: String -> String -> String
154     de_slash acc []       = reverse acc
155     de_slash acc ('/':xs) = de_slash []      xs
156     de_slash acc (x:xs)   = de_slash (x:acc) xs
157 \end{code}