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))))); 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;