PUBLIC void rec_handlesmtp()
{
-BINTYP binding;
+SOCTYP **bindings;
int phase;
_Bool proceed;
-(void) memset(&binding,'\000',sizeof(BINTYP));
-binding.ip=strdup("127.0.0.25");
-binding.port=strdup("2525");
+bindings=(SOCTYP **)0;
+bindings=soc_mkbindinf(bindings,pro_smtp,"127.0.0.25","2525",10);
phase=0;
proceed=true;
while (proceed==true) {
case 0 : //looping forever email receiving processes
(void) prc_settitle("emlrec with pid='%06d'",getpid());
break;
- case 1 : //Opening a channel
- if (soc_setbind(&binding)<0)
+ case 1 : //Opening ONE channel
+ if (soc_setbind(*bindings)<0)
phase=999; //doc not open!
break;
case 2 : //Terminating all remaining process
}
phase++;
}
+bindings=soc_freebindinf(bindings);
}
/*
^L
/* name. */
/* */
/********************************************************/
-const char *rou_getversion()
+PUBLIC const char *rou_getversion()
{
return VERSION"."RELEASE;
}
/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to free memory used by a */
+/* string, do not proceed if pointer is NULL. */
+/* */
+/********************************************************/
+char *rou_freestr(register char *str)
+
+{
+if (str!=(char *)0) {
+ (void) free(str);
+ str=(char *)0;
+ }
+return str;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Subroutine to get add a pointer (not null) */
+/* to a list of pointer. */
+/* */
+/********************************************************/
+PUBLIC void **rou_addlist(void **list,void *entry)
+
+{
+if (entry!=(void *)0) {
+ register int num;
+
+ num=0;
+ if (list==(void **)0)
+ list=(void **)calloc(num+2,sizeof(void *));
+ else {
+ while (list[num]!=(void *)0)
+ num++;
+ list=realloc((void *)list,(num+2)*sizeof(void *));
+ }
+ list[num]=entry;
+ num++;
+ list[num]=(void *)0;
+ }
+return list;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to free one entry part of list */
+/* return true if found, false otherwize. */
+/* */
+/********************************************************/
+PUBLIC _Bool rou_rmlist(void **list,void *entry,freehandler_t handler)
+
+{
+_Bool found;
+
+found=false;
+if ((list!=(void **)0)&&(entry!=(void **)0)) {
+ void **ptr;
+
+ ptr=list;
+ while (*ptr!=(void *)0) {
+ if (*ptr==entry) {
+ void **nxt;
+
+ nxt=ptr+1;
+ if (handler!=(freehandler_t)0)
+ (void) handler(*ptr);
+ while (*ptr!=(void *)0) {
+ *ptr=*nxt;
+ ptr++;
+ nxt++;
+ }
+ found=true;
+ break;
+ }
+ ptr++;
+ }
+ }
+return found;
+}
+/*
^L
*/
/********************************************************/
/* logs. */
/* */
/********************************************************/
-char *rou_setappname(const char *newname)
+PUBLIC char *rou_setappname(const char *newname)
{
char *name;
/* directory if needed */
/* */
/********************************************************/
-char *rou_apppath(const char *path)
+PUBLIC char *rou_apppath(const char *path)
{
char *root;
/* Subroutine to log event on syslog */
/* */
/********************************************************/
-void rou_valert(const int dlevel,const char *fmt,va_list ap)
+PUBLIC void rou_valert(const int dlevel,const char *fmt,va_list ap)
#define DEBMAX 120
/* Subroutine to log event on syslog */
/* */
/********************************************************/
-void rou_alert(const int dlevel,const char *fmt,...)
+PUBLIC void rou_alert(const int dlevel,const char *fmt,...)
{
va_list args;
va_end(args);
}
/*
-^L
-*/
-/********************************************************/
-/* */
-/* Procedure to "open" usager to module. */
-/* homework purpose */
-/* return zero if everything right */
-/* */
-/********************************************************/
-int rou_opensubrou()
-
-{
-int status;
-
-status=0;
-if (modopen==false) {
- debug=0;
- foreground=false;
- off64_time=(time_t)0;
- off_date=(time_t)0;
- if (appname!=(char *)0)
- (void) free(appname);
- appname=strdup(APPNAME);
- if (rootdir!=(char *)0) {
- (void) free(rootdir);
- status=-1; //Rootdir should be found as NULL
- }
- rootdir=strdup("");
- (void) openlog(APPNAME,LOG_PID,LOG_DAEMON);
- (void) rou_alert(0,"Starting: %s-%s",APPNAME,rou_getversion());
- modopen=true;
- }
-return status;
-}
-/*
\f
*/
/********************************************************/
/* Subroutine to CORE-DUMP the application */
/* */
/********************************************************/
-void rou_crash(const char *fmt,...)
+PUBLIC void rou_crash(const char *fmt,...)
{
#define RELAX 5
/* message and terminate application */
/* */
/********************************************************/
-void rou_core_dump(const char *fmt,...)
+PUBLIC void rou_core_dump(const char *fmt,...)
{
#define MAXCRASH 10 //maximun crash file within drop zone
/* return zero if everything right */
/* */
/********************************************************/
-int rou_modesubrou(_Bool mode)
+PUBLIC int rou_modesubrou(_Bool mode)
{
#define OPEP "subrou.c:rou_modesubrou"
if (mode!=modopen) {
switch ((int)mode) {
case true :
+ off64_time=(time_t)0;
+ off_date=(time_t)0;
(void) srand(getpid()*355);
if (foreground==true)
(void) srand((int)(M_PI*100000000));
#define APPNAME "maild" //application name
+typedef void (*freehandler_t)(void *);
+
//--- Variables defined within subrou.c ---------
extern int debug; //application debug mode
extern _Bool foreground; //process is in foreground mode
//return program version
extern const char *rou_getversion();
+//Procedure to free a string pointer and return
+//a NULL pointer
+extern char *rou_freestr(char *str);
+
+//to add a not null pointer to a list of pointer
+extern void **rou_addlist(void **list,void *entry);
+
+//Procedure to free one entry part of list
+// return true if found, false otherwize.
+extern _Bool rou_rmlist(void **list,void *entry,freehandler_t handler);
+
//change the application name
extern char *rou_setappname(const char *newname);
/********************************************************/
#include <sys/types.h>
#include <sys/socket.h>
+#include <errno.h>
+#include <fcntl.h>
#include <netdb.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "subrou.h"
#include "unisoc.h"
static _Bool modopen; //module open/close status
/*
-^L
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to free memory used by a */
+/* binding info. */
+/* */
+/* */
+/********************************************************/
+static SOCTYP *freebinding(SOCTYP *binding)
+
+{
+if (binding!=(SOCTYP *)0) {
+ binding->port=rou_freestr(binding->port);
+ binding->ip=rou_freestr(binding->ip);
+ (void) free(binding);
+ binding=(SOCTYP *)0;
+ }
+return binding;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to bind a socket to a specific */
+/* address and return the linked handle */
+/* */
+/********************************************************/
+static int bindhandle(struct addrinfo *ai,SOCTYP *binding)
+
+{
+#define OPEP "unisoc.c:bindhandle,"
+#define BFSZ 30 //working buffer size
+
+int handle;
+struct linger slg;
+char *buf;
+int flags;
+int phase;
+_Bool proceed;
+
+handle=-1;
+(void) memset(&slg,'\000',sizeof(struct linger));
+buf=calloc(BFSZ,sizeof(char));
+flags=0;
+phase=0;
+proceed=true;
+while (proceed==true) {
+ switch (phase) {
+ case 0 : //lets get a socket
+ if ((handle=socket(ai->ai_family,ai->ai_socktype,ai->ai_protocol))<0) {
+ (void) rou_alert(0,"%s Unable to open socket for <%s> (error='%s')",
+ OPEP,ai->ai_canonname,strerror(errno));
+ phase=999; //trouble trouble
+ }
+ break;
+ case 1 : //setting socket option (address)
+ if (setsockopt(handle,SOL_SOCKET,SO_REUSEADDR,buf,BFSZ*sizeof(char))<0) {
+ (void) rou_alert(0,"%s Unable to get socket option "
+ "SO_REUSEADDR for <%s> (error='%s')",
+ OPEP,ai->ai_canonname,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 2 : //setting socket option (port)
+ if (setsockopt(handle,SOL_SOCKET,SO_REUSEPORT,buf,BFSZ*sizeof(char))<0) {
+ (void) rou_alert(0,"%s Unable to get socket option "
+ "SO_REUSEPORT for <%s> (error='%s')",
+ OPEP,ai->ai_canonname,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 3 : //SO_LINGER allow Connection reset by peer"
+ if (setsockopt(handle,SOL_SOCKET,SO_LINGER,&slg,sizeof(slg))<0) {
+ (void) rou_alert(0,"%s Unable to set socket option "
+ "SO_LINGER for <%s> (error='%s')",
+ OPEP,ai->ai_canonname,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 4 : /*getting socket option */
+ if ((flags=fcntl(handle,F_GETFL,0))<0) {
+ (void) rou_alert(0,"%s Unable to set socket descriptor "
+ "for <%s> (error='%s')",
+ OPEP,ai->ai_canonname,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 5 : //setting the socket working setting
+ if (fcntl(handle,F_SETFL,flags|O_NONBLOCK|O_ASYNC)<0) {
+ (void) rou_alert(0,"%s Unable to set socket in none "
+ "block mode for <%s> (error='%s')",
+ OPEP,ai->ai_canonname,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 6 : //getting socket option
+ if (bind(handle,ai->ai_addr,ai->ai_addrlen)<0) {
+ (void) rou_alert(0,"%s Unable to bind on IP/port <%s/%s> (error='%s')",
+ OPEP,ai->ai_canonname,binding->port,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 7 : /*preparing listen */
+ if (listen(handle,5)<0) {
+ (void) rou_alert(0,"%s Unable to listen on IP/port <%s/%s> (error='%s')",
+ OPEP,ai->ai_canonname,binding->port,strerror(errno));
+ phase=999; //trouble cleanup phase
+ }
+ break;
+ case 8 : /*reporting listen */
+ (void) rou_alert(1,"Now Listening on IP/PORT <%s/%s>",
+ ai->ai_canonname,binding->port);
+ proceed=false; //evrything fine no need to go further
+ break;
+ default : /*SAFE Guard */
+ if (handle>=0)
+ close(handle);
+ proceed=false;
+ break;
+ }
+ phase++;
+ }
+(void) free(buf);
+return handle;
+#undef OPEP
+}
+/*
+\f
*/
/********************************************************/
/* */
-/* Procedure to bind a sockt to a specific */
-/* IP/PORT. */
+/* Procedure to free memory used by a bind */
+/* definition. */
+/* */
+/********************************************************/
+PUBLIC SOCTYP **soc_freebindinf(SOCTYP **bindref)
+
+{
+if (bindref!=(SOCTYP **)0) {
+ int i;
+
+ for (i=0;bindref[i]!=(SOCTYP *)0;i++) {
+ bindref[i]=freebinding(bindref[i]);
+ }
+ (void) free(bindref);
+ bindref=(SOCTYP **)0;
+ }
+return bindref;
+}
+/*
+\f
+*/
+/********************************************************/
+/* */
+/* Procedure to set memory used by a bin */
+/* definition. */
/* */
/********************************************************/
-static int bindhandle(struct addrinfo *ai,BINTYP *binding)
+PUBLIC SOCTYP **soc_mkbindinf(SOCTYP **bindings,PROTYP proto,
+ const char *ip,const char *port,int iteration)
{
-return -1;
+SOCTYP *bininf;
+
+bininf=(SOCTYP *)calloc(1,sizeof(SOCTYP));
+bininf->proto=proto;
+bininf->ip=strdup(ip);
+bininf->port=strdup(port);
+bininf->iteration=iteration;
+bindings=(SOCTYP **)rou_addlist((void **)bindings,(void *)bininf);
+return bindings;
}
/*
^L
/* IP/PORT. */
/* */
/********************************************************/
-PUBLIC int soc_setbind(BINTYP *binding)
+PUBLIC int soc_setbind(SOCTYP *binding)
{
#define OPEP "unisoc.c:soc_setbind"
while (proceed==true) {
switch (phase) {
case 0 : //sanity check
- if (binding==(BINTYP *)0) {
+ if (binding==(SOCTYP *)0) {
(void) rou_alert(0,"%s, socket binding reference is NULL (Bug!?)",OPEP);
phase=999; //no need to go further
}
#include <stdbool.h>
#include <time.h>
+//defining email protocol value.
+typedef enum {
+ pro_smtp, //text SMTP protocol, in clear mode
+ pro_startls, //Text SMTP protocol, encrypted upon request
+ pro_smtps, //Text SMTP protocol, text encrypted from start
+ pro_unknwn //Protcole undefined
+ }PROTYP;
+
typedef struct {
+ PROTYP proto; //Connexion protocol type
char *ip; //Binding IP //IPV4 or IPV6
char *port; //Binding Port
time_t lasttry; //successful binding last time
- }BINTYP;
+ int iteration; //number of handle ready on the soc
+ int handle; //connexion handle
+ }SOCTYP;
+
+//procedure to free all memory used by a TCP socket
+//definition (once closed)
+extern SOCTYP **soc_freebindinf(SOCTYP **bindref);
+
+//procedure to assign memory to be used by a TCP socket
+//definition
+extern SOCTYP **soc_mkbindinf(SOCTYP **bindings,PROTYP proto,
+ const char *ip,const char *port,int iteration);
//procedure to open a socketand retunr handle to socket
-extern int soc_setbind(BINTYP *binding);
+extern int soc_setbind(SOCTYP *binding);
//homework to be done before starting/stopping module.
extern int soc_modeunisoc(_Bool mode);