Abbozzo di fortune server con le message queues
authorSimone Piccardi <piccardi@gnulinux.it>
Mon, 26 Aug 2002 21:11:49 +0000 (21:11 +0000)
committerSimone Piccardi <piccardi@gnulinux.it>
Mon, 26 Aug 2002 21:11:49 +0000 (21:11 +0000)
ipc.tex
sources/MQFortuneServer.c [new file with mode: 0644]

diff --git a/ipc.tex b/ipc.tex
index 0637d47..286cfdd 100644 (file)
--- a/ipc.tex
+++ b/ipc.tex
@@ -124,7 +124,7 @@ consiste nell'inviare l'output di un processo (lo standard output) sull'input
 di un'altro. Realizzeremo il programma di esempio nella forma di un
 \textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un
   programma che permette la creazione dinamica di un oggetto da inserire
 di un'altro. Realizzeremo il programma di esempio nella forma di un
 \textit{CGI}\footnote{Un CGI (\textit{Common Gateway Interface}) è un
   programma che permette la creazione dinamica di un oggetto da inserire
-  all'interno di una pagina HTML.}  per apache, che genera una immagine JPEG
+  all'interno di una pagina HTML.}  per Apache, che genera una immagine JPEG
 di un codice a barre, specificato come parametro di input.
 
 Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
 di un codice a barre, specificato come parametro di input.
 
 Un programma che deve essere eseguito come \textit{CGI} deve rispondere a
@@ -558,7 +558,7 @@ leggerli, quando i dati inviati sono destinati a loro.
 Per risolvere questo problema, si può usare un'architettura come quella
 illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le
 richieste al server su una fifo nota mentre le risposte vengono reinviate dal
 Per risolvere questo problema, si può usare un'architettura come quella
 illustrata in \figref{fig:ipc_fifo_server_arch} in cui i client inviano le
 richieste al server su una fifo nota mentre le risposte vengono reinviate dal
-server a ciascuno di essi su una fifo temporanea creata per l'occazione.
+server a ciascuno di essi su una fifo temporanea creata per l'occasione.
 
 \begin{figure}[htb]
   \centering
 
 \begin{figure}[htb]
   \centering
@@ -1229,11 +1229,11 @@ coda.
                                           messaggi. \\
     \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
                                           messaggio.\\
                                           messaggi. \\
     \macro{MSGMAX}& 8192& \file{msgmax} & Dimensione massima di un singolo
                                           messaggio.\\
-    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima di una coda di 
-                                          messaggi.\\
+    \macro{MSGMNB}&16384& \file{msgmnb} & Dimensione massima del contenuto di 
+                                          una coda.\\
     \hline
   \end{tabular}
     \hline
   \end{tabular}
-  \caption{Valori delle costanti associati ai limiti delle code di messaggi.}
+  \caption{Valori delle costanti associate ai limiti delle code di messaggi.}
   \label{tab:ipc_msg_limits}
 \end{table}
 
   \label{tab:ipc_msg_limits}
 \end{table}
 
@@ -1297,7 +1297,7 @@ riportato nella figura. In questa struttura il kernel\footnote{come accennato
   questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel
   della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle
   funzioni dell'interfaccia.  In \figref{fig:ipc_msgid_sd} sono elencati i
   questo vale fino ai kernel della serie 2.2.x, essa viene usata nei kernel
   della serie 2.4.x solo per compatibilità in quanto è quella restituita dalle
   funzioni dell'interfaccia.  In \figref{fig:ipc_msgid_sd} sono elencati i
-  campi significativi definiti in \file{sys/msg.h}, a cui si sono agguinti gli
+  campi significativi definiti in \file{sys/msg.h}, a cui si sono aggiunti gli
   ultimi tre campi che sono previsti dalla implementazione originale di System
   V, ma non dallo standard Unix98.}  mantiene le principali informazioni
 riguardo lo stato corrente della coda.  Quando si crea una nuova coda con
   ultimi tre campi che sono previsti dalla implementazione originale di System
   V, ma non dallo standard Unix98.}  mantiene le principali informazioni
 riguardo lo stato corrente della coda.  Quando si crea una nuova coda con
@@ -1315,9 +1315,10 @@ invece:
   rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
   messaggio sulla coda, sono inizializzati a 0.
 \item il campo \var{msg\_ctime} viene inizializzato al tempo corrente.
   rispettivamente il tempo in cui è stato inviato o ricevuto l'ultimo
   messaggio sulla coda, sono inizializzati a 0.
 \item il campo \var{msg\_ctime} viene inizializzato al tempo corrente.
