Created
May 23, 2010 07:27
-
-
Save doublec/410727 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| staload "libc/SATS/signal.sats" | |
| staload "libc/SATS/stdio.sats" | |
| staload "libc/SATS/unistd.sats" | |
| staload "libc/sys/SATS/wait.sats" | |
| staload "libc/sys/SATS/types.sats" | |
| staload "libc/sys/SATS/socket.sats" | |
| staload "libc/netinet/SATS/in.sats" | |
| staload "libc/arpa/SATS/inet.sats" | |
| staload "prelude/DATS/array0.dats" | |
| %{ | |
| ats_ptr_type fdopen_exn (ats_int_type id, ats_ptr_type mode) { | |
| FILE *fil = fdopen((int)id, (char*)mode) ; | |
| if (!fil) { | |
| perror ("fdopen") ; atspre_exit_prerrf ( | |
| 1, "exit(ATS): [fdopen(\"%d\", \"%s\")] failed\n", id, mode | |
| ) ; | |
| } | |
| return fil ; | |
| } | |
| %} | |
| extern fun fdopen_exn {m:fm} | |
| (id: int, m: file_mode m):<!exnref> FILEref | |
| = "fdopen_exn" | |
| fun fork_child {fd:int} (pf_sock: !socket_v(fd,listen) | fd:int fd, | |
| f: (!socket_v(fd,listen) | int fd,pid_t) -<fun1> void): pid_t = let | |
| val pid = fork_exn(); | |
| val ipid = int_of_pid(pid); | |
| in | |
| if ipid = 0 then begin | |
| f (pf_sock | fd, pid); | |
| exit(0); | |
| end else pid | |
| end; | |
| extern fun child {fd:int} (pf_sock: !socket_v(fd,listen) | fd: int fd, pid: pid_t):<fun1> void | |
| implement child {fd} (pf_sock | fd, pid) = let | |
| val ipid:int = int_of_pid(getpid()); | |
| val (pf_sock_c | client) = accept_null_exn(pf_sock | fd); | |
| val file = fdopen_exn(client, $extval (file_mode rw, "\"r+\"")); | |
| val () = fprintf(file, "Child %d echo> ", @(ipid)); | |
| val () = fflush_exn(file); | |
| val line = input_line(file); | |
| val () = assert_errmsg(stropt_is_some line, #LOCATION); | |
| val () = output_line(file, stropt_unsome(line)); | |
| val () = socket_close_exn(pf_sock_c | client); | |
| in | |
| child (pf_sock | fd, pid) | |
| end ; | |
| fun make_server_socket (port: int) : [fd:int] (socket_v(fd,listen) | int fd) = let | |
| val (pf_sock_s | sockfd) = socket_family_type_exn (AF_INET, SOCK_STREAM); | |
| var servaddr: sockaddr_in_struct_t; | |
| val servport = in_port_nbo_of_int (port); | |
| val in4addr = in_addr_nbo_of_hbo (INADDR_ANY); | |
| val () = sockaddr_ipv4_init (servaddr, AF_INET, in4addr, servport); | |
| val () = bind_ipv4_exn (pf_sock_s | sockfd, servaddr); | |
| val () = listen_exn (pf_sock_s | sockfd, 10); | |
| in | |
| (pf_sock_s | sockfd) | |
| end; | |
| implement main () = let | |
| val (pf_sock_s | sockfd) = make_server_socket (5000); | |
| val children = array0_make_arraysize($arrsz{pid_t} (fork_child(pf_sock_s | sockfd, child), | |
| fork_child(pf_sock_s | sockfd, child))); | |
| val () = array0_foreach(children, lam(pid) => $effmask_all(printf("Forked: %d\n", @(int_of_pid(pid))))); | |
| var status:int = 0; | |
| val () = array0_foreach(children, lam(pid) => let | |
| var status:int = 0; | |
| val p = $effmask_all(waitpid(pid, status, WNONE)) | |
| in | |
| () | |
| end); | |
| val () = socket_close_exn(pf_sock_s | sockfd); | |
| in | |
| () | |
| end; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment