Insight into something.
////////////////////////////////////////////////////////////////////////////////
/**
 *  @file guthrn.c
 *  @brief A file storage server implemented in C.
 *
 *  The server will be multithreaded using the pthreads library. In particular,
 *  clients connect via sockets. The server must hand off the incoming
 *  connections to dedicated threads. You can either create threads on-demand or
 *  manage a pool of available threads.
 *
 *  @title guthrn
 *  @author Nicholas Guthrie
 *  @email guthrn@rpi.edu
 *  @web http//nickguthrie.com
 *  @created April 22, 2013
 *
 *  Compile with: gcc -g -o file-server file-server.c -lpthread
 */
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------ :Libraries:
//                      _    _ _                 _
//                     | |  (_) |__ _ _ __ _ _ _(_)___ ___
//                     | |__| | '_ \ '_/ _` | '_| / -_|_-<
//                     |____|_|_.__/_| \__,_|_| |_\___/__/
//
// -----------------------------------------------------------------------------
#include <stdio.h>          // for printf()
#include <stdlib.h>         // for exit()
#include <string.h>         // for strcpy(),strerror() and strlen()
#include <fcntl.h>          // for file i/o constants
#include <sys/stat.h>       // for file i/o constants
#include <errno.h>
// FOR BSD UNIX/LINUX
#include <sys/types.h>      //
#include <netinet/in.h>     //
#include <sys/socket.h>     // for socket system calls
#include <arpa/inet.h>      // for socket system calls (bind)
#include <sched.h>
#include <pthread.h>        // P-thread implementation
#include <signal.h>         // for signal
#include <semaphore.h>      // for p-thread semaphores
//--------------------------------------------------------------------- :Global:
//                            ___ _     _          _
//                           / __| |___| |__  __ _| |
//                          | (_ | / _ \ '_ \/ _` | |
//                           \___|_\___/_.__/\__,_|_|
//
// -----------------------------------------------------------------------------
#define BUF_SIZE            1024     // buffer size in bytes
#define PEND_CONNECTIONS     100     // pending connections to hold
#define TRUE                   1
#define FALSE                  0
#define NTHREADS 5                     /* Number of child threads        */
#define NUM_LOOPS  10                  /* Number of local loops          */
#define SCHED_INTVL 5                  /* thread scheduling interval     */
#define HIGHPRIORITY 10
#define D_STORAGE ".storage"
// global variables ------------------------------------------------------------
sem_t thread_sem[NTHREADS];
int   next_thread;
int   can_run;
int   i_stopped[NTHREADS];
unsigned int  client_s;               // Client socket descriptor
//----- HTTP response messages -------------------------------------------------
#define YESFILE   "FILE EXISTS"
#define NOFILE    "NO SUCH FILE"
#define ACK       "ACK"
#define ERROR     "ERROR"
//------------------------------------------------------------------ :Functions:
//                      ___             _   _
//                     | __|  _ _ _  __| |_(_)___ _ _  ___
//                     | _| || | ' \/ _|  _| / _ \ ' \(_-<
//                     |_| \_,_|_||_\__|\__|_\___/_||_/__/
//
//
// -----------------------------------------------------------------------------
void print_id()
{
    fprintf(stdout, "\n[thread %d] ", getpid());
}
////////////////////////////////////////////////////////////////////////////////
/**
 *  @brief Child thread implementation
 *  @param[in] arg
 *  @return void*
 */