-\item il campo \var{msg\_qbytes} viene inizializzati al limite di sistema.
+\item il campo \var{msg\_qbytes} viene inizializzato al valore preimpostato
+  del sistema (\macro{MSGMNB}).
 \item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
 \item i campi \var{msg\_first} e \var{msg\_last} che esprimono l'indirizzo del
-  primo e ultimo messagio sono inizializzati a \macro{NULL} e
+  primo e ultimo messaggio sono inizializzati a \macro{NULL} e
   \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
   inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
   e non devono essere utilizzati da programmi in user space).
   \var{msg\_cbytes}, che esprime la dimensione in byte dei messaggi presenti è
   inizializzato a zero. Questi campi sono ad uso interno dell'implementazione
   e non devono essere utilizzati da programmi in user space).
@@ -1356,7 +1357,7 @@ mantenuta all'indirizzo \param{buf}, per la coda specificata
 dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
 valore dell'argomento \param{cmd}, che specifica il tipo di azione da
 eseguire; i valori possibili sono:
 dall'identificatore \param{msqid}. Il comportamento della funzione dipende dal
 valore dell'argomento \param{cmd}, che specifica il tipo di azione da
 eseguire; i valori possibili sono:
-\begin{basedescript}{\desclabelwidth{3cm}\desclabelstyle{\nextlinelabel}}
+\begin{basedescript}{\desclabelwidth{2.2cm}\desclabelstyle{\nextlinelabel}}
 \item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
   struttura indicata da \param{buf}. Occorre avere il permesso di lettura
   sulla coda.
 \item[\macro{IPC\_STAT}] Legge le informazioni riguardo la coda nella
   struttura indicata da \param{buf}. Occorre avere il permesso di lettura
   sulla coda.
@@ -1373,9 +1374,8 @@ eseguire; i valori possibili sono:
   struttura \var{msqid\_ds} puntata da \param{buf}.  Per modificare i valori
   di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
   essere il proprietario o il creatore della coda, oppure l'amministratore; lo
   struttura \var{msqid\_ds} puntata da \param{buf}.  Per modificare i valori
   di \var{msg\_perm.mode}, \var{msg\_perm.uid} e \var{msg\_perm.gid} occorre
   essere il proprietario o il creatore della coda, oppure l'amministratore; lo
-  stesso vale per \var{msg\_qbytes}, con la restrizione che solo
-  l'amministratore può incrementarne il valore a limiti superiori a
-  \macro{MSGMNB}.
+  stesso vale per \var{msg\_qbytes}, ma l'amministratore ha la facoltà di
+  incrementarne il valore a limiti superiori a \macro{MSGMNB}.
 \end{basedescript}
 
 
 \end{basedescript}
 
 
@@ -1413,22 +1413,31 @@ La funzione inserisce il messaggio sulla coda specificata da \param{msqid}; il
 messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso
 l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre in una
 forma che corrisponda alla struttura \var{msgbuf} riportata in
 messaggio ha lunghezza specificata da \param{msgsz} ed è passato attraverso
 l'argomento \param{msgp}.  Quest'ultimo deve venire passato sempre in una
 forma che corrisponda alla struttura \var{msgbuf} riportata in
