Module Unix
Author: Christian.Queinnec@lip6.fr

## Module `Unix`

On trouve dans ce module l'interface avec les principales fonctions des bibliothèques du système Unix. Cependant, comme nous l'avons déjà signalé, une partie importante de ce module a été portée sous Windows et est donc accessible depuis ce dernier. Nous signalerons, lorsque nécessaire, les restrictions d'utilisation des fonctions présentées. Un tableau résumant ces restrictions est donné figure 18.1.
La bibliothèque `Unix` fait partie des bibliothèques non standard d'Objective CAML qu'il est nécessaire de lier par la commande `-custom` du compilateur (voir chapitre 7, page ??). Suivant l'usage que l'on destine au programme, on écrit sous Unix l'une des commandes suivantes, pour obtenir du code-octet, du code natif ou une boucle d'interaction :

    $ ocamlc -custom unix.cma  fichiers.ml -cclib -lunix
    $ ocamlopt unix.cma fichiers.ml -cclib -lunix
    $ ocamlmktop -custom -o unixtop unix.cma -cclib -lunix

L'intérêt de construire une boucle d'interaction (dont le nom sera ici `unixtop`) est de permettre un développement incrémentiel. On obtient rapidement la compilation de chaque fonction avec son indication de type. On peut même procéder à quelques tests fonctionnels.
Suivant l'Unix utilisé, la bibliothèque système peut ne pas être à l'emplacement prévu par défaut. Si nécessaire, on peut préciser le chemin d'accès des bibliothèques avec l'option `-ccopt` (voir chapitre 7).
Sous Windows, les commandes de compilation deviennent :

    $ ocamlc -custom unix.cma  fichiers.ml %CAMLLIB%\libunix.lib wsock32.lib
    $ ocamlopt unix.cma fichiers.ml %CAMLLIB%\libunix.lib wsock32.lib
    $ ocamlmktop -custom -o unixtop.exe unix.cma %CAMLLIB%\libunix.lib wsock32.lib

Le nom de la boucle d'interaction ainsi obtenue est `unixtop.exe`.

### Gestion des erreurs

Les erreurs provoquées par les appels système déclenchent l'exception `Unix_error` qui peut être traitée depuis un programme Objective CAML. Cette erreur contient trois arguments : une valeur de type `Unix.error` qu'il est possible de traduire sous forme d'une chaîne de caractères par la fonction `error_message`, une chaîne contenant le nom de la fonction ayant provoqué l'erreur et une chaîne contenant éventuellement l'argument de la fonction lorsqu'il est de type string.
On peut ainsi définir une fonction générique d'appel de fonction et de traitement des erreurs :

    # let capsule_unix fonct arg =
       try (fonct arg) with
        Unix.Unix_error (e,fm,argm) ->
          Printf.printf "%s %s %s" (Unix.error_message e) fm argm ;;
    val capsule_unix : ('a -> unit) -> 'a -> unit = <fun>

La fonction `capsule_unix` prend une fonction, son argument et applique l'une à l'autre. Si une erreur Unix survient, un message explicatif est affiché. Une fonction équivalente est définie dans le module `Unix` :

    # Unix.handle_unix_error ;;
    - : ('a -> 'b) -> 'a -> 'b = <fun>

### Portabilité des appels système

La figure 18.1 indique quelles fonctions, de communication et de gestion des processus, présentées dans ce chapitre sont accessibles sous Windows. Les deux manques principaux sont la fonction `fork` pour la duplication du processus courant et la fonction `kill` d'émission de signaux.

> Fonction | Unix | Windows | Commentaire
> `openfile` | × | × |
> `close` | × | × |
> `dup` | × | × |
> `dup2` | × | × |
> `read` | × | × |
> `write` | × | × |
> `lseek` | × | × |
> `execv` | × | × |
> `execve` | × | × |
> `execvp` | × | × |
> `execvpe` | × | × |
> `fork` | × |  | utiliser `create_process`
> `getpid` | × | × |
> `sleep` | × | × |
> `wait` | × |  |
> `waitpid` | × | × | uniquement pour un numéro de
> |  |  | processus donné
> `create_process` | × | × |
> `create_process_env` | × | × |
> `kill` | × |  |
> `pipe` | × | × |
> `mkfifo` | × |  |
> `open_process` | × |  | utilise l'interprète de commandes
> |  |  | `/bin/sh`
> `close_process` | × |  |

> Figure 18.1 : Portabilité des fonctions du module `Unix` utilisées dans ce chapitre

De plus la fonction `wait` d'attente de fin d'un processus fils n'est pas implantée car `fork` ne l'est pas.