e scritte routine e programma di prova.
una interfaccia completamente nuova, che tratteremo in questa sezione.
-
\subsection{Considerazioni generali}
\label{sec:ipc_posix_generic}
-Il Linux non tutti gli oggetti del POSIX IPC sono supportati nel kernel
-ufficiale; solo la memoria condivisa è presente, ma solo a partire dal kernel
-2.4.x, per gli altri oggetti esistono patch e librerie non ufficiali.
-Nonostante questo è importante esaminare questa interfaccia per la sua netta
-superiorità nei confronti di quella del \textit{SysV IPC}.
+In Linux non tutti gli oggetti del POSIX IPC sono pienamente supportati nel
+kernel ufficiale; solo la memoria condivisa è presente con l'interfaccia
+completa, ma solo a partire dal kernel 2.4.x, i semafori sono forniti dalle
+\acr{glibc} nella sezione che implementa i thread POSIX, e sono utilizzabili
+solo all'interno dei thread generati dallo stesso processo,\footnote{sono cioè
+ oggetti che non possono, al contrario dei semafori del SysV IPC, essere
+ utilizzati per sincronizzare processi diversi.} le code di messaggi non
+hanno alcun tipo di supporto ufficiale. Esistono tuttavia dei patch e delle
+librerie aggiuntive che supportano alcune di queste interfacce, anche se
+sperimentali e di uso limitato.
+
+La caratteristica fondamentale dell'interfaccia POSIX è l'abbandono dell'uso
+degli identificatori e delle chiavi visti nel SysV IPC, per passare ai
+\textit{Posix IPC names}\index{Posix IPC names}, che sono sostanzialmente
+equivalenti ai nomi dei file. Tutte le funzioni che creano un oggetto di IPC
+Posix prendono come primo argomento una stringa che indica uno di questi nomi;
+lo standard è molto generico riguardo l'implementazione, ed i nomi stessi
+possono avere o meno una corrispondenza sul filesystem.
+
+
+ le caratteristiche di questi nomi,
+per i quali richiede che:
+\begin{itemize}
+\item debbano essere conformi alle regole che caratterizzano i
+ \textit{pathname}, in particolare non essere più lunghi di \const{PATH\_MAX}
+ byte e terminati da un carattere nullo.
+\item se il nome inizia per una \texttt{/}
+\end{itemize}
+
+
\subsection{Code di messaggi}
ufficiale;\footnote{esiste però una proposta di implementazione di Krzysztof
Benedyczak, a partire dal kernel 2.5.50.} inoltre esse possono essere
implementate, usando la memoria condivisa ed i mutex, con funzioni di
-libreria. In generale, come le corrispettive del SysV IPC, sono poco usate,
+libreria. In generale, come le corrispettive del SysV IPC, sono poco usate,
dato che i socket\index{socket}, nei casi in cui sono sufficienti, sono più
comodi, e negli altri casi la comunicazione può essere gestita direttamente
-con mutex e memoria condivisa. Per questo ci limiteremo ad una descrizione
-essenziale.
+con mutex e memoria condivisa. Per questo, in assenza di una implementazione
+uffiale, ne tralasciamo la descrizione.
livello di libreria ed è fornita dalla libreria dei thread; questa però li
implementa solo a livello di thread e non di processi. Esiste un'altra
versione, realizzata da Konstantin Knizhnik, che reimplementa l'interfaccia
-POSIX usando i semafori di SysV IPC.
+POSIX usando i semafori di SysV IPC.
+
+
\subsection{Memoria condivisa}
all'interno del ciclo (linee \texttt{\small 6--8}). I dati inviati dal client
vengono letti dal socket con una semplice \func{read} (che ritorna solo in
presenza di dati in arrivo), la riscrittura viene invece gestita dalla
-funzione \func{SockWrite} (descritta in \figref{fig:sock_SockWrite_code}) che
+funzione \func{FullWrite} (descritta in \figref{fig:sock_FullWrite_code}) che
si incarica di tenere conto automaticamente della possibilità che non tutti i
dati di cui è richiesta la scrittura vengano trasmessi con una singola
\func{write}.
/* main loop, reading 0 char means client close connection */
while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) {
- nwrite = SockWrite(sockfd, buffer, nread);
+ nwrite = FullWrite(sockfd, buffer, nread);
}
return;
}
char sendbuff[MAXLINE], recvbuff[MAXLINE];
int nread;
while (fgets(sendbuff, MAXLINE, filein) != NULL) {
- SockWrite(socket, sendbuff, strlen(sendbuff));
- nread = SockRead(socket, recvbuff, strlen(sendbuff));
+ FullWrite(socket, sendbuff, strlen(sendbuff));
+ nread = FullRead(socket, recvbuff, strlen(sendbuff));
recvbuff[nread] = 0;
fputs(recvbuff, stdout);
}
presi dallo \file{stdin} usando la funzione \func{fgets} che legge una
linea di testo (terminata da un \texttt{CR} e fino al massimo di
\const{MAXLINE} caratteri) e la salva sul buffer di invio, la funzione
-\func{SockWrite} (\texttt{\small 3}) scrive detti dati sul socket (gestendo
+\func{FullWrite} (\texttt{\small 3}) scrive detti dati sul socket (gestendo
l'invio multiplo qualora una singola \func{write} non basti, come spiegato
in \secref{sec:sock_io_behav}).
-I dati che vengono riletti indietro con una \func{SockRead} sul buffer di
+I dati che vengono riletti indietro con una \func{FullRead} sul buffer di
ricezione e viene inserita la terminazione della stringa (\texttt{\small
7--8}) e per poter usare la funzione \func{fputs} per scriverli su
\file{stdout}.
\begin{lstlisting}{}
#include <unistd.h>
-ssize_t SockRead(int fd, void *buf, size_t count)
+ssize_t FullRead(int fd, void *buf, size_t count)
{
size_t nleft;
ssize_t nread;
return (count - nleft);
}
\end{lstlisting}
- \caption{Funzione \func{SockRead}, legge \var{count} byte da un socket }
- \label{fig:sock_SockRead_code}
+ \caption{Funzione \func{FullRead}, legge \var{count} byte da un socket }
+ \label{fig:sock_FullRead_code}
\end{figure}
Per questo motivo, seguendo l'esempio di W. R. Stevens in \cite{UNP1}, si sono
-definite due funzioni \func{SockRead} e \func{SockWrite} che eseguono la
+definite due funzioni \func{FullRead} e \func{FullWrite} che eseguono la
lettura da un socket tenendo conto di questa caratteristica, ed in grado di
ritornare dopo avere letto o scritto esattamente il numero di byte
-specificato; il sorgente è riportato in \figref{fig:sock_SockRead_code} e
-\figref{fig:sock_SockWrite_code} ed è disponibile fra i sorgenti allegati alla
-guida nei files \file{SockRead.c} e \file{SockWrite.c}.
+specificato; il sorgente è riportato in \figref{fig:sock_FullRead_code} e
+\figref{fig:sock_FullWrite_code} ed è disponibile fra i sorgenti allegati alla
+guida nei files \file{FullRead.c} e \file{FullWrite.c}.
\begin{figure}[htb]
\centering
\begin{lstlisting}{}
#include <unistd.h>
-ssize_t SockWrite(int fd, const void *buf, size_t count)
+ssize_t FullWrite(int fd, const void *buf, size_t count)
{
size_t nleft;
ssize_t nwritten;
return (count);
}
\end{lstlisting}
- \caption{Funzione \func{SockWrite}, scrive \var{count} byte su un socket.}
- \label{fig:sock_SockWrite_code}
+ \caption{Funzione \func{FullWrite}, scrive \var{count} byte su un socket.}
+ \label{fig:sock_FullWrite_code}
\end{figure}
Come si può notare le funzioni ripetono la lettura/scrittura in un ciclo fino
*
* Usage: echo -h give all info's
*
- * $Id: ElemEchoTCPClient.c,v 1.4 2002/12/03 11:06:05 piccardi Exp $
+ * $Id: ElemEchoTCPClient.c,v 1.5 2003/02/02 20:35:33 piccardi Exp $
*
****************************************************************/
/*
char sendbuff[MAXLINE], recvbuff[MAXLINE];
int nread;
while (fgets(sendbuff, MAXLINE, filein) != NULL) {
- SockWrite(socket, sendbuff, strlen(sendbuff));
- nread = SockRead(socket, recvbuff, strlen(sendbuff));
+ FullWrite(socket, sendbuff, strlen(sendbuff));
+ nread = FullRead(socket, recvbuff, strlen(sendbuff));
recvbuff[nread] = 0;
fputs(recvbuff, stdout);
}
*
* Usage: echod -h give all info
*
- * $Id: ElemEchoTCPServer.c,v 1.4 2002/12/03 11:06:05 piccardi Exp $
+ * $Id: ElemEchoTCPServer.c,v 1.5 2003/02/02 20:35:33 piccardi Exp $
*
****************************************************************/
/*
/* main loop, reading 0 char means client close connection */
while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) {
printf("Letti %d bytes, %s ", nread, buffer);
- nwrite = SockWrite(sockfd, buffer, nread);
+ nwrite = FullWrite(sockfd, buffer, nread);
}
return;
}
--- /dev/null
+/* FullRead.c
+ *
+ * Copyright (C) 2001 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Routine FullRead
+ * Routine to read an exact number of bytes from a socket
+ *
+ * Author: Simone Piccardi
+ * Jun. 2001
+ *
+ * $Id: FullRead.c,v 1.1 2003/02/02 20:35:33 piccardi Exp $
+ *
+ ****************************************************************/
+#include <unistd.h>
+#include <errno.h>
+
+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);
+}
+
--- /dev/null
+/* FullWrite.c
+ *
+ * Copyright (C) 2001 Simone Piccardi
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+/****************************************************************
+ *
+ * Routine FullWrite
+ * Routine to write an exact number of bytes into a socket
+ *
+ * Author: Simone Piccardi
+ * Jun. 2001
+ *
+ * $Id: FullWrite.c,v 1.1 2003/02/02 20:35:33 piccardi Exp $
+ *
+ ****************************************************************/
+#include <unistd.h>
+#include <errno.h>
+
+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);
+}
+
*
* Author: S. Piccardi
*
- * $Id: Gapil.h,v 1.5 2003/01/07 23:00:34 piccardi Exp $
+ * $Id: Gapil.h,v 1.6 2003/02/02 20:35:33 piccardi Exp $
*
*****************************************************************************/
#include <sys/sem.h> /* IPC semaphore declarations */
/*
* Socket service functions
*/
-/* Function SockRead: to read from a socket. See SockRead.c */
-ssize_t SockRead(int fd, void *buf, size_t count);
-/* Function SockWrite: to read from a socket. See SockWrite.c */
-ssize_t SockWrite(int fd, const void *buf, size_t count);
+/* Function FullRead: to read from a socket. See FullRead.c */
+ssize_t FullRead(int fd, void *buf, size_t count);
+/* Function FullWrite: to read from a socket. See FullWrite.c */
+ssize_t FullWrite(int fd, const void *buf, size_t count);
/*
* File miscellaneous
*/
-/* Function DirScan: simple scan for a directory */
+/* Function DirScan: simple scan for a directory. See DirScan.c */
int DirScan(char * dirname, int(*compute)(struct dirent *));
+/*
+ * Shared memory handling functions. See SharedMem.c
+ */
+/* Function ShmCreate: create a SysV shared memory */
+void * ShmCreate(key_t ipc_key, int shm_size, int perm, char fill);
+/* Function ShmFind: find an existing SysV shared memory */
+void * ShmFind(key_t ipc_key, int shm_size);
+/* Function ShmRemove: remove a SysV shared memory */
+int ShmRemove(key_t ipc_key, void * shm_ptr);
+/* Function CreateShm: create a POSIX shared memory */
+void * CreateShm(char * shm_name, int shm_size, int perm, char fill);
+/* Function FindShm: find an existing POSIX shared memory */
+void * FindShm(char * shm_name, int shm_size);
+/* Function RemoveShm: remove a POSIX shared memory */
+int RemoveShm(char * shm_name);
LIB = libgapil.so
-OBJ = SockRead.o SockWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o DirScan.o
+OBJ = FullRead.o FullWrite.o SigHand.o Mutex.o SharedMem.o LockFile.o DirScan.o
FINAL = forktest errcode echo echod daytimed iterdaytimed daytime testfopen \
testren fortune fortuned mqfortune mqfortuned flock myls dirmonitor \
- readmon ipctestid
+ readmon ipctestid writeshm readshm
$(LIB): $(OBJ)
- gcc -shared $^ -o $@
+ gcc -shared -lrt $^ -o $@
$(OBJ): Gapil.h
ipctestid: IPCTestId.c
$(CC) $^ -o $@
+writeshm: WriteShm.c
+ $(CC) $(CFLAGJ) $^ -o $@
+
+#readshm: ReadShm.c
+# $(CC) $(CFLAGJ) $^ -o $@
+
# Macro per la generazione della tarball dei sorgenti
package: clean gapil_source.tgz
/***************************************************************
*
* File SharedMem.c
- * Routine for Shared Memory use
+ * Routines for Shared Memory use.
+ *
+ * Define two interfaces, the first one use SysV shared memory, the
+ * second POSIX shared memory.
*
* Author: S. Piccardi
*
- * $Id: SharedMem.c,v 1.2 2002/12/03 22:30:11 piccardi Exp $
+ * $Id: SharedMem.c,v 1.3 2003/02/02 20:35:33 piccardi Exp $
*
***************************************************************/
#include <sys/shm.h> /* SysV IPC shared memory declarations */
#include <stdio.h> /* standard I/O functions */
#include <fcntl.h>
#include <signal.h> /* signal handling declarations */
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+/* *************************************************************************
+ *
+ * Functions for SysV shared memory
+ *
+ * ************************************************************************* */
/*
* Function ShmCreate:
* Create and attach a SysV shared memory segment to the current process.
*
* Input: an IPC key value
* the shared memory segment size
- * Return: the address of the segment
+ * the permissions
+ * the fill value
+ * Return: the address of the shared memory segment (NULL on error)
*/
-void * ShmCreate(key_t ipc_key, int shm_size, char fill)
+void * ShmCreate(key_t ipc_key, int shm_size, int perm, char fill)
{
- void * shptr;
- int shmid; /* ID of the IPC shared memory segment */
- shmid = shmget(ipc_key,shm_size,IPC_CREAT|0666); /* get shm ID */
- if (shmid < 0) {
- return (void *) shmid;
+ 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;
}
- shptr = shmat(shmid,0,0); /* take the pointer to it */
- if ( shptr == 0 ){
- perror("cannot attach shared memory");
- exit(1);
+ shm_ptr = shmat(shm_id, NULL, 0); /* map it into memory */
+ if (shm_ptr < 0) {
+ return NULL;
}
- memset((void *)shptr, fill, shm_size); /* second counter starts from "0" */
- return shptr;
+ memset((void *)shm_ptr, fill, shm_size); /* fill segment */
+ return shm_ptr;
}
/*
* Function ShmFind:
- * Find a shared memory segment
+ * Find a SysV shared memory segment
* Input: an IPC key value
* the shared memory segment size
- * Return: the address of the segment
+ * Return: the address of the segment (NULL on error)
*/
void * ShmFind(key_t ipc_key, int shm_size)
{
- void * shptr;
- int shmid; /* ID of the IPC shared memory segment */
- if ( (shmid=shmget(ipc_key,shm_size,0))<0 ){ /* find shared memory ID */
- perror("cannot find shared memory");
- exit(1);
+ 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:
+ * Scheudle removal for a SysV shared memory segment
+ * Input: an IPC key value
+ * the shared memory segment size
+ * Return: 0 on success, -1 on error
+ */
+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 ( (shptr=shmat(shmid,0,0)) < 0 ){ /* take the pointer to it */
- perror("cannot attach shared memory");
- exit(1);
+ if (shmctl(shm_id, IPC_RMID, NULL) < 0) { /* ask for removal */
+ if (errno == EIDRM) return 0;
+ return -1;
}
- return shptr;
+ return 0;
+}
+/* *************************************************************************
+ *
+ * Functions for POSIX shared memory
+ *
+ * ************************************************************************* */
+/*
+ * Function CreateShm:
+ * Create a POSIX shared memory segment and map it to the current process.
+ *
+ *
+ * Input: a pathname
+ * the shared memory segment size
+ * the permissions
+ * the fill value
+ * Return: the address of the shared memory segment (NULL on error)
+ */
+void * CreateShm(char * shm_name, int shm_size, int perm, char fill)
+{
+ void * shm_ptr;
+ int fd;
+ int flag;
+ /* first open the object, creating it if not existent */
+ flag = O_RDWR|O_TRUNC|O_CREAT|O_EXCL;
+ 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
+ * Input: a name
+ * the shared memory segment size
+ * Return: the address of the segment (NULL on error)
+ */
+void * FindShm(char * shm_name, int 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
+ * Input: the object name
+ * Return: 0 on success, -1 on error
+ */
+int RemoveShm(char * shm_name)
+{
+ shm_unlink(shm_name);
+ return 0;
}
*
* Usage: echo -h give all info's
*
- * $Id: SimpleEchoTCPClient.c,v 1.5 2002/12/03 11:06:05 piccardi Exp $
+ * $Id: SimpleEchoTCPClient.c,v 1.6 2003/02/02 20:35:33 piccardi Exp $
*
****************************************************************/
/*
char sendbuff[MAXLINE], recvbuff[MAXLINE];
int nread;
while (fgets(sendbuff, MAXLINE, filein) != NULL) {
- SockWrite(socket, sendbuff, strlen(sendbuff));
- nread = SockRead(socket, recvbuff, strlen(sendbuff));
+ FullWrite(socket, sendbuff, strlen(sendbuff));
+ nread = FullRead(socket, recvbuff, strlen(sendbuff));
recvbuff[nread] = 0;
fputs(recvbuff, stdout);
}
*
* Usage: echod
*
- * $Id: SimpleEchoTCPServer.c,v 1.5 2002/12/03 11:06:05 piccardi Exp $
+ * $Id: SimpleEchoTCPServer.c,v 1.6 2003/02/02 20:35:34 piccardi Exp $
*
****************************************************************/
/*
/* main loop, reading 0 char means client close connection */
while ( (nread = read(sockfd, buffer, MAXLINE)) != 0) {
printf("Letti %d bytes, %s ", nread, buffer);
- nwrite = SockWrite(sockfd, buffer, nread);
+ nwrite = FullWrite(sockfd, buffer, nread);
}
return;
}
+++ /dev/null
-/* SockRead.c
- *
- * Copyright (C) 2001 Simone Piccardi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/****************************************************************
- *
- * Routine SockRead
- * Routine to read an exact number of bytes from a socket
- *
- * Author: Simone Piccardi
- * Jun. 2001
- *
- * $Id: SockRead.c,v 1.3 2001/09/09 22:45:34 piccardi Exp $
- *
- ****************************************************************/
-#include <unistd.h>
-#include <errno.h>
-
-ssize_t SockRead(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);
-}
-
+++ /dev/null
-/* SockWrite.c
- *
- * Copyright (C) 2001 Simone Piccardi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or (at
- * your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/****************************************************************
- *
- * Routine SockWrite
- * Routine to write an exact number of bytes into a socket
- *
- * Author: Simone Piccardi
- * Jun. 2001
- *
- * $Id: SockWrite.c,v 1.3 2001/09/09 22:45:34 piccardi Exp $
- *
- ****************************************************************/
-#include <unistd.h>
-#include <errno.h>
-
-ssize_t SockWrite(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);
-}
-