-\figref{fig:ipc_msbug}.  La struttura è solo un modello, la sola cosa che
-conta è abbia come primo membro un campo \var{mtype}, come nell'esempio; esso
-infatti serve ad identificare il tipo di messaggio e deve essere sempre
-specificato come intero positivo.  Il campo \var{mtext} invece può essere di
-qualsiasi tipo e dimensione, e deve contenere il testo del messaggio.
-
-In generale pertanto occorrerà ridefinire una struttura analoga a quella di
-\figref{fig:ipc_msbug}, adattando alle proprie esigenze il campo \var{mtype},
-e avendo cura di mantenere come primo campo un valore di tipo \ctyp{long}. Il
-resto della struttura andrà a costituire il corpo del messaggio, la cui
-dimensione deve essere specificata sempre attraverso \param{msgsz}. Si tenga
-presente che la lunghezza che deve essere indicata in questo argomento è solo
-quella del messaggio, non di tutta la struttura, se cioè \var{message} è la
-struttura che si passa alla funzione, \param{msgsz} dovrà essere uguale a
-\code{sizeof(message)-sizeof(long)} (se consideriamo il caso dell'esempio in
-\figref{fig:ipc_msbug} \param{msgsz} dovrà essere pari a \macro{LENGHT}).
+\figref{fig:ipc_msbug}.  La dimensione massima per il testo di un messaggio
+non può comunque superare il limite \macro{MSGMAX}.
+
+La struttura di \figref{fig:ipc_msbug} comunque è solo un modello, tanto che
+la definizione contenuta in \file{sys/msg.h} usa esplicitamente per il secondo
+campo il valore \code{mtext[1]}, che non è di nessuna utilità ai fini pratici.
+La sola cosa che conta è che abbia come primo membro un campo \var{mtype},
+come nell'esempio; esso infatti serve ad identificare il tipo di messaggio e
+deve essere sempre specificato come intero positivo.  Il campo \var{mtext}
+invece può essere di qualsiasi tipo e dimensione, e deve contenere il testo
+del messaggio.
+
+In generale pertanto per inviare un messaggio con \func{msgsnd} si usa
+ridefinire una struttura simile a quella di \figref{fig:ipc_msbug}, adattando
+alle proprie esigenze il campo \var{mtype}, (o ridefinendo come si vuole il
+corpo del messaggio, anche con più campi o con strutture più complesse) avendo
+però la cura di mantenere nel primo campo un valore di tipo \ctyp{long} che ne
+indica il tipo.
+
+Si tenga presente che la lunghezza che deve essere indicata in questo
+argomento è solo quella del messaggio, non quella di tutta la struttura, se
+cioè \var{message} è una propria struttura che si passa alla funzione,
+\param{msgsz} dovrà essere uguale a \code{sizeof(message)-sizeof(long)}, (se
+consideriamo il caso dell'esempio in \figref{fig:ipc_msbug}, \param{msgsz}
+dovrà essere pari a \macro{LENGHT}).
 
 \begin{figure}[!htb]
   \footnotesize \centering
 
 \begin{figure}[!htb]
   \footnotesize \centering
@@ -1512,46 +1521,51 @@ rimosso dalla stessa) 
 }
 \end{functions}
 
 }
 \end{functions}
 
