Stephen Fry

"Education is the sum of what students teach each other in between lectures and seminars. " - Stephen Fry
Showing posts with label Unix error. Show all posts
Showing posts with label Unix error. Show all posts

Wednesday, 28 November 2012

System programming in OCaml - Part 1

This series of articles will follow my journey through "Unix system programming in OCaml", available as a pdf here. After this series, I hope to move onto a series on Mirage system programming in OCaml and working with Signposts (a framework for managing end-to-end connectivity between devices using DNS infrastructure for signalling)

Introducing the Sys and Unix

The modules that give access to the system in OCaml are:
  • Sys - functions common to all OS's that run OCaml
  • Unix - functions specific to unix
To make use of these modules in some OCaml code, we can add open Sys or/and open Unix to the top of the OCaml program.

NOTE that Unix and Sys can overwrite some of the functions in the Pervasive module, so to access a function from the Pervasive module you need to add Pervasives. in front of the function call.

When using ocamlc to compile OCaml programs that made use of  Unix, you need to pass unix.cma to the compiler e.g.

$ ocamlc unix.cma hello.ml -o hello

The same is not true of sys.cma

PASSING INFORMATION TO YOUR PROGRAM

Now we are going to consider 2 different ways of passing information from your terminal to your ocaml program

1) Passing the information as arguments to the executable. For this we are going to use Sys.argv which will return a string array of arguments passed to the program. The first index of the argument array that we use here is 1, this is because the 0th element in the array is the command used to call the program. Consider the following simple example:



open Sys;;
print_string argv.(1)
 

Now provided that at least one argument is passed to the program, this argument will be printed. We can now extend this program, to print the number of arguments and then exactly what the user will have just entered

open Sys;;

let args = Array.length argv;;
print_int args ;;
print_newline ();;
for i=0 to args-1 do
  print_string argv.(i);
  print_char ' ';
done;
2a ) Passing information using the environment variables, this can be fetched from within the OCaml programing using Sys.enviroment, this will return as array of environment variables

open Unix;;

let env = environment();;
for i=0 to (Array.length env) -1  do
 print_string env.(i);
 print_newline);
done;

Don't forget then when you compile this, you need to add unix.cma to the command as we are making use of the Unix library

2b ) We can also lookup the values of environment variables using the Sys.getenv (or Unix.getenv) functions that takes a variable name and returns the value associated with it

open Sys;;

let var = argv.(1);;
print_string (getenv var)

Exceptions

Unless otherwise stated in the documentation, all function in the Unix module raise the exception Unix_error.

Exception Unix_error of error * string * string

The first argument is the error code, the second argument is the name of the system call that raised the error and third argument identifies the object on which the error was called.

If an exception reaches the top-level then the program will halt. The Unix module provides a function for clearly describing exceptions. We can make 2a use this function as follows:

open Unix;;

let prog () = 

  let env = environment();;
   for i=0 to (Array.length env) -1  do
    print_string env.(i);
    print_newline);
   done;

 done;

 handle_unix_error prog ();;



Monday, 16 July 2012

Running the Ocaml Server - Demo Pt 1

-->
I've got some code here and here in OCaml & Java, that I have been tasked with running, testing and fixing. I've already taken a look at the basic syntax but now its time to get to grips with some the libraries and related packages that Signposts makes use off.

THE SERVER IN OCAML


The first thing that took me by surprise was the number of files in the repo, considering that this is suppose to be a fairly straight forward project.

Oasis


The repo contains a file called “_oasis”, which on closer inspection includes a collection of metadata on the project. OASIS is a tools to integrate a configure, build and install system into an OCaml project. The _oasis files tells me that the entry point for the program is “server.ml” and the build dependences are the findlib packages lwt.syntax, lwt.unix, re, re.str.

The creater of the program will have ran “oasis setup”, which has generated setup.ml, _tags and myocamlbiuld.ml.

According to the instructions for OASIS you can configure, build and install the Ocaml program using:

  • ocaml setup.ml -configure

  • ocaml setup.ml -build

  • ocaml setup.ml -install

Re_str

The server.ml file makes use of Re_str and two of the biuld dependences are the findlib packages re and re.str. I have found the packages here on github. Re stands for Regular expression and ocaml-re is a regular expression library doe Ocaml (that is still under development). This project has also made use of OASIS and installs without a problem

Compiling the Code

I cd into the directory and run ocaml setup.ml -configure, ocaml setup.ml -build and ocaml setup.ml -install. This generates a new dirctory “_biuld” and a new link to an executable in _biuld

Running the Code

I run a link to the execuated in _biuld and it return the following error:
Fatal error: exception Unix.Unix_error(50, "bind", "")

This means that the socked that the code is try to bind to is already in use. I inspected the code, identified the ports that were being used and ran “sudo netstat -ap | grep ':<portnumber>' “. This identified a process already using the port, the process was in fact an earlier attempt to run the project. I identified the process ID and killed the process, re-running “sudo netstat -ap | grep ':<portnumber>' “ showed that the port was now free. I can now happily run the executable in the _build directory. As this is a client-server implementation, I now need to move my attention to the client code