Rewrote most of newlib_backend to be more "robust". Added sycall server to tree
authorPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 3 Sep 2009 19:48:04 +0000 (12:48 -0700)
committerPaul Pearce <pearce@eecs.berkeley.edu>
Thu, 3 Sep 2009 19:48:04 +0000 (12:48 -0700)
My first pass at newlib_backend was functional,  but ultimately not maintainable.
It was also not able to be annotated with Ivy, so I rewrote it with Ivy in mind.
The code is now much cleaner, shorter, and will be easier to annoate with Ivy.

Removed the inclusion of newlib_backend.h in parlib.h (not needed, casued errors).

Added a tools directory to the repo with the syscall server.

tools/syscall_server.c [new file with mode: 0644]
tools/syscall_server.h [new file with mode: 0644]
user/parlib/inc/newlib_backend.h
user/parlib/inc/parlib.h
user/parlib/src/i386/newlib_backend.c

diff --git a/tools/syscall_server.c b/tools/syscall_server.c
new file mode 100644 (file)
index 0000000..f584eb8
--- /dev/null
@@ -0,0 +1,656 @@
+#include "syscall_server.h"
+#include <sys/ioctl.h>
+#include <termios.h>
+
+/* Remote Syscall Server app. 
+   Written by Paul Pearce.
+   This is an UGLY HACK to avoid sockets to work with the 
+   ugly hack that is the current tesselaton udp wrapping.
+
+   If you search for the comment UDP you can see how to revert this back
+   to socket niceness.
+
+   Note: The server.h has a shared structure with the newlib_backend.h. These must be kept in sync
+         The only difference is Paul's GCC won't allow unions without names, so the 'subheader' name was added
+*/
+
+// UDP BRANCH
+#include <netdb.h>
+char udp_arr[4096];
+int udp_arr_size = 0;
+int udp_cur_pos = 0;
+// END UDP BRANCH
+
+// TODO: A syscall_id_t that says close the link, and deal with that in the main switch statement.
+int main()
+{
+       // Listen for connections.
+       int data_port = listen_for_connections();
+
+       // Once here, we are inside of new processes, setup the new port.
+       int data_fd = setup_data_connection(data_port);
+
+       // Begin processing data from the connection
+       process_connections(data_fd);
+}
+
+// Bind to LISTEN_PORT and listen for connections on the specified port.
+// If a client requests a connection, spawn off a new process, then continue.
+// In new process, return with the port we are going to listen for data on
+int listen_for_connections()
+{
+       //UDP BRANCH. Do nothing, as this is UDP
+       return -1;
+       // END UDP BRANCH
+
+       // Sockets
+       int listen_socket, data_socket;
+
+       // Address structures
+       struct sockaddr_in server_addr, client_addr;
+
+       // Self explanatory
+       int num_connections, response_msg;
+
+       // Size of our address structure
+       unsigned int addr_len = sizeof(struct sockaddr_in);
+
+       // Fork response for determining if child or parent
+       int child;
+
+       // Create socket
+       if ((listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+       {
+               printf("Error: Could not create socket.\n");
+               exit(1);
+       }
+
+       // Setup sockaddr_in
+       server_addr.sin_family = AF_INET;
+       server_addr.sin_port = htons(LISTEN_PORT);
+       server_addr.sin_addr.s_addr = INADDR_ANY;
+       bzero(&(server_addr.sin_zero), 8);      // This is apparently a source of bugs? Who knew.
+
+       // Bind to the given port.
+       if (bind(listen_socket, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)))
+       {
+               printf("Error: Could not bind to port: %i\n", LISTEN_PORT);
+               exit(1);
+       }
+
+       // Listen on the socket
+    if (listen(listen_socket, BACKLOG_LEN) < 0)
+    {
+       printf("Error: Could not listen on socket.\n");
+       exit(1);
+    }
+
+       printf("Server started.\n");
+
+       // Main loop to listen for connections.
+       while(1)
+       {
+               printf("Waiting for connections on port: %i\n", LISTEN_PORT);
+
+               if ((data_socket = accept(listen_socket, (struct sockaddr *)&client_addr,  &addr_len)) < 0)
+               {
+                       printf("Error: Could not accept a new connection.\n");
+               }
+
+               num_connections++;
+               response_msg = num_connections + LISTEN_PORT;
+
+               printf("New connection detected. Assigning port: %i\n", response_msg);
+               if (send(data_socket, (char*)(&response_msg), sizeof(int), 0) < 0)
+               {
+                       printf("Error: Could not send response. New client may not have received port. Continuing.\n");
+                       close(data_socket);
+                       continue;
+               }
+               close(data_socket);
+
+               // Spawn a new process for the connection and offload further communications to that process.
+               if ((child = fork()) == -1)
+               {
+                       printf("Error: Fork failed. Client responses will be ignored. Continuing.\n");
+                       continue;
+               }
+               else if (child)
+               {
+                       // Spawned Process, break out of loop for cleanup and initialization of the listen function.
+                       break;
+               }
+               else
+               {
+                       // Original Process
+                       // Nothing to do. Continue loop.
+               }
+       }
+
+       // Only reach here inside of new process, after spawning. Clean up.
+       close(listen_socket);
+
+       return response_msg;
+}
+
+
+// Perform socket setup on the new port
+int setup_data_connection(int port)
+{
+       // UDP BRANCH
+       port = 44444;
+       // END UDP BRANCH
+
+       // Sockets
+       int listen_socket, data_socket;
+
+       // Address structures
+       struct sockaddr_in server_addr, client_addr;
+
+       // Size of our address structure
+       unsigned int addr_len = sizeof(struct sockaddr_in);
+
+       // Create socket
+       // UDP BRANCH
+       // if ((listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
+       if ((listen_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+       {
+               printf("Error: Spawned Process, PORT: %i. Could not create socket.\n", port);
+               exit(1);
+       }
+
+       // Setup sockaddr_in
+       server_addr.sin_family = AF_INET;
+       server_addr.sin_port = htons(port);
+       server_addr.sin_addr.s_addr=INADDR_ANY;
+       bzero(&(server_addr.sin_zero), 8);      // This is apparently a source of bugs? Who knew.
+
+       // Bind to the given port.
+       if (bind(listen_socket, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)))
+       {
+               printf("Error: Spawned Process, PORT: %i. Could not bind to port.\n", port);
+               exit(1);
+       }
+
+       //UDP BRANCH
+       data_socket = listen_socket;
+
+       // UDP BRANCH COMMENTED
+       /*
+
+       // Listen on the socket
+    if (listen(listen_socket, BACKLOG_LEN) < 0)
+    {
+       printf("Error: Spawned Process, PORT: %i. Could not listen on socket.\n", port);
+       exit(1);
+    }
+
+       if ((data_socket = accept(listen_socket, (struct sockaddr *)&client_addr,  &addr_len)) < 0)
+       {
+               printf("Error:  Spawned Process, PORT: %i. Could not accept a new connection.\n", port);
+       }
+
+       */ // UDP BRANCH END COMMENT
+
+       printf("Spawned Process, PORT: %i. FD: %i. Established.\n", port, data_socket);
+
+       // END SOCKET SETUP
+
+       return data_socket;
+}
+
+// Poll for a message, return a pointer to message. Caller is required to manage memory of the buffer
+// Called by the server to get data
+void process_connections(int fd) {
+
+       // Variables for the fixed filds.
+       syscall_id_t id;
+
+       int just_read;
+       
+       msg_t temp_msg;
+
+       // TODO: Better msg cleanup on close. Channel cleanup in general
+       while(1)
+       {
+               // Read data from the socket.
+               // Peek == 1, thus if no data is avaiable, return. Else, wait until full syscall_id_t is avaiable
+               just_read = read_header_from_socket(&temp_msg, fd);
+
+               if (just_read == 0)
+               {
+                       //sleep(1);
+                       continue;
+               }
+               
+               id = temp_msg.id;
+
+               // If we couldnt read data, or the ID we got is bad, terminate process.
+               if ((just_read == -1) || (id < 0) || (id > NUM_CALLS))
+               {
+                       printf("error on id: %d\n", id);
+                       send_error(fd);
+
+                       return;
+               }
+
+               msg_t * msg = NULL;
+               response_t * return_msg = NULL;
+               int return_len = -1;
+
+               switch (id) {
+                       case OPEN_ID:
+                               msg = malloc(sizeof(msg_t) + temp_msg.subheader.open.len);
+                               if (msg == NULL) {
+                                       send_error(fd);
+                                       return;
+                               }
+                               
+                               *msg = temp_msg;
+                               just_read = read_buffer_from_socket(msg->subheader.open.buf, fd, msg->subheader.open.len);
+                               
+                               if (just_read != msg->subheader.open.len) {
+                                       free(msg);
+                                       send_error(fd);
+                                       return;
+                               }
+
+                               return_msg = handle_open(msg);
+                               free(msg);
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case CLOSE_ID:
+                               return_msg = handle_close(&temp_msg);
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case READ_ID:
+                               return_msg = handle_read(&temp_msg);
+                               if (return_msg != NULL)
+                                       return_len = sizeof(response_t) + ((return_msg->ret >= 0)  ? return_msg->ret : 0);
+                               break;
+
+                       case WRITE_ID:
+
+                               msg = malloc(sizeof(msg_t) + temp_msg.subheader.write.len);
+                               if (msg == NULL) {
+                                       send_error(fd);
+                                       return;
+                               }
+                               
+                               *msg = temp_msg;
+                               just_read = read_buffer_from_socket(msg->subheader.write.buf, fd, msg->subheader.write.len);
+
+                               if (just_read != msg->subheader.write.len) {
+                                       free(msg);
+                                       send_error(fd);
+                                       return;
+                               }
+
+                               return_msg = handle_write(msg);
+                               free(msg);
+
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case LSEEK_ID:
+
+                               return_msg = handle_lseek(&temp_msg);
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case ISATTY_ID:
+                               return_msg = handle_isatty(&temp_msg);
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case UNLINK_ID:
+                               msg = malloc(sizeof(msg_t) + temp_msg.subheader.unlink.len);
+                               if (msg == NULL) {
+                                       send_error(fd);
+                                       return;
+                               }
+                               
+                               *msg = temp_msg;
+                               just_read = read_buffer_from_socket(msg->subheader.unlink.buf, fd, msg->subheader.unlink.len);
+                               
+                               if (just_read != msg->subheader.unlink.len) {
+                                       free(msg);
+                                       send_error(fd);
+                                       return;
+                               }
+                       
+                               return_msg = handle_unlink(msg);
+                               free(msg);
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case LINK_ID:
+                       
+                               msg = malloc(sizeof(msg_t) + temp_msg.subheader.link.old_len + temp_msg.subheader.link.new_len);
+                               if (msg == NULL) {
+                                       send_error(fd);
+                                       return;
+                               }
+                               
+                               *msg = temp_msg;
+                               just_read = read_buffer_from_socket(msg->subheader.link.buf, fd, temp_msg.subheader.link.old_len + temp_msg.subheader.link.new_len);
+                               
+                               if (just_read != (temp_msg.subheader.link.old_len + temp_msg.subheader.link.new_len)) {
+                                       free(msg);
+                                       send_error(fd);
+                                       return;
+                               }
+                       
+                               return_msg = handle_link(msg);
+                               free(msg);
+                               return_len = sizeof(response_t);
+                               break;
+
+                       case FSTAT_ID:
+                               return_msg = handle_fstat(&temp_msg);
+                               return_len = sizeof(response_t);
+
+                               break;
+
+                       case STAT_ID:
+                               msg = malloc(sizeof(msg_t) + temp_msg.subheader.stat.len);
+                               if (msg == NULL) {
+                                       send_error(fd);
+                                       return;
+                               }
+                       
+                               *msg = temp_msg;
+                               just_read = read_buffer_from_socket(msg->subheader.stat.buf, fd, msg->subheader.stat.len);
+                       
+                               if (just_read != msg->subheader.stat.len) {
+                                       free(msg);
+                                       send_error(fd);
+                                       return;
+                               }
+
+                               return_msg = handle_stat(msg);
+                               free(msg);
+                               return_len = sizeof(response_t);
+
+                               break;
+                       default:
+                               send_error(fd);
+                               return;
+               }
+
+               if (return_msg == NULL)
+               {
+                       send_error(fd);
+                       return;
+               }
+
+               // UDP BRANCH. 
+               struct hostent *hp;
+               hp = gethostbyname("192.168.0.10");
+               struct sockaddr_in addr;
+               memset(&addr, 0, sizeof(addr));
+               addr.sin_family = AF_INET;
+               memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
+               addr.sin_port = htons(44443);
+               // END UDP BRANCH
+
+               if ( sendto(fd, return_msg, return_len, 0, (struct sockaddr *)&addr, sizeof(addr)) != return_len)
+               //if (write(fd, return_msg, return_len) != return_len)
+               {
+                       free(return_msg);
+                       // If we cant write to the socket, cant send CONNECTION_TERMINATED. Just die.
+                       printf("Error: Spawned Process, FD: %i. Could not send data out. Dying.\n", fd);
+                       return;
+               }
+
+               free(return_msg);
+       }
+}
+
+int read_header_from_socket(msg_t* msg, int socket) {
+       return read_from_socket((char*)msg, socket, sizeof(msg_t), PEEK);
+}
+
+int read_buffer_from_socket(char* buf, int socket, int len) {
+       return read_from_socket(buf, socket, len, NO_PEEK);
+}
+
+// UDP HACK VERSION
+// Read len bytes from the given socket to the buffer.
+// If peek is NO_PEEK, will wait indefinitely until that much data is read.
+// If peek is PEEK, if no data is available, will return immediately.
+//             However once some data is available, it will block until the entire amount is available.
+// Return values are:
+// -1 if error
+// 0 if peek and nothing avaiable
+// else len
+int read_from_socket(char* buf, int socket, int len, int peek) {
+
+       // This function is now super hacked to deal with UDP uglyness. Do not use this to revert once we get tcpip online!
+
+       int total_read = 0;
+
+       if (udp_arr_size == 0) {
+               udp_arr_size = recvfrom(socket, udp_arr, 4096, 0, 0, 0);
+
+               if (udp_arr_size == 0)
+                       return -1;
+       }
+
+       if ((udp_cur_pos + len) > udp_arr_size)
+               return -1;
+
+       memcpy(buf, udp_arr + udp_cur_pos, len);
+
+       udp_cur_pos = udp_cur_pos + len;
+
+       if (udp_cur_pos == udp_arr_size) {
+               udp_cur_pos = 0;
+               udp_arr_size = 0;
+       }
+
+       return len;
+
+       // UDP BRANCH
+       //int just_read = read(socket, buf, len);
+       int just_read = recvfrom(socket, buf, len, 0, 0, 0);
+
+       if (just_read < 0) return just_read;
+       if (just_read == 0 && peek) return just_read;
+
+       total_read += just_read;
+
+       while (total_read != len) {
+               // UDP BRANCH
+               //just_read = read(socket, buf + total_read, len - total_read);
+               just_read = recvfrom(socket, buf + total_read, len - total_read, 0, 0, 0);
+
+               if (just_read == -1) return -1;
+
+               total_read += just_read;
+       }
+
+       return total_read;
+}
+
+// Non hacky UDP version
+/*
+int read_from_socket(char* buf, int socket, int len, int peek) {
+        int total_read = 0;
+        //printf("\t\treading %i bytes on socket %i with peek %i\n", len, socket, peek);
+        int just_read = read(socket, buf, len);
+        //printf("\t\tread    %i bytes on socket %i with peek %i\n", just_read, socket, peek);
+                                        
+        if (just_read < 0) return just_read;
+        if (just_read == 0 && peek) return just_read;
+                                
+        total_read += just_read;
+                                
+        while (total_read != len) {
+                just_read = read(socket, buf + total_read, len - total_read);
+                if (just_read == -1) return -1;
+                total_read += just_read;
+        }                       
+                
+        return total_read;
+}*/
+
+
+// Send CONNECTION_TERMINATED over the FD (if possible)
+// Not fully functional.
+void send_error(int fd)
+{
+       printf("Error: Spawned Process, FD: %i. Could not read from from socket. Sending CONNECTION_TERMINATED.... ", fd);
+
+       int error_msg = CONNECTION_TERMINATED;
+
+       /*if (write(fd, (char*)(&error_msg) , sizeof(int)) != sizeof(int))
+       {
+               printf("Could not send CONNECTION_TERMINATED.\n");
+       }
+       else
+       {
+               printf("Sent.\n");
+
+       }*/
+
+       close(fd);
+}
+
+
+response_t* handle_open(msg_t *msg)
+{
+       printf("opening: %s\n", msg->subheader.open.buf);
+       
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+
+       response->ret = open(msg->subheader.open.buf, msg->subheader.open.flags, msg->subheader.open.mode);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_close(msg_t *msg)
+{              
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+
+       response->ret = close(msg->subheader.close.fd);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_read(msg_t * msg) 
+{      
+       response_t * response = malloc(sizeof(response_t) + msg->subheader.read.len);
+       if (response == NULL) return NULL;
+
+       response->ret = read(msg->subheader.read.fd, response->buf, msg->subheader.read.len);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_write(msg_t * msg) 
+{
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+       response->ret = write(msg->subheader.write.fd, msg->subheader.write.buf, msg->subheader.write.len);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_lseek(msg_t * msg)
+{
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+       response->ret = lseek(msg->subheader.lseek.fd, msg->subheader.lseek.ptr, msg->subheader.lseek.dir);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+}
+
+response_t* handle_isatty(msg_t * msg) 
+{
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+       
+       response->ret = isatty(msg->subheader.isatty.fd);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_unlink(msg_t * msg)
+{
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+
+       response->ret = unlink(msg->subheader.unlink.buf);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_link(msg_t * msg) 
+{
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+
+       response->ret = link(msg->subheader.link.buf, msg->subheader.link.buf + msg->subheader.link.old_len);
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_stat(msg_t * msg) {
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+
+       response->ret = stat(msg->subheader.stat.buf, &(response->st));
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
+
+response_t* handle_fstat(msg_t *msg) {
+       
+       response_t * response = malloc(sizeof(response_t));
+       if (response == NULL) return NULL;
+
+       response->ret = fstat(msg->subheader.fstat.fd, &(response->st));
+       
+       if (response->ret == -1) {
+               response->err = errno;
+       }
+
+       return response;
+}
diff --git a/tools/syscall_server.h b/tools/syscall_server.h
new file mode 100644 (file)
index 0000000..7ff316e
--- /dev/null
@@ -0,0 +1,157 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+// Todo: review the laundry list of includes.
+
+// Backlog for the listen() call.
+#define BACKLOG_LEN 16
+
+#define LISTEN_PORT 12345
+#define SERVER_IP "128.32.35.43"
+
+#define OPEN_ID                0
+#define CLOSE_ID       1
+#define READ_ID                2
+#define WRITE_ID       3
+#define LINK_ID                4
+#define UNLINK_ID      5
+#define LSEEK_ID       6
+#define FSTAT_ID       7
+#define ISATTY_ID      8
+#define STAT_ID                9
+#define NUM_CALLS      10
+
+// New errno we want to define if a channel error occurs
+// Not yet fully implimented
+#define ECHANNEL -999
+
+// Value to send across the channel as a function return value in the event of server side termination
+// Note yet fully implimented
+#define CONNECTION_TERMINATED -2
+
+// Macros for the read_from_channel function
+#define PEEK    1
+#define NO_PEEK 0
+
+// Should refactor this next typedef. Just leave it as type int.
+typedef int syscall_id_t;
+
+// ALL STRUCTS MUST BE PADDED TO THE SAME SIZE.
+// Basically, to make IVY annotation possible with as few TC's as possible
+// We do some ugly things with unions, which results in us needing this padding
+typedef struct open_subheader {
+       uint32_t flags;
+       uint32_t mode;
+       uint32_t len;
+       char buf[0];
+} open_subheader_t;
+
+typedef struct close_subheader {
+       uint32_t fd;
+       uint32_t FILL1;
+       uint32_t FILL2;
+} close_subheader_t;
+
+typedef struct read_subheader {
+       uint32_t fd;
+       uint32_t len;
+       uint32_t FILL1;
+} read_subheader_t;
+
+typedef struct write_subheader {
+       uint32_t fd;
+       uint32_t len;
+       uint32_t FILL1;
+       char buf[0];
+} write_subheader_t;
+
+typedef struct lseek_subheader {
+       uint32_t fd;
+       uint32_t ptr;
+       uint32_t dir;
+} lseek_subheader_t;
+
+typedef struct isatty_subheader {
+       uint32_t fd;
+       uint32_t FILL1;
+       uint32_t FILL2;
+} isatty_subheader_t;
+
+typedef struct link_subheader {
+       uint32_t old_len;
+       uint32_t new_len;
+       uint32_t FILL1;
+       char buf[0];
+} link_subheader_t;
+
+typedef struct unlink_subheader {
+       uint32_t len;
+       uint32_t FILL1;
+       uint32_t FILL2;
+       char buf[0];
+} unlink_subheader_t;
+
+typedef struct fstat_subheader {
+       uint32_t fd;
+       uint32_t FILL1;
+       uint32_t FILL2;
+} fstat_subheader_t;
+
+typedef struct stat_subheader {
+       uint32_t len;
+       uint32_t FILL1;
+       uint32_t FILL2;
+       char buf[0];
+} stat_subheader_t;
+
+typedef struct backend_msg {
+       syscall_id_t id;
+       union {
+               open_subheader_t open;
+               close_subheader_t close;
+               read_subheader_t read;
+               write_subheader_t write;
+               lseek_subheader_t lseek;
+               isatty_subheader_t isatty;
+               link_subheader_t link;
+               unlink_subheader_t unlink;
+               fstat_subheader_t fstat;
+               stat_subheader_t stat;  
+       } subheader;
+} msg_t;
+
+typedef struct response {
+       int32_t ret;
+       uint32_t err;
+       struct stat st;
+       char buf[0];
+} response_t;
+
+#undef errno
+extern int errno;
+
+response_t* handle_open(msg_t * msg);
+response_t* handle_close(msg_t * msg);
+response_t* handle_read(msg_t * msg);
+response_t* handle_write(msg_t * msg);
+response_t* handle_lseek(msg_t * msg);
+response_t* handle_isatty(msg_t * msg);
+response_t* handle_unlink(msg_t * msg);
+response_t* handle_link(msg_t * msg);
+response_t* handle_stat(msg_t * msg);
+response_t* handle_fstat(msg_t * msg);
+
+int listen_for_connections();
+int setup_data_connection(int data_port);
+void process_connections(int fd);
+int read_from_socket(char* buf, int socket, int len, int peek);
+int read_header_from_socket(msg_t* msg, int socket);
+int read_buffer_from_socket(char* buf, int socket, int len);
+void send_error(int fd);
index 868c0fe..0dea51e 100644 (file)
 #define STAT_ID                9
 #define NUM_CALLS      10
 
+#define debug_in_out(...) // debug(__VA_ARGS__)  
+#define debug_write_check(fmt, ...)  //debug(fmt, __VA_ARGS__)
+
+typedef uint32_t syscall_id_t;
+
+// ALL STRUCTS MUST BE PADDED TO THE SAME SIZE.
+// Basically, to make IVY annotation possible with as few TC's as possible
+// We do some ugly things with unions, which results in us needing this padding
+typedef struct open_subheader {
+       uint32_t flags;
+       uint32_t mode;
+       uint32_t len;
+       char buf[0];
+} open_subheader_t;
+
+typedef struct close_subheader {
+       uint32_t fd;
+       uint32_t FILL1;
+       uint32_t FILL2;
+} close_subheader_t;
+
+typedef struct read_subheader {
+       uint32_t fd;
+       uint32_t len;
+       uint32_t FILL1;
+} read_subheader_t;
+
+typedef struct write_subheader {
+       uint32_t fd;
+       uint32_t len;
+       uint32_t FILL1;
+       char buf[0];
+} write_subheader_t;
+
+typedef struct lseek_subheader {
+       uint32_t fd;
+       uint32_t ptr;
+       uint32_t dir;
+} lseek_subheader_t;
+
+typedef struct isatty_subheader {
+       uint32_t fd;
+       uint32_t FILL1;
+       uint32_t FILL2;
+} isatty_subheader_t;
+
+typedef struct link_subheader {
+       uint32_t old_len;
+       uint32_t new_len;
+       uint32_t FILL1;
+       char buf[0];
+} link_subheader_t;
+
+typedef struct unlink_subheader {
+       uint32_t len;
+       uint32_t FILL1;
+       uint32_t FILL2;
+       char buf[0];
+} unlink_subheader_t;
+
+typedef struct fstat_subheader {
+       uint32_t fd;
+       uint32_t FILL1;
+       uint32_t FILL2;
+} fstat_subheader_t;
+
+typedef struct stat_subheader {
+       uint32_t len;
+       uint32_t FILL1;
+       uint32_t FILL2;
+       char buf[0];
+} stat_subheader_t;
+
+typedef struct backend_msg {
+       syscall_id_t id;
+       union {
+               open_subheader_t open;
+               close_subheader_t close;
+               read_subheader_t read;
+               write_subheader_t write;
+               lseek_subheader_t lseek;
+               isatty_subheader_t isatty;
+               link_subheader_t link;
+               unlink_subheader_t unlink;
+               fstat_subheader_t fstat;
+               stat_subheader_t stat;  
+       };
+} msg_t;
+
+typedef struct response {
+       int32_t ret;
+       uint32_t err;
+       struct stat st;
+       char buf[0];
+} response_t;
 
-// Fixed size of the client->server msgs for the various calls.
-#define OPEN_MESSAGE_FIXED_SIZE       sizeof(syscall_id_t) + 3*sizeof(int)
-#define CLOSE_MESSAGE_FIXED_SIZE      sizeof(syscall_id_t) + sizeof(int)
-#define READ_MESSAGE_FIXED_SIZE       sizeof(syscall_id_t) + 2*sizeof(int)
-#define WRITE_MESSAGE_FIXED_SIZE      sizeof(syscall_id_t) + 2*sizeof(int)
-#define LSEEK_MESSAGE_FIXED_SIZE      sizeof(syscall_id_t) + 3*sizeof(int)
-#define ISATTY_MESSAGE_FIXED_SIZE     sizeof(syscall_id_t) + sizeof(int)
-#define LINK_MESSAGE_FIXED_SIZE       sizeof(syscall_id_t) + 2*sizeof(int)
-#define UNLINK_MESSAGE_FIXED_SIZE     sizeof(syscall_id_t) + sizeof(int)
-#define FSTAT_MESSAGE_FIXED_SIZE      sizeof(syscall_id_t) + sizeof(int)
-#define STAT_MESSAGE_FIXED_SIZE       sizeof(syscall_id_t) + sizeof(int)
-
-// What is the max number of arguments (besides the syscall_id_t) we can have.
-// This should be the max of the above sizes.
-// This exists so we can  allocate a fixed amount of memory to process all incoming msgs
-// TODO: This makes the implicit assumption when referenced in server.c that each argument is of type int.
-//             If we change the above defs to no longer be sizeof(int) this will break in server.c
-#define MAX_FIXED_ARG_COUNT 3
 
 // New errno we want to define if a channel error occurs
 // Not yet fully implimented
 #define PEEK    1
 #define NO_PEEK 0
 
-typedef uint32_t syscall_id_t;
 
 /* Read len bytes from the given channel to the buffer.
  * If peek is NO_PEEK, will wait indefinitely until that much data is read.
@@ -61,11 +137,15 @@ typedef uint32_t syscall_id_t;
  */
 int read_from_channel(char * buf, int len, int peek);
 
+int read_response_from_channel(response_t *response);
+int read_buffer_from_channel(char *buf, int len);
+
+
 /* send_message()
  * Write the message defined in buffer out across the channel, and wait for a response.
  * Caller is responsible for management of both the buffer passed in and the buffer ptr returned.
  */
-char *send_message(char *message, int len);
+response_t *send_message(msg_t *msg, int len);
 
 /* write_to_channel()
  * Send a message out over the channel, defined by msg, of length len
index efc89cc..7d1a193 100644 (file)
@@ -12,7 +12,7 @@
 #include <ros/syscall.h>
 #include <ros/error.h>
 #include <ros/procdata.h>
-#include <newlib_backend.h>
+#include <errno.h>
 
 enum {
        PG_RDONLY = 4,
index ddc6267..893a38d 100644 (file)
@@ -1,5 +1,15 @@
 /* See COPYRIGHT for copyright information. */
-/* Kevin Klues <klueska@cs.berkeley.edu>       */
+
+/** @file
+ * @brief Backend file for newlib functionality
+ *
+ * This file is responsible for defining the syscalls needed by newlib to 
+ * impliment the newlib library
+ * *
+ * @author Paul Pearce <pearce@eecs.berkeley.edu>
+ * @author Kevin Klues <klueska@cs.berkeley.edu>
+ *
+ */
 
 #ifdef __DEPUTY__
 #pragma nodeputy
@@ -14,9 +24,6 @@
 #include <stdio.h>
 #include <debug.h>
 
-#define debug_in_out(...)  //debug(__VA_ARGS__)  
-#define debug_write_check(fmt, ...) // debug(fmt, __VA_ARGS__)
-
 /* environ
  * A pointer to a list of environment variables and their values. 
  * For a minimal environment, this empty list is adequate.
@@ -47,35 +54,28 @@ int close(int file) {
                return 0;
 
        // Allocate a new buffer of proper size
-       char *out_msg = malloc(CLOSE_MESSAGE_FIXED_SIZE);
-       if (out_msg == NULL)
+       msg_t *msg = malloc(sizeof(msg_t));
+       if (msg == NULL)
                return -1;
-
-       char *out_msg_pos = out_msg;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = CLOSE_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = file;
-       out_msg_pos += sizeof(int);
-
-
+       
+       msg->id = CLOSE_ID;
+       msg->close.fd = file;
+       
        // Send message
-       char *result = send_message(out_msg, CLOSE_MESSAGE_FIXED_SIZE);
+       response_t *result = send_message(msg, sizeof(msg_t));
 
-       free(out_msg);
+       free(msg);
 
        int return_val;
 
-       if (result != NULL) {
-               // Read result
-               return_val = *((int *) result);
-               if (return_val == -1) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
+       } else {
+               // Read result
+               return_val = result->ret;
+               if (return_val == -1) errno = result->err;
+               free(result);
        }
        
        return return_val;
@@ -108,53 +108,51 @@ int fork(void)
  * Status of an open file. 
  * For consistency with other minimal implementations in these stubs, 
  * all files are regarded as character special devices. 
- * The sys/stat.h header file required is distributed in the include 
+ * The sys/stat.h msg file required is distributed in the include 
  * subdirectory for the newlib C library.
  */
 int fstat(int file, struct stat *st) 
 {
        debug_in_out("FSTAT\n");        
 
-       st->st_mode = S_IFCHR;
+       // Kevin added this. I believe its needed for the serial branch
+       // Not used with the stdout hack. Review for removing stdout hack.
+       //st->st_mode = S_IFCHR;
        
        // stdout hack
-       if (file == 1)
+       if (file == 1) {
                st->st_mode = 8592;
-       return 0;
+               return 0;
+       }
 
 
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(FSTAT_MESSAGE_FIXED_SIZE);
-       if(out_msg == NULL)
+       // Allocate a new buffer of proper size 
+       msg_t *msg = malloc(sizeof(msg_t));
+       if (msg == NULL)
                return -1;
-       char *out_msg_pos = out_msg;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = FSTAT_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = file;
-       out_msg_pos += sizeof(int);
+       
+       msg->id = FSTAT_ID;
+       msg->fstat.fd = file;
 
        // Send message
-       char *result = send_message(out_msg, FSTAT_MESSAGE_FIXED_SIZE);
+       response_t *result = send_message(msg, sizeof(msg_t));
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
+       if (result == NULL) {
+               errno = ECHANNEL;
+               return_val = -1;
+       } else {
+               return_val = result->ret;
                if (return_val == -1)
-                       errno = *(((char *)result) + 
-                                       sizeof(int) + sizeof(struct stat));
+                       errno = result->err;
                else
-                       memcpy(st, ((int *)result) + 1, sizeof(struct stat));
+                       memcpy(st, (&result->st), sizeof(struct stat));
+                       
                free(result);
-       } else {
-               errno = ECHANNEL;
-               return_val = -1;
        }
 
        return return_val;
@@ -184,37 +182,32 @@ int isatty(int file)
        if ((STDIN_FILENO == file) || (STDOUT_FILENO == file) 
                                || (STDERR_FILENO == file))
                return 1;
-
        
        // Allocate a new buffer of proper size
-       char *out_msg = malloc(ISATTY_MESSAGE_FIXED_SIZE);
-       if(out_msg == NULL)
+       msg_t *msg = malloc(sizeof(msg_t));
+       if (msg == NULL)
                return -1;
-       char *out_msg_pos = out_msg;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = ISATTY_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = file;
-       out_msg_pos += sizeof(int);
+       
+       msg->id = ISATTY_ID;
+       msg->isatty.fd = file;
 
        // Send message
-       char *result = send_message(out_msg, ISATTY_MESSAGE_FIXED_SIZE);
+       response_t *result = send_message(msg, sizeof(msg_t));
 
-       free(out_msg);
+       free(msg);
 
-       int return_val;
+       int return_val; 
 
-       if (result != NULL) {
-               // Read result
-               return_val = *((int *) result);
-               if (return_val == 0) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       // Note: Ret val of 0 defined to be an error, not < 0. Go figure.
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = 0;
-       }
+       } else {
+               // Read result
+               return_val = result->ret;
+               if (return_val == 0) errno = result->err;
+               free(result);
+       } 
        
        return return_val;
 }
@@ -241,45 +234,32 @@ int link(char *old, char *new)
        int s_len_old = strlen(old) + 1; // Null terminator
        int s_len_new = strlen(new) + 1; // Null terminator
 
-       int out_msg_len = LINK_MESSAGE_FIXED_SIZE + s_len_old + s_len_new;
-
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(out_msg_len);
-       char *out_msg_pos = out_msg;
-
-       if (out_msg == NULL)
+       msg_t *msg = malloc(sizeof(msg_t) + s_len_old + s_len_new);
+       if (msg == NULL)
                return -1;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = LINK_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = s_len_old;
-       out_msg_pos += sizeof(int);
-
-       *((int*)out_msg_pos) = s_len_new;
-       out_msg_pos += sizeof(int);
-
-       memcpy(out_msg_pos, old, s_len_old);
-       out_msg_pos += s_len_old;
-
-       memcpy(out_msg_pos, new, s_len_new);
+       
+       msg->id = LINK_ID;
+       msg->link.old_len = s_len_old;
+       msg->link.new_len = s_len_new;
+       
+       memcpy(msg->link.buf, old, s_len_old);
+       memcpy(msg->link.buf + s_len_old, new, s_len_new);
 
        // Send message
-       char *result = send_message(out_msg, out_msg_len);
+       response_t *result = send_message(msg, sizeof(msg_t) + s_len_old + s_len_new);
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
-               if (return_val == -1) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
+       } else {
+               return_val = result->ret;
+               if (return_val == -1) errno = result->err;
+               free(result);
        }
 
        return return_val;
@@ -293,40 +273,31 @@ off_t lseek(int file, off_t ptr, int dir)
 {
        debug_in_out("LSEEK\n");        
        
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(LSEEK_MESSAGE_FIXED_SIZE);
-       if(out_msg == NULL)
+       // Allocate a new buffer of proper size and pack
+       msg_t *msg = malloc(sizeof(msg_t));
+       if (msg == NULL)
                return -1;
-       char *out_msg_pos = out_msg;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = LSEEK_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = file;
-       out_msg_pos += sizeof(int);
-
-       *((int*)out_msg_pos) = ptr;
-       out_msg_pos += sizeof(int);
-
-       *((int*)out_msg_pos) = dir;
-       out_msg_pos += sizeof(int);
+       
+       msg->id = LSEEK_ID;
+       msg->lseek.fd = file;
+       msg->lseek.ptr = ptr;
+       msg->lseek.dir = dir;
 
        // Send message
-       char *result = send_message(out_msg, LSEEK_MESSAGE_FIXED_SIZE);
+       response_t *result = send_message(msg, sizeof(msg_t));
 
-       free(out_msg);
+       free(msg);
 
        int return_val;
 
-       if (result != NULL) {
-               // Read result
-               return_val = *((int *) result);
-               if (return_val == -1) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
+       } else {
+               // Read result
+               return_val = result->ret;
+               if (return_val == -1) errno = result->err;
+               free(result);
        }
 
        return return_val;
@@ -340,46 +311,34 @@ int open(const char *name, int flags, int mode)
        debug_in_out("OPEN\n");
 
        int s_len = strlen(name) + 1; // Null terminator
-       int out_msg_len = OPEN_MESSAGE_FIXED_SIZE + s_len;
-
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(out_msg_len);
-       char *out_msg_pos = out_msg;
 
-       if (out_msg == NULL)
+       msg_t *msg = malloc(sizeof(msg_t) + s_len);
+       if (msg == NULL)
                return -1;
 
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = OPEN_ID;
-       out_msg_pos += sizeof(syscall_id_t);
+       msg->id = OPEN_ID;
+       msg->open.flags = flags;
+       msg->open.mode = mode;
+       msg->open.len = s_len;
 
-       *((int*)out_msg_pos) = flags;
-       out_msg_pos += sizeof(int);
-
-       *((int*)out_msg_pos) = mode;
-       out_msg_pos += sizeof(int);
-
-       *((int*)out_msg_pos) = s_len;
-       out_msg_pos += sizeof(int);
-
-       memcpy(out_msg_pos, name, s_len);
+       memcpy(msg->open.buf, name, s_len);
 
        // Send message
-       char *result = send_message(out_msg, out_msg_len);
+       response_t *result = send_message(msg, sizeof(msg_t) + s_len);
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
-               if (return_val == -1) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
-       }
+       } else {
+               return_val = result->ret;
+               if (return_val == -1) errno = result->err;
+               free(result);
+       } 
 
        return return_val;
 }
@@ -391,48 +350,41 @@ ssize_t read(int file, void *ptr, size_t len)
 {
        debug_in_out("READ\n");
 
+       // Console hack.
        if (file == STDIN_FILENO) {
                for(int i=0; i<len; i++)        
                        ((uint8_t*)ptr)[i] = sys_cgetc();
                return len;
        }
 
-       // Allocate a new buffer of proper size
-       char *out_msg = (char*)malloc(READ_MESSAGE_FIXED_SIZE);
-       if (out_msg == NULL)
+       // Allocate a new buffer of proper size and pack
+       msg_t *msg = malloc(sizeof(msg_t));
+       if (msg == NULL)
                return -1;
-
-       char *out_msg_pos = out_msg;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = READ_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int *)out_msg_pos) = file;
-       out_msg_pos += sizeof(int);
-
-       *((int *)out_msg_pos) = len;
-       out_msg_pos += sizeof(int);
-
+       
+       msg->id = READ_ID;
+       msg->read.fd = file;
+       msg->read.len = len;
+       
        // Send message
-       char *result = send_message(out_msg, READ_MESSAGE_FIXED_SIZE);
+       response_t *result = send_message(msg, sizeof(msg_t));
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
-               if (return_val > 0)
-                       memcpy(ptr, ((int *)result) + 1, return_val);
-               else 
-                       errno = *(((int *)result) + 1);
-
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
+       } else {
+               return_val = result->ret;
+               if (return_val < 0)
+                       errno = result->err;
+               else
+                       memcpy(ptr, result->buf, return_val);
+
+               free(result);
        }
 
        return return_val;
@@ -470,6 +422,20 @@ int read_from_channel(char * buf, int len, int peek)
        return total_read;
 }
 
+int read_response_from_channel(response_t *response) 
+{
+       return read_from_channel(       (char*) response, 
+                                                       sizeof(response_t), 
+                                                               NO_PEEK);
+}
+
+int read_buffer_from_channel(char *buf, int len) 
+{
+       return read_from_channel(       buf, 
+                                                       len, 
+                                                               NO_PEEK);
+}
+
 /* sbrk()
  * Increase program data space. 
  * As malloc and related functions depend on this, it is 
@@ -504,106 +470,54 @@ void* sbrk(ptrdiff_t incr)
  * Write the message in buffer out on the channel, and wait for a response.
  * Caller is responsible for management of buffer passed in and buffer returned.
  */
-char *send_message(char *message, int len)
+response_t *send_message(msg_t *msg, int len)
 {
-       syscall_id_t this_call_id = *((syscall_id_t*)message);
+       syscall_id_t this_call_id = msg->id;
 
-       if (write_to_channel(message, len) != len)
+       if (write_to_channel(msg, len) != len)
                return NULL;
 
-       int response_value;
+       int ret_value, buffer_size;
+       
+       response_t temp_response;
+       response_t *return_response = NULL;
 
        // Pull the response from the server out of the channel.
-       if (read_from_channel( (char*)&response_value, 
-                               sizeof(int), 
-                               NO_PEEK) == -1) 
+       if (read_response_from_channel( &temp_response ) == -1) 
                return NULL;
 
-       char* return_msg = NULL;
-       char* errno_pos = NULL;
-       int extra_space = (response_value == -1) ? sizeof(int) : 0;
-
-       // TODO: Make these sizes an array we index into, and only have this code once.
-       // TODO: Will have a flag that tells us we have a variable length response (right now only for read case)
-       // TODO: Default clause with error handling.
-       switch (this_call_id) {
-               case ISATTY_ID:
-                       // This case must be at the top! Else extra space will be wrong at times 
-                       // ISATTY is special, 0 signifies error, not -1. Annoying.
-                       extra_space = (response_value == 0) ? sizeof(int) : 0;
-               case OPEN_ID:           
-               case CLOSE_ID:
-               case WRITE_ID:  
-               case LSEEK_ID:
-               case UNLINK_ID:
-               case LINK_ID:
-                        return_msg = (char*)malloc(sizeof(int) + extra_space);
-                       if (return_msg == NULL)
-                                return NULL;
-
-                       errno_pos = return_msg + sizeof(int);
-                        if (extra_space && (-1 == read_from_channel(errno_pos,
-                                                                    sizeof(int), 
-                                                                    NO_PEEK))) {
-                               free(return_msg);
-                                return NULL;
-                       }
-
-                        break;
-
-                case STAT_ID:
-               case FSTAT_ID:
-                       return_msg = (char*)malloc(sizeof(int) 
-                                                    + sizeof(struct stat)
-                                                    + extra_space);
-                        if (return_msg == NULL)
-                                return NULL;
-
-                       if (-1 == read_from_channel(return_msg + sizeof(int),
-                                                    sizeof(struct stat), 
-                                                    NO_PEEK)) {
-                               free(return_msg);
-                                return NULL;
-                       }
-
-                        errno_pos = return_msg + sizeof(int) 
-                                               + sizeof(struct stat);
-
-                        if (extra_space && (-1 == read_from_channel(errno_pos,
-                                                                    sizeof(int), 
-                                                                    NO_PEEK))) {
-                               free(return_msg);
-                               return NULL;
-                       }
-
-                       break;
-               
-               case READ_ID:
-                       if (response_value > 0)
-                               extra_space = response_value;
-                       else
-                               extra_space = extra_space;
-
-                       return_msg = (char*)malloc(sizeof(int) + extra_space);
-
-                       if (return_msg == NULL)
-                               return NULL;
-
-                       if (-1 == read_from_channel(return_msg + sizeof(int),
-                                                    extra_space,
-                                                    NO_PEEK)) {
-                                free(return_msg);
-                                return NULL;
-                        }
+       ret_value = temp_response.ret;
+       
+       char* buffer = NULL;
 
-                       break;
+       if (this_call_id == READ_ID) 
+       {
+               if (ret_value < 0)
+                       buffer_size = 0;
+               else
+                       buffer_size = ret_value;
+                       
+               return_response = malloc(sizeof(response_t) + buffer_size);
 
+               if (return_response == NULL)
+                       return NULL;
+               
+               if (read_buffer_from_channel(return_response->buf, buffer_size) == -1)
+                       return NULL;
+
+       } 
+       else 
+       {
+                       
+               return_response = malloc(sizeof(response_t));
+               
+               if (return_response == NULL)
+                       return NULL;
        }
 
-       // Copy response value in place
-       memcpy(return_msg, &response_value, sizeof(int));
+       *return_response = temp_response;
 
-       return return_msg;
+       return return_response;
 }
 
 
@@ -616,46 +530,38 @@ int stat(char *file, struct stat *st)
        debug_in_out("STAT\n");
        
        int s_len = strlen(file) + 1; // Null terminator
-       int out_msg_len = STAT_MESSAGE_FIXED_SIZE + s_len;
-
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(out_msg_len);
-       char *out_msg_pos = out_msg;
 
-       if (out_msg == NULL)
+       // Allocate a new buffer of proper size and pack
+       msg_t *msg = malloc(sizeof(msg_t) + s_len);
+       if (msg == NULL)
                return -1;
+       
+       msg->id = STAT_ID;
+       msg->stat.len = s_len;
 
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = STAT_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = s_len;
-       out_msg_pos += sizeof(int);
-
-       memcpy(out_msg_pos, file, s_len);
+       memcpy(msg->stat.buf, file, s_len);
 
        // Send message
-       char *result = send_message(out_msg, out_msg_len);
+       response_t *result = send_message(msg, sizeof(msg_t) + s_len);
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
+       if (result == NULL) {
+               errno = ECHANNEL;
+               return_val = -1;
+       } else {
+               return_val = result->ret;
 
                if (return_val == -1)
-                       errno = *(((char *)result) + sizeof(int) 
-                                                   + sizeof(struct stat));
+                       errno = result->err;
                else
-                       memcpy(st, ((int *)result) + 1, sizeof(struct stat));
+                       memcpy(st, &(result->st), sizeof(struct stat));
 
                free(result);
 
-       } else {
-               errno = ECHANNEL;
-               return_val = -1;
        }
 
        return return_val;
@@ -680,40 +586,34 @@ int unlink(char *name)
        debug_in_out("UNLINK\n");
        
        int s_len = strlen(name) + 1; // Null terminator
-       int out_msg_len = UNLINK_MESSAGE_FIXED_SIZE + s_len;
 
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(out_msg_len);
-       char *out_msg_pos = out_msg;
-
-       if (out_msg == NULL)
+       // Allocate a new buffer of proper size and pack
+       msg_t *msg = malloc(sizeof(msg_t) + s_len);
+       if (msg == NULL)
                return -1;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = UNLINK_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = s_len;
-       out_msg_pos += sizeof(int);
-
-       memcpy(out_msg_pos, name, s_len);
+       
+       msg->id = UNLINK_ID;
+       msg->unlink.len = s_len;
+       
+       memcpy(msg->unlink.buf, name, s_len);
 
        // Send message
-       char *result = send_message(out_msg, out_msg_len);
+       response_t *result = send_message(msg, sizeof(msg_t) + s_len);
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
-               if (return_val == -1) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
-       }
+       } else {
+               return_val = result->ret;
+               if (return_val == -1) errno = result->err;
+               free(result);
+       } 
+       
        return return_val;
 }
 
@@ -742,40 +642,33 @@ ssize_t write(int file, void *ptr, size_t len) {
                                    || (file == STDOUT_FILENO))
                return sys_cputs(ptr, len);
        
-       int out_msg_len = WRITE_MESSAGE_FIXED_SIZE + len;
-
-       // Allocate a new buffer of proper size
-       char *out_msg = malloc(out_msg_len);
-       char *out_msg_pos = out_msg;
-
-       // Fill the buffer
-       *((syscall_id_t *)out_msg_pos) = WRITE_ID;
-       out_msg_pos += sizeof(syscall_id_t);
-
-       *((int*)out_msg_pos) = file;
-       out_msg_pos += sizeof(int);
-
-       *((int*)out_msg_pos) = len;
-       out_msg_pos += sizeof(int);
+       // Allocate a new buffer of proper size and pack
+       msg_t *msg = malloc(sizeof(msg_t) + len);
+       if (msg == NULL)
+               return -1;
+       
+       msg->id = WRITE_ID;
+       msg->write.fd = file;
+       msg->write.len = len;
 
-       memcpy(out_msg_pos, ptr, len);
+       memcpy(msg->write.buf, ptr, len);
 
        // Send message
-       char *result = send_message(out_msg, out_msg_len);
+       response_t *result = send_message(msg, sizeof(msg_t) + len);
 
-       free(out_msg);
+       free(msg);
 
        // Read result
        int return_val;
 
-       if (result != NULL) {
-               return_val = *((int *)result);
-               if (return_val == -1) errno = *(((int *)result) + 1);
-               free(result);
-       } else {
+       if (result == NULL) {
                errno = ECHANNEL;
                return_val = -1;
-       }
+       } else {
+               return_val = result->ret;
+               if (return_val == -1) errno = result->err;
+               free(result);
+       } 
 
        return return_val;
 }
@@ -787,7 +680,6 @@ ssize_t write(int file, void *ptr, size_t len) {
 int write_to_channel(char * msg, int len)
 {
        //return sys_serial_write((char*)msg, len);
-       return sys_eth_write((char*)msg, len);
+       return sys_eth_write(msg, len);
        
-}
-
+}
\ No newline at end of file