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