////////////////////////////////////////////////////////////////////////////////
void *my_thread(void * arg)
{
    unsigned int    myClient_s;                //copy socket
    // other local variables ---------------------------------------------------
    char           in_buf[BUF_SIZE];           // input buffer for GET resquest
    char           out_buf[BUF_SIZE];          // output buffer for HTML response
    char           fname[100];                 // file name
    char           command[10];                // command given by user
    unsigned int   fh;                         // file handle (file descriptor)
    unsigned int   buf_len;                    // buffer length for file reads
    unsigned int   retcode;                    // return code
    struct stat st;                            // stores file information
    myClient_s = *(unsigned int *)arg;        // copy the socket
    // receive the command
    int pos = 0;
    while(1)
    {
	retcode = recv(client_s, in_buf, 1, 0);
	if (retcode < 0)
	{
	    printf("recv error detected ...\n");
	    return;
	}
	if(in_buf[0] == ' ')
	    break;
	command[pos++] = in_buf[0];
    }
    command[pos] = '\0';
    // receive the file name
    pos = 0;
    while(1)
    {
	retcode = recv(client_s, in_buf, 1, 0);
	if (retcode < 0)
	{
	    printf("recv error detected ...\n");
	    return;
	}
	if(in_buf[0] == '\n' || in_buf[0] == ' ')
	    break;
	fname[pos++] = in_buf[0];
    }
    fname[pos] = '\0';
    print_id();
    fprintf(stdout, "Rcvd: %s %s", command, fname);
    fflush(stdout);
    
    char cor_fname[100] = D_STORAGE;
    strcat(cor_fname, "/");
    strcat(cor_fname, fname);
    strcpy(fname, cor_fname);
    
    //////////////////////////////////////////////////////////////////////
    // ADD <filename> <bytes>\n<file-contents>
    // - add <filename> to the storage server
    // - IF the file already exists, return "FILE EXISTS" error
    // - return "ACK" if successful, "ERROR" if not
    //////////////////////////////////////////////////////////////////////
    if(strcmp(command, "ADD") == 0)
    {
	// File Exists
	if( access( fname, F_OK ) != -1 )
	{
	    // Send Message Back
	    print_id();
	    fprintf(stdout, "Sent: %s", YESFILE);
	    fflush(stdout);
	    strcpy(out_buf, YESFILE);
	    write(client_s, out_buf, strlen(out_buf) );
	}
	// File doesn't exist
	else
	{
	    // Read the File Size
	    char sf_size[50];
	    pos = 0;
	    while(1)
	    {
		retcode = recv(client_s, in_buf, 1, 0);
		if ( retcode < 0 )
		{
		    puts("recv error detected ...\n");
		    return;
		}
		if(in_buf[0] == '\n')
		    break;
		sf_size[pos++] = in_buf[0];
	    }
	    sf_size[pos] = '\0';
	    int file_size = (int) atoi(sf_size);
	    fprintf(stdout, " %d", file_size);
	    fflush(stdout);
	    // Write File ------------------------------------------------------
	    FILE *wfile;
	    wfile = fopen(fname,"wb+");
	    // Recieve File Data and Write on Server
	    int BUFFSIZ = 100;
	    int remain_data = file_size;
	    int len;
	    char * buffer = (char*)malloc(BUFFSIZ * sizeof(char));
	    while (((len = recv(client_s, buffer, BUFSIZ, 0)) > 0) &&
		   (remain_data > 0))
	    {
                fwrite(buffer, sizeof(char), len, wfile);
                remain_data -= len;
                //fprintf(stdout, "Receive %d bytes and we hope :- %d bytes\n", len, remain_data);
	    }
	    fclose(wfile);
	    //free(buffer);
	    print_id();
	    fprintf(stdout, "Transferred file (%d bytes)", file_size);
	    fflush(stdout);
	    // Send Success Message to Client
	    print_id();
	    fprintf(stdout, "Sent: %s %d", ACK, file_size);
	    fflush(stdout);
	    strcpy(out_buf, ACK);
	    write(client_s, out_buf, strlen(out_buf) );
	}
    }
    //////////////////////////////////////////////////////////////////////
    // UPDATE <filename> <bytes>\n<file-contents>
    // - update existing file <filename> on the storage server
    // - the file's contents will be overwritten
    // - IF the file does not already exist, return "NO SUCH FILE" error
    // - return "ACK" if successful, "ERROR" if not
    //////////////////////////////////////////////////////////////////////
    else if(strcmp(command, "UPDATE") == 0)
    {
	// File Exists
	if( access( fname, F_OK ) != -1 )
	{
	    // Read the File Size
	    char sf_size[50];
	    pos = 0;
	    while(1)
	    {
		retcode = recv(client_s, in_buf, 1, 0);
		if ( retcode < 0 )
		{
		    puts("recv error detected ...\n");
		    return;
		}
		if(in_buf[0] == '\n')
		    break;
		sf_size[pos++] = in_buf[0];
	    }
	    sf_size[pos] = '\0';
	    int file_size = (int) atoi(sf_size);
	    fprintf(stdout, " %d", file_size);
	    // Write File ------------------------------------------------------
	    FILE *wfile;
	    wfile = fopen(fname,"wb");
	    // Recieve File Data and Write on Server
	    int BUFFSIZ = 100;
	    int remain_data = file_size;
	    int len;
	    char * buffer = (char*)malloc(BUFFSIZ * sizeof(char));
	    while (((len = recv(client_s, buffer, BUFSIZ, 0)) > 0) &&
		   (remain_data > 0))
	    {
		fwrite(buffer, sizeof(char), len, wfile);
		remain_data -= len;
	    }
	    print_id();
	    fprintf(stdout, "Transferred file (%d bytes)", file_size);
	    fflush(stdout);
	    // Send Message Back
	    print_id();
	    fprintf(stdout, "Sent: %s", ACK);
	    fflush(stdout);
	    strcpy(out_buf, ACK);
	    write(client_s, out_buf, strlen(out_buf) );
	}
	// File doesn't exist
	else
	{
	    print_id();
	    fprintf(stdout, "Sent: %s", NOFILE);
	    fflush(stdout);
	    strcpy(out_buf, NOFILE);
	    write(client_s, out_buf, strlen(out_buf) );
	}
    }
    //////////////////////////////////////////////////////////////////////
    // READ <filename>\n
    // - server returns the length (in bytes) and content of <filename>
    // - note that this does NOT remove the file on the server
    // - IF the file does not exist, return "NO SUCH FILE" error
    // - RETURN "ACK" if successful, "ERROR" if not
    // - IF "ACK" is sent, follow it with file length and file as follows:
    //   ACK <bytes>\n<file-contents>
    //////////////////////////////////////////////////////////////////////
    else if(strcmp(command, "READ") == 0)
    {
	// File Exists
	if( access( fname, F_OK ) != -1 )
	{
	    FILE *xfile;                    //File to Read from Server
	    char buf[150];                  //Temporary Storage Buffer
	    xfile = fopen(fname, "rb");
	    if (xfile == NULL)
	    {
		perror ("The following error occurred");
		fprintf( stdout, "Value of errno: %d\n", errno );
	    }
	    	
	    // Get File Size
	    stat(fname, &st);
	    int file_size = st.st_size;    //Size of the file as sent
	    char str[100];                 //File Size in a String
	    sprintf(str, "%d", file_size); //convert int to string
	    // Add to buf
	    strcat(buf, "ACK ");
	    strcat(buf, str);
	    strcat(buf, "\n");
	    // Read the File Into An Array
	    char *bdata = (char*)malloc(strlen(buf) * sizeof(char)
					+ file_size * sizeof(char));
	    char *tdata = (char*)malloc(file_size * sizeof(char));
	    int pos = 0;
	    int c;
	    while ( (c = fgetc(xfile)) != EOF )
	    {		
		tdata[pos++] = (char) c;
	    }
	    strcat(bdata, buf);    //copy command and size
	    strcat(bdata, tdata);  //copy file contents
	    
	    // Write to Server
	    write( client_s, bdata, strlen( bdata ) );
	    print_id();
	    fprintf(stdout, "Transferred file (%d bytes)", file_size);
	    fflush(stdout);
	    // Close Data
	    fclose(xfile);
	    free(bdata);
	    free(tdata);
	}
	else
	{
	    print_id();
	    fprintf(stdout, "Sent: %s", ERROR);
	    fflush(stdout);
	    strcpy(out_buf, ERROR);
	    write(client_s, out_buf, strlen(out_buf) );
	    return;
	}
    }
    ////////////////////
    // Exiting
    ////////////////////
    close(client_s); // close the client connection
    pthread_exit(NULL);
}
////////////////////////////////////////////////////////////////////////////////
//----------------------------------------------------------------------- :Main:
//                              __  __      _
//                             |  \/  |__ _(_)_ _
//                             | |\/| / _` | | ' \
//                             |_|  |_\__,_|_|_||_|
//
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
int main ( int argc, char* argv[] )
{
    // Variables ---------------------------------------------------------------
    unsigned int          server_s;         // server socket descriptor
    struct sockaddr_in    server_addr;      // server internet address
    struct sockaddr_in    client_addr;      // client internet address
    struct in_addr        client_ip_addr;   // client IP address
    int                   addr_len;         // internet address length
    unsigned int          ids;              // holds thread arguments
    pthread_attr_t        attr;             // pthread attributes
    pthread_t             threads;          // thread ID (for os)
    int                   port_num;
    // Create Storage Directory
    struct stat info;
    if(lstat(D_STORAGE,&info) != 0)
    {
	//  doesn't exist
	if(errno == ENOENT)
	{
	    char new_dir[]= D_STORAGE;
	    if (mkdir(new_dir, S_IRWXU|S_IRGRP|S_IXGRP) != 0)
		perror("mkdir() error"); 
	}
    }
    
    // Start Server
    printf("Started file-server\n");
    if (argc == 2)
    {
	sscanf(argv[1], "%d", &port_num);
	printf("Listening on port %d", port_num);
	if(port_num < 8000 || port_num > 9000)
	{
	    perror("ERROR: Port number must from 8000-9000.\n");
	    return -1;
	}
    }
    else
    {
	perror("ERROR: Port number must from 8000-9000.\n");
	return -1;
    }
    // create a new socket
    server_s = socket(AF_INET, SOCK_STREAM, 0);
    // fill-in address information, and then bind it
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port_num);
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));
    // listen for connections and then accept
    listen( server_s, PEND_CONNECTIONS );
    ////////////////////////////////////////
    // Main Server Loop
    ////////////////////////////////////////
    pthread_attr_init(&attr);
    while(TRUE)
    {
	// wait for the next client to arrive
	addr_len = sizeof( client_addr );
	client_s = accept(server_s, (struct sockaddr *)&client_addr, &addr_len);
	// error handling when creating socket
	if (client_s == FALSE)
	{
	    printf("ERROR - Unable to create socket \n");
	    exit(FALSE);
	}
	// create child thread
	else
	{
	    printf("\nRecieved incoming connecint from <client-hostname>");
	    ids = client_s;
	    pthread_create (&threads, &attr,my_thread,&ids);
	}
    }
    ////////////////////
    // Exiting
    ////////////////////
    close (server_s);     // close the primary socket
    return (TRUE);
}