-La funzione permette di estrarre un messaggio dalla coda e di scriverlo nel
-buffer indicato da \param{msgp}, che deve puntare ad una struttura della forma
-mostrata in \figref{fig:ipc_msbug}. L'argomento \param{msgsz} indica la
-lunghezza massima del testo del messaggio (equivalente al valore del parametro
-\macro{LENGHT} nell'esempio di \figref{fig:ipc_msbug}). 
+La funzione legge un messaggio dalla coda specificata scrivendolo nel buffer
+indicato da \param{msgp}, che avrà un formato analogo a quello di
+\figref{fig:ipc_msbug}. L'argomento \param{msgsz} indica la lunghezza massima
+del testo del messaggio (equivalente al valore del parametro \macro{LENGHT}
+nell'esempio di \figref{fig:ipc_msbug}).
 
 Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
 
 Se il testo del messaggio ha lunghezza inferiore a \param{msgsz} esso viene
-rimosso dalla coda, in caso contrario se \param{msgflg} è impostato a
-\macro{MSG\_NOERROR} il messaggio viene troncato e la parte in eccesso viene
+rimosso dalla coda; in caso contrario, se \param{msgflg} è impostato a
+\macro{MSG\_NOERROR}, il messaggio viene troncato e la parte in eccesso viene
 perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con
 un errore di \macro{E2BIG}.
 
 L'argomento \param{msgtyp} permette di restringere la ricerca ad un
 perduta, altrimenti il messaggio non viene estratto e la funzione ritorna con
 un errore di \macro{E2BIG}.
 
 L'argomento \param{msgtyp} permette di restringere la ricerca ad un
-sottoinsieme dei messaggi presenti sulla coda; in particolare:
+sottoinsieme dei messaggi presenti sulla coda; la ricerca infatti è fatta con
+una scansione della struttura mostrata in \figref{fig:ipc_mq_schema},
+restituendo il primo messaggio incontrato che corrisponde ai criteri
+specificati (che quindi, visto che i messaggi vengono sempre inseriti dalla
+coda, è quello meno recente); in particolare:
 \begin{itemize}
 \item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
   quello fra i presenti che è stato inserito inserito per primo. 
 \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
 \begin{itemize}
 \item se \param{msgtyp} è 0 viene estratto il messaggio in cima alla coda, cioè
   quello fra i presenti che è stato inserito inserito per primo. 
 \item se \param{msgtyp} è positivo viene estratto il primo messaggio il cui
-  tipo (il valore del campo \var{mtype}) corrisponde a quanto specificato.
-\item se \param{msgtyp} è negativo viene estratto il primo messaggio nella coda
-  con il tipo più basso, fra quelli di tipo inferiore al valore assoluto di
-  quanto specificato.
+  tipo (il valore del campo \var{mtype}) corrisponde al valore di
+  \param{msgtyp}.
+\item se \param{msgtyp} è negativo viene estratto il primo fra i messaggi con
+  il tipo di valore più basso, fra tutti quelli con un tipo inferiore al
+  valore assoluto di \param{msgtyp}.
 \end{itemize}
 
 Il valore di \param{msgflg} permette di controllare il comportamento della
 \end{itemize}
 
 Il valore di \param{msgflg} permette di controllare il comportamento della
-funzione, esso può assumere valore nullo o essere specificato come maschera
-binaria di uno o più dei valori. Oltre al precedente \macro{MSG\_NOERROR}, si
-può impostare il valore \macro{MSG\_EXCEPT}, che quando \param{msgtyp} è
-positivo permette di leggere il primo messaggio nella coda con tipo diverso da
-\param{msgtyp}, ed il valore \macro{IPC\_NOWAIT} che causa il ritorno
-immediato della funzione quando non ci sono messaggi sulla coda.
-
-Il comportamento usuale della funzione infatti, quando non ci sono messaggi
+funzione, esso può essere nullo o una maschera binaria composta da uno o più
+valori.  Oltre al precedente \macro{MSG\_NOERROR}, sono possibili altri due
+valori: \macro{MSG\_EXCEPT}, che permette, quando \param{msgtyp} è positivo,
+di leggere il primo messaggio nella coda con tipo diverso da \param{msgtyp}, e
+\macro{IPC\_NOWAIT} che causa il ritorno immediato della funzione quando non
+ci sono messaggi sulla coda.
+
+Il comportamento usuale della funzione infatti, se non ci sono messaggi
 disponibili per la lettura, è di bloccare il processo in stato di
 disponibili per la lettura, è di bloccare il processo in stato di
-\textit{sleep}; nel caso però si sia specificato \macro{IPC\_NOWAIT} la
+\textit{sleep}. Nel caso però si sia specificato \macro{IPC\_NOWAIT} la
 funzione ritorna immediatamente con un errore \macro{ENOMSG}. Altrimenti la
 funzione ritorna normalmente non appena viene inserito un messaggio del tipo
 funzione ritorna immediatamente con un errore \macro{ENOMSG}. Altrimenti la
 funzione ritorna normalmente non appena viene inserito un messaggio del tipo
-desiderato, oppure ritorna con errore qualora la cosa sia rimossa (con un
-\macro{EIDRM}) o se il processo viene interrotto da un segnale (con un
-\macro{EINTR}).
+desiderato, oppure ritorna con errore qualora la coda sia rimossa (con
+\var{errno} settata a \macro{EIDRM}) o se il processo viene interrotto da un
+segnale (con \var{errno} settata a \macro{EINTR}).
 
 Una volta completata con successo l'estrazione del messaggio dalla coda, la
 funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
 
 Una volta completata con successo l'estrazione del messaggio dalla coda, la
 funzione aggiorna i dati mantenuti in \var{msqid\_ds}, in particolare vengono
@@ -1563,6 +1577,10 @@ modificati:
 \item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente.
 \end{itemize}
 
 \item Il valore \var{msg\_rtime}, che viene impostato al tempo corrente.
 \end{itemize}
 
+Come esempio dell'uso delle code di messaggi possiamo riscrivere il nostro
+server di \textit{fortunes} usando queste al posto delle fifo. In questo caso
+useremo una coda di messaggi, usando il \acr{pid} del client come valore per
+il tipo di messaggio, per restituire indietro le frasi ai client.
 
 
 
 
 
 
@@ -1621,7 +1639,6 @@ struct semid_ds
     time_t sem_ctime;                   /* last time changed by semctl() */
     unsigned long int sem_nsems;        /* number of semaphores in set */
 };
     time_t sem_ctime;                   /* last time changed by semctl() */
     unsigned long int sem_nsems;        /* number of semaphores in set */
 };
-
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
     \end{lstlisting}
   \end{minipage} 
   \normalsize 
@@ -1630,6 +1647,24 @@ struct semid_ds
   \label{fig:ipc_semid_sd}
 \end{figure}
 
   \label{fig:ipc_semid_sd}
 \end{figure}
 
+\begin{table}[htb]
+  \footnotesize
+  \centering
+  \begin{tabular}[c]{|c|r|l|l|}
+    \hline
+    \textbf{Costante} & \textbf{Valore} & \textbf{Significato} \\
+    \hline
+    \hline
+    \macro{SEMMNI}&   16& Numero massimo di insiemi di semafori. \\
+    \macro{SEMMAX}& 8192& .\\
+    \macro{SEMMNB}&16384& .\\
+    \hline
+  \end{tabular}
+  \caption{Valori delle costanti associate ai limiti degli insiemi di
+    semafori.} 
+  \label{tab:ipc_sem_limits}
+\end{table}
+
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_sysv_shm}
 
 \subsection{Memoria condivisa}
 \label{sec:ipc_sysv_shm}
