Back to index

courier  0.68.2
moduledel.h
Go to the documentation of this file.
00001 /*
00002 ** Copyright 1998 - 1999 Double Precision, Inc.
00003 ** See COPYING for distribution information.
00004 */
00005 
00006 #ifndef       moduledel_h
00007 #define       moduledel_h
00008 
00009 #if    HAVE_CONFIG_H
00010 #include      "libs/courier_lib_config.h"
00011 #endif
00012 
00013 /*
00014 ** Some convenient functions used by modules to handle deliveries
00015 ** of messages.
00016 **
00017 ** The functions implement receiving delivery dispatches from courierd,
00018 ** forking and running child processes to handle them, then notifying
00019 ** courierd when the deliveries has been completed.
00020 **
00021 ** A parent process receives messages and forks child processes.
00022 */
00023 
00024 #ifdef __cplusplus
00025 extern "C" {
00026 #endif
00027 
00028 #include      <sys/types.h>
00029 #include      <time.h>
00030 
00031 struct moduledel {
00032        ino_t  inum;
00033        const char *msgid;
00034        const char *sender;
00035        const char *delid;
00036        const char *host;
00037        unsigned nreceipients;
00038        char **receipients;
00039        } ;
00040 
00041 extern unsigned module_nchildren;
00042 extern unsigned *module_delids;
00043 extern pid_t *module_pids;
00044 
00045 /*
00046 ** module_getdel reads a line from stdin, and returns a pointer to
00047 ** moduledel structure, ready for action.  All memory is internally
00048 ** allocated, and overwritten on each call.
00049 **
00050 ** In most cases, that's all that's needed.  But, when things get tricky:
00051 **
00052 ** The first argument to module_getline is a pointer to a function that
00053 ** returns the next character read from an arbitrary input stream.
00054 ** The second argument is a pointer that is supplied to as the sole
00055 ** argument to the function.  module_getline repeatedly calls the function
00056 ** until it returns a newline character, then returns the line read
00057 ** using an internally-allocated buffer. module_getline ignores
00058 ** EINTR errors.
00059 **
00060 ** module_parsecols() takes a null-terminated line, and returns an
00061 ** array pointing to the start of each column in this delivery instruction.
00062 ** Note that each column is not null-terminated, only the last one.
00063 ** All but the last column is terminated by the tab character.
00064 **
00065 ** module_parsedel takes the output of module_parsecols, and creates
00066 ** an internal moduledel structure out of it, this time actually replacing
00067 ** all tab characters with null bytes, and using an internally allocated
00068 ** array to store the pointers to each field.
00069 */
00070 
00071 struct moduledel *module_getdel();
00072 
00073 char *module_getline( int (*)(void *), void *);
00074 char **module_parsecols(char *);
00075 struct moduledel *module_parsedel(char **);
00076 
00077 /* Some macros */
00078 
00079 #define       MODULEDEL_MSGNUM(c)  ((c)[0])
00080 #define       MODULEDEL_MSGID(c)   ((c)[1])
00081 #define       MODULEDEL_SENDER(c)  ((c)[2])
00082 #define       MODULEDEL_DELID(c)   ((c)[3])
00083 #define       MODULEDEL_HOST(c)    ((c)[4])
00084 
00085 /*
00086 ** module_init is called to initialize the parent processes.  The number
00087 ** of child processes is calculated, and a signal handler is set up to
00088 ** handle terminated child processes.
00089 **
00090 ** When a child process is terminated, module_completed will be called.
00091 ** Pass a non-null pointer to a function to have this function called
00092 ** instead of module_completed.
00093 ** The first argument will be the child process index # (0 up to n-1, where
00094 ** n is the maximum number of child processes).  The second argument will
00095 ** be the delivery ID that the process hath received.
00096 */
00097 
00098 void module_init(void (*)(unsigned, unsigned));
00099 void module_completed(unsigned, unsigned);
00100 
00101 /* Set a watchdog timer for delivery attempts */
00102 
00103 void module_delivery_timeout(time_t n);
00104 
00105 /*
00106 ** module_fork calls fork(), and returns the exit value from fork().
00107 ** The first argument is the delivery ID, which will be passed as the
00108 ** second argument to the module_completed function.
00109 ** If the second argument is not null, it points to the slot number
00110 ** we want to track the child process as, otherwise we'll find the
00111 ** first unused one.
00112 */
00113 
00114 pid_t module_fork(unsigned, unsigned *);
00115 
00116 /* module_fork_noblock forks a child process without blocking SIGCHLD,
00117 ** Use that if we want to fork off a new child process while in a middle
00118 ** of the signal handler called due to previous child process termination.
00119 */
00120 
00121 pid_t module_fork_noblock(unsigned, unsigned *);
00122 
00123 /*
00124 ** Some complicated modules impose value-added stuff on top of child
00125 ** management.  They can child_blockset and child_blockclr to suspend
00126 ** child process termination handling in order to access per-process
00127 ** data in an atomic fashion.
00128 */
00129 void module_blockset();
00130 void module_blockclr();
00131 
00132 /* Remove signal handler, restore to default */
00133 
00134 void module_restore();
00135 
00136 /*
00137 ** When the main courierd process dies, kill all pending child procs
00138 */
00139 
00140 void module_signal(int);
00141 
00142 #ifdef __cplusplus
00143 }
00144 #endif
00145 
00146 #endif