From: Simone Piccardi Date: Sun, 6 Apr 2003 00:47:57 +0000 (+0000) Subject: Finita la conversione dei listati in file separati. Passato anche alla nuova X-Git-Url: https://gapil.gnulinux.it/gitweb/?p=gapil.git;a=commitdiff_plain;h=06661f47754a536098afe2b30cb04469918f2fa3 Finita la conversione dei listati in file separati. Passato anche alla nuova versione di listings. --- diff --git a/elemtcp.tex b/elemtcp.tex index efd8a05..fc1d1d7 100644 --- a/elemtcp.tex +++ b/elemtcp.tex @@ -700,10 +700,7 @@ Per specificare un indirizzo generico con IPv4 si usa il valore \const{INADDR\_ANY}, il cui valore, come visto anche negli esempi precedenti è pari a zero, nell'esempio \figref{fig:net_serv_code} si è usata un'assegnazione immediata del tipo: - -\begin{lstlisting}[stepnumber=0,frame=]{} - serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ -\end{lstlisting} +\includecodesnip{listati/serv_addr_sin_addr.c} Si noti che si è usato \func{htonl} per assegnare il valore \const{INADDR\_ANY}, benché essendo questo pari a zero il riordinamento sia @@ -741,9 +738,7 @@ Per questo motivo nell'header \file{netinet/in.h} \const{in6addr\_any} (dichiarata come \direct{extern}, ed inizializzata dal sistema al valore \const{IN6ADRR\_ANY\_INIT}) che permette di effettuare una assegnazione del tipo: -\begin{lstlisting}[stepnumber=0,frame=]{} - serv_add.sin6_addr = in6addr_any; /* connect from anywhere */ -\end{lstlisting} +\includecodesnip{listati/serv_addr_sin6_addr.c} in maniera analoga si può utilizzare la variabile \const{in6addr\_loopback} per indicare l'indirizzo di \textit{loopback}, che a sua volta viene inizializzata staticamente a \const{IN6ADRR\_LOOPBACK\_INIT}. @@ -1121,61 +1116,11 @@ rispetto al precedente esempio. Al solito il sorgente completo del server \file{ElemDaytimeTCPCuncServ.c} è allegato nella directory dei sorgenti. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -#include /* predefined types */ -#include /* include unix standard library */ -#include /* IP addresses conversion utililites */ -#include /* socket library */ -#include /* include standard I/O library */ -#include - -int main(int argc, char *argv[]) -{ - int list_fd, conn_fd; - int i; - struct sockaddr_in serv_add, client; - char buffer[MAXLINE]; - socklen_t len; - time_t timeval; - pid_t pid; - int logging=0; - ... - /* write daytime to client */ - while (1) { - if ( (conn_fd = accept(list_fd, (struct sockaddr *)&client, &len)) - <0 ) { - perror("accept error"); - exit(-1); - } - /* fork to handle connection */ - if ( (pid = fork()) < 0 ){ - perror("fork error"); - exit(-1); - } - if (pid == 0) { /* child */ - close(list_fd); - timeval = time(NULL); - snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval)); - if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) { - perror("write error"); - exit(-1); - } - if (logging) { - inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer)); - printf("Request from host %s, port %d\n", buffer, - ntohs(client.sin_port)); - } - close(conn_fd); - exit(0); - } else { /* parent */ - close(conn_fd); - } - } - /* normal exit, never reached */ - exit(0); -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/ElemDaytimeTCPCuncServ.c} + \end{minipage} + \normalsize \caption{Esempio di codice di un server concorrente elementare per il servizio daytime.} \label{fig:TCPel_serv_code} diff --git a/fileadv.tex b/fileadv.tex index 9980d89..d184c31 100644 --- a/fileadv.tex +++ b/fileadv.tex @@ -211,17 +211,11 @@ negativo indica un'attesa indefinita). \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct pollfd { - int fd; /* file descriptor */ - short events; /* requested events */ - short revents; /* returned events */ -}; - \end{lstlisting} + \includestruct{listati/pollfd.h} \end{minipage} \normalsize - \caption{La struttura \struct{pollfd}, utilizzata per specificare le modalità - di controllo di un file descriptor alla funzione \func{poll}.} + \caption{La struttura \structd{pollfd}, utilizzata per specificare le + modalità di controllo di un file descriptor alla funzione \func{poll}.} \label{fig:file_pollfd} \end{figure} @@ -421,21 +415,10 @@ disponibilit \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct aiocb -{ - int aio_fildes; /* File descriptor. */ - off_t aio_offset; /* File offset */ - int aio_lio_opcode; /* Operation to be performed. */ - int aio_reqprio; /* Request priority offset. */ - volatile void *aio_buf; /* Location of buffer. */ - size_t aio_nbytes; /* Length of transfer. */ - struct sigevent aio_sigevent; /* Signal number and value. */ -}; - \end{lstlisting} + \includestruct{listati/aiocb.h} \end{minipage} \normalsize - \caption{La struttura \struct{aiocb}, usata per il controllo dell'I/O + \caption{La struttura \structd{aiocb}, usata per il controllo dell'I/O asincrono.} \label{fig:file_aiocb} \end{figure} @@ -471,20 +454,11 @@ esse. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sigevent -{ - sigval_t sigev_value; - int sigev_signo; - int sigev_notify; - void (*sigev_notify_function)(sigval_t); - pthread_attr_t *sigev_notify_attributes; -}; - \end{lstlisting} + \includestruct{listati/sigevent.h} \end{minipage} \normalsize - \caption{La struttura \struct{sigevent}, usata per specificare le modalità di - notifica degli eventi relativi alle operazioni di I/O asincrono.} + \caption{La struttura \structd{sigevent}, usata per specificare le modalità + di notifica degli eventi relativi alle operazioni di I/O asincrono.} \label{fig:file_sigevent} \end{figure} @@ -818,15 +792,10 @@ il secondo, \var{iov\_len}, la dimensione dello stesso. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct iovec { - __ptr_t iov_base; /* Starting address */ - size_t iov_len; /* Length in bytes */ -}; - \end{lstlisting} + \includestruct{listati/iovec.h} \end{minipage} \normalsize - \caption{La struttura \struct{iovec}, usata dalle operazioni di I/O + \caption{La struttura \structd{iovec}, usata dalle operazioni di I/O vettorizzato.} \label{fig:file_iovec} \end{figure} @@ -1512,18 +1481,10 @@ regione bloccata. \begin{figure}[!bht] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct flock { - short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ - short int l_whence; /* Where `l_start' is relative to (like `lseek').*/ - off_t l_start; /* Offset where the lock begins. */ - off_t l_len; /* Size of the locked area; zero means until EOF.*/ - pid_t l_pid; /* Process holding the lock. */ -}; - \end{lstlisting} + \includestruct{listati/flock.h} \end{minipage} \normalsize - \caption{La struttura \struct{flock}, usata da \func{fcntl} per il file + \caption{La struttura \structd{flock}, usata da \func{fcntl} per il file locking.} \label{fig:struct_flock} \end{figure} @@ -1717,60 +1678,7 @@ necessario a soddisfare l'operazione richiesta. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[]) -{ - int type = F_UNLCK; /* lock type: default to unlock (invalid) */ - off_t start = 0; /* start of the locked region: default to 0 */ - off_t len = 0; /* length of the locked region: default to 0 */ - int fd, res, i; /* internal variables */ - int bsd = 0; /* semantic type: default to POSIX */ - int cmd = F_SETLK; /* lock command: default to non-blocking */ - struct flock lock; /* file lock structure */ - ... - if ((argc - optind) != 1) { /* There must be remaing parameters */ - printf("Wrong number of arguments %d\n", argc - optind); - usage(); - } - if (type == F_UNLCK) { /* There must be a -w or -r option set */ - printf("You should set a read or a write lock\n"); - usage(); - } - fd = open(argv[optind], O_RDWR); /* open the file to be locked */ - if (fd < 0) { /* on error exit */ - perror("Wrong filename"); - exit(1); - } - /* do lock */ - if (bsd) { /* if BSD locking */ - /* rewrite cmd for suitables flock operation values */ - if (cmd == F_SETLKW) { /* if no-blocking */ - cmd = LOCK_NB; /* set the value for flock operation */ - } else { /* else */ - cmd = 0; /* default is null */ - } - if (type == F_RDLCK) cmd |= LOCK_SH; /* set for shared lock */ - if (type == F_WRLCK) cmd |= LOCK_EX; /* set for exclusive lock */ - res = flock(fd, cmd); /* esecute lock */ - } else { /* if POSIX locking */ - /* setting flock structure */ - lock.l_type = type; /* set type: read or write */ - lock.l_whence = SEEK_SET; /* start from the beginning of the file */ - lock.l_start = start; /* set the start of the locked region */ - lock.l_len = len; /* set the length of the locked region */ - res = fcntl(fd, cmd, &lock); /* do lock */ - } - /* check lock results */ - if (res) { /* on error exit */ - perror("Failed lock"); - exit(1); - } else { /* else write message */ - printf("Lock acquired\n"); - } - pause(); /* stop the process, use a signal to exit */ - return 0; -} - \end{lstlisting} + \includecodesample{listati/Flock.c} \end{minipage} \normalsize \caption{Sezione principale del codice del programma \file{Flock.c}.} diff --git a/ipc.tex b/ipc.tex index e4c32b7..bd3aa42 100644 --- a/ipc.tex +++ b/ipc.tex @@ -190,55 +190,7 @@ nel file \file{BarCodePage.c} che si trova nella directory dei sorgenti. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[], char *envp[]) -{ - ... - /* create two pipes, pipein and pipeout, to handle communication */ - if ( (retval = pipe(pipein)) ) { - WriteMess("input pipe creation error"); - exit(0); - } - if ( (retval = pipe(pipeout)) ) { - WriteMess("output pipe creation error"); - exit(0); - } - /* First fork: use child to run barcode program */ - if ( (pid = fork()) == -1) { /* on error exit */ - WriteMess("child creation error"); - exit(0); - } - /* if child */ - if (pid == 0) { - close(pipein[1]); /* close pipe write end */ - dup2(pipein[0], STDIN_FILENO); /* remap stdin to pipe read end */ - close(pipeout[0]); - dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */ - execlp("barcode", "barcode", size, NULL); - } - close(pipein[0]); /* close input side of input pipe */ - write(pipein[1], argv[1], strlen(argv[1])); /* write parameter to pipe */ - close(pipein[1]); /* closing write end */ - waitpid(pid, NULL, 0); /* wait child completion */ - /* Second fork: use child to run ghostscript */ - if ( (pid = fork()) == -1) { - WriteMess("child creation error"); - exit(0); - } - /* second child, convert PS to JPEG */ - if (pid == 0) { - close(pipeout[1]); /* close write end */ - dup2(pipeout[0], STDIN_FILENO); /* remap read end to stdin */ - /* send mime type */ - write(STDOUT_FILENO, content, strlen(content)); - execlp("gs", "gs", "-q", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL); - } - /* still parent */ - close(pipeout[1]); - waitpid(pid, NULL, 0); - exit(0); -} - \end{lstlisting} + \includecodesample{listati/BarCodePage.c} \end{minipage} \normalsize \caption{Sezione principale del codice del \textit{CGI} @@ -423,37 +375,7 @@ invocato dopo. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[], char *envp[]) -{ - FILE *pipe[4]; - FILE *pipein; - char *cmd_string[4]={ - "pnmtopng", - "pnmmargin -white 10", - "pnmcrop", - "gs -sDEVICE=ppmraw -sOutputFile=- -sNOPAUSE -q - -c showpage -c quit" - }; - char content[]="Content-type: image/png\n\n"; - int i; - /* write mime-type to stdout */ - write(STDOUT_FILENO, content, strlen(content)); - /* execute chain of command */ - for (i=0; i<4; i++) { - pipe[i] = popen(cmd_string[i], "w"); - dup2(fileno(pipe[i]), STDOUT_FILENO); - } - /* create barcode (in PS) */ - pipein = popen("barcode", "w"); - /* send barcode string to barcode program */ - write(fileno(pipein), argv[1], strlen(argv[1])); - /* close all pipes (in reverse order) */ - for (i=4; i==0; i--) { - pclose((pipe[i])); - } - exit(0); -} - \end{lstlisting} + \includecodesample{listati/BarCode.c} \end{minipage} \normalsize \caption{Codice completo del \textit{CGI} \file{BarCode.c}.} @@ -594,60 +516,7 @@ diverso da quelli preimpostati. Il codice completo \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -char *fifoname = "/tmp/fortune.fifo"; -int main(int argc, char *argv[]) -{ -/* Variables definition */ - int i, n = 0; - char *fortunefilename = "/usr/share/games/fortunes/linux"; - char **fortune; - char line[80]; - int fifo_server, fifo_client; - int nread; - ... - if (n==0) usage(); /* if no pool depth exit printing usage info */ - Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ - Signal(SIGINT, HandSIGTERM); - Signal(SIGQUIT, HandSIGTERM); - i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */ - if (mkfifo(fifoname, 0622)) { /* create well known fifo if does't exist */ - if (errno!=EEXIST) { - perror("Cannot create well known fifo"); - exit(1); - } - } - daemon(0, 0); - /* open fifo two times to avoid EOF */ - fifo_server = open(fifoname, O_RDONLY); - if (fifo_server < 0) { - perror("Cannot open read only well known fifo"); - exit(1); - } - if (open(fifoname, O_WRONLY) < 0) { - perror("Cannot open write only well known fifo"); - exit(1); - } - /* Main body: loop over requests */ - while (1) { - nread = read(fifo_server, line, 79); /* read request */ - if (nread < 0) { - perror("Read Error"); - exit(1); - } - line[nread] = 0; /* terminate fifo name string */ - n = random() % i; /* select random value */ - fifo_client = open(line, O_WRONLY); /* open client fifo */ - if (fifo_client < 0) { - perror("Cannot open"); - exit(1); - } - nread = write(fifo_client, /* write phrase */ - fortune[n], strlen(fortune[n])+1); - close(fifo_client); /* close client fifo */ - } -} - \end{lstlisting} + \includecodesample{listati/FortuneServer.c} \end{minipage} \normalsize \caption{Sezione principale del codice del server di \textit{fortunes} @@ -737,44 +606,7 @@ principale del programma e le definizioni delle variabili. Il codice completo \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[]) -{ -/* Variables definition */ - int n = 0; - char *fortunefilename = "/tmp/fortune.fifo"; - char line[80]; - int fifo_server, fifo_client; - char fifoname[80]; - int nread; - char buffer[PIPE_BUF]; - ... - snprintf(fifoname, 80, "/tmp/fortune.%d", getpid()); /* compose name */ - if (mkfifo(fifoname, 0622)) { /* open client fifo */ - if (errno!=EEXIST) { - perror("Cannot create well known fifo"); - exit(-1); - } - } - fifo_server = open(fortunefilename, O_WRONLY); /* open server fifo */ - if (fifo_server < 0) { - perror("Cannot open well known fifo"); - exit(-1); - } - nread = write(fifo_server, fifoname, strlen(fifoname)+1); /* write name */ - close(fifo_server); /* close server fifo */ - fifo_client = open(fifoname, O_RDONLY); /* open client fifo */ - if (fifo_client < 0) { - perror("Cannot open well known fifo"); - exit(-1); - } - nread = read(fifo_client, buffer, sizeof(buffer)); /* read answer */ - printf("%s", buffer); /* print fortune */ - close(fifo_client); /* close client */ - close(fifo_server); /* close server */ - unlink(fifoname); /* remove client fifo */ -} - \end{lstlisting} + \includecodesample{listati/FortuneClient.c} \end{minipage} \normalsize \caption{Sezione principale del codice del client di \textit{fortunes} @@ -1002,18 +834,7 @@ mantiene varie propriet \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{}%,frame=,indent=1cm ]{} -struct ipc_perm -{ - key_t key; /* Key. */ - uid_t uid; /* Owner's user ID. */ - gid_t gid; /* Owner's group ID. */ - uid_t cuid; /* Creator's user ID. */ - gid_t cgid; /* Creator's group ID. */ - unsigned short int mode; /* Read/write permission. */ - unsigned short int seq; /* Sequence number. */ -}; - \end{lstlisting} + \includestruct{listati/ipc_perm.h} \end{minipage} \normalsize \caption{La struttura \structd{ipc\_perm}, come definita in @@ -1210,41 +1031,7 @@ s \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[]) -{ - ... - switch (type) { - case 'q': /* Message Queue */ - debug("Message Queue Try\n"); - for (i=0; i 0 */ - char mtext[LENGTH]; /* message data */ - }; - \end{lstlisting} + \includestruct{listati/msgbuf.h} \end{minipage} \normalsize \caption{Schema della struttura \structd{msgbuf}, da utilizzare come @@ -1755,57 +1523,8 @@ in maniera indipendente con client diversi. \begin{figure}[!bht] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int msgid; /* Message queue identifier */ -int main(int argc, char *argv[]) -{ -/* Variables definition */ - int i, n = 0; - char **fortune; /* array of fortune message string */ - char *fortunefilename = "/usr/share/games/fortunes/linux"; /* file name */ - struct msgbuf_read { /* message struct to read request from clients */ - long mtype; /* message type, must be 1 */ - long pid; /* message data, must be the pid of the client */ - } msg_read; - struct msgbuf_write { /* message struct to write result to clients */ - long mtype; /* message type, will be the pid of the client*/ - char mtext[MSGMAX]; /* message data, will be the fortune */ - } msg_write; - key_t key; /* Message queue key */ - int size; /* message size */ - ... - Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ - Signal(SIGINT, HandSIGTERM); - Signal(SIGQUIT, HandSIGTERM); - if (n==0) usage(); /* if no pool depth exit printing usage info */ - i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */ - /* Create the queue */ - key = ftok("./MQFortuneServer.c", 1); - msgid = msgget(key, IPC_CREAT|0666); - if (msgid < 0) { - perror("Cannot create message queue"); - exit(1); - } - /* Main body: loop over requests */ - daemon(0, 0); - while (1) { - msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR); - n = random() % i; /* select random value */ - strncpy(msg_write.mtext, fortune[n], MSGMAX); - size = min(strlen(fortune[n])+1, MSGMAX); - msg_write.mtype=msg_read.pid; /* use request pid as type */ - msgsnd(msgid, &msg_write, size, 0); - } -} -/* - * Signal Handler to manage termination - */ -void HandSIGTERM(int signo) { - msgctl(msgid, IPC_RMID, NULL); /* remove message queue */ - exit(0); -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/MQFortuneServer.c} \end{minipage} \normalsize \caption{Sezione principale del codice del server di \textit{fortunes} @@ -1878,26 +1597,8 @@ gestore \code{HandSIGTERM}, che semplicemente si limita a cancellare la coda \begin{figure}[!bht] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[]) -{ - ... - key = ftok("./MQFortuneServer.c", 1); - msgid = msgget(key, 0); - if (msgid < 0) { - perror("Cannot find message queue"); - exit(1); - } - /* Main body: do request and write result */ - msg_read.mtype = 1; /* type for request is always 1 */ - msg_read.pid = getpid(); /* use pid for communications */ - size = sizeof(msg_read.pid); - msgsnd(msgid, &msg_read, size, 0); /* send request message */ - msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR); - printf("%s", msg_write.mtext); -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/MQFortuneClient.c} \end{minipage} \normalsize \caption{Sezione principale del codice del client di \textit{fortunes} @@ -2087,15 +1788,7 @@ semaforo all'uscita del processo. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct semid_ds -{ - struct ipc_perm sem_perm; /* operation permission struct */ - time_t sem_otime; /* last semop() time */ - time_t sem_ctime; /* last time changed by semctl() */ - unsigned long int sem_nsems; /* number of semaphores in set */ -}; - \end{lstlisting} + \includestruct{listati/semid_ds.h} \end{minipage} \normalsize \caption{La struttura \structd{semid\_ds}, associata a ciascun insieme di @@ -2137,14 +1830,7 @@ controllo. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sem { - short sempid; /* pid of last operation */ - ushort semval; /* current value */ - ushort semncnt; /* num procs awaiting increase in semval */ - ushort semzcnt; /* num procs awaiting semval = 0 */ -}; - \end{lstlisting} + \includestruct{listati/sem.h} \end{minipage} \normalsize \caption{La struttura \structd{sem}, che contiene i dati di un singolo @@ -2234,15 +1920,7 @@ specificata con \param{cmd}, ed opera o sull'intero insieme specificato da \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -union semun { - int val; /* value for SETVAL */ - struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ - unsigned short *array; /* array for GETALL, SETALL */ - /* Linux specific part: */ - struct seminfo *__buf; /* buffer for IPC_INFO */ -}; - \end{lstlisting} + \includestruct{listati/semun.h} \end{minipage} \normalsize \caption{La definizione dei possibili valori di una \direct{union} @@ -2388,14 +2066,7 @@ effettivamente eseguite se e soltanto se \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sembuf -{ - unsigned short int sem_num; /* semaphore number */ - short int sem_op; /* semaphore operation */ - short int sem_flg; /* operation flag */ -}; - \end{lstlisting} + \includestruct{listati/sembuf.h} \end{minipage} \normalsize \caption{La struttura \structd{sembuf}, usata per le operazioni sui @@ -2571,57 +2242,7 @@ nullo per segnalarne l'indisponibilit \begin{figure}[!bht] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -/* Function MutexCreate: create a mutex/semaphore */ -int MutexCreate(key_t ipc_key) -{ - const union semun semunion={1}; /* semaphore union structure */ - int sem_id, ret; - sem_id = semget(ipc_key, 1, IPC_CREAT|0666); /* get semaphore ID */ - if (sem_id == -1) { /* if error return code */ - return sem_id; - } - ret = semctl(sem_id, 0, SETVAL, semunion); /* init semaphore */ - if (ret == -1) { - return ret; - } - return sem_id; -} -/* Function MutexFind: get the semaphore/mutex Id given the IPC key value */ -int MutexFind(key_t ipc_key) -{ - return semget(ipc_key,1,0); -} -/* Function MutexRead: read the current value of the mutex/semaphore */ -int MutexRead(int sem_id) -{ - return semctl(sem_id, 0, GETVAL); -} -/* Define sembuf structures to lock and unlock the semaphore */ -struct sembuf sem_lock={ /* to lock semaphore */ - 0, /* semaphore number (only one so 0) */ - -1, /* operation (-1 to use resource) */ - SEM_UNDO}; /* flag (set for undo at exit) */ -struct sembuf sem_ulock={ /* to unlock semaphore */ - 0, /* semaphore number (only one so 0) */ - 1, /* operation (1 to release resource) */ - SEM_UNDO}; /* flag (in this case 0) */ -/* Function MutexLock: to lock a mutex/semaphore */ -int MutexLock(int sem_id) -{ - return semop(sem_id, &sem_lock, 1); -} -/* Function MutexUnlock: to unlock a mutex/semaphore */ -int MutexUnlock(int sem_id) -{ - return semop(sem_id, &sem_ulock, 1); -} -/* Function MutexRemove: remove a mutex/semaphore */ -int MutexRemove(int sem_id) -{ - return semctl(sem_id, 0, IPC_RMID); -} - \end{lstlisting} + \includecodesample{listati/Mutex.c} \end{minipage} \normalsize \caption{Il codice delle funzioni che permettono di creare o recuperare @@ -2749,18 +2370,7 @@ norma, significa insieme a dei semafori. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct shmid_ds { - struct ipc_perm shm_perm; /* operation perms */ - int shm_segsz; /* size of segment (bytes) */ - time_t shm_atime; /* last attach time */ - time_t shm_dtime; /* last detach time */ - time_t shm_ctime; /* last change time */ - unsigned short shm_cpid; /* pid of creator */ - unsigned short shm_lpid; /* pid of last operator */ - short shm_nattch; /* no. of current attaches */ -}; - \end{lstlisting} + \includestruct{listati/shmid_ds.h} \end{minipage} \normalsize \caption{La struttura \structd{shmid\_ds}, associata a ciascun segmento di @@ -2776,7 +2386,7 @@ campo \var{shm\_perm} viene inizializzato come illustrato in \secref{sec:ipc_sysv_access_control}, e valgono le considerazioni ivi fatte relativamente ai permessi di accesso; per quanto riguarda gli altri campi invece: -\begin{itemize*} +\begin{itemize} \item il campo \var{shm\_segsz}, che esprime la dimensione del segmento, viene inizializzato al valore di \param{size}. \item il campo \var{shm\_ctime}, che esprime il tempo di creazione del @@ -2790,7 +2400,7 @@ invece: creato il segmento, viene inizializzato al \acr{pid} del processo chiamante. \item il campo \var{shm\_nattac}, che esprime il numero di processi agganciati al segmento viene inizializzato a zero. -\end{itemize*} +\end{itemize} Come per le code di messaggi e gli insiemi di semafori, anche per i segmenti di memoria condivisa esistono una serie di limiti imposti dal sistema. Alcuni @@ -3044,67 +2654,10 @@ In caso di successo la funzione aggiorna anche i seguenti campi di inoltre la regione di indirizzi usata per il segmento di memoria condivisa viene tolta dallo spazio di indirizzi del processo. -Come esempio di uso di queste funzioni vediamo come implementare una serie di -funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni -più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in -\figref{fig:ipc_sysv_shm_func}. - \begin{figure}[!bht] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -/* Function ShmCreate Create a SysV shared memory segment */ -void * ShmCreate(key_t ipc_key, int shm_size, int perm, int fill) -{ - void * shm_ptr; - int shm_id; /* ID of the IPC shared memory segment */ - shm_id = shmget(ipc_key, shm_size, IPC_CREAT|perm); /* get shm ID */ - if (shm_id < 0) { - return NULL; - } - shm_ptr = shmat(shm_id, NULL, 0); /* map it into memory */ - if (shm_ptr < 0) { - return NULL; - } - memset((void *)shm_ptr, fill, shm_size); /* fill segment */ - return shm_ptr; -} -/* Function ShmFind: Find a SysV shared memory segment */ -void * ShmFind(key_t ipc_key, int shm_size) -{ - void * shm_ptr; - int shm_id; /* ID of the SysV shared memory segment */ - shm_id = shmget(ipc_key, shm_size, 0); /* find shared memory ID */ - if (shm_id < 0) { - return NULL; - } - shm_ptr = shmat(shm_id, NULL, 0); /* map it into memory */ - if (shm_ptr < 0) { - return NULL; - } - return shm_ptr; -} -/* Function ShmRemove: Schedule removal for a SysV shared memory segment */ -int ShmRemove(key_t ipc_key, void * shm_ptr) -{ - int shm_id; /* ID of the SysV shared memory segment */ - /* first detach segment */ - if (shmdt(shm_ptr) < 0) { - return -1; - } - /* schedule segment removal */ - shm_id = shmget(ipc_key, 0, 0); /* find shared memory ID */ - if (shm_id < 0) { - if (errno == EIDRM) return 0; - return -1; - } - if (shmctl(shm_id, IPC_RMID, NULL) < 0) { /* ask for removal */ - if (errno == EIDRM) return 0; - return -1; - } - return 0; -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/SharedMem.c} \end{minipage} \normalsize \caption{Il codice delle funzioni che permettono di creare, trovare e @@ -3112,6 +2665,11 @@ int ShmRemove(key_t ipc_key, void * shm_ptr) \label{fig:ipc_sysv_shm_func} \end{figure} +Come esempio di uso di queste funzioni vediamo come implementare una serie di +funzioni di libreria che ne semplifichino l'uso, automatizzando le operazioni +più comuni; il codice, contenuto nel file \file{SharedMem.c}, è riportato in +\figref{fig:ipc_sysv_shm_func}. + La prima funzione (\texttt{\small 3--16}) è \func{ShmCreate} che, data una chiave, crea il segmento di memoria condivisa restituendo il puntatore allo stesso. La funzione comincia (\texttt{\small 6}) con il chiamare @@ -3185,58 +2743,8 @@ video; al solito il codice completo si trova con i sorgenti allegati nel file \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -/* global variables for shared memory segment */ -struct DirProp { - int tot_size; - int tot_files; - int tot_regular; - int tot_fifo; - int tot_link; - int tot_dir; - int tot_block; - int tot_char; - int tot_sock; -} *shmptr; -key_t key; -int mutex; -/* main body */ -int main(int argc, char *argv[]) -{ - int i, pause = 10; - ... - if ((argc - optind) != 1) { /* There must be remaing parameters */ - printf("Wrong number of arguments %d\n", argc - optind); - usage(); - } - if (chdir(argv[1])) { /* chdir to be sure dir exist */ - perror("Cannot find directory to monitor"); - } - Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ - Signal(SIGINT, HandSIGTERM); - Signal(SIGQUIT, HandSIGTERM); - key = ftok("~/gapil/sources/DirMonitor.c", 1); /* define a key */ - shmptr = ShmCreate(key, 4096, 0666, 0); /* get a shared memory segment */ - if (!shmptr) { - perror("Cannot create shared memory"); - exit(1); - } - if ((mutex = MutexCreate(key)) == -1) { /* get a Mutex */ - perror("Cannot create mutex"); - exit(1); - } - /* main loop, monitor directory properties each 10 sec */ - daemon(1, 0); /* demonize process, staying in monitored dir */ - while (1) { - MutexLock(mutex); /* lock shared memory */ - memset(shmptr, 0, sizeof(struct DirProp)); /* erase previous data */ - DirScan(argv[1], ComputeValues); /* execute scan */ - MutexUnlock(mutex); /* unlock shared memory */ - sleep(pause); /* sleep until next watch */ - } -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/DirMonitor.c} \end{minipage} \normalsize \caption{Codice della funzione principale del programma \file{DirMonitor.c}.} @@ -3287,6 +2795,16 @@ sar di interfaccia già descritte in \secref{sec:ipc_sysv_sem}, anche un mutex, che utilizzeremo per regolare l'accesso alla memoria condivisa. +\begin{figure}[!htb] + \footnotesize \centering + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/ComputeValues.c} + \end{minipage} + \normalsize + \caption{Codice delle funzioni ausiliarie usate da \file{DirMonitor.c}.} + \label{fig:ipc_dirmonitor_sub} +\end{figure} + Completata l'inizializzazione e la creazione degli oggetti di intercomunicazione il programma entra nel ciclo principale (\texttt{\small 40--49}) dove vengono eseguite indefinitamente le attività di monitoraggio. @@ -3305,41 +2823,6 @@ degli stessi utilizzando la funzione \func{DirScan}; infine (\texttt{\small (\texttt{\small 47}) per il periodo di tempo specificato a riga di comando con l'opzione \code{-p} con una \func{sleep}. - -\begin{figure}[!htb] - \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -/* Routine to compute directory properties inside DirScan */ -int ComputeValues(struct dirent * direntry) -{ - struct stat data; - stat(direntry->d_name, &data); /* get stat data */ - shmptr->tot_size += data.st_size; - shmptr->tot_files++; - if (S_ISREG(data.st_mode)) shmptr->tot_regular++; - if (S_ISFIFO(data.st_mode)) shmptr->tot_fifo++; - if (S_ISLNK(data.st_mode)) shmptr->tot_link++; - if (S_ISDIR(data.st_mode)) shmptr->tot_dir++; - if (S_ISBLK(data.st_mode)) shmptr->tot_block++; - if (S_ISCHR(data.st_mode)) shmptr->tot_char++; - if (S_ISSOCK(data.st_mode)) shmptr->tot_sock++; - return 0; -} -/* Signal Handler to manage termination */ -void HandSIGTERM(int signo) { - MutexLock(mutex); - ShmRemove(key, shmptr); - MutexRemove(mutex); - exit(0); -} - \end{lstlisting} - \end{minipage} - \normalsize - \caption{Codice delle funzione ausiliarie usate da \file{DirMonitor.c}.} - \label{fig:ipc_dirmonitor_sub} -\end{figure} - Si noti come per il calcolo dei valori da mantenere nella memoria condivisa si sia usata ancora una volta la funzione \func{DirScan}, già utilizzata (e descritta in dettaglio) in \secref{sec:file_dir_read}, che ci permette di @@ -3374,36 +2857,8 @@ rimuove il mutex con \func{MutexRemove} ed esce (\texttt{\small 22}). \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -int main(int argc, char *argv[]) -{ - key_t key; - ... - /* create needed IPC objects */ - key = ftok("~/gapil/sources/DirMonitor.c", 1); /* define a key */ - if (!(shmptr = ShmFind(key, 4096))) { /* get a shared memory segment */ - perror("Cannot find shared memory"); - exit(1); - } - if ((mutex = MutexFind(key)) == -1) { /* get the Mutex */ - perror("Cannot find mutex"); - exit(1); - } - /* main loop */ - MutexLock(mutex); /* lock shared memory */ - printf("Ci sono %d file dati\n", shmptr->tot_regular); - printf("Ci sono %d directory\n", shmptr->tot_dir); - printf("Ci sono %d link\n", shmptr->tot_link); - printf("Ci sono %d fifo\n", shmptr->tot_fifo); - printf("Ci sono %d socket\n", shmptr->tot_sock); - printf("Ci sono %d device a caratteri\n", shmptr->tot_char); - printf("Ci sono %d device a blocchi\n", shmptr->tot_block); - printf("Totale %d file, per %d byte\n", - shmptr->tot_files, shmptr->tot_size); - MutexUnlock(mutex); /* unlock shared memory */ -} - \end{lstlisting} + \begin{minipage}[c]{15.6 cm} + \includecodesample{listati/ReadMonitor.c} \end{minipage} \normalsize \caption{Codice del programma client del monitor delle proprietà di una @@ -3592,26 +3047,8 @@ cancella con \func{unlink}. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -#include -#include -#include /* unix standard functions */ -/* - * Function LockFile: - */ -int LockFile(const char* path_name) -{ - return open(path_name, O_EXCL|O_CREAT); -} -/* - * Function UnlockFile: - */ -int UnlockFile(const char* path_name) -{ - return unlink(path_name); -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/LockFile.c} \end{minipage} \normalsize \caption{Il codice delle funzioni \func{LockFile} e \func{UnlockFile} che @@ -3672,64 +3109,8 @@ leggermente pi \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -/* Function CreateMutex: Create a mutex using file locking. */ -int CreateMutex(const char *path_name) -{ - return open(path_name, O_EXCL|O_CREAT); -} -/* Function UnlockMutex: unlock a file. */ -int FindMutex(const char *path_name) -{ - return open(path_name, O_RDWR); -} -/* Function LockMutex: lock mutex using file locking. */ -int LockMutex(int fd) -{ - struct flock lock; /* file lock structure */ - /* set flock structure */ - lock.l_type = F_WRLCK; /* set type: read or write */ - lock.l_whence = SEEK_SET; /* start from the beginning of the file */ - lock.l_start = 0; /* set the start of the locked region */ - lock.l_len = 0; /* set the length of the locked region */ - /* do locking */ - return fcntl(fd, F_SETLKW, &lock); -} -/* Function UnlockMutex: unlock a file. */ -int UnlockMutex(int fd) -{ - struct flock lock; /* file lock structure */ - /* set flock structure */ - lock.l_type = F_UNLCK; /* set type: unlock */ - lock.l_whence = SEEK_SET; /* start from the beginning of the file */ - lock.l_start = 0; /* set the start of the locked region */ - lock.l_len = 0; /* set the length of the locked region */ - /* do locking */ - return fcntl(fd, F_SETLK, &lock); -} -/* Function RemoveMutex: remove a mutex (unlinking the lock file). */ -int RemoveMutex(const char *path_name) -{ - return unlink(path_name); -} -/* Function ReadMutex: read a mutex status. */ -int ReadMutex(int fd) -{ - int res; - struct flock lock; /* file lock structure */ - /* set flock structure */ - lock.l_type = F_WRLCK; /* set type: unlock */ - lock.l_whence = SEEK_SET; /* start from the beginning of the file */ - lock.l_start = 0; /* set the start of the locked region */ - lock.l_len = 0; /* set the length of the locked region */ - /* do locking */ - if ( (res = fcntl(fd, F_GETLK, &lock)) ) { - return res; - } - return lock.l_type; -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/MutexLocking.c} \end{minipage} \normalsize \caption{Il codice delle funzioni che permettono per la gestione dei @@ -4037,14 +3418,7 @@ struttura \struct{mq\_attr}, la cui definizione \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct mq_attr { - long mq_flags; /* message queue flags */ - long mq_maxmsg; /* maximum number of messages */ - long mq_msgsize; /* maximum message size */ - long mq_curmsgs; /* number of messages currently queued */ -}; - \end{lstlisting} + \includestruct{listati/mq_attr.h} \end{minipage} \normalsize \caption{La struttura \structd{mq\_attr}, contenente gli attributi di una @@ -4514,54 +3888,8 @@ descriptor che fa riferimento ad un segmento distinto da eventuali precedenti. \begin{figure}[!htb] \footnotesize \centering - \begin{minipage}[c]{15cm} - \begin{lstlisting}{} -/* Function CreateShm: Create a shared memory segment mapping it */ -void * CreateShm(char * shm_name, off_t shm_size, mode_t perm, int fill) -{ - void * shm_ptr; - int fd; - int flag; - /* first open the object, creating it if not existent */ - flag = O_CREAT|O_EXCL|O_RDWR; - fd = shm_open(shm_name, flag, perm); /* get object file descriptor */ - if (fd < 0) { - return NULL; - } - /* set the object size */ - if (ftruncate(fd, shm_size)) { - return NULL; - } - /* map it in the process address space */ - shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); - if (shm_ptr == MAP_FAILED) { - return NULL; - } - memset((void *) shm_ptr, fill, shm_size); /* fill segment */ - return shm_ptr; -} -/* Function FindShm: Find a POSIX shared memory segment */ -void * FindShm(char * shm_name, off_t shm_size) -{ - void * shm_ptr; - int fd; /* ID of the IPC shared memory segment */ - /* find shared memory ID */ - if ((fd = shm_open(shm_name, O_RDWR|O_EXCL, 0)) < 0) { - return NULL; - } - /* take the pointer to it */ - shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); - if (shm_ptr == MAP_FAILED) { - return NULL; - } - return shm_ptr; -} -/* Function RemoveShm: Remove a POSIX shared memory segment */ -int RemoveShm(char * shm_name) -{ - return shm_unlink(shm_name); -} - \end{lstlisting} + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/MemShared.c} \end{minipage} \normalsize \caption{Il codice delle funzioni di gestione dei segmenti di memoria diff --git a/listati/BarCode.c b/listati/BarCode.c new file mode 100644 index 0000000..f2b1fe6 --- /dev/null +++ b/listati/BarCode.c @@ -0,0 +1,29 @@ +int main(int argc, char *argv[], char *envp[]) +{ + FILE *pipe[4]; + FILE *pipein; + char *cmd_string[4]={ + "pnmtopng", + "pnmmargin -white 10", + "pnmcrop", + "gs -sDEVICE=ppmraw -sOutputFile=- -sNOPAUSE -q - -c showpage -c quit" + }; + char content[]="Content-type: image/png\n\n"; + int i; + /* write mime-type to stdout */ + write(STDOUT_FILENO, content, strlen(content)); + /* execute chain of command */ + for (i=0; i<4; i++) { + pipe[i] = popen(cmd_string[i], "w"); + dup2(fileno(pipe[i]), STDOUT_FILENO); + } + /* create barcode (in PS) */ + pipein = popen("barcode", "w"); + /* send barcode string to barcode program */ + write(fileno(pipein), argv[1], strlen(argv[1])); + /* close all pipes (in reverse order) */ + for (i=4; i==0; i--) { + pclose((pipe[i])); + } + exit(0); +} diff --git a/listati/BarCodePage.c b/listati/BarCodePage.c new file mode 100644 index 0000000..26a8290 --- /dev/null +++ b/listati/BarCodePage.c @@ -0,0 +1,47 @@ +int main(int argc, char *argv[], char *envp[]) +{ + ... + /* create two pipes, pipein and pipeout, to handle communication */ + if ( (retval = pipe(pipein)) ) { + WriteMess("input pipe creation error"); + exit(0); + } + if ( (retval = pipe(pipeout)) ) { + WriteMess("output pipe creation error"); + exit(0); + } + /* First fork: use child to run barcode program */ + if ( (pid = fork()) == -1) { /* on error exit */ + WriteMess("child creation error"); + exit(0); + } + /* if child */ + if (pid == 0) { + close(pipein[1]); /* close pipe write end */ + dup2(pipein[0], STDIN_FILENO); /* remap stdin to pipe read end */ + close(pipeout[0]); + dup2(pipeout[1], STDOUT_FILENO); /* remap stdout in pipe output */ + execlp("barcode", "barcode", size, NULL); + } + close(pipein[0]); /* close input side of input pipe */ + write(pipein[1], argv[1], strlen(argv[1])); /* write parameter to pipe */ + close(pipein[1]); /* closing write end */ + waitpid(pid, NULL, 0); /* wait child completion */ + /* Second fork: use child to run ghostscript */ + if ( (pid = fork()) == -1) { + WriteMess("child creation error"); + exit(0); + } + /* second child, convert PS to JPEG */ + if (pid == 0) { + close(pipeout[1]); /* close write end */ + dup2(pipeout[0], STDIN_FILENO); /* remap read end to stdin */ + /* send mime type */ + write(STDOUT_FILENO, content, strlen(content)); + execlp("gs", "gs", "-q", "-sDEVICE=jpeg", "-sOutputFile=-", "-", NULL); + } + /* still parent */ + close(pipeout[1]); + waitpid(pid, NULL, 0); + exit(0); +} diff --git a/listati/ClientEcho.c b/listati/ClientEcho.c new file mode 100644 index 0000000..0a64e94 --- /dev/null +++ b/listati/ClientEcho.c @@ -0,0 +1,12 @@ +void ClientEcho(FILE * filein, int socket) +{ + char sendbuff[MAXLINE], recvbuff[MAXLINE]; + int nread; + while (fgets(sendbuff, MAXLINE, filein) != NULL) { + FullWrite(socket, sendbuff, strlen(sendbuff)); + nread = FullRead(socket, recvbuff, strlen(sendbuff)); + recvbuff[nread] = 0; + fputs(recvbuff, stdout); + } + return; +} diff --git a/listati/ComputeValues.c b/listati/ComputeValues.c new file mode 100644 index 0000000..bc11c28 --- /dev/null +++ b/listati/ComputeValues.c @@ -0,0 +1,23 @@ +/* Routine to compute directory properties inside DirScan */ +int ComputeValues(struct dirent * direntry) +{ + struct stat data; + stat(direntry->d_name, &data); /* get stat data */ + shmptr->tot_size += data.st_size; + shmptr->tot_files++; + if (S_ISREG(data.st_mode)) shmptr->tot_regular++; + if (S_ISFIFO(data.st_mode)) shmptr->tot_fifo++; + if (S_ISLNK(data.st_mode)) shmptr->tot_link++; + if (S_ISDIR(data.st_mode)) shmptr->tot_dir++; + if (S_ISBLK(data.st_mode)) shmptr->tot_block++; + if (S_ISCHR(data.st_mode)) shmptr->tot_char++; + if (S_ISSOCK(data.st_mode)) shmptr->tot_sock++; + return 0; +} +/* Signal Handler to manage termination */ +void HandSIGTERM(int signo) { + MutexLock(mutex); + ShmRemove(key, shmptr); + MutexRemove(mutex); + exit(0); +} diff --git a/listati/DirMonitor.c b/listati/DirMonitor.c new file mode 100644 index 0000000..edd5bb9 --- /dev/null +++ b/listati/DirMonitor.c @@ -0,0 +1,49 @@ +/* global variables for shared memory segment */ +struct DirProp { + int tot_size; + int tot_files; + int tot_regular; + int tot_fifo; + int tot_link; + int tot_dir; + int tot_block; + int tot_char; + int tot_sock; +} *shmptr; +key_t key; +int mutex; +/* main body */ +int main(int argc, char *argv[]) +{ + int i, pause = 10; + ... + if ((argc - optind) != 1) { /* There must be remaing parameters */ + printf("Wrong number of arguments %d\n", argc - optind); + usage(); + } + if (chdir(argv[1])) { /* chdir to be sure dir exist */ + perror("Cannot find directory to monitor"); + } + Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ + Signal(SIGINT, HandSIGTERM); + Signal(SIGQUIT, HandSIGTERM); + key = ftok("~/gapil/sources/DirMonitor.c", 1); /* define a key */ + shmptr = ShmCreate(key, 4096, 0666, 0); /* get a shared memory segment */ + if (!shmptr) { + perror("Cannot create shared memory"); + exit(1); + } + if ((mutex = MutexCreate(key)) == -1) { /* get a Mutex */ + perror("Cannot create mutex"); + exit(1); + } + /* main loop, monitor directory properties each 10 sec */ + daemon(1, 0); /* demonize process, staying in monitored dir */ + while (1) { + MutexLock(mutex); /* lock shared memory */ + memset(shmptr, 0, sizeof(struct DirProp)); /* erase previous data */ + DirScan(argv[1], ComputeValues); /* execute scan */ + MutexUnlock(mutex); /* unlock shared memory */ + sleep(pause); /* sleep until next watch */ + } +} diff --git a/listati/EchoServerWrong.c b/listati/EchoServerWrong.c new file mode 100644 index 0000000..f9a67b6 --- /dev/null +++ b/listati/EchoServerWrong.c @@ -0,0 +1,32 @@ +int main(int argc, char *argv[]) +{ +/* + * Variables definition + */ + int sock_fd, i; + struct sockaddr_in serv_add; + ... + /* create socket */ + if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Socket creation error"); + return -1; + } + /* initialize address */ + memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */ + serv_add.sin_family = AF_INET; /* address type is INET */ + serv_add.sin_port = htons(7); /* echo port is 7 */ + /* build address using inet_pton */ + if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) { + perror("Address creation error"); + return -1; + } + /* extablish connection */ + if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { + perror("Connection error"); + return -1; + } + /* read daytime from server */ + ClientEcho(stdin, sock_fd); + /* normal exit */ + return 0; +} diff --git a/listati/ElemDaytimeTCPClient.c b/listati/ElemDaytimeTCPClient.c new file mode 100644 index 0000000..e1459d9 --- /dev/null +++ b/listati/ElemDaytimeTCPClient.c @@ -0,0 +1,48 @@ +#include /* predefined types */ +#include /* include unix standard library */ +#include /* IP addresses conversion utilities */ +#include /* socket library */ +#include /* include standard I/O library */ + +int main(int argc, char *argv[]) +{ + int sock_fd; + int i, nread; + struct sockaddr_in serv_add; + char buffer[MAXLINE]; + ... + /* create socket */ + if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Socket creation error"); + return -1; + } + /* initialize address */ + memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */ + serv_add.sin_family = AF_INET; /* address type is INET */ + serv_add.sin_port = htons(13); /* daytime post is 13 */ + /* build address using inet_pton */ + if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) { + perror("Address creation error"); + return -1; + } + /* extablish connection */ + if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { + perror("Connection error"); + return -1; + } + /* read daytime from server */ + while ( (nread = read(sock_fd, buffer, MAXLINE)) > 0) { + buffer[nread]=0; + if (fputs(buffer, stdout) == EOF) { /* write daytime */ + perror("fputs error"); + return -1; + } + } + /* error on read */ + if (nread < 0) { + perror("Read error"); + return -1; + } + /* normal exit */ + return 0; +} diff --git a/listati/ElemDaytimeTCPCuncServ.c b/listati/ElemDaytimeTCPCuncServ.c new file mode 100644 index 0000000..9af8cc7 --- /dev/null +++ b/listati/ElemDaytimeTCPCuncServ.c @@ -0,0 +1,52 @@ +#include /* predefined types */ +#include /* include unix standard library */ +#include /* IP addresses conversion utililites */ +#include /* socket library */ +#include /* include standard I/O library */ +#include + +int main(int argc, char *argv[]) +{ + int list_fd, conn_fd; + int i; + struct sockaddr_in serv_add, client; + char buffer[MAXLINE]; + socklen_t len; + time_t timeval; + pid_t pid; + int logging=0; + ... + /* write daytime to client */ + while (1) { + if ( (conn_fd = accept(list_fd, (struct sockaddr *)&client, &len)) + <0 ) { + perror("accept error"); + exit(-1); + } + /* fork to handle connection */ + if ( (pid = fork()) < 0 ){ + perror("fork error"); + exit(-1); + } + if (pid == 0) { /* child */ + close(list_fd); + timeval = time(NULL); + snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval)); + if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) { + perror("write error"); + exit(-1); + } + if (logging) { + inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer)); + printf("Request from host %s, port %d\n", buffer, + ntohs(client.sin_port)); + } + close(conn_fd); + exit(0); + } else { /* parent */ + close(conn_fd); + } + } + /* normal exit, never reached */ + exit(0); +} diff --git a/listati/ElemDaytimeTCPServer.c b/listati/ElemDaytimeTCPServer.c new file mode 100644 index 0000000..5f9b116 --- /dev/null +++ b/listati/ElemDaytimeTCPServer.c @@ -0,0 +1,56 @@ +#include /* predefined types */ +#include /* include unix standard library */ +#include /* IP addresses conversion utilities */ +#include /* socket library */ +#include /* include standard I/O library */ +#include +#define MAXLINE 80 +#define BACKLOG 10 +int main(int argc, char *argv[]) +{ +/* + * Variables definition + */ + int list_fd, conn_fd; + int i; + struct sockaddr_in serv_add; + char buffer[MAXLINE]; + time_t timeval; + ... + /* create socket */ + if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Socket creation error"); + exit(-1); + } + /* initialize address */ + memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */ + serv_add.sin_family = AF_INET; /* address type is INET */ + serv_add.sin_port = htons(13); /* daytime port is 13 */ + serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ + /* bind socket */ + if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { + perror("bind error"); + exit(-1); + } + /* listen on socket */ + if (listen(list_fd, BACKLOG) < 0 ) { + perror("listen error"); + exit(-1); + } + /* write daytime to client */ + while (1) { + if ( (conn_fd = accept(list_fd, (struct sockaddr *) NULL, NULL)) <0 ) { + perror("accept error"); + exit(-1); + } + timeval = time(NULL); + snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval)); + if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) { + perror("write error"); + exit(-1); + } + close(conn_fd); + } + /* normal exit */ + exit(0); +} diff --git a/listati/ElemEchoTCPServer.c b/listati/ElemEchoTCPServer.c new file mode 100644 index 0000000..a434957 --- /dev/null +++ b/listati/ElemEchoTCPServer.c @@ -0,0 +1,52 @@ +/* Subroutines declaration */ +void ServEcho(int sockfd); +/* Program beginning */ +int main(int argc, char *argv[]) +{ + int list_fd, conn_fd; + pid_t pid; + struct sockaddr_in serv_add; + ... + /* create socket */ + if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("Socket creation error"); + exit(-1); + } + /* initialize address */ + memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */ + serv_add.sin_family = AF_INET; /* address type is INET */ + serv_add.sin_port = htons(13); /* daytime port is 13 */ + serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ + /* bind socket */ + if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { + perror("bind error"); + exit(-1); + } + /* listen on socket */ + if (listen(list_fd, BACKLOG) < 0 ) { + perror("listen error"); + exit(-1); + } + /* handle echo to client */ + while (1) { + /* accept connection */ + if ( (conn_fd = accept(list_fd, NULL, NULL)) < 0) { + perror("accept error"); + exit(-1); + } + /* fork to handle connection */ + if ( (pid = fork()) < 0 ){ + perror("fork error"); + exit(-1); + } + if (pid == 0) { /* child */ + close(list_fd); /* close listening socket */ + SockEcho(conn_fd); /* handle echo */ + exit(0); + } else { /* parent */ + close(conn_fd); /* close connected socket */ + } + } + /* normal exit, never reached */ + exit(0); +} diff --git a/listati/Flock.c b/listati/Flock.c new file mode 100644 index 0000000..cf85d3b --- /dev/null +++ b/listati/Flock.c @@ -0,0 +1,52 @@ +int main(int argc, char *argv[]) +{ + int type = F_UNLCK; /* lock type: default to unlock (invalid) */ + off_t start = 0; /* start of the locked region: default to 0 */ + off_t len = 0; /* length of the locked region: default to 0 */ + int fd, res, i; /* internal variables */ + int bsd = 0; /* semantic type: default to POSIX */ + int cmd = F_SETLK; /* lock command: default to non-blocking */ + struct flock lock; /* file lock structure */ + ... + if ((argc - optind) != 1) { /* There must be remaing parameters */ + printf("Wrong number of arguments %d\n", argc - optind); + usage(); + } + if (type == F_UNLCK) { /* There must be a -w or -r option set */ + printf("You should set a read or a write lock\n"); + usage(); + } + fd = open(argv[optind], O_RDWR); /* open the file to be locked */ + if (fd < 0) { /* on error exit */ + perror("Wrong filename"); + exit(1); + } + /* do lock */ + if (bsd) { /* if BSD locking */ + /* rewrite cmd for suitables flock operation values */ + if (cmd == F_SETLKW) { /* if no-blocking */ + cmd = LOCK_NB; /* set the value for flock operation */ + } else { /* else */ + cmd = 0; /* default is null */ + } + if (type == F_RDLCK) cmd |= LOCK_SH; /* set for shared lock */ + if (type == F_WRLCK) cmd |= LOCK_EX; /* set for exclusive lock */ + res = flock(fd, cmd); /* esecute lock */ + } else { /* if POSIX locking */ + /* setting flock structure */ + lock.l_type = type; /* set type: read or write */ + lock.l_whence = SEEK_SET; /* start from the beginning of the file */ + lock.l_start = start; /* set the start of the locked region */ + lock.l_len = len; /* set the length of the locked region */ + res = fcntl(fd, cmd, &lock); /* do lock */ + } + /* check lock results */ + if (res) { /* on error exit */ + perror("Failed lock"); + exit(1); + } else { /* else write message */ + printf("Lock acquired\n"); + } + pause(); /* stop the process, use a signal to exit */ + return 0; +} diff --git a/listati/FortuneClient.c b/listati/FortuneClient.c new file mode 100644 index 0000000..f0c1030 --- /dev/null +++ b/listati/FortuneClient.c @@ -0,0 +1,36 @@ +int main(int argc, char *argv[]) +{ +/* Variables definition */ + int n = 0; + char *fortunefilename = "/tmp/fortune.fifo"; + char line[80]; + int fifo_server, fifo_client; + char fifoname[80]; + int nread; + char buffer[PIPE_BUF]; + ... + snprintf(fifoname, 80, "/tmp/fortune.%d", getpid()); /* compose name */ + if (mkfifo(fifoname, 0622)) { /* open client fifo */ + if (errno!=EEXIST) { + perror("Cannot create well known fifo"); + exit(-1); + } + } + fifo_server = open(fortunefilename, O_WRONLY); /* open server fifo */ + if (fifo_server < 0) { + perror("Cannot open well known fifo"); + exit(-1); + } + nread = write(fifo_server, fifoname, strlen(fifoname)+1); /* write name */ + close(fifo_server); /* close server fifo */ + fifo_client = open(fifoname, O_RDONLY); /* open client fifo */ + if (fifo_client < 0) { + perror("Cannot open well known fifo"); + exit(-1); + } + nread = read(fifo_client, buffer, sizeof(buffer)); /* read answer */ + printf("%s", buffer); /* print fortune */ + close(fifo_client); /* close client */ + close(fifo_server); /* close server */ + unlink(fifoname); /* remove client fifo */ +} diff --git a/listati/FortuneServer.c b/listati/FortuneServer.c new file mode 100644 index 0000000..7c45d23 --- /dev/null +++ b/listati/FortuneServer.c @@ -0,0 +1,52 @@ +char *fifoname = "/tmp/fortune.fifo"; +int main(int argc, char *argv[]) +{ +/* Variables definition */ + int i, n = 0; + char *fortunefilename = "/usr/share/games/fortunes/linux"; + char **fortune; + char line[80]; + int fifo_server, fifo_client; + int nread; + ... + if (n==0) usage(); /* if no pool depth exit printing usage info */ + Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ + Signal(SIGINT, HandSIGTERM); + Signal(SIGQUIT, HandSIGTERM); + i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */ + if (mkfifo(fifoname, 0622)) { /* create well known fifo if does't exist */ + if (errno!=EEXIST) { + perror("Cannot create well known fifo"); + exit(1); + } + } + daemon(0, 0); + /* open fifo two times to avoid EOF */ + fifo_server = open(fifoname, O_RDONLY); + if (fifo_server < 0) { + perror("Cannot open read only well known fifo"); + exit(1); + } + if (open(fifoname, O_WRONLY) < 0) { + perror("Cannot open write only well known fifo"); + exit(1); + } + /* Main body: loop over requests */ + while (1) { + nread = read(fifo_server, line, 79); /* read request */ + if (nread < 0) { + perror("Read Error"); + exit(1); + } + line[nread] = 0; /* terminate fifo name string */ + n = random() % i; /* select random value */ + fifo_client = open(line, O_WRONLY); /* open client fifo */ + if (fifo_client < 0) { + perror("Cannot open"); + exit(1); + } + nread = write(fifo_client, /* write phrase */ + fortune[n], strlen(fortune[n])+1); + close(fifo_client); /* close client fifo */ + } +} diff --git a/listati/FullRead.c b/listati/FullRead.c new file mode 100644 index 0000000..fcc265b --- /dev/null +++ b/listati/FullRead.c @@ -0,0 +1,23 @@ +#include + +ssize_t FullRead(int fd, void *buf, size_t count) +{ + size_t nleft; + ssize_t nread; + + nleft = count; + while (nleft > 0) { /* repeat until no left */ + if ( (nread = read(fd, buf, nleft)) < 0) { + if (errno == EINTR) { /* if interrupted by system call */ + continue; /* repeat the loop */ + } else { + return(nread); /* otherwise exit */ + } + } else if (nread == 0) { /* EOF */ + break; /* break loop here */ + } + nleft -= nread; /* set left to read */ + buf +=nread; /* set pointer */ + } + return (count - nleft); +} diff --git a/listati/FullWrite.c b/listati/FullWrite.c new file mode 100644 index 0000000..505a1b8 --- /dev/null +++ b/listati/FullWrite.c @@ -0,0 +1,21 @@ +#include + +ssize_t FullWrite(int fd, const void *buf, size_t count) +{ + size_t nleft; + ssize_t nwritten; + + nleft = count; + while (nleft > 0) { /* repeat until no left */ + if ( (nwritten = write(fd, buf, nleft)) < 0) { + if (errno == EINTR) { /* if interrupted by system call */ + continue; /* repeat the loop */ + } else { + return(nwritten); /* otherwise exit with error */ + } + } + nleft -= nwritten; /* set left to write */ + buf +=nwritten; /* set pointer */ + } + return (count); +} diff --git a/listati/IPCTestId.c b/listati/IPCTestId.c new file mode 100644 index 0000000..4508c6f --- /dev/null +++ b/listati/IPCTestId.c @@ -0,0 +1,33 @@ +int main(int argc, char *argv[]) +{ + ... + switch (type) { + case 'q': /* Message Queue */ + debug("Message Queue Try\n"); + for (i=0; i +#include +#include /* unix standard functions */ +/* + * Function LockFile: + */ +int LockFile(const char* path_name) +{ + return open(path_name, O_EXCL|O_CREAT); +} +/* + * Function UnlockFile: + */ +int UnlockFile(const char* path_name) +{ + return unlink(path_name); +} diff --git a/listati/MQFortuneClient.c b/listati/MQFortuneClient.c new file mode 100644 index 0000000..84f86c6 --- /dev/null +++ b/listati/MQFortuneClient.c @@ -0,0 +1,17 @@ +int main(int argc, char *argv[]) +{ + ... + key = ftok("./MQFortuneServer.c", 1); + msgid = msgget(key, 0); + if (msgid < 0) { + perror("Cannot find message queue"); + exit(1); + } + /* Main body: do request and write result */ + msg_read.mtype = 1; /* type for request is always 1 */ + msg_read.pid = getpid(); /* use pid for communications */ + size = sizeof(msg_read.pid); + msgsnd(msgid, &msg_read, size, 0); /* send request message */ + msgrcv(msgid, &msg_write, MSGMAX, msg_read.pid, MSG_NOERROR); + printf("%s", msg_write.mtext); +} diff --git a/listati/MQFortuneServer.c b/listati/MQFortuneServer.c new file mode 100644 index 0000000..cd0dd1e --- /dev/null +++ b/listati/MQFortuneServer.c @@ -0,0 +1,48 @@ +int msgid; /* Message queue identifier */ +int main(int argc, char *argv[]) +{ +/* Variables definition */ + int i, n = 0; + char **fortune; /* array of fortune message string */ + char *fortunefilename = "/usr/share/games/fortunes/linux"; /* file name */ + struct msgbuf_read { /* message struct to read request from clients */ + long mtype; /* message type, must be 1 */ + long pid; /* message data, must be the pid of the client */ + } msg_read; + struct msgbuf_write { /* message struct to write result to clients */ + long mtype; /* message type, will be the pid of the client*/ + char mtext[MSGMAX]; /* message data, will be the fortune */ + } msg_write; + key_t key; /* Message queue key */ + int size; /* message size */ + ... + Signal(SIGTERM, HandSIGTERM); /* set handlers for termination */ + Signal(SIGINT, HandSIGTERM); + Signal(SIGQUIT, HandSIGTERM); + if (n==0) usage(); /* if no pool depth exit printing usage info */ + i = FortuneParse(fortunefilename, fortune, n); /* parse phrases */ + /* Create the queue */ + key = ftok("./MQFortuneServer.c", 1); + msgid = msgget(key, IPC_CREAT|0666); + if (msgid < 0) { + perror("Cannot create message queue"); + exit(1); + } + /* Main body: loop over requests */ + daemon(0, 0); + while (1) { + msgrcv(msgid, &msg_read, sizeof(int), 1, MSG_NOERROR); + n = random() % i; /* select random value */ + strncpy(msg_write.mtext, fortune[n], MSGMAX); + size = min(strlen(fortune[n])+1, MSGMAX); + msg_write.mtype=msg_read.pid; /* use request pid as type */ + msgsnd(msgid, &msg_write, size, 0); + } +} +/* + * Signal Handler to manage termination + */ +void HandSIGTERM(int signo) { + msgctl(msgid, IPC_RMID, NULL); /* remove message queue */ + exit(0); +} diff --git a/listati/MemShared.c b/listati/MemShared.c new file mode 100644 index 0000000..dfeea8d --- /dev/null +++ b/listati/MemShared.c @@ -0,0 +1,45 @@ +/* Function CreateShm: Create a shared memory segment mapping it */ +void * CreateShm(char * shm_name, off_t shm_size, mode_t perm, int fill) +{ + void * shm_ptr; + int fd; + int flag; + /* first open the object, creating it if not existent */ + flag = O_CREAT|O_EXCL|O_RDWR; + fd = shm_open(shm_name, flag, perm); /* get object file descriptor */ + if (fd < 0) { + return NULL; + } + /* set the object size */ + if (ftruncate(fd, shm_size)) { + return NULL; + } + /* map it in the process address space */ + shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); + if (shm_ptr == MAP_FAILED) { + return NULL; + } + memset((void *) shm_ptr, fill, shm_size); /* fill segment */ + return shm_ptr; +} +/* Function FindShm: Find a POSIX shared memory segment */ +void * FindShm(char * shm_name, off_t shm_size) +{ + void * shm_ptr; + int fd; /* ID of the IPC shared memory segment */ + /* find shared memory ID */ + if ((fd = shm_open(shm_name, O_RDWR|O_EXCL, 0)) < 0) { + return NULL; + } + /* take the pointer to it */ + shm_ptr = mmap(NULL, shm_size, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0); + if (shm_ptr == MAP_FAILED) { + return NULL; + } + return shm_ptr; +} +/* Function RemoveShm: Remove a POSIX shared memory segment */ +int RemoveShm(char * shm_name) +{ + return shm_unlink(shm_name); +} diff --git a/listati/Mutex.c b/listati/Mutex.c new file mode 100644 index 0000000..3d0c4c0 --- /dev/null +++ b/listati/Mutex.c @@ -0,0 +1,49 @@ +/* Function MutexCreate: create a mutex/semaphore */ +int MutexCreate(key_t ipc_key) +{ + const union semun semunion={1}; /* semaphore union structure */ + int sem_id, ret; + sem_id = semget(ipc_key, 1, IPC_CREAT|0666); /* get semaphore ID */ + if (sem_id == -1) { /* if error return code */ + return sem_id; + } + ret = semctl(sem_id, 0, SETVAL, semunion); /* init semaphore */ + if (ret == -1) { + return ret; + } + return sem_id; +} +/* Function MutexFind: get the semaphore/mutex Id given the IPC key value */ +int MutexFind(key_t ipc_key) +{ + return semget(ipc_key,1,0); +} +/* Function MutexRead: read the current value of the mutex/semaphore */ +int MutexRead(int sem_id) +{ + return semctl(sem_id, 0, GETVAL); +} +/* Define sembuf structures to lock and unlock the semaphore */ +struct sembuf sem_lock={ /* to lock semaphore */ + 0, /* semaphore number (only one so 0) */ + -1, /* operation (-1 to use resource) */ + SEM_UNDO}; /* flag (set for undo at exit) */ +struct sembuf sem_ulock={ /* to unlock semaphore */ + 0, /* semaphore number (only one so 0) */ + 1, /* operation (1 to release resource) */ + SEM_UNDO}; /* flag (in this case 0) */ +/* Function MutexLock: to lock a mutex/semaphore */ +int MutexLock(int sem_id) +{ + return semop(sem_id, &sem_lock, 1); +} +/* Function MutexUnlock: to unlock a mutex/semaphore */ +int MutexUnlock(int sem_id) +{ + return semop(sem_id, &sem_ulock, 1); +} +/* Function MutexRemove: remove a mutex/semaphore */ +int MutexRemove(int sem_id) +{ + return semctl(sem_id, 0, IPC_RMID); +} diff --git a/listati/MutexLocking.c b/listati/MutexLocking.c new file mode 100644 index 0000000..1b45315 --- /dev/null +++ b/listati/MutexLocking.c @@ -0,0 +1,55 @@ +/* Function CreateMutex: Create a mutex using file locking. */ +int CreateMutex(const char *path_name) +{ + return open(path_name, O_EXCL|O_CREAT); +} +/* Function UnlockMutex: unlock a file. */ +int FindMutex(const char *path_name) +{ + return open(path_name, O_RDWR); +} +/* Function LockMutex: lock mutex using file locking. */ +int LockMutex(int fd) +{ + struct flock lock; /* file lock structure */ + /* set flock structure */ + lock.l_type = F_WRLCK; /* set type: read or write */ + lock.l_whence = SEEK_SET; /* start from the beginning of the file */ + lock.l_start = 0; /* set the start of the locked region */ + lock.l_len = 0; /* set the length of the locked region */ + /* do locking */ + return fcntl(fd, F_SETLKW, &lock); +} +/* Function UnlockMutex: unlock a file. */ +int UnlockMutex(int fd) +{ + struct flock lock; /* file lock structure */ + /* set flock structure */ + lock.l_type = F_UNLCK; /* set type: unlock */ + lock.l_whence = SEEK_SET; /* start from the beginning of the file */ + lock.l_start = 0; /* set the start of the locked region */ + lock.l_len = 0; /* set the length of the locked region */ + /* do locking */ + return fcntl(fd, F_SETLK, &lock); +} +/* Function RemoveMutex: remove a mutex (unlinking the lock file). */ +int RemoveMutex(const char *path_name) +{ + return unlink(path_name); +} +/* Function ReadMutex: read a mutex status. */ +int ReadMutex(int fd) +{ + int res; + struct flock lock; /* file lock structure */ + /* set flock structure */ + lock.l_type = F_WRLCK; /* set type: unlock */ + lock.l_whence = SEEK_SET; /* start from the beginning of the file */ + lock.l_start = 0; /* set the start of the locked region */ + lock.l_len = 0; /* set the length of the locked region */ + /* do locking */ + if ( (res = fcntl(fd, F_GETLK, &lock)) ) { + return res; + } + return lock.l_type; +} diff --git a/listati/ReadMonitor.c b/listati/ReadMonitor.c new file mode 100644 index 0000000..8881795 --- /dev/null +++ b/listati/ReadMonitor.c @@ -0,0 +1,27 @@ +int main(int argc, char *argv[]) +{ + key_t key; + ... + /* create needed IPC objects */ + key = ftok("~/gapil/sources/DirMonitor.c", 1); /* define a key */ + if (!(shmptr = ShmFind(key, 4096))) { /* get a shared memory segment */ + perror("Cannot find shared memory"); + exit(1); + } + if ((mutex = MutexFind(key)) == -1) { /* get the Mutex */ + perror("Cannot find mutex"); + exit(1); + } + /* main loop */ + MutexLock(mutex); /* lock shared memory */ + printf("Ci sono %d file dati\n", shmptr->tot_regular); + printf("Ci sono %d directory\n", shmptr->tot_dir); + printf("Ci sono %d link\n", shmptr->tot_link); + printf("Ci sono %d fifo\n", shmptr->tot_fifo); + printf("Ci sono %d socket\n", shmptr->tot_sock); + printf("Ci sono %d device a caratteri\n", shmptr->tot_char); + printf("Ci sono %d device a blocchi\n", shmptr->tot_block); + printf("Totale %d file, per %d byte\n", + shmptr->tot_files, shmptr->tot_size); + MutexUnlock(mutex); /* unlock shared memory */ +} diff --git a/listati/ServEcho.c b/listati/ServEcho.c new file mode 100644 index 0000000..917c7c4 --- /dev/null +++ b/listati/ServEcho.c @@ -0,0 +1,10 @@ +void ServEcho(int sockfd) { + char buffer[MAXLINE]; + int nread, nwrite; + + /* main loop, reading 0 char means client close connection */ + while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) { + nwrite = FullWrite(sockfd, buffer, nread); + } + return; +} diff --git a/listati/SetTermAttr.c b/listati/SetTermAttr.c new file mode 100644 index 0000000..41656f2 --- /dev/null +++ b/listati/SetTermAttr.c @@ -0,0 +1,21 @@ +#include +#include +#include + +int SetTermAttr(int fd, tcflag_t flag) +{ + struct termios values; + int res; + res = tcgetattr (desc, &values); + if (res) { + perror("Cannot get attributes"); + return res; + } + values.c_lflag |= flag; + res = tcsetattr (desc, TCSANOW, &values); + if (res) { + perror("Cannot set attributes"); + return res; + } + return 0; +} diff --git a/listati/SharedMem.c b/listati/SharedMem.c new file mode 100644 index 0000000..9f5b438 --- /dev/null +++ b/listati/SharedMem.c @@ -0,0 +1,51 @@ +/* Function ShmCreate Create a SysV shared memory segment */ +void * ShmCreate(key_t ipc_key, int shm_size, int perm, int fill) +{ + void * shm_ptr; + int shm_id; /* ID of the IPC shared memory segment */ + shm_id = shmget(ipc_key, shm_size, IPC_CREAT|perm); /* get shm ID */ + if (shm_id < 0) { + return NULL; + } + shm_ptr = shmat(shm_id, NULL, 0); /* map it into memory */ + if (shm_ptr < 0) { + return NULL; + } + memset((void *)shm_ptr, fill, shm_size); /* fill segment */ + return shm_ptr; +} +/* Function ShmFind: Find a SysV shared memory segment */ +void * ShmFind(key_t ipc_key, int shm_size) +{ + void * shm_ptr; + int shm_id; /* ID of the SysV shared memory segment */ + shm_id = shmget(ipc_key, shm_size, 0); /* find shared memory ID */ + if (shm_id < 0) { + return NULL; + } + shm_ptr = shmat(shm_id, NULL, 0); /* map it into memory */ + if (shm_ptr < 0) { + return NULL; + } + return shm_ptr; +} +/* Function ShmRemove: Schedule removal for a SysV shared memory segment */ +int ShmRemove(key_t ipc_key, void * shm_ptr) +{ + int shm_id; /* ID of the SysV shared memory segment */ + /* first detach segment */ + if (shmdt(shm_ptr) < 0) { + return -1; + } + /* schedule segment removal */ + shm_id = shmget(ipc_key, 0, 0); /* find shared memory ID */ + if (shm_id < 0) { + if (errno == EIDRM) return 0; + return -1; + } + if (shmctl(shm_id, IPC_RMID, NULL) < 0) { /* ask for removal */ + if (errno == EIDRM) return 0; + return -1; + } + return 0; +} diff --git a/listati/UnSetTermAttr.c b/listati/UnSetTermAttr.c new file mode 100644 index 0000000..fbeec75 --- /dev/null +++ b/listati/UnSetTermAttr.c @@ -0,0 +1,17 @@ +int UnSetTermAttr(int fd, tcflag_t flag) +{ + struct termios values; + int res; + res = tcgetattr (desc, &values); + if (res) { + perror("Cannot get attributes"); + return res; + } + values.c_lflag &= (~flag); + res = tcsetattr (desc, TCSANOW, &values); + if (res) { + perror("Cannot set attributes"); + return res; + } + return 0; +} diff --git a/listati/aiocb.h b/listati/aiocb.h new file mode 100644 index 0000000..fd3c643 --- /dev/null +++ b/listati/aiocb.h @@ -0,0 +1,10 @@ +struct aiocb +{ + int aio_fildes; /* File descriptor. */ + off_t aio_offset; /* File offset */ + int aio_lio_opcode; /* Operation to be performed. */ + int aio_reqprio; /* Request priority offset. */ + volatile void *aio_buf; /* Location of buffer. */ + size_t aio_nbytes; /* Length of transfer. */ + struct sigevent aio_sigevent; /* Signal number and value. */ +}; diff --git a/listati/flock.h b/listati/flock.h new file mode 100644 index 0000000..4768dcd --- /dev/null +++ b/listati/flock.h @@ -0,0 +1,7 @@ +struct flock { + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek').*/ + off_t l_start; /* Offset where the lock begins. */ + off_t l_len; /* Size of the locked area; zero means until EOF.*/ + pid_t l_pid; /* Process holding the lock. */ +}; diff --git a/listati/iovec.h b/listati/iovec.h new file mode 100644 index 0000000..963751b --- /dev/null +++ b/listati/iovec.h @@ -0,0 +1,4 @@ +struct iovec { + __ptr_t iov_base; /* Starting address */ + size_t iov_len; /* Length in bytes */ +}; diff --git a/listati/ipc_perm.h b/listati/ipc_perm.h new file mode 100644 index 0000000..9c7949e --- /dev/null +++ b/listati/ipc_perm.h @@ -0,0 +1,10 @@ +struct ipc_perm +{ + key_t key; /* Key. */ + uid_t uid; /* Owner's user ID. */ + gid_t gid; /* Owner's group ID. */ + uid_t cuid; /* Creator's user ID. */ + gid_t cgid; /* Creator's group ID. */ + unsigned short int mode; /* Read/write permission. */ + unsigned short int seq; /* Sequence number. */ +}; diff --git a/listati/mq_attr.h b/listati/mq_attr.h new file mode 100644 index 0000000..be2ef47 --- /dev/null +++ b/listati/mq_attr.h @@ -0,0 +1,6 @@ +struct mq_attr { + long mq_flags; /* message queue flags */ + long mq_maxmsg; /* maximum number of messages */ + long mq_msgsize; /* maximum message size */ + long mq_curmsgs; /* number of messages currently queued */ +}; diff --git a/listati/msgbuf.h b/listati/msgbuf.h new file mode 100644 index 0000000..a487e48 --- /dev/null +++ b/listati/msgbuf.h @@ -0,0 +1,4 @@ +struct msgbuf { + long mtype; /* message type, must be > 0 */ + char mtext[LENGTH]; /* message data */ +}; diff --git a/listati/msqid_ds.h b/listati/msqid_ds.h new file mode 100644 index 0000000..4efeabe --- /dev/null +++ b/listati/msqid_ds.h @@ -0,0 +1,13 @@ +struct msqid_ds { + struct ipc_perm msg_perm; /* structure for operation permission */ + time_t msg_stime; /* time of last msgsnd command */ + time_t msg_rtime; /* time of last msgrcv command */ + time_t msg_ctime; /* time of last change */ + msgqnum_t msg_qnum; /* number of messages currently on queue */ + msglen_t msg_qbytes; /* max number of bytes allowed on queue */ + pid_t msg_lspid; /* pid of last msgsnd() */ + pid_t msg_lrpid; /* pid of last msgrcv() */ + struct msg *msg_first; /* first message on queue, unused */ + struct msg *msg_last; /* last message in queue, unused */ + unsigned long int msg_cbytes; /* current number of bytes on queue */ +}; diff --git a/listati/oflag.c b/listati/oflag.c new file mode 100644 index 0000000..9b4a965 --- /dev/null +++ b/listati/oflag.c @@ -0,0 +1,2 @@ + c_oflag &= (~CRDLY); + c_oflag |= CR1; diff --git a/listati/pollfd.h b/listati/pollfd.h new file mode 100644 index 0000000..cb1cbb4 --- /dev/null +++ b/listati/pollfd.h @@ -0,0 +1,5 @@ +struct pollfd { + int fd; /* file descriptor */ + short events; /* requested events */ + short revents; /* returned events */ +}; diff --git a/listati/sem.h b/listati/sem.h new file mode 100644 index 0000000..a219929 --- /dev/null +++ b/listati/sem.h @@ -0,0 +1,6 @@ +struct sem { + short sempid; /* pid of last operation */ + ushort semval; /* current value */ + ushort semncnt; /* num procs awaiting increase in semval */ + ushort semzcnt; /* num procs awaiting semval = 0 */ +}; diff --git a/listati/sembuf.h b/listati/sembuf.h new file mode 100644 index 0000000..277b34f --- /dev/null +++ b/listati/sembuf.h @@ -0,0 +1,6 @@ +struct sembuf +{ + unsigned short int sem_num; /* semaphore number */ + short int sem_op; /* semaphore operation */ + short int sem_flg; /* operation flag */ +}; diff --git a/listati/semid_ds.h b/listati/semid_ds.h new file mode 100644 index 0000000..24d797b --- /dev/null +++ b/listati/semid_ds.h @@ -0,0 +1,7 @@ +struct semid_ds +{ + struct ipc_perm sem_perm; /* operation permission struct */ + time_t sem_otime; /* last semop() time */ + time_t sem_ctime; /* last time changed by semctl() */ + unsigned long int sem_nsems; /* number of semaphores in set */ +}; diff --git a/listati/semun.h b/listati/semun.h new file mode 100644 index 0000000..3b90c50 --- /dev/null +++ b/listati/semun.h @@ -0,0 +1,7 @@ +union semun { + int val; /* value for SETVAL */ + struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */ + unsigned short *array; /* array for GETALL, SETALL */ + /* Linux specific part: */ + struct seminfo *__buf; /* buffer for IPC_INFO */ +}; diff --git a/listati/serv_addr_sin6_addr.c b/listati/serv_addr_sin6_addr.c new file mode 100644 index 0000000..a758ebb --- /dev/null +++ b/listati/serv_addr_sin6_addr.c @@ -0,0 +1 @@ + serv_add.sin6_addr = in6addr_any; diff --git a/listati/serv_addr_sin_addr.c b/listati/serv_addr_sin_addr.c new file mode 100644 index 0000000..97a9181 --- /dev/null +++ b/listati/serv_addr_sin_addr.c @@ -0,0 +1 @@ + serv_add.sin_addr.s_addr = htonl(INADDR_ANY); diff --git a/listati/shmid_ds.h b/listati/shmid_ds.h new file mode 100644 index 0000000..37ea5e3 --- /dev/null +++ b/listati/shmid_ds.h @@ -0,0 +1,10 @@ +struct shmid_ds { + struct ipc_perm shm_perm; /* operation perms */ + int shm_segsz; /* size of segment (bytes) */ + time_t shm_atime; /* last attach time */ + time_t shm_dtime; /* last detach time */ + time_t shm_ctime; /* last change time */ + unsigned short shm_cpid; /* pid of creator */ + unsigned short shm_lpid; /* pid of last operator */ + short shm_nattch; /* no. of current attaches */ +}; diff --git a/listati/sigchildhand.c b/listati/sigchildhand.c new file mode 100644 index 0000000..8ded584 --- /dev/null +++ b/listati/sigchildhand.c @@ -0,0 +1,5 @@ + ... + /* install SIGCHLD handler */ + Signal(SIGCHLD, sigchld_hand); /* establish handler */ + /* create socket */ + ... diff --git a/listati/sigevent.h b/listati/sigevent.h new file mode 100644 index 0000000..6b6539a --- /dev/null +++ b/listati/sigevent.h @@ -0,0 +1,8 @@ +struct sigevent +{ + sigval_t sigev_value; + int sigev_signo; + int sigev_notify; + void (*sigev_notify_function)(sigval_t); + pthread_attr_t *sigev_notify_attributes; +}; diff --git a/listati/sockaddr.h b/listati/sockaddr.h new file mode 100644 index 0000000..8a85177 --- /dev/null +++ b/listati/sockaddr.h @@ -0,0 +1,4 @@ +struct sockaddr { + sa_family_t sa_family; /* address family: AF_xxx */ + char sa_data[14]; /* address (protocol-specific) */ +}; diff --git a/listati/sockaddr_atalk.h b/listati/sockaddr_atalk.h new file mode 100644 index 0000000..e0b13fa --- /dev/null +++ b/listati/sockaddr_atalk.h @@ -0,0 +1,9 @@ +struct sockaddr_atalk { + sa_family_t sat_family; /* address family */ + uint8_t sat_port; /* port */ + struct at_addr sat_addr; /* net/node */ +}; +struct at_addr { + uint16_t s_net; + uint8_t s_node; +}; diff --git a/listati/sockaddr_in.h b/listati/sockaddr_in.h new file mode 100644 index 0000000..a4b1587 --- /dev/null +++ b/listati/sockaddr_in.h @@ -0,0 +1,9 @@ +struct sockaddr_in { + sa_family_t sin_family; /* address family: AF_INET */ + in_port_t sin_port; /* port in network byte order */ + struct in_addr sin_addr; /* internet address */ +}; +/* Internet address. */ +struct in_addr { + in_addr_t s_addr; /* address in network byte order */ +}; diff --git a/listati/sockaddr_in6.h b/listati/sockaddr_in6.h new file mode 100644 index 0000000..34bc216 --- /dev/null +++ b/listati/sockaddr_in6.h @@ -0,0 +1,10 @@ +struct sockaddr_in6 { + uint16_t sin6_family; /* AF_INET6 */ + in_port_t sin6_port; /* port number */ + uint32_t sin6_flowinfo; /* IPv6 flow information */ + struct in6_addr sin6_addr; /* IPv6 address */ + uint32_t sin6_scope_id; /* Scope id (new in 2.4) */ +}; +struct in6_addr { + uint8_t s6_addr[16]; /* IPv6 address */ +}; diff --git a/listati/sockaddr_ll.h b/listati/sockaddr_ll.h new file mode 100644 index 0000000..ad9030f --- /dev/null +++ b/listati/sockaddr_ll.h @@ -0,0 +1,9 @@ +struct sockaddr_ll { + unsigned short sll_family; /* Always AF_PACKET */ + unsigned short sll_protocol; /* Physical layer protocol */ + int sll_ifindex; /* Interface number */ + unsigned short sll_hatype; /* Header type */ + unsigned char sll_pkttype; /* Packet type */ + unsigned char sll_halen; /* Length of address */ + unsigned char sll_addr[8]; /* Physical layer address */ +}; diff --git a/listati/sockaddr_un.h b/listati/sockaddr_un.h new file mode 100644 index 0000000..fb1c01e --- /dev/null +++ b/listati/sockaddr_un.h @@ -0,0 +1,5 @@ +#define UNIX_PATH_MAX 108 +struct sockaddr_un { + sa_family_t sun_family; /* AF_UNIX */ + char sun_path[UNIX_PATH_MAX]; /* pathname */ +}; diff --git a/listati/termios.h b/listati/termios.h new file mode 100644 index 0000000..b0be108 --- /dev/null +++ b/listati/termios.h @@ -0,0 +1,10 @@ +struct termios { + tcflag_t c_iflag; /* input modes */ + tcflag_t c_oflag; /* output modes */ + tcflag_t c_cflag; /* control modes */ + tcflag_t c_lflag; /* local modes */ + cc_t c_cc[NCCS]; /* control characters */ + cc_t c_line; /* line discipline */ + speed_t c_ispeed; /* input speed */ + speed_t c_ospeed; /* output speed */ +}; diff --git a/listati/value_c_cc.c b/listati/value_c_cc.c new file mode 100644 index 0000000..922ab3c --- /dev/null +++ b/listati/value_c_cc.c @@ -0,0 +1 @@ + value.c_cc[VEOL2] = '\n'; diff --git a/session.tex b/session.tex index b53320c..dbee219 100644 --- a/session.tex +++ b/session.tex @@ -1092,18 +1092,7 @@ ulteriori informazioni.\footnote{la definizione della struttura si trova in \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct termios { - tcflag_t c_iflag; /* input modes */ - tcflag_t c_oflag; /* output modes */ - tcflag_t c_cflag; /* control modes */ - tcflag_t c_lflag; /* local modes */ - cc_t c_cc[NCCS]; /* control characters */ - cc_t c_line; /* line discipline */ - speed_t c_ispeed; /* input speed */ - speed_t c_ospeed; /* output speed */ -; - \end{lstlisting} + \includestruct{listati/termios.h} \end{minipage} \normalsize \caption{La struttura \structd{termios}, che identifica le proprietà di un @@ -1284,10 +1273,7 @@ della maschera, i valori da immettere infatti (quelli riportati nella spiegazione corrispondente) sono numerici e non per bit, per cui possono sovrapporsi fra di loro. Occorrerà perciò utilizzare un codice del tipo: -\begin{lstlisting}[stepnumber=0,frame=]{} - c_oflag &= (~CRDLY); - c_oflag |= CR1; -\end{lstlisting} +\includecodesnip{listati/oflag.c} \noindent che prima cancella i bit della maschera in questione e poi setta il valore. @@ -1556,9 +1542,7 @@ completo dei caratteri di controllo, con le costanti e delle funzionalit associate è riportato in \tabref{tab:sess_termios_cc}, usando quelle definizioni diventa possibile assegnare un nuovo carattere di controllo con un codice del tipo: -\begin{lstlisting}[stepnumber=0,frame=]{} - value.c_cc[VEOL2] = '\n'; -\end{lstlisting} +\includecodesnip{listati/value_c_cc.c} La maggior parte di questi caratteri (tutti tranne \const{VTIME} e \const{VMIN}) hanno effetto solo quando il terminale viene utilizzato in modo @@ -1651,30 +1635,11 @@ effettuano pi chiamata a \func{tcgetattr} che essi siano stati eseguiti tutti quanti. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -#include -#include -#include - -int SetTermAttr(int fd, tcflag_t flag) -{ - struct termios values; - int res; - res = tcgetattr (desc, &values); - if (res) { - perror("Cannot get attributes"); - return res; - } - values.c_lflag |= flag; - res = tcsetattr (desc, TCSANOW, &values); - if (res) { - perror("Cannot set attributes"); - return res; - } - return 0; -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/SetTermAttr.c} + \end{minipage} + \normalsize \caption{Codice della funzione \func{SetTermAttr} che permette di impostare uno dei flag di controllo locale del terminale.} \label{fig:term_set_attr} @@ -1703,33 +1668,18 @@ infine si scrive il nuovo valore modificato con \func{tcsetattr} o uscendo normalmente. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -int UnSetTermAttr(int fd, tcflag_t flag) -{ - struct termios values; - int res; - res = tcgetattr (desc, &values); - if (res) { - perror("Cannot get attributes"); - return res; - } - values.c_lflag &= (~flag); - res = tcsetattr (desc, TCSANOW, &values); - if (res) { - perror("Cannot set attributes"); - return res; - } - return 0; -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/UnSetTermAttr.c} + \end{minipage} + \normalsize \caption{Codice della funzione \func{UnSetTermAttr} che permette di rimuovere uno dei flag di controllo locale del terminale.} \label{fig:term_unset_attr} \end{figure} La seconda funzione, \func{UnSetTermAttr}, è assolutamente identica alla -prima, solo che in questo caso (in \texttt{\small 15}) si rimuovono i bit +prima, solo che in questo caso, in (\texttt{\small 15}), si rimuovono i bit specificati dall'argomento \param{flag} usando un AND binario del valore negato. diff --git a/signal.tex b/signal.tex index 2fa13ad..7a680d4 100644 --- a/signal.tex +++ b/signal.tex @@ -1,4 +1,4 @@ -%% signal.tex +a%% signal.tex %% %% Copyright (C) 2000-2002 Simone Piccardi. Permission is granted to %% copy, distribute and/or modify this document under the terms of the GNU Free @@ -2260,14 +2260,14 @@ l'I/O asincrono (vedi \secref{sec:file_asyncronous_io}) o per le code di messaggi POSIX (vedi \secref{sec:ipc_posix_mq}); pertanto devono essere inviati esplicitamente. -Inoltre per poter usufruire della capacità di restituire dei dati i relativi -gestori devono essere installati con \func{sigaction} specificando la modalità -\const{SA\_SIGINFO} che permette di utilizzare la forma estesa -\var{sa\_sigaction} (vedi \secref{sec:sig_sigaction}). In questo modo tutti i -segnali real-time possono restituire al gestore una serie di informazioni -aggiuntive attraverso l'argomento \struct{siginfo\_t}, la cui definizione -abbiamo già visto in \figref{fig:sig_siginfo_t}, nella trattazione dei gestori -in forma estesa. +Inoltre, per poter usufruire della capacità di restituire dei dati, i relativi +gestori devono essere installati con \func{sigaction}, specificando per +\var{sa\_flags} la modalità \const{SA\_SIGINFO} che permette di utilizzare la +forma estesa \var{sa\_sigaction} (vedi \secref{sec:sig_sigaction}). In questo +modo tutti i segnali real-time possono restituire al gestore una serie di +informazioni aggiuntive attraverso l'argomento \struct{siginfo\_t}, la cui +definizione abbiamo già visto in \figref{fig:sig_siginfo_t}, nella trattazione +dei gestori in forma estesa. In particolare i campi utilizzati dai segnali real-time sono \var{si\_pid} e \var{si\_uid} in cui vengono memorizzati rispettivamente il \acr{pid} e diff --git a/simpltcp.tex b/simpltcp.tex index b4b9931..cd3dce8 100644 --- a/simpltcp.tex +++ b/simpltcp.tex @@ -61,61 +61,11 @@ parte, riportata in \figref{fig:TCPsimpl_serv_code}, nel precedente esempio esaminato in \secref{sec:TCPel_cunc_serv}. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -/* Subroutines declaration */ -void ServEcho(int sockfd); -/* Program beginning */ -int main(int argc, char *argv[]) -{ - int list_fd, conn_fd; - pid_t pid; - struct sockaddr_in serv_add; - ... - /* create socket */ - if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("Socket creation error"); - exit(-1); - } - /* initialize address */ - memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */ - serv_add.sin_family = AF_INET; /* address type is INET */ - serv_add.sin_port = htons(13); /* daytime port is 13 */ - serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ - /* bind socket */ - if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { - perror("bind error"); - exit(-1); - } - /* listen on socket */ - if (listen(list_fd, BACKLOG) < 0 ) { - perror("listen error"); - exit(-1); - } - /* handle echo to client */ - while (1) { - /* accept connection */ - if ( (conn_fd = accept(list_fd, NULL, NULL)) < 0) { - perror("accept error"); - exit(-1); - } - /* fork to handle connection */ - if ( (pid = fork()) < 0 ){ - perror("fork error"); - exit(-1); - } - if (pid == 0) { /* child */ - close(list_fd); /* close listening socket */ - SockEcho(conn_fd); /* handle echo */ - exit(0); - } else { /* parent */ - close(conn_fd); /* close connected socket */ - } - } - /* normal exit, never reached */ - exit(0); -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/ElemEchoTCPServer.c} + \end{minipage} + \normalsize \caption{Codice della funzione \code{main} della prima versione del server per il servizio \texttt{echo}.} \label{fig:TCPsimpl_serv_code} @@ -142,19 +92,11 @@ dati di cui \func{write}. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -void ServEcho(int sockfd) { - char buffer[MAXLINE]; - int nread, nwrite; - - /* main loop, reading 0 char means client close connection */ - while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) { - nwrite = FullWrite(sockfd, buffer, nread); - } - return; -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/ServEcho.c} + \end{minipage} + \normalsize \caption{Codice della prima versione della funzione \code{ServEcho} per la gestione del servizio \texttt{echo}.} \label{fig:TCPsimpl_server_elem_sub} @@ -174,42 +116,13 @@ esso ricalca la struttura del precedente client per il servizio \texttt{daytime} (vedi \secref{sec:net_cli_sample}) ma, come per il server, lo si è diviso in due parti, inserendo la parte relativa alle operazioni specifiche previste per il protocollo \texttt{echo} in una funzione a parte. + \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -int main(int argc, char *argv[]) -{ -/* - * Variables definition - */ - int sock_fd, i; - struct sockaddr_in serv_add; - ... - /* create socket */ - if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("Socket creation error"); - return -1; - } - /* initialize address */ - memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */ - serv_add.sin_family = AF_INET; /* address type is INET */ - serv_add.sin_port = htons(7); /* echo port is 7 */ - /* build address using inet_pton */ - if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) { - perror("Address creation error"); - return -1; - } - /* extablish connection */ - if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { - perror("Connection error"); - return -1; - } - /* read daytime from server */ - ClientEcho(stdin, sock_fd); - /* normal exit */ - return 0; -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15.6 cm} + \includecodesample{listati/EchoServerWrong.c} + \end{minipage} + \normalsize \caption{Codice della prima versione del client \texttt{echo}.} \label{fig:TCPsimpl_client_elem} \end{figure} @@ -227,21 +140,11 @@ preoccupa di gestire la comunicazione, leggendo una riga alla volta dallo ricevuto in risposta dal server. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -void ClientEcho(FILE * filein, int socket) -{ - char sendbuff[MAXLINE], recvbuff[MAXLINE]; - int nread; - while (fgets(sendbuff, MAXLINE, filein) != NULL) { - FullWrite(socket, sendbuff, strlen(sendbuff)); - nread = FullRead(socket, recvbuff, strlen(sendbuff)); - recvbuff[nread] = 0; - fputs(recvbuff, stdout); - } - return; -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15.6cm} + \includecodesample{listati/ClientEcho.c} + \end{minipage} + \normalsize \caption{Codice della prima versione della funzione \texttt{ClientEcho} per la gestione del servizio \texttt{echo}.} \label{fig:TCPsimpl_client_echo_sub} @@ -429,14 +332,7 @@ Per questo useremo la funzione \code{Signal}, illustrata in \figref{fig:sig_Signal_code}, per installare il semplice gestore che riceve i segnali dei processi figli terminati già visto in \figref{fig:sig_sigchld_handl}; aggiungendo il seguente codice: -\begin{lstlisting}{} - ... - /* install SIGCHLD handler */ - Signal(SIGCHLD, sigchld_hand); /* establish handler */ - /* create socket */ - ... -\end{lstlisting} - +\includecodesnip{listati/sigchildhand.c} \noindent all'esempio illustrato in \figref{fig:TCPsimpl_serv_code}, e linkando il tutto alla funzione \code{sigchld\_hand}, si risolverà completamente il problema diff --git a/socket.tex b/socket.tex index 1c9d1a7..ba5c608 100644 --- a/socket.tex +++ b/socket.tex @@ -361,12 +361,7 @@ una struttura generica per gli indirizzi dei socket, \struct{sockaddr}, che si \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sockaddr { - sa_family_t sa_family; /* address family: AF_xxx */ - char sa_data[14]; /* address (protocol-specific) */ -}; - \end{lstlisting} + \includestruct{listati/sockaddr.h} \end{minipage} \caption{La struttura generica degli indirizzi dei socket \structd{sockaddr}.} @@ -442,17 +437,7 @@ si usa IPv4) \begin{figure}[!htb] \footnotesize\centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sockaddr_in { - sa_family_t sin_family; /* address family: AF_INET */ - in_port_t sin_port; /* port in network byte order */ - struct in_addr sin_addr; /* internet address */ -}; -/* Internet address. */ -struct in_addr { - in_addr_t s_addr; /* address in network byte order */ -}; - \end{lstlisting} + \includestruct{listati/sockaddr_in.h} \end{minipage} \caption{La struttura degli indirizzi dei socket internet (IPv4) \structd{sockaddr\_in}.} @@ -503,18 +488,7 @@ in \figref{fig:sock_sa_ipv6_struct}. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sockaddr_in6 { - uint16_t sin6_family; /* AF_INET6 */ - in_port_t sin6_port; /* port number */ - uint32_t sin6_flowinfo; /* IPv6 flow information */ - struct in6_addr sin6_addr; /* IPv6 address */ - uint32_t sin6_scope_id; /* Scope id (new in 2.4) */ -}; -struct in6_addr { - uint8_t s6_addr[16]; /* IPv6 address */ -}; - \end{lstlisting} + \includestruct{listati/sockaddr_in6.h} \end{minipage} \caption{La struttura degli indirizzi dei socket IPv6 \structd{sockaddr\_in6}.} @@ -555,13 +529,7 @@ ad uno di questi socket si deve usare una struttura degli indirizzi di tipo \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -#define UNIX_PATH_MAX 108 -struct sockaddr_un { - sa_family_t sun_family; /* AF_UNIX */ - char sun_path[UNIX_PATH_MAX]; /* pathname */ -}; - \end{lstlisting} + \includestruct{listati/sockaddr_un.h} \end{minipage} \caption{La struttura degli indirizzi dei socket locali (detti anche \textit{unix domain}) \structd{sockaddr\_un} definita in \file{sys/un.h}.} @@ -603,17 +571,7 @@ file \file{netatalk/at.h}. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sockaddr_atalk { - sa_family_t sat_family; /* address family */ - uint8_t sat_port; /* port */ - struct at_addr sat_addr; /* net/node */ -}; -struct at_addr { - uint16_t s_net; - uint8_t s_node; -}; - \end{lstlisting} + \includestruct{listati/sockaddr_atalk.h} \end{minipage} \caption{La struttura degli indirizzi dei socket AppleTalk \structd{sockaddr\_atalk}.} @@ -684,17 +642,7 @@ occorre usare la funzione \func{bind} per agganciare il socket a quest'ultima. \begin{figure}[!htb] \footnotesize \centering \begin{minipage}[c]{15cm} - \begin{lstlisting}[stepnumber=0]{} -struct sockaddr_ll { - unsigned short sll_family; /* Always AF_PACKET */ - unsigned short sll_protocol; /* Physical layer protocol */ - int sll_ifindex; /* Interface number */ - unsigned short sll_hatype; /* Header type */ - unsigned char sll_pkttype; /* Packet type */ - unsigned char sll_halen; /* Length of address */ - unsigned char sll_addr[8]; /* Physical layer address */ -}; - \end{lstlisting} + \includestruct{listati/sockaddr_ll.h} \end{minipage} \caption{La struttura \structd{sockaddr\_ll} degli indirizzi dei \textit{packet socket}.} @@ -1043,33 +991,11 @@ sono disponibili: \secref{sec:ipc_pipes}). \begin{figure}[htb] - \centering - \footnotesize - \begin{lstlisting}{} -#include - -ssize_t FullRead(int fd, void *buf, size_t count) -{ - size_t nleft; - ssize_t nread; - - nleft = count; - while (nleft > 0) { /* repeat until no left */ - if ( (nread = read(fd, buf, nleft)) < 0) { - if (errno == EINTR) { /* if interrupted by system call */ - continue; /* repeat the loop */ - } else { - return(nread); /* otherwise exit */ - } - } else if (nread == 0) { /* EOF */ - break; /* break loop here */ - } - nleft -= nread; /* set left to read */ - buf +=nread; /* set pointer */ - } - return (count - nleft); -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/FullRead.c} + \end{minipage} + \normalsize \caption{Funzione \func{FullRead}, legge esattamente \var{count} byte da un file descriptor, iterando opportunamente le letture.} \label{fig:sock_FullRead_code} @@ -1086,30 +1012,11 @@ disponibile fra i sorgenti allegati alla guida nei file \file{FullRead.c} e \begin{figure}[htb] \centering - \footnotesize - \begin{lstlisting}{} -#include - -ssize_t FullWrite(int fd, const void *buf, size_t count) -{ - size_t nleft; - ssize_t nwritten; - - nleft = count; - while (nleft > 0) { /* repeat until no left */ - if ( (nwritten = write(fd, buf, nleft)) < 0) { - if (errno == EINTR) { /* if interrupted by system call */ - continue; /* repeat the loop */ - } else { - return(nwritten); /* otherwise exit with error */ - } - } - nleft -= nwritten; /* set left to write */ - buf +=nwritten; /* set pointer */ - } - return (count); -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/FullWrite.c} + \end{minipage} + \normalsize \caption{Funzione \func{FullWrite}, scrive \var{count} byte su un socket.} \label{fig:sock_FullWrite_code} \end{figure} @@ -1143,57 +1050,11 @@ standard che restituisce l'ora locale della macchina a cui si effettua la richiesta. \begin{figure}[!htb] - \footnotesize - \begin{lstlisting}{} -#include /* predefined types */ -#include /* include unix standard library */ -#include /* IP addresses conversion utilities */ -#include /* socket library */ -#include /* include standard I/O library */ - -int main(int argc, char *argv[]) -{ - int sock_fd; - int i, nread; - struct sockaddr_in serv_add; - char buffer[MAXLINE]; - ... - /* create socket */ - if ( (sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("Socket creation error"); - return -1; - } - /* initialize address */ - memset((void *) &serv_add, 0, sizeof(serv_add)); /* clear server address */ - serv_add.sin_family = AF_INET; /* address type is INET */ - serv_add.sin_port = htons(13); /* daytime post is 13 */ - /* build address using inet_pton */ - if ( (inet_pton(AF_INET, argv[optind], &serv_add.sin_addr)) <= 0) { - perror("Address creation error"); - return -1; - } - /* extablish connection */ - if (connect(sock_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { - perror("Connection error"); - return -1; - } - /* read daytime from server */ - while ( (nread = read(sock_fd, buffer, MAXLINE)) > 0) { - buffer[nread]=0; - if (fputs(buffer, stdout) == EOF) { /* write daytime */ - perror("fputs error"); - return -1; - } - } - /* error on read */ - if (nread < 0) { - perror("Read error"); - return -1; - } - /* normal exit */ - return 0; -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/ElemDaytimeTCPClient.c} + \end{minipage} + \normalsize \caption{Esempio di codice di un client elementare per il servizio daytime.} \label{fig:net_cli_code} \end{figure} @@ -1265,65 +1126,11 @@ nuovamente mostrato in \figref{fig:net_serv_code}, il sorgente completo directory \file{sources}. \begin{figure}[!htbp] - \footnotesize - \begin{lstlisting}{} -#include /* predefined types */ -#include /* include unix standard library */ -#include /* IP addresses conversion utilities */ -#include /* socket library */ -#include /* include standard I/O library */ -#include -#define MAXLINE 80 -#define BACKLOG 10 -int main(int argc, char *argv[]) -{ -/* - * Variables definition - */ - int list_fd, conn_fd; - int i; - struct sockaddr_in serv_add; - char buffer[MAXLINE]; - time_t timeval; - ... - /* create socket */ - if ( (list_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - perror("Socket creation error"); - exit(-1); - } - /* initialize address */ - memset((void *)&serv_add, 0, sizeof(serv_add)); /* clear server address */ - serv_add.sin_family = AF_INET; /* address type is INET */ - serv_add.sin_port = htons(13); /* daytime port is 13 */ - serv_add.sin_addr.s_addr = htonl(INADDR_ANY); /* connect from anywhere */ - /* bind socket */ - if (bind(list_fd, (struct sockaddr *)&serv_add, sizeof(serv_add)) < 0) { - perror("bind error"); - exit(-1); - } - /* listen on socket */ - if (listen(list_fd, BACKLOG) < 0 ) { - perror("listen error"); - exit(-1); - } - /* write daytime to client */ - while (1) { - if ( (conn_fd = accept(list_fd, (struct sockaddr *) NULL, NULL)) <0 ) { - perror("accept error"); - exit(-1); - } - timeval = time(NULL); - snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&timeval)); - if ( (write(conn_fd, buffer, strlen(buffer))) < 0 ) { - perror("write error"); - exit(-1); - } - close(conn_fd); - } - /* normal exit */ - exit(0); -} - \end{lstlisting} + \footnotesize \centering + \begin{minipage}[c]{15cm} + \includecodesample{listati/ElemDaytimeTCPServer.c} + \end{minipage} + \normalsize \caption{Esempio di codice di un semplice server per il servizio daytime.} \label{fig:net_serv_code} \end{figure}