diff --git a/sources/MQFortuneServer.c b/sources/MQFortuneServer.c
new file mode 100644 (file)
index 0000000..e131978
--- /dev/null
@@ -0,0 +1,147 @@
+/* MQFortuneServer.c
+ * 
+ * Copyright (C) 2002 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.
+ */
+/****************************************************************
+ *
+ * Program fortuned 
+ * Fortune server - Using Messag queues
+ *
+ * Author: Simone Piccardi
+ * Aug. 2002
+ *
+ * Usage: fortuned -h give all info
+ *
+ * $Id: MQFortuneServer.c,v 1.1 2002/08/26 21:11:49 piccardi Exp $
+ *
+ ****************************************************************/
+/* 
+ * Include needed headers
+ */
+#include <sys/types.h>   /* predefined types */
+#include <sys/stat.h>    /*  */
+#include <unistd.h>      /* include unix standard library */
+#include <stdio.h>       /* include standard I/O library */
+#include <stdlib.h>     /* standard library */
+#include <string.h>     /* ANSI C standard string */
+#include <errno.h>      /* errorstring */
+#include <signal.h>     /* signals */
+#include <fcntl.h>      /*  */
+
+#include "macros.h"
+#include "wrappers.h"
+
+/* Subroutines declaration */
+void usage(void);
+void HandSIGTERM(int signo);
+int FortuneParse(char *file, char **fortune, int n);
+
+/* name of well known fifo */
+int main(int argc, char *argv[])
+{
+/* Variables definition */
+    int i, n = 0;
+    char **fortune;
+    struct msgbuf_read {
+       long mtype;      /* message type, must be > 0 */
+       int pid;         /* message data */
+    } msg_read;
+    struct msgbuf_write {
+       long mtype;      /* message type, must be > 0 */
+       char mtext[MSGMAX];  /* message data */
+    } msg_write;
+    int msgid;
+    key_t key;
+    int size;
+    /*
+     * Input section: decode parameters passed in the calling 
+     * Use getopt function
+     */
+    opterr = 0;                                     /* don't want writing to stderr */
+    while ( (i = getopt(argc, argv, "hn:f:")) != -1) {
+       switch (i) {
+       /* 
+        * Handling options 
+        */ 
+       case 'h':  
+           printf("Wrong -h option use\n");
+           usage();
+           return(0);
+           break;
+       case 'f':
+           fortunefilename = optarg;
+           break;
+       case 'n':
+           n = strtol(optarg, NULL, 10);
+           fortune = (char **) calloc(sizeof(*fortune), n);
+           break;
+       case '?':                                    /* unrecognized options */
+           printf("Unrecognized options -%c\n",optopt);
+           usage();
+       default:                                       /* should not reached */
+           usage();
+       }
+    }
+    /* ***********************************************************
+     * 
+     *          Options processing completed
+     *
+     *               Main code beginning
+     * 
+     * ***********************************************************/
+    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 */
+    for (n=0; n<i; n++) debug("%s%%\n", fortune[n]);
+    /* 
+     * Comunication section 
+     */
+    key = ftok("./MQFortuneServer.c", 1); 
+    msgid = msgget(key, IPC_CREAT|666); 
+    
+    /* Main body: loop over requests */
+    while (1) {
+       msgrcv(msgid, &msg_read, 1, sizeof(int), MSG_NOERROR);
+       n = random() % i;                             /* select random value */
+       strncpy(msgbuf_write.mtext, fortune[n], MSGMAX);
+       size = min(strlen(fortune[n])+1, MSGMAX);  
+       msgsnd(msgid,  &msg_write, size, 0);
+    }
+    debug("Exiting for unknown reasons\n");
+}
+/*
+ * routine to print usage info and exit
+ */
+void usage(void) {
+    printf("Elementary fortune server\n");
+    printf("Usage:\n");
+    printf("  fortuned [-h] [-f] -n XXX \n");
+    printf("  -h   print this help\n");
+    printf("  -f filename   set file for fortunes\n");
+    printf("  -n XXX        set pool depth\n");
+    exit(1);
+}
+/*
+ * Signal Handler to manage termination
+ */
+void HandSIGTERM(int signo) {
+    debug("Terminated by %s\n", strsignal(signo));
+    unlink(fifoname);
+    exit(0);
+}