Index: /branches/rel_avx_2_7_2/src/backend/Makefile
===================================================================
--- /branches/rel_avx_2_7_2/src/backend/Makefile	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/backend/Makefile	(working copy)
@@ -22,6 +22,7 @@
        -L${TOP}/lib/vtch -lvtch -lmsgpack -lresolv\
        -lxmlrpc_util -lxmlrpc -lxmlrpc_client\
        -L ../library/ca_util -lcautil -L ../library/ca_ui -lcaui -L ../library/node_man -lnode \
+       -L ../library/ca_mail -lcamail \
        -L${TOP}/lib/libopenssl-1.1.1  -lcrypto-tls13 -lssl-tls13 \
        -lutil  -L ../library/avxnet -lavxnet \
        -L$(TOP)/src/library/management -lsuppress_print \
@@ -48,7 +49,8 @@
 
 FLAGS =$(JSON_LIB) -Wformat -Wall -Wno-long-long  -O -I${TOP}/kern/monitor -I${TOP}/lib/ \
 	 -I${TOP}/lib/casnmp -I${TOP}/lib/avxpci -I${TOP}/lib/feactl  \
-     -I ${TOP}/src/library/avxnet/ \
+         -I ${TOP}/src/library/avxnet/ \
+	 -I ${TOP}/src/library/ca_mail/ \
 	 -I ${TOP}/src/library/avx_log -I$(TOP)/src/library/avxha \
 	 -I ${TOP}/src/library/avxresource/ -L${TOP}/src/library/avxresource/ 
 
Index: /branches/rel_avx_2_7_2/src/backend/backend.c
===================================================================
--- /branches/rel_avx_2_7_2/src/backend/backend.c	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/backend/backend.c	(working copy)
@@ -43,11 +43,12 @@
 #include "proxy_shm.h"
 #include "ca_ui.h"
 #include "ca_util.h"
+#include "../library/ca_mail/sys_mail.h"
 #include "node_sys.h"
 #include "node_cmd.h"
 #include "sys_tool.h"
 #include "users.h"
-#include "suppress_print.h"
+#include "../library/management/suppress_print.h"
 #include "libvirt_connection.h"
 #include "va_resource.h"
 #include "va_utils.h"
Index: /branches/rel_avx_2_7_2/src/bin/eventlogd/Makefile
===================================================================
--- /branches/rel_avx_2_7_2/src/bin/eventlogd/Makefile	(revision 0)
+++ /branches/rel_avx_2_7_2/src/bin/eventlogd/Makefile	(working copy)
@@ -0,0 +1,11 @@
+# ArrayOS
+NO_MAN=
+PROG=	eventlogd
+SRCS=	eventlogd.c
+CFLAGS+=-I${.CURDIR}/../../library/ca_mail
+
+.if defined(USTACK)
+LDADD+= -L${.OBJDIR}/../../lib/libuinet-atcp/lib/libuinet_sysctl -luinet_sysctl \
+	-L${.OBJDIR}/../../lib/libuinet-atcp/lib/libuinetnv -luinetnv \
+	-lrt -lcrypto
+.endif
Index: /branches/rel_avx_2_7_2/src/bin/eventlogd/eventlogd.c
===================================================================
--- /branches/rel_avx_2_7_2/src/bin/eventlogd/eventlogd.c	(revision 0)
+++ /branches/rel_avx_2_7_2/src/bin/eventlogd/eventlogd.c	(working copy)
@@ -0,0 +1,585 @@
+/*-----------------------------------------------------------------------------
+ *
+ * Copyright (C) 2000-2001
+ * Array Networks Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification is not permitted unless authorized in writing by a duly 
+ * appointed officer of Array Networks Inc. or its derivatives
+ *
+ * @(#) eventlogd.c
+ * This is the daemon file for event log
+ *
+ * $ArrayOS$
+ *
+ *---------------------------------------------------------------------------
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/time.h> /*for gettimeofday*/
+#include <sys/wait.h>
+#include <sys/shm.h>
+#include <unistd.h>  /*for pause*/
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <click/app/fastlog/seclog_common.h>
+#include <../../proxy_shm.h>
+#include <../../library/ca_mail/sys_mail.h>
+#include <click/app/proxy/prxconfig.h> /* for url filter */
+
+#define ROOT_MAIL_PATH "/var/mail/root"
+#define ROOT_MAIL_MAXSIZE 10485760 /*10M*/
+
+sys_mail_conf_t *sys_mail_conf_p;
+
+/*define functions*/
+static int eventlog_shm_init(void);
+static int eventlog_sig_init(void);
+static void eventlog_sig_child(int signo);
+static void eventlog_sendmail(int signo);
+
+char *get_from_header(char *hostname);
+char *get_sender_name(char *from_header);
+
+/****f cli [1.0]---------------------------------------------------
+ *  
+ *  NAME        :
+ *                main
+ *  SYNOPSIS    :
+ *               
+ *  FUNCTION    :
+ *                main function for event log daemon
+ *  INPUT       :
+ *                none.
+ *  RESULT      :
+ *                none.
+ *  EXAMPLE     :
+ *               
+ *  NOTES       :
+ *               
+ *  BUGS        :
+ *                
+ *  SEE ALSO    :
+ *                    
+ *
+ ******----------------------------------------------------------------
+ */ 
+int 
+main(int argc, char *argv[])
+{
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+	/* init shared memory */
+	eventlog_shm_init();
+
+    /*init all the signals*/
+    eventlog_sig_init();
+    for ( ; ; ) 
+	pause();
+   
+    /*NOTREACHED*/
+    return 0; 
+}
+
+
+/*handle child dead signal*/
+static void
+eventlog_sig_child(int signo)
+{
+    int sig_state;
+
+    /*not start at the beginning*/
+    if(waitpid(-1, &sig_state, WNOHANG) > 0) {
+	
+	/*currently do nothing*/
+    }	    
+    
+    return;
+}
+
+static int
+eventlog_shm_init(void)
+{
+	int shm_id = 0;
+
+	shm_id = shmget(SYS_MAIL_SHM_KEY, SYS_MAIL_SHM_SZ,
+			SYS_MAIL_SHM_MODE|IPC_CREAT);
+	if (shm_id == -1) {
+		return -1;
+	}
+
+	sys_mail_conf_p = (sys_mail_conf_t *)shmat(shm_id, NULL, 0);
+	if (sys_mail_conf_p == NULL) {
+		return -1;
+	}
+
+	bzero(sys_mail_conf_p, sizeof(sys_mail_conf_t));
+
+	return 0;
+}
+
+/*set all the signal handlers*/
+static int 
+eventlog_sig_init(void)
+{
+    struct itimerval one_tick;    
+    
+    /*ignore some signals*/
+    signal(SIGCHLD, eventlog_sig_child);
+    signal(SIGURG,  SIG_IGN);    
+    signal(SIGUSR1, SIG_IGN);
+    signal(SIGUSR2, SIG_IGN);        
+    
+    /*set sigalarm signal*/
+    signal(SIGALRM, eventlog_sendmail);
+        
+    /*round to the beginning of a minute*/
+    one_tick.it_value.tv_sec = FASTLOG_SENDMAIL_TIME;
+    one_tick.it_value.tv_usec = 0;       
+    one_tick.it_interval.tv_sec = FASTLOG_SENDMAIL_TIME;
+    one_tick.it_interval.tv_usec = 0;   
+
+    setitimer(ITIMER_REAL, &one_tick, NULL);        
+    return 0;
+}
+
+
+
+/*signal handlers for sigalrm, send alert data to outside mailers*/
+#define RM_MAIL                      "/bin/rm -rf /var/spool/mqueue/*"                       
+#define SENDMAIL_PATH                "/usr/sbin/sendmail"
+#define SENDMAIL_HEADER_FROM         "From: %s<alert@log.domain>\n"
+#define SENDMAIL_HEADER_TO           "To: Alert Log System Operator(s)<%s>\n"
+/*#define SENDMAIL_HEADER_SUBJECT      "Subject: **Alert Log System**  ID %d: %s\n"*/	    
+#define SENDMAIL_HEADER_SUBJECT      "Subject: Log Alert ID: %d - %s\n"	    
+#define SENDMAIL_MESSAGE_COUNT       "ID %d: match %d time(s).\n"
+
+/* ssmtp is not supported on debian 10, use msmtp instead*/
+#if defined(__linux__)
+#define SSMTP_PATH                   "/usr/sbin/ssmtp"
+#define SSMTP_PATH_BIN               "ssmtp"
+
+#ifdef UOS_X86
+#undef  SSMTP_PATH
+#undef  SSMTP_PATH_BIN
+#define SSMTP_PATH                   "/usr/bin/msmtp"
+#define SSMTP_PATH_BIN               "msmtp"
+
+#endif
+#else
+#define SSMTP_PATH                   "/usr/local/sbin/ssmtp"
+#endif
+
+#define UF_SENDMAIL_HEADER_FROM      "From: %s<alert@log.domain>\n"
+#define UF_SENDMAIL_HEADER_TO        "To: Alert Log System Operator(s)<%s>\n"
+#define UF_SENDMAIL_HEADER_SUBJECT   "Subject: Filter Alert vip:%d.%d.%d.%d -- %d request(s) dropped\n"
+#define UF_SENDMAIL_MESSAGE_COUNT    "Request droped %d time(s).\n"	
+#define FROM_STR_SSMTP               "From: <%s>\n"
+#define FROM_STR                     "From: "
+
+static void
+eventlog_sendmail(int signo)
+{
+    uf_alerts_t ufalert;
+
+    /*alert log configuration and data variables*/
+    log_alert_buffer_t labuf;
+    log_mbox_buffer_t lmbuf;    
+    /*fastlog_config_data_t lconf;*/
+    log_alert_t *alert;
+    log_mbox_t *mbox;
+
+    /*help variables*/
+    char str[FASTLOG_MAX_LINE_SIZE + 1] = "";
+    char hostname[FASTLOG_MAX_LONG_TOKEN_SIZE + 1] = "";
+    int fd[2];   /*for the pipe between the parent and the child*/
+    int pid;
+    size_t len;    
+    int i, j;
+
+    char *email;
+    struct stat sstat;
+    char *from, *sender;
+
+    /*remove old mbox file, currently we do not do the re-transmit*/
+    system(RM_MAIL);
+
+    /*get alert log settings*/
+    len = sizeof(log_alert_buffer_t);
+    if (sysctlbyname("net.inet.clicktcp.alert_buffer",
+		      (void *)&labuf, &len, NULL, 0) < 0) 
+	return;  /*error*/
+    
+    /*get mail box data*/
+    len = sizeof(log_mbox_buffer_t);
+    if (sysctlbyname("net.inet.clicktcp.fastlog_alert_data",
+		      (void *)&lmbuf, &len, NULL, 0) < 0) 
+	return;  /*error*/    
+
+#if 0
+    len = sizeof(log_mbox_buffer_t);
+    if (sysctlbyname("net.inet.clicktcp.mbox_buffer",
+		      (void *)&lmbuf, &len, NULL, 0) < 0) 
+	return;  /*error*/
+
+    /*tell kernel to clean mail boxes*/
+    kern_fastlog_cli_config(LOG_ACTION_SENDMAIL, &lconf, sizeof(lconf));
+#endif 
+    
+    /*get local host name, used as From: field in email*/
+    memset(hostname, 0, sizeof(hostname));
+    if (gethostname(hostname, sizeof(hostname) -1) < 0) {
+
+	/*do nothing for now*/
+    }
+    
+	from = get_from_header(hostname);
+	sender = get_sender_name(from);
+
+    /*send the data out*/
+    for (i = 1; i <= FASTLOG_MAX_ALERT_NUM; i++) {
+	
+	alert = &labuf.alerts[i];
+	mbox = &lmbuf.mboxes[i];
+	if (  (alert->flags & FASTLOG_ALERT_INUSE) &&
+	      (!alert->timer) && 
+	      ( ( (alert->flags & FASTLOG_ALERT_COUNT) && (alert->count) ) || 
+	   	  (mbox->len > 0) ) ) {
+
+	    /*setup the pipe between the parent and the child*/
+	    if (pipe(fd) < 0) {
+		
+		/*currently do nothing*/
+		return;
+	    }
+	    
+	    /*fork the child process to send the email*/
+	    if ((pid = fork()) < 0) {
+
+		/*currently do nothing, but return*/
+		return;
+	    }
+
+	    if (!pid) {
+		
+		/*in child process, send the mail, but need to read message*/
+		/*from parent*/
+
+		/*close standard file descriptors*/
+		close(STDIN_FILENO);
+		close(STDOUT_FILENO);
+		close(STDERR_FILENO);
+		
+		/*close fd[1], that is used by the parent, dup stdin, out to fd[0]*/
+		close(fd[1]);
+		dup(fd[0]);
+		dup(fd[0]);
+		
+		/*remove if the /var/mail/root reaches the limit size ROOT_MAIL_MAXSIZE*/
+		bzero(&sstat, sizeof(sstat));
+		if((stat(ROOT_MAIL_PATH, &sstat) == 0) && (sstat.st_size >= ROOT_MAIL_MAXSIZE)) {
+		   unlink(ROOT_MAIL_PATH);
+		}
+
+		/*execute the */
+		if (sys_mail_conf_p->extern_mail_on) {
+			if (execl(SSMTP_PATH, SSMTP_PATH_BIN, alert->email, NULL) < 0) {
+				printf("Error in %s.\n",SSMTP_PATH_BIN);
+				exit(-1);
+			}
+
+		} else {
+			if (sys_mail_conf_p->hostname_behavior) {
+				if (execl(SENDMAIL_PATH, "sendmail", "-C", SENDMAIL_CONF_FILE, "-f", sender,
+						"-t", alert->email, NULL) < 0) {
+					printf("Error in sendmail.\n");
+					exit(-1);
+				}
+			} else {
+				if (execl(SENDMAIL_PATH, "sendmail", "-f", sender,
+						"-t", alert->email, NULL) < 0) {
+					printf("Error in sendmail.\n");
+					exit(-1);
+				}
+			}
+		}
+
+		exit(0);
+	    }
+
+	    /*now, in parent, close fd[1]*/
+	    close(fd[0]);
+
+	    /*
+	     * Here, we set the email header fields, includ: from, to, subject
+	     * Then send all the data
+	     *
+	     */
+	    if (sys_mail_conf_p->extern_mail_on) {
+		    snprintf(str, sizeof(str), FROM_STR_SSMTP, sys_mail_conf_p->mextern_server.user);
+		    write(fd[1], str, strlen(str));
+	    } else {
+		    write(fd[1], from, strlen(from));
+	    }
+	    
+	    snprintf(str, sizeof(str), SENDMAIL_HEADER_TO, alert->email);
+	    write(fd[1], str, strlen(str));
+	    
+	    /*subject is like: ID 5: fail*return */
+	    snprintf(str, sizeof(str), SENDMAIL_HEADER_SUBJECT, i, alert->match);
+	    write(fd[1], str, strlen(str));
+
+	    if (sys_mail_conf_p->extern_mail_on) {
+		    /*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+		    write(fd[1], "\n", 1);
+	    }
+
+	    /*begin to send data*/
+	    if (alert->flags & FASTLOG_ALERT_COUNT) {
+		
+		/*need to combinize the string*/
+		snprintf(str, sizeof(str), SENDMAIL_MESSAGE_COUNT, i, alert->count);
+		write(fd[1], str, strlen(str));
+	    }
+	    else {
+
+		/*get data from mbox*/
+		/*get data from dedicated mbox firstly*/		    
+		write(fd[1], mbox->data, mbox->len);
+		if (mbox->len > (FASTLOG_MAX_DATA_SIZE - MAX_LOG_STRING) ) {
+		    
+		    /*check the extra mboxes*/
+		    for (j = FASTLOG_MAX_ALERT_NUM + 1; j < FASTLOG_MAX_MBOX_NUM; j++) {
+
+			mbox = &lmbuf.mboxes[j];
+			if (mbox->id == i)    /*send data in the extra mboxes*/
+			    write(fd[1], mbox->data, mbox->len);
+		    }
+		}
+	    }
+	    
+	    /*send out all the data*/
+	    close(fd[1]);
+    	}
+    } 
+#if 0
+    /*get alert log settings*/
+    len = sizeof(uf_alerts_t);
+    if (sysctlbyname("net.inet.clicktcp.uf_alert",
+		      (void *)&ufalert, &len, NULL, 0) < 0) 
+	return;
+#endif
+
+    /*get mail box data, and reset the kernel data*/
+    len = sizeof(uf_alerts_t);
+    if (sysctlbyname("net.inet.clicktcp.uf_alert_data",
+		      (void *)&ufalert, &len, NULL, 0) < 0) 
+	return;  /*error*/
+
+    for(i=0; i < URLFILTER_MAX_ALERT; i++) {
+
+	if (ufalert.mbox[i].send_flag > 0) {
+	    uint8_t *ptr;
+
+	    email = ufalert.mbox[i].email;
+	    ptr = (uint8_t *)&ufalert.mbox[i].ip;
+#if 0
+	printf("%s--, %d, %d\n",
+	       email, ufalert.mbox[i].thold, ufalert.mbox[i].send_flag);
+#endif
+
+	    /*setup the pipe between the parent and the child*/
+	    if (pipe(fd) < 0) {
+		
+		/*currently do nothing*/
+		return;
+	    }
+
+	    /*fork the child process to send the email*/
+	    if ((pid = fork()) < 0) {
+
+		/*currently do nothing, but return*/
+		return;
+	    }
+
+	    if (!pid) {
+		
+		/*in child process, send the mail, but need to read message*/
+		/*from parent*/
+
+		/*close standard file descriptors*/
+		close(STDIN_FILENO);
+		close(STDOUT_FILENO);
+		close(STDERR_FILENO);
+		
+		/*close fd[1], that is used by the parent, dup stdin, out to fd[0]*/
+		close(fd[1]);
+		dup(fd[0]);
+		dup(fd[0]);
+		
+		/*remove if the /var/mail/root reaches the limit size ROOT_MAIL_MAXSIZE*/
+		bzero(&sstat, sizeof(sstat));
+		if((stat(ROOT_MAIL_PATH, &sstat) == 0) && (sstat.st_size >= ROOT_MAIL_MAXSIZE)) {
+		   unlink(ROOT_MAIL_PATH);
+		}
+		
+		/*execute the */
+		if (sys_mail_conf_p->extern_mail_on) {
+			if (execl(SSMTP_PATH, SSMTP_PATH_BIN, email, NULL) < 0) {
+			    printf("Error in %s.\n",SSMTP_PATH_BIN);
+			    exit(-1);
+			}
+		} else {
+			if (sys_mail_conf_p->hostname_behavior) {
+				if (execl(SENDMAIL_PATH, "sendmail", "-C", SENDMAIL_CONF_FILE, "-f", sender,
+						"-t", email, NULL) < 0) {
+					printf("Error in sendmail.\n");
+					exit(-1);
+				}
+			} else {
+				if (execl(SENDMAIL_PATH, "sendmail", "-f", sender,
+						"-t", email, NULL) < 0) {
+				    printf("Error in sendmail.\n");
+				    exit(-1);
+				}
+			}
+		}
+		
+		exit(0);
+	    }
+
+	    /*now, in parent, close fd[1]*/
+	    close(fd[0]);
+
+	    /*
+	     * Here, we set the email header fields, includ: from, to, subject
+	     * Then send all the data
+	     *
+	     */
+	    if (sys_mail_conf_p->extern_mail_on) {
+		    snprintf(str, sizeof(str), FROM_STR_SSMTP, sys_mail_conf_p->mextern_server.user);
+		    write(fd[1], str, strlen(str));
+	    } else {
+		    write(fd[1], from, strlen(from));
+	    }
+	    snprintf(str, sizeof(str), UF_SENDMAIL_HEADER_TO, email);
+	    write(fd[1], str, strlen(str));
+
+	    /*subject is like: ID 5: fail*return */
+	    snprintf(str, sizeof(str), UF_SENDMAIL_HEADER_SUBJECT,
+		     *ptr, *(ptr+1), *(ptr+2), *(ptr+3),ufalert.mbox[i].thold);
+	    write(fd[1], str, strlen(str));
+
+	    if (sys_mail_conf_p->extern_mail_on) {
+	    	/*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+	    	write(fd[1], "\n", 1);
+	    }
+#if 0
+	    /*need to combinize the string*/
+	    snprintf(str, sizeof(str), UF_SENDMAIL_MESSAGE_COUNT, ufalert.mbox[i].thold);
+
+	    write(fd[0], str, strlen(str));
+#endif
+	    /*send out all the data*/
+	    close(fd[1]);
+	}
+    }
+   
+    return;
+}
+
+#define MAX_FROM_HEADER_LEN             1024
+
+char *
+get_from_header(char *hostname)
+{
+	int esc = 0, n = 0;
+	char *str = sys_mail_conf_p->from;
+	static char from[MAX_FROM_HEADER_LEN + 1];
+
+	n += sprintf((from+n), FROM_STR);
+	while (*str) {
+		if (esc == 1) {
+			esc = 0;
+			switch (*str) {
+			case 'h':
+				n += sprintf((from+n), "%s", hostname);
+				break;
+
+			case 'q':
+				n += sprintf((from+n), "\"");
+				break;
+
+			case '%':
+				n += sprintf((from+n), "%%");
+				break;
+
+			default:
+				break;
+			}
+		} else if (*str == '%') {
+			esc = 1;
+		} else {
+			n += sprintf((from+n), "%c", *str);
+		}
+
+		str++;
+	}
+
+	n += sprintf((from+n), "\n");
+	/*write(fd, from, n);*/
+
+	return from;
+}
+
+/*
+*Get sender name from from header:
+*From: tmx@arraynetworks.com.cn\n       ->     tmx
+*From: hostname<alert@log.domain>\n     ->     alert
+*From: AN\n                             ->     AN
+*/
+char *
+get_sender_name(char *from_header)
+{
+	static char name[MAX_FROM_HEADER_LEN + 1];
+	char *at_pos = NULL;
+	char *beg_pos = NULL;
+
+	if ((at_pos = strchr(from_header, '@')) != NULL) {
+		beg_pos = at_pos;
+		
+		do {
+			beg_pos--;
+		} while((*beg_pos != '<') && beg_pos != from_header);
+
+		/*From: hostname<alert@log.domain>\n     ->     alert*/
+		if (*beg_pos == '<') {
+			beg_pos++;
+		} else  {
+			/*From: tmx@arraynetworks.com.cn\n       ->     tmx*/
+			if(strncmp(from_header, FROM_STR, strlen(FROM_STR)) == 0) {
+			beg_pos = from_header + strlen(FROM_STR);
+			}
+		}
+
+		*at_pos = '\0';
+		sprintf(name, beg_pos);
+		*at_pos = '@';
+
+	} else {
+
+		/*From: AN\n    ->     AN*/
+		beg_pos = from_header;
+		if(strncmp(from_header, FROM_STR, strlen(FROM_STR)) == 0) {
+			beg_pos = beg_pos + strlen(FROM_STR);
+		}
+
+		strncpy(name, beg_pos, strlen(beg_pos)-1);
+		*(name+strlen(beg_pos)-1)= '\0';
+
+	}
+	return name;
+}

Property changes on: src/bin/eventlogd/eventlogd.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/rel_avx_2_7_2/src/bin/tracker/Makefile
===================================================================
--- /branches/rel_avx_2_7_2/src/bin/tracker/Makefile	(revision 0)
+++ /branches/rel_avx_2_7_2/src/bin/tracker/Makefile	(working copy)
@@ -0,0 +1,19 @@
+# ArrayOS
+NO_MAN=
+PROG=	tracker
+SRCS=	tracker.c
+CFLAGS+=-I${.CURDIR}/../../../lib/libfeactl \
+	-I${.CURDIR}/../../lib/libip \
+	-I${.CURDIR}/../../lib/libfastlog \
+	-I${.CURDIR}/../../lib/libtracker_cli \
+	-I${.CURDIR}/../../lib/libkernelapi \
+	-I${.OBJDIR}/../../lib/libkernelapi \
+	-I${.CURDIR}/../../library/libca_mail
+
+LDADD=${.OBJDIR}/../../lib/libkernelapi/libkernelapi.a \
+	${.OBJDIR}/../../lib/libfeactl/libfeactl.a \
+	${.OBJDIR}/../../lib/libversion/libversion.a \
+	${.OBJDIR}/../../lib/libip/libip.a \
+	-lfastlog \
+	${.OBJDIR}/../../lib/libenglog/libenglog.a \
+	-lssl -lcrypt -lcrypto

Property changes on: src/bin/tracker/Makefile
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/rel_avx_2_7_2/src/bin/tracker/tracker.c
===================================================================
--- /branches/rel_avx_2_7_2/src/bin/tracker/tracker.c	(revision 0)
+++ /branches/rel_avx_2_7_2/src/bin/tracker/tracker.c	(working copy)
@@ -0,0 +1,1579 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include "feactl.h"
+#include <string.h>
+#include <time.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <click/netinet/cafw.h>
+#include <click/sys/clickaddr.h>
+#include <../../proxy_shm.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "fastlog.h"
+#include "aes.h"
+#include "userWrapper.h"
+#include "../../library/ca_mail/sys_mail.h"
+//#include "nsae_sm2_lic_dec.h"
+
+void maintain_history();
+void update_history(uint64_t licensed_bandwidth);
+uint64_t get_interface_traffic(struct if_info *if_info_pi);
+void update_current(uint64_t low, uint64_t peak, uint64_t accumulate, uint64_t count_five, int count_violation);
+extern uint64_t feactl_bandwidth(void);
+void display_history(FILE *history);
+void mail_info(uint64_t, uint64_t, struct tm* );
+void get_bandwidth_unit(uint64_t bandwidth, float* p_bandwidth, char* p_unit);
+
+/*char* write_license_server(void);*/
+
+int update_grace_period(int update);
+int get_server_confirmation();
+int feactl_expire_check_vol(int counter_grace);
+int check_vol_key();
+int contact_server(FILE *p_licconf);
+void mail_info_vol(struct tm*, int flag);
+
+#define LICENSE_SERVER_CONFIRM	"/tmp/pingout.txt"  
+#define CONFIRM_SUCCESS		0
+#define CONFIRM_CONNECT         100
+#define CONFIRM_AUTH   	        120
+#define CONFIRM_LICENSE         140
+#define CONFIRM_REG             160
+#define CONFIRM_BANDWIDTH       180
+#define CONFIRM_OTHER           200
+
+#define SENDMAIL_PATH "/usr/sbin/sendmail"
+#define SENDMAIL_HEADER_FROM         "From: %s<alert@log.domain>\n"
+#define SENDMAIL_HEADER_TO           "To: Alert Log System Operator(s)<%s>\n"
+#define SENDMAIL_HEADER_SUBJECT      "Subject: Tracker detected bandwidth overshoot\n"
+#define SENDMAIL_HEADER_BODY	     "%d/%d/%d %d:%d Bandwidth: %lu. Exceeded the licensed bandwidth %lu. Please contact array admin to upgrade license\n.\n"
+#define SSMTP_PATH                   "/usr/local/sbin/ssmtp"
+#define FROM_STR_SSMTP               "From: <%s>\n"
+
+int 
+main(int argc,char **argv)
+{
+        FILE *current, *history;
+        FILE *temp_update, *temp_maintain, *temp_current;
+	struct if_info if_info;
+        uint64_t total_bandwidth;
+        time_t cur_time;
+        struct tm *timeinfo;
+        int written = 0,last_hour = 0;
+        uint64_t low,peak,accumulate,licensed_bandwidth, licensed_bandwidth_c, last_low, last_peak, last_accumulate, count_five, last_count_five;
+	int year, month, day, count_violation, last_count_violation;
+
+	time_t daemon_start;
+	time_t daemon_end;
+	time_t daemon_cost;
+	time_t sleep_time;
+	int restart_flag = 0; 
+
+	struct stat st;
+	int status;
+
+	FILE *p_licconf;
+
+	setbuf(stdout, NULL);
+	setbuf(stderr, NULL);
+
+#if defined(__linux__)
+	if (uhi_shared_mem_attach() != 0) {	
+		return -1;
+	}
+#endif
+
+	/* counter for grace period, will update the file every 60min */
+	int counter_grace = 12;
+
+	/* contact the server 24hrs later after one successful contact, will contact the server everytime track is restarted */
+	int cutomorrow = 0;
+
+	/* use sysctl to get licensed bandwidth in bits */
+	licensed_bandwidth_c= feactl_bandwidth();
+
+	/*
+ 	 * Check for directory exixtence
+  	 */
+	if( stat("/var/log/bandwidth", &st) != 0){
+		status = mkdir("/var/log/bandwidth",S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+		if (status == -1){
+			fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);
+			exit(0);
+		}
+	}
+		
+	temp_current = fopen("/var/log/bandwidth/temp_current", "r");
+	current = fopen("/var/log/bandwidth/current", "r");
+	if ((current == NULL)&&(temp_current != NULL)){
+		rename("/var/log/bandwidth/temp_current", "/var/log/bandwidth/current");
+	}
+
+	history = fopen("/var/log/bandwidth/history", "r");
+	temp_maintain = fopen("/var/log/bandwidth/temp_maintain", "r");
+
+	/* shut down happens during maintain/update history file */  
+
+	/* If history and temp_maintain both exist, after booting it will do the maintain job again then update */
+	if((history == NULL)&&(temp_maintain != NULL)){
+		rename("/var/log/bandwidth/temp_maintain","/var/log/bandwidth/history");
+	}
+
+	temp_update = fopen("/var/log/bandwidth/temp_update", "r");
+
+	if((history == NULL) && (temp_update != NULL)){
+		rename("/var/log/bandwidth/temp_update","/var/log/bandwidth/history");	
+	}
+	else if((history != NULL) && (temp_update != NULL)){
+       		remove("/var/log/bandwidth/temp_update");
+	}
+
+	if (current){
+		fclose(current);
+	}	
+	if (history){
+		fclose(history);
+	}
+
+	if (temp_maintain){
+		fclose(temp_maintain);
+	}	
+	
+	if (temp_update){
+		fclose(temp_update);
+	}	
+		
+	if (temp_current){
+		fclose(temp_current);
+	}
+
+	/* opening in a+ because if file exists we don't want
+       	* to lose its contents
+       	*/
+       	history = fopen("/var/log/bandwidth/history","a+");
+       	current = fopen("/var/log/bandwidth/current","a+");
+
+	if(history == NULL || current == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+
+	/*	
+       	 * Initialize the variables, if current is empty
+       	 * if current has content initalize the param to current
+	 * read from the currnent file if there are contents already
+       	 * This can happen when system is rebooting
+       	 */
+
+	time(&cur_time);
+	timeinfo = localtime(&cur_time);
+
+	/* If current is empty */
+        if(fscanf(current,"%d %d %d %lu %lu %lu %lu %d\n",&year,&month,&day,&last_low,&last_peak,&last_accumulate,&last_count_five,&last_count_violation) != 8) {
+		memset(&if_info, 0, sizeof(if_info));
+		if ((total_bandwidth = get_interface_traffic(&if_info)) == -1){
+			return(0);
+		}	
+
+		low = peak = total_bandwidth;	
+		accumulate = 0;
+		count_five = 0;
+		count_violation = 0;
+	}
+	
+	/* If reboot happened in the same day */
+	else if(year == timeinfo->tm_year+1900 && month == timeinfo->tm_mon+1 && day == timeinfo->tm_mday){
+		low = last_low;
+		peak = last_peak;	
+		accumulate = 0;
+		count_five = 0;
+		count_violation = 0;
+	}
+
+	/* If reboot happened in different days */
+	else{
+		maintain_history();				
+		update_history(licensed_bandwidth_c);
+
+		memset(&if_info, 0, sizeof(if_info));
+ 		if ((total_bandwidth = get_interface_traffic(&if_info))	== -1){
+			return(0);
+		}
+
+		low = peak = total_bandwidth;
+		accumulate = 0;
+		count_five = 0;
+		count_violation = 0;
+	}
+
+	fclose(history);
+	fclose(current);
+
+	while(1){
+		
+     		/* start time of this cycle */ 
+		time(&daemon_start);
+
+		/* decrease grace period by 1 hour and reset the counter */
+		if (counter_grace <= 0){
+		 	update_grace_period(1);	
+			counter_grace = 12;
+		}
+
+		/* Read the information from the driver for all the NICs */
+		memset(&if_info, 0, sizeof(if_info));
+		if ((total_bandwidth = get_interface_traffic(&if_info)) == -1) {
+				return(0);
+		}
+
+		/* update the variables every 5 min */
+		if (low > total_bandwidth){
+	                low = total_bandwidth;
+		}
+		if( peak < total_bandwidth){
+                          peak = total_bandwidth;
+		}
+
+		accumulate += total_bandwidth;
+		count_five ++;
+       
+		
+		/* check the violation case every 5 min, will not check violation for physical APV */ 
+		printf("bandwidth check: total %lu, license %lu\n", total_bandwidth, licensed_bandwidth_c);
+		if(total_bandwidth > licensed_bandwidth_c && licensed_bandwidth_c != 0){
+			float bandwidth, licensed;
+			char  bandwidth_unit[12], licensed_unit[12];
+			count_violation ++;
+			get_bandwidth_unit(total_bandwidth, &bandwidth, bandwidth_unit);
+			get_bandwidth_unit(licensed_bandwidth_c, &licensed, licensed_unit);
+			/* Send a fastog message and an email */ 
+			fastlog_logex(TRACKER_BANDWIDTH_EXCEEDED, 4, (int)bandwidth, bandwidth_unit, (int)licensed, licensed_unit);  
+       	                time(&cur_time);
+               		timeinfo = localtime(&cur_time);
+			mail_info(total_bandwidth, licensed_bandwidth_c, timeinfo); 
+			printf("bandwidth violation: total %lu, license %lu\n", total_bandwidth, licensed_bandwidth_c);             
+		}
+		
+		/*
+  		* History file is updated once every day after 23:53
+ 		* current file is updated every 2 hrs
+		* use last_hour to store the last write time to current
+		*/ 
+		time(&cur_time);
+		timeinfo = localtime(&cur_time);
+
+		/* If last_hour is more than current time, then its start of a 
+ 		* new day, hence initializing it to 0. Since we keep track of
+		* count every day, we initilize it to 0 as well.
+ 		*/
+		if ( last_hour > timeinfo->tm_hour){
+               		/* new day, so make last hour 0 */
+               		last_hour = 0;
+               		written = 0;
+		}
+
+
+		/* Update the current file every 2 hrs */
+		if (timeinfo->tm_hour - last_hour > 1){
+			/* Update the current file, with the current values */
+			update_current(low,peak,accumulate,count_five,count_violation);
+			accumulate = 0;		
+			count_five = 0;
+			count_violation = 0;
+			
+			last_hour = timeinfo->tm_hour;
+		}
+
+		/* update the history file at the end of the day 
+		* Start tryng if the min time > 52 itself 
+		* written is a variable which is set if the history
+		* file is updated at the end of the day. This is needed
+		* so that even if we get a change to satisfy the first condition
+		* twice during the same day we dont write it twice in history
+		*/ 
+		if( timeinfo->tm_hour == 23 && timeinfo->tm_min > 53 && written == 0){
+				
+			/* Update the current file b4 updating history */
+			update_current(low,peak,accumulate,count_five,count_violation);
+			last_hour = timeinfo->tm_hour;
+
+			/* This purges the first entry in file, if the history file
+			 * has 400 days of data to give room for new data
+			 */
+	 		maintain_history();
+
+			/* This is the actual update function where entry from current
+			 * is copied into history
+			 */
+			update_history(licensed_bandwidth_c);
+			written = 1;
+
+			/* pass the first cycle, if tracker just started */
+			if (restart_flag != 0){		
+			
+	                	/* contact the server */
+        	        	if (cutomorrow <= 0 && check_vol_key() > 0){
+                	        	p_licconf = fopen(LICENSE_SERVER_CONF_TEMP, "r");
+                        		if (p_licconf != NULL){
+                               	 		int error_code;
+                                		int confirm_retry = 0;
+
+               		                	while(confirm_retry < 2){
+                                        		error_code = contact_server(p_licconf);
+
+        	                                	/* if couldn't open the file, give it one more try */
+							if (error_code != -1){
+                	                                	switch(error_code)
+                        	                        	{
+                                	                	case CONFIRM_SUCCESS:
+                                        	                	fastlog_static(LOG_DEBUG, TRACKER_CONFIRM_SUCCESS);
+									counter_grace = 12;
+                                                	        	cutomorrow = 288;
+                   	        	                        	if (write_grace_period(GRACEPERIOD_INIT) == -1){
+                        	                                        	printf("Grace Period reset failed \n");
+                                        	                		fastlog_static(LOG_ALERT, TRACKER_GRACEPERIOD_RESET_FAIL);
+									}
+									fastlog_static(LOG_DEBUG, TRACKER_GRACEPERIOD_RESET);
+                                              	                	break;
+                           	                        	case CONFIRM_CONNECT:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_CONNECT);
+									feactl_expire_check_vol(counter_grace);
+									break;
+                                  	                	case CONFIRM_AUTH:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_AUTH);
+                                           	        		feactl_expire_check_vol(counter_grace);
+									break;
+								case CONFIRM_LICENSE:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_LICENSE);
+                                            	        		feactl_expire_check_vol(counter_grace);
+									break;
+								case CONFIRM_REG:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_REG);
+                                       		        		feactl_expire_check_vol(counter_grace);
+									break;
+								case CONFIRM_BANDWIDTH:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_BANDWIDTH);
+                                       	                		feactl_expire_check_vol(counter_grace);
+									break;
+								case CONFIRM_OTHER:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_OTHER);
+                                              	        		feactl_expire_check_vol(counter_grace);
+									break;
+								default:
+									fastlog_static(LOG_ALERT, TRACKER_CONFIRM_OTHER);
+                                                               		feactl_expire_check_vol(counter_grace);
+
+                                                		}
+                                                		break;
+                                        		}
+                                        		confirm_retry ++;
+                                		}
+						if (confirm_retry == 2 && error_code == -1){
+					 		fastlog_static(LOG_ALERT, TRACKER_CONFIRM_FILE);	
+							feactl_expire_check_vol(counter_grace);
+						}
+					} else {
+                                		/* activation server has not been configured, check if it has a volume license */
+                                		int ret;
+                                		ret = check_vol_key();
+                                		if (ret > 0){
+                                        		printf ("device has a vol lic \n");
+                                               		fastlog_static(LOG_ALERT, TRACKER_SERVER_CONFIG);
+							feactl_expire_check_vol(counter_grace);
+                                		}
+                         		}	
+				
+                		}
+			} else {
+				/* check the configuration in the next cycle */
+				restart_flag = 1;
+			}
+
+	
+			time(&daemon_end);
+			daemon_cost = daemon_end - daemon_start;
+			sleep_time = daemon_cost > 300 ? 0 : (300 - daemon_cost); 		
+
+			/* sleep for 5 min and then initialize the param for the next day */ 
+			sleep(sleep_time);
+			
+			/* update grace period counter */
+			if (check_vol_key() > 0){
+				counter_grace --;
+				if (cutomorrow > 0){
+					cutomorrow --;
+				}
+			}
+	
+			memset(&if_info, 0, sizeof(if_info));
+			if((total_bandwidth = get_interface_traffic(&if_info)) == -1){
+				return (0);
+			}
+
+			low = peak = total_bandwidth;
+			accumulate = 0;
+			count_five = 0;
+			count_violation = 0;		
+		
+			continue;	
+
+		}
+		/* use sysctl to get licensed bandwidth in bits */
+		licensed_bandwidth = feactl_bandwidth();
+		if (licensed_bandwidth_c != licensed_bandwidth) { 
+			/* when license bandwidth change, force record history */
+			update_current(low, peak, accumulate, count_five, count_violation);
+			maintain_history();
+			update_history(licensed_bandwidth_c);
+			licensed_bandwidth_c = licensed_bandwidth;
+
+			memset(&if_info, 0, sizeof(if_info));
+			if((total_bandwidth = get_interface_traffic(&if_info)) == -1){
+				return (0);
+			}
+			low = peak = total_bandwidth;
+			accumulate = 0;
+			count_five = 0;
+			count_violation = 0;
+			last_hour = timeinfo->tm_hour;
+		}
+
+		if (restart_flag != 0){
+
+			/* contact the server */
+                	if (cutomorrow <= 0 && check_vol_key() > 0){
+				p_licconf = fopen(LICENSE_SERVER_CONF_TEMP, "r");
+				if (p_licconf != NULL){	
+					int error_code;  
+                        		int confirm_retry = 0;
+                        	
+					while(confirm_retry < 2){
+                                		error_code = contact_server(p_licconf);
+
+                                		if (error_code != -1){
+                                        		switch(error_code)
+                                        		{
+                                                	case CONFIRM_SUCCESS:
+								fastlog_static(LOG_DEBUG, TRACKER_CONFIRM_SUCCESS);
+                                                        	counter_grace = 12;
+                                                        	cutomorrow = 288;
+                                                        	if (write_grace_period(GRACEPERIOD_INIT) == -1){
+                                                       			printf("Grace Period reset failed \n");
+                                                                	fastlog_static(LOG_ALERT, TRACKER_GRACEPERIOD_RESET_FAIL);
+                                                        	}
+                                                        	fastlog_static(LOG_DEBUG, TRACKER_GRACEPERIOD_RESET);
+                                                        	break;
+                                                	case CONFIRM_CONNECT:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_CONNECT);
+                                                        	feactl_expire_check_vol(counter_grace);
+                                                        	break;
+                                                	case CONFIRM_AUTH:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_AUTH);
+                                                        	feactl_expire_check_vol(counter_grace);
+                                                        	break;
+                                                	case CONFIRM_LICENSE:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_LICENSE);
+                                                        	feactl_expire_check_vol(counter_grace);
+                                                        	break;
+                                                	case CONFIRM_REG:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_REG);
+                                                        	feactl_expire_check_vol(counter_grace);
+                                                        	break;
+                                                	case CONFIRM_BANDWIDTH:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_BANDWIDTH);
+                                                        	feactl_expire_check_vol(counter_grace);
+                                                        	break;
+                                                	case CONFIRM_OTHER:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_OTHER);
+                                                        	feactl_expire_check_vol(counter_grace);
+                                                        	break;
+                                                	default:
+                                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_OTHER);
+                                                        	feactl_expire_check_vol(counter_grace);
+
+                                               		}
+                                                	break;
+                                        	}
+                                        	confirm_retry ++;
+					}
+                                	if (confirm_retry == 2 && error_code == -1){
+                                        	fastlog_static(LOG_ALERT, TRACKER_CONFIRM_FILE);
+                                        	feactl_expire_check_vol(counter_grace);
+                                	}
+					
+				} else {
+                			/* activation server has not been configured, check if it has a volume license */
+                        		int ret;
+                        		ret = check_vol_key();
+                        		if (ret > 0){
+						fastlog_static(LOG_ALERT, TRACKER_SERVER_CONFIG);
+						feactl_expire_check_vol(counter_grace);
+                        		}
+				} 
+                	}
+		} else {
+			/* check the configuration in the next cycle */
+			restart_flag = 1;
+		}	
+
+		time(&daemon_end);
+		daemon_cost = daemon_end - daemon_start;
+		
+		syslog(LOG_DEBUG, "daemon_end, start, cost is %lu, %lu, %lu \n", daemon_end, daemon_start, daemon_cost);
+	
+		sleep_time = daemon_cost > 300 ? 0 : (300 - daemon_cost);
+		
+		/* Update is over, sleep for 5 min */
+		sleep(sleep_time);
+		
+		/* update grace period counter */
+		if (check_vol_key() > 0){
+			counter_grace --;
+			if (cutomorrow > 0){
+				cutomorrow --;
+			}
+		}
+	}
+}
+
+sys_mail_conf_t *
+tracker_attach_sys_mail_conf(void)
+{
+	int shm_id = 0;
+	sys_mail_conf_t *conf_p = NULL;
+
+	shm_id = shmget(SYS_MAIL_SHM_KEY, 0, 0);
+	if (shm_id == -1) {
+		return NULL;
+	}
+
+	conf_p = (sys_mail_conf_t *)shmat(shm_id, NULL, 0);
+	if (conf_p == NULL) {
+		return NULL;
+	}
+
+	return conf_p;
+}
+
+void
+tracker_detach_sys_mail_conf(sys_mail_conf_t *conf_p)
+{
+	shmdt(conf_p);
+}
+
+#define MAX_FROM_HEADER_LEN 			1024
+#define FROM_STR					 "From: "
+
+char *
+tracker_get_from_header(char *hostname, sys_mail_conf_t *conf_p)
+{
+	int esc = 0, n = 0;
+	char *str = conf_p->from;
+	static char from[MAX_FROM_HEADER_LEN + 1];
+
+	n += sprintf((from + n), FROM_STR);
+	while (*str) {
+		if (esc == 1) {
+			esc = 0;
+			switch (*str) {
+				case 'h':
+					n += sprintf((from + n), "%s", hostname);
+					break;
+
+				case 'q':
+					n += sprintf((from + n), "\"");
+					break;
+
+				case '%':
+					n += sprintf((from + n), "%%");
+					break;
+
+				default:
+					break;
+			}
+		} else if (*str == '%') {
+			esc = 1;
+		} else {
+			n += sprintf((from + n), "%c", *str);
+		}
+
+		str++;
+	}
+
+	n += sprintf((from + n), "\n");
+	return from;
+}
+
+/*
+*Get sender name from from header:
+*From: tmx@arraynetworks.com.cn\n       ->     tmx
+*From: hostname<alert@log.domain>\n     ->     alert
+*From: AN\n                             ->     AN
+*/
+char *
+tracker_get_sender_name(char *from_header)
+{
+	static char name[MAX_FROM_HEADER_LEN + 1];
+	char *at_pos = NULL;
+	char *beg_pos = NULL;
+
+	if ((at_pos = strchr(from_header, '@')) != NULL) {
+		beg_pos = at_pos;
+		
+		do {
+			beg_pos--;
+		} while((*beg_pos != '<') && beg_pos != from_header);
+
+		/*From: hostname<alert@log.domain>\n     ->     alert*/
+		if (*beg_pos == '<') {
+			beg_pos++;
+		} else  {
+			/*From: tmx@arraynetworks.com.cn\n       ->     tmx*/
+			if(strncmp(from_header, FROM_STR, strlen(FROM_STR)) == 0) {
+			beg_pos = from_header + strlen(FROM_STR);
+			}
+		}
+
+		*at_pos = '\0';
+		sprintf(name, beg_pos);
+		*at_pos = '@';
+
+	} else {
+
+		/*From: AN\n    ->     AN*/
+		beg_pos = from_header;
+		if(strncmp(from_header, FROM_STR, strlen(FROM_STR)) == 0) {
+			beg_pos = beg_pos + strlen(FROM_STR);
+		}
+
+		strncpy(name, beg_pos, strlen(beg_pos)-1);
+		*(name+strlen(beg_pos)-1)= '\0';
+
+	}
+	return name;
+}
+
+
+/*
+ * This function emails the admin every time when there is a bandwidth exceeded.
+ */
+void 
+mail_info(uint64_t total_bandwidth, uint64_t licensed_bandwidth, struct tm * timeinfo)
+{
+	char *admin_email_address;
+	log_alert_buffer_t labuf;
+	log_alert_t *alert;
+	int fd[2];
+	int pid;
+	char str[256 + 1] = "";
+	char hostname[64 + 1] = "";
+	size_t len;
+	int i;
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = tracker_attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		return;
+	}
+
+	admin_email_address = (char *)malloc(100);
+	if(admin_email_address == NULL){
+		tracker_detach_sys_mail_conf(conf_p);
+		return;
+	}
+	len = sizeof(log_alert_buffer_t);
+	if (sysctlbyname("net.inet.clicktcp.alert_buffer",(void *)&labuf, &len, NULL, 0) < 0){
+		free(admin_email_address);
+		tracker_detach_sys_mail_conf(conf_p);
+        return;  /*error*/
+	}
+
+	for (i = 1; i <= FASTLOG_MAX_ALERT_NUM; i++) {
+		alert = &labuf.alerts[i];
+		if( alert->flags & FASTLOG_ALERT_INUSE){
+			strncpy(admin_email_address,alert->email,99);
+			admin_email_address[99] = '\0';
+		
+			/* If email address is located, dont have to loop*/
+			if(strlen(admin_email_address) > 5)
+				break;
+		}
+	}
+
+	/* Didn't find an admin email address, so returning */
+	if( strlen(admin_email_address) <5){
+		free(admin_email_address);
+		tracker_detach_sys_mail_conf(conf_p);
+		return;
+	}
+	/* set up a pipe */
+	if (pipe(fd) < 0) {
+                /*currently do nothing*/
+		free(admin_email_address);
+		tracker_detach_sys_mail_conf(conf_p);
+		return;
+	}
+	/*get local host name, used as From: field in email*/
+	memset(hostname, 0, sizeof(hostname));
+	if (gethostname(hostname, sizeof(hostname) - 1) < 0) {
+		/*do nothing for now*/
+	}
+
+	char *from = tracker_get_from_header(hostname, conf_p);
+	char *sender = tracker_get_sender_name(from);
+
+	printf("\n admin email add is %s\n", admin_email_address);
+	/* Fork a child process which can exec sendmail */
+	if ((pid = fork()) < 0){
+		printf("\n error in process creation");
+	}
+	if(!pid){
+	/* In child process */
+		close(STDIN_FILENO);
+		close(STDOUT_FILENO);
+		close(STDERR_FILENO);
+		close(fd[0]);
+		dup(fd[1]);
+		dup(fd[1]);
+		/* execute the send mail */
+		if (conf_p->extern_mail_on) {
+			if (execl(SSMTP_PATH, "ssmtp", admin_email_address, NULL) < 0) {
+				printf("Error in ssmtp.\n");
+				exit(-1);
+			}
+		} else {
+			if(execl(SENDMAIL_PATH, "sendmail", "-f", sender, 
+					"-v", admin_email_address, NULL) < 0) {
+				printf("Error in sendmail.\n");
+				exit(-1);
+			}
+		}
+		free(admin_email_address);
+		tracker_detach_sys_mail_conf(conf_p);
+		exit(0);
+	}
+	
+	/* Parent process */
+	close(fd[1]);
+	/* Send the mail parameters to fd[0] */
+	if (conf_p->extern_mail_on) {
+		snprintf(str, sizeof(str), FROM_STR_SSMTP, conf_p->mextern_server.user);
+		write(fd[0], str, strlen(str));
+	} else {
+		snprintf(str, sizeof(str), SENDMAIL_HEADER_FROM, "AN");
+		write(fd[0], str, strlen(str));
+	}
+
+	snprintf(str, sizeof(str), SENDMAIL_HEADER_TO, admin_email_address);	
+	write(fd[0], str, strlen(str));
+	
+	/* Send the subject to fd[0] */
+	snprintf(str, sizeof(str), SENDMAIL_HEADER_SUBJECT);
+	write(fd[0], str, strlen(str));
+
+	if (conf_p->extern_mail_on) {
+		/*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+		write(fd[0], "\n", 1);
+	}
+
+	/* Send data to fd[0] */
+	snprintf(str, sizeof(str), SENDMAIL_HEADER_BODY, timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_year+1900,timeinfo->tm_hour, timeinfo->tm_min, total_bandwidth, licensed_bandwidth);
+	write(fd[0], str, strlen(str));
+
+	/* send out all the dat a*/
+	close(fd[0]);
+	
+	free(admin_email_address);
+	tracker_detach_sys_mail_conf(conf_p);
+}
+
+
+/* This file checks if the history file reaches 400 lines
+ * oldest entry will be deleted
+ */
+#define MAX_STR_LEN 128
+void 
+maintain_history()
+{
+	FILE *history, *temp_maintain;
+	int line=0, i;
+	char mystring[MAX_STR_LEN];
+	
+	history = fopen("/var/log/bandwidth/history","a+");
+	if(history == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+
+	rewind(history);
+	
+	/* count the lines in history to check if there are more than 399 lines */
+	while(fgets(mystring, MAX_STR_LEN, history) != NULL){
+		line++;
+	}
+
+
+	/* purge the oldest line if there are 400 lines else return*/
+	if ( line < 400){
+		fclose(history);
+		return;
+	}
+
+	/*
+	 * create a temp_maintain file and copy remaining lines in history to it 
+	 */
+  	temp_maintain = fopen("/var/log/bandwidth/temp_maintain","w+");
+	if(temp_maintain == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+	
+	rewind(history);
+	
+	for (i = 0; i < 399; i++){
+		fgets(mystring, MAX_STR_LEN, history);
+		fputs(mystring, temp_maintain);
+	}
+
+
+	fclose(temp_maintain);
+	fclose(history);
+	remove("/var/log/bandwidth/history");
+	rename("/var/log/bandwidth/temp_maintain","/var/log/bandwidth/history");	
+}
+
+/* Update the curent file */
+void 
+update_current(uint64_t low, uint64_t peak, uint64_t accumulate, uint64_t count_five, int count_violation)
+{
+	FILE *current, *temp_current;
+	uint64_t last_low, last_peak, last_accumulate, last_count_five;
+	int year, month, day, last_count_violation;
+        uint64_t total_bandwidth;
+	struct if_info if_info;
+
+	current = fopen("/var/log/bandwidth/current", "r");	
+	if(current == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+
+	if(fscanf(current,"%d %d %d %lu %lu %lu %lu %d",&year, &month, &day, &last_low, &last_peak, &last_accumulate, &last_count_five, &last_count_violation) != 8){
+		memset(&if_info, 0, sizeof(if_info));
+		if((total_bandwidth = get_interface_traffic(&if_info)) == -1){
+			return;
+		}
+	
+		last_low = last_peak = total_bandwidth;
+		last_accumulate = 0;
+		last_count_five = 0;
+		last_count_violation = 0;
+	} 
+	
+	temp_current = fopen("/var/log/bandwidth/temp_current", "w+");
+	if(temp_current == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+
+	struct tm *timeinfo;	
+	time_t cur_time;
+	time (&cur_time);
+	timeinfo = localtime(&cur_time);
+	year = timeinfo->tm_year+1900;
+	month = timeinfo->tm_mon+1;
+	day = timeinfo->tm_mday;
+
+	/* update low and peak */
+	if(last_low<low){
+		low=last_low;
+	}
+	
+	if(last_peak>peak){
+		peak=last_peak;
+	}
+
+	/* update accumulate, count_five and count_violation every 5 min */
+	fprintf(temp_current,"%d %d %d %lu %lu %lu %lu %d\n", year, month, day, low, peak, (last_accumulate+accumulate), (last_count_five+count_five), (last_count_violation+count_violation));
+
+	fclose(temp_current);
+	fclose(current);
+	remove("/var/log/bandwidth/current");
+	rename("/var/log/bandwidth/temp_current", "/var/log/bandwidth/current");
+}
+
+/* In this function, current contents are added to history file*/
+void 
+update_history(uint64_t licensed_bandwidth)
+{
+	
+	FILE *history, *current, *temp_update;
+	uint64_t low,average,peak, accumulate, count_five;
+	int year, month, day, count_violation;
+	float *pmin, *pavg, *pmax, *plicensed;
+	char *pmin_unit, *pavg_unit, *pmax_unit, *plicensed_unit;
+	int buff;
+
+	temp_update = fopen("/var/log/bandwidth/temp_update","w+");
+	current = fopen("/var/log/bandwidth/current", "r");
+	if(temp_update == NULL || current == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);
+		exit(0);
+	}
+
+	/* update the temp file */
+	
+	fscanf(current,"%d %d %d %lu %lu %lu %lu %d\n", &year, &month, &day, &low, &peak, &accumulate, &count_five, &count_violation);
+	/* calculate the average */
+	average = accumulate/count_five;
+
+
+	pmin = (float*) malloc (sizeof(uint64_t));
+	pavg = (float*) malloc (sizeof(uint64_t));
+	pmax = (float*) malloc (sizeof(uint64_t));
+	plicensed = (float*) malloc (sizeof(uint64_t));
+	pmin_unit = (char*) malloc (12);
+	pavg_unit = (char*) malloc (12);
+	pmax_unit = (char*) malloc (12);
+	plicensed_unit = (char*) malloc (12);
+
+	if (pmin == NULL || pavg == NULL || pmax == NULL || plicensed == NULL || pmin_unit == NULL || pavg_unit == NULL || pmax_unit == NULL || plicensed_unit == NULL){
+		printf("update_history():unable to malloc\n");
+		if(pmin != NULL)
+			free(pmin);
+		if(pavg != NULL)
+			free(pavg);
+		if(pmax != NULL)
+			free(pmax);
+		if(plicensed != NULL)
+			free(plicensed);
+		if(pmin_unit != NULL)
+			free(pmin_unit);		
+		if(pavg_unit != NULL)
+			free(pavg_unit);
+		if(pmax_unit != NULL)
+			free(pmax_unit);
+		if(plicensed_unit != NULL)
+			free(plicensed_unit);
+		return;
+	}
+		
+	/* Get the unit for min, avg and max */
+	get_bandwidth_unit(low, pmin, pmin_unit);
+	get_bandwidth_unit(average, pavg, pavg_unit);
+	get_bandwidth_unit(peak, pmax, pmax_unit);
+	get_bandwidth_unit(licensed_bandwidth, plicensed, plicensed_unit);
+
+
+	/* Adding the contents of current into temp_update. Using "*" indicates the violation case */
+	if (count_violation == 0){
+		fprintf(temp_update,"  %d%s%d%s%d %s%.3f%s %s%.3f%s %s%.3f%s %s%d%s%s%d%s\n", year, "-", month, "-", day, "Min:", *pmin, pmin_unit, "Avg:", *pavg, pavg_unit, "Max:", *pmax, pmax_unit, "Violation(Licensed Bandwidth ", (int)*plicensed, plicensed_unit, "):", count_violation, "time"); 
+	}else if (count_violation == 1){
+		fprintf(temp_update,"%s %d%s%d%s%d %s%.3f%s %s%.3f%s %s%.3f%s %s%d%s%s%d%s\n", "*", year, "-", month, "-", day, "Min:", *pmin, pmin_unit, "Avg:", *pavg, pavg_unit, "Max:", *pmax, pmax_unit, "Violation(Licensed Bandwidth ", (int)*plicensed, plicensed_unit, "):", count_violation, "time");
+	}else{
+		fprintf(temp_update,"%s %d%s%d%s%d %s%.3f%s %s%.3f%s %s%.3f%s %s%d%s%s%d%s\n", "*", year, "-", month, "-", day, "Min:", *pmin, pmin_unit, "Avg:", *pavg, pavg_unit, "Max:", *pmax, pmax_unit, "Violation(Licensed Bandwidth ", (int)*plicensed, plicensed_unit, "):", count_violation, "times");
+	}
+
+	free(pmin);
+	free(pavg);
+	free(pmax);
+	free(pmin_unit);
+	free(pavg_unit);
+	free(pmax_unit);
+
+
+	history = fopen("/var/log/bandwidth/history","r");
+	if(history == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+
+	
+	/* Create temp_update file and copy contents of history to temp_update */
+	rewind(history);
+
+	while((buff = fgetc(history)) != EOF){
+		fputc(buff, temp_update);	
+	}
+
+	fclose(current);
+	fclose(history);
+	fclose(temp_update);
+
+	remove("/var/log/bandwidth/history");
+	rename("/var/log/bandwidth/temp_update","/var/log/bandwidth/history");	
+			
+	/*make sure remove the current file after remove temp_update*/
+	remove("/var/log/bandwidth/current");
+	current = fopen("/var/log/bandwidth/current","w+");
+	if(current == NULL){
+		printf("\n Error in open");
+		fflush(0);
+		fastlog_static(LOG_NOTICE, TRACKER_BANDWIDTH_CREATEFILE);  
+		exit(0);
+	}
+	fclose(current);	
+	printf("\n update succeeded");
+}
+
+
+/* Find the average, low and peak traffic
+ * by adding 5min throughput obtained from
+ * each interface
+ */
+uint64_t 
+get_interface_traffic(struct if_info *if_info_pi)
+{
+        uint64_t total_bandwidth[2];
+        struct clickaddresses *ca;
+        size_t len;
+        cafw_ifnode_t   *ifn_p;
+        unsigned *total_nic;
+        nic_ca_t *nic_ca_p,*nic_ca;
+	struct cafw_share *ca_ptr;
+        uint64_t in,out=0;
+	int i;
+	int bandwidth_timer;
+
+        len = sizeof(ca);
+        if (sysctlbyname("kern.clickbuf", &ca, &len, NULL, 0) < 0) {
+                printf("sysctlbyname error\n");
+                return -1;
+        }
+
+        total_nic = &ca->total_nic;
+        ca_ptr = &ca->cafw_share;
+	nic_ca = ca->nic_ca;
+	len = sizeof(bandwidth_timer);
+	if (sysctlbyname("net.inet.clicktcp.bandwidth_timer", &bandwidth_timer, &len, NULL, 0)) {
+		perror("Error read bandwidth timer information");
+		return -1;
+	}
+		
+        for (i = 0; i< *total_nic; i++) {
+                nic_ca_p = &nic_ca[i];
+                ifn_p = ca_ptr->ifnodes[nic_ca_p - nic_ca];
+		if (ifn_p != NULL) {
+			in += ifn_p->if_stats.bandwidth_in_bytes;
+			out += ifn_p->if_stats.bandwidth_out_bytes;
+		}
+        }
+        total_bandwidth[0] = (in/bandwidth_timer << 3);
+        total_bandwidth[1] = (out/bandwidth_timer << 3);
+        return total_bandwidth[0];
+}
+
+
+/*Get a proper unit based on the actual bandwidth*/
+
+void
+get_bandwidth_unit(uint64_t bandwidth, float* p_bandwidth, char* p_unit)
+{
+
+	float div;
+
+	if(bandwidth < 1000){
+		*p_bandwidth = bandwidth;
+		strcpy(p_unit, "bps");
+		return;
+	}else if(bandwidth < 1000000){
+		div = 1000;
+		*p_bandwidth = bandwidth/div;
+		strcpy(p_unit, "Kbps");
+		return;
+	}else if(bandwidth < 1000000000){
+		div = 1000000;
+		*p_bandwidth = bandwidth/div;
+		strcpy(p_unit, "Mbps");
+		return;
+	}else{
+		div = 1000000000;
+		*p_bandwidth = bandwidth/div;
+		strcpy(p_unit, "Gbps");
+		return;
+	}
+	return;
+}
+	
+
+int
+update_grace_period(int update){
+        int remain_hour;
+
+        remain_hour = get_grace_period();
+        if (remain_hour == 0){
+                printf("Grace period has expired \n");
+                return -1;
+        }
+
+        if (remain_hour == -1){
+                printf("Grace period record doesn't exist \n");
+                init_grace_period();
+                return 0;
+        }
+
+        printf("grace period remain %d hour \n", remain_hour);
+
+        if (update == 1){
+                write_grace_period(remain_hour-1);
+        }
+
+        return 0;
+}
+
+
+int 
+get_server_confirmation(){
+
+	FILE *p_confirm;		
+	int error_code = -1;
+	char str[500];
+	char *pch;
+
+	p_confirm = fopen(LICENSE_SERVER_CONFIRM, "r");
+	if (p_confirm != NULL){
+		while(fgets(str, 500, p_confirm) != NULL){
+ 	        	pch = strstr(str, "ERROR CODE:");
+			if (pch != NULL){
+				sscanf(pch, "ERROR CODE:%d", &error_code);
+				fclose(p_confirm);
+				return error_code;
+			}
+		}
+
+		fclose(p_confirm);
+	}
+	return error_code;
+}
+
+int
+feactl_expire_check_vol(int counter_grace){
+
+	/* create the WILL_EXPIRE log when counter_grace is 11, make sure that log is created only once a day */
+	int remain_hours;	
+	int64_t remain_days = 0;
+	feactl_t * feactl_p;
+        time_t cur_time;
+        struct tm *timeinfo;
+	FILE *fp;
+	char cmd[100];
+	char str[100];
+	char * pch;
+
+	remain_hours = get_grace_period();
+
+	syslog(LOG_EMERG, "tracker: remain_hours is %d", remain_hours);
+	if (remain_hours <= 0){
+		/* disable system */
+		
+		feactl_p = attach_feactlp();
+		if (feactl_p == NULL) {
+			printf("Fail to attach feactl !\n");
+			return -1;
+		}
+		if (feactl_p->flag != FEACTL_FL_EXPIRED) {
+			feactl_p->flag = FEACTL_FL_EXPIRED;
+			fastlog_logex(FC_LIC_HAS_EXPIRED, 0);
+		        time(&cur_time);
+                        timeinfo = localtime(&cur_time);
+			mail_info_vol(timeinfo, remain_days);				
+
+			/* save DNS information for email notification, before clear */	
+		        sprintf(cmd, "/ca/bin/backend -c \"show ip nameserver\"`echo -e \"\\0374\"` | sed \"s/`echo -e \"\\0374\"`//g\"");
+                	if ((fp = popen(cmd, "r")) == NULL){
+                        	printf ("cannot show ip nameserver \n");
+                        	return 0;
+                	}
+
+			system("/ca/bin/backend -c \"clear config secondary\"`echo -e \"\\0374\"` > /dev/null 2>/dev/null");
+			printf("CMD:clear config secondary \n");
+			system("/ca/bin/backend -c \"log on\"`echo -e \"\\0374\"` > /dev/null 2>/dev/null");
+		
+			/* re-configure DNS */	
+	                while (fgets(str, 300, fp) != NULL){
+                        	printf("%s", str);
+                        	pch = strstr(str, "name server");
+                        	if (pch != NULL){
+                                	char des[20];
+                                	strncpy(des, str+12, 15);
+                                	sprintf(cmd, "/ca/bin/backend -c \"ip nameserver %s\"`echo -e \"\\0374\"` > /dev/null 2>/dev/null", des);
+                                	printf("%s \n", cmd);
+                                	system(cmd);
+                        	}
+                	}
+
+			pclose (fp);
+
+		}
+		detach_feactlp(feactl_p);
+		set_kernel_license_features();
+	
+		return 0;
+	}
+
+	if (remain_hours > 72){
+		/* warning if the grace period remains <= 3 days */
+		return 0;
+	} else if (remain_hours == -1){
+	 	/* cannot get grace period */	
+		return -1;
+	} else if (remain_hours == 24 && counter_grace == 11){
+		/* one day left warning */
+		remain_days = 1;
+	        time(&cur_time);
+       		timeinfo = localtime(&cur_time);
+        	mail_info_vol(timeinfo, remain_days);
+        	snmp_send_license_trap((uint32_t)remain_days);
+        	fastlog_logex(FC_LIC_WILL_EXPIRE, 1, (uint)remain_days);
+	} else if (remain_hours == 48 && counter_grace == 11){
+		/* two days left warning */
+		remain_days = 2;
+                time(&cur_time);
+                timeinfo = localtime(&cur_time);
+                mail_info_vol(timeinfo, remain_days);
+                snmp_send_license_trap((uint32_t)remain_days);
+                fastlog_logex(FC_LIC_WILL_EXPIRE, 1, (uint)remain_days);
+	} else if (remain_hours == 72 && counter_grace == 11){
+		/* three days left warning */
+		remain_days = 3;
+                time(&cur_time);
+                timeinfo = localtime(&cur_time);
+                mail_info_vol(timeinfo, remain_days);
+                snmp_send_license_trap((uint32_t)remain_days);
+                fastlog_logex(FC_LIC_WILL_EXPIRE, 1, (uint)remain_days);
+	}
+
+	return 0; 
+
+}
+
+/* check if the license key is a volume license 
+ * return: 1:volume license 0:non-volume license -1:invalid
+ */ 
+
+int 
+check_vol_key(void)
+{
+	int keylen;
+        FILE *p_lic;
+	char lickey[LICKEYLEN_MAX];
+        char encrypt_features_str[BLOCK_LEN];
+	uint32_t encrypt_features_low = 0;
+	char ptr_lickey_dec[LICKEYLEN_IDATE] = {0};
+	
+	p_lic = fopen(LICENSEFN, "r");
+        if (p_lic != NULL) {
+	        fscanf(p_lic, "%s", lickey);
+                fclose(p_lic);
+                p_lic = NULL;
+        
+	}else{
+		return -1;
+	}
+
+	keylen = strlen(lickey) + 1;
+	if (keylen <= 6 * BLOCK_LEN) {
+		return 0;
+	}
+        /*get the encrypted features*/
+        memset(encrypt_features_str, 0, BLOCK_LEN);
+        /*copy encrypt_features_str lower 32 bits from lic key, skip the middle '-'*/
+	if (strlen(lickey) == LICKEYLEN_ENC - 1) {
+#ifndef ARM64
+		license_decrypt_ext(lickey, ptr_lickey_dec, sizeof(ptr_lickey_dec));
+		strlcpy(encrypt_features_str, &ptr_lickey_dec[6 * BLOCK_LEN], sizeof(encrypt_features_str));
+#endif
+	} else {
+		strlcpy(encrypt_features_str, &lickey[6 * BLOCK_LEN], sizeof(encrypt_features_str));
+	}
+        encrypt_features_low = strtoul(encrypt_features_str, NULL, 16);
+
+	return (encrypt_features_low & AFM_VOL_LIC);
+
+}
+
+
+int
+contact_server(FILE *p_licconf){
+	        char cmd1[3];
+                char cmd2[8];
+                char cmd3[7];
+                char ip_str[16];
+                int port_int;
+                char user_str[20];
+                char user_str_noquote[20];
+                char pwd_str[120];
+                int  user_len, pwd_len, start = 10, cipher_num = 0;
+                char *plaintext;
+                unsigned char* ciphertext;
+                char buf[512];
+                EVP_CIPHER_CTX *de;
+                unsigned int salt[] = {12345, 54321};
+                unsigned char *key_data;
+                int key_data_len;
+                char * key = "iamstupid";
+                key_data = (unsigned char *)key;
+                key_data_len = 9;
+
+ 		/* get the server information and decrypt the password */ 		
+
+		if (p_licconf == NULL){
+			p_licconf = fopen(LICENSE_SERVER_CONF_TEMP, "r");
+		}               
+
+		de = EVP_CIPHER_CTX_new();
+                if (aes_init(key_data, key_data_len, (unsigned char *)&salt, de, 0)) {
+                       printf("Couldn't initialize AES cipher\n");
+			EVP_CIPHER_CTX_free(de);
+                       return -1;
+                }
+
+		fscanf(p_licconf, "%s %s %s %s %d %s %s ", cmd1, cmd2, cmd3, ip_str, &port_int, user_str, pwd_str);
+
+		user_len = strlen(user_str);
+                memcpy(user_str_noquote, &user_str[1], user_len-2);
+
+                pwd_len = strlen(pwd_str);
+
+                ciphertext = (unsigned char*)malloc(sizeof(unsigned char)*(pwd_len-2-9+1));
+
+                while ( start < pwd_len - 1 ){
+	                 char pwd_2[2];
+                         memcpy (pwd_2, &pwd_str[start], 2);
+                         ciphertext[cipher_num] = (unsigned char)strtol(pwd_2, NULL, 16);
+                         start = start + 2;
+                         cipher_num = cipher_num + 1;
+                }
+
+                plaintext = (char *)aes_decrypt_tracker(de, ciphertext, &cipher_num);
+		EVP_CIPHER_CTX_free(de);
+
+                system("rm -r /tmp/pingout.txt");
+
+                memset(&buf[0], 0, sizeof(buf));
+		
+		 /* call the php function to send the messages */
+                snprintf(buf, sizeof(buf), "/ca/an_apache/cmaphp/php -f /ca/webui/htdocs/proxy/new/cmAgent/cmaContactActServer.php %s %d %s %s > /tmp/pingout.txt", ip_str, port_int, user_str_noquote, plaintext);
+
+		fastlog_static(LOG_DEBUG, TRACKER_SEND_USAGEDATA);	
+
+                system(buf);
+           	 
+		fclose(p_licconf);
+		 
+	        return (get_server_confirmation());
+
+}
+
+
+/*
+ * Email information for license has expired and license will expire 
+ */
+void
+mail_info_vol(struct tm * timeinfo, int flag)
+{
+        
+	char admin_email_address[90] = "";
+        int fd[2];
+        int pid;
+        char str[256 + 1] = "";
+	FILE *p_licconf;
+	char hostname[65] = "";
+	FILE *fp;
+	char cmd[200];
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = tracker_attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		/*currently do nothing*/
+		return;
+	}
+
+
+        p_licconf = fopen(LICENSE_SERVER_CONF_TEMP, "r");
+        if (p_licconf){
+                char s1[5];
+                char s2[5];
+                char s3[5];
+                char s4[5];
+                char s5[5];
+                char s6[5];
+                int p;
+                fscanf(p_licconf, "%s %s %s %s %d %s %s %s", s1, s2, s3, s4, &p, s5, s6, admin_email_address);
+
+                fclose (p_licconf);
+	} else {
+		printf ("ip license server hasn't been configured \n");
+		tracker_detach_sys_mail_conf(conf_p);
+		return;
+	}
+
+	 /*get local host name, used as From: field in email*/
+	memset(hostname, 0, sizeof(hostname));
+	if (gethostname(hostname, sizeof(hostname) -1) < 0) {
+
+		/*do nothing for now*/
+	}
+
+	char *from = tracker_get_from_header(hostname, conf_p);
+	char *sender = tracker_get_sender_name(from);
+	printf ("the eamil address is %s \n", admin_email_address);
+
+	/* set up a pipe */
+	if (pipe(fd) < 0) {
+		printf("fail to set up pipe \n" );
+		tracker_detach_sys_mail_conf(conf_p);
+		return;
+        }
+
+        
+        /* Fork a child process which can exec sendmail */
+        if ((pid = fork()) < 0){
+                printf("\n error in process creation");
+        }
+        if(!pid){
+        /* In child process */
+                close(STDIN_FILENO);
+                close(STDOUT_FILENO);
+                close(STDERR_FILENO);
+                close(fd[0]);
+                dup(fd[1]);
+                dup(fd[1]);
+                /* execute the send mail */
+		if (conf_p->extern_mail_on) {
+			if (execl(SSMTP_PATH, "ssmtp", admin_email_address, NULL) < 0) {
+				printf("Error in ssmtp.\n");
+				exit(-1);
+			}
+		} else {
+			if ((execl(SENDMAIL_PATH, "sendmail", "-f", sender, 
+					"-v", admin_email_address, NULL)) < 0) {
+				printf("Error in sendmail.\n");
+				exit(-1);
+			}
+		}
+                exit(0);
+        }
+
+        /* Parent process */
+        close(fd[1]);
+        /* Send the mail parameters to fd[0] */
+	if (conf_p->extern_mail_on) {
+		snprintf(str, sizeof(str), FROM_STR_SSMTP, conf_p->mextern_server.user);
+		write(fd[0], str, strlen(str));
+	} else {
+		write(fd[0], from, strlen(from));
+	}
+
+        snprintf(str, sizeof(str), "To: System Administrator<%s>\n", admin_email_address);
+        write(fd[0], str, strlen(str));
+
+
+	if (flag == 0){
+
+		/* Send the subject to fd[0] */
+		snprintf(str, sizeof(str), "Subject: License Key has expired! System has been disabled! \n");
+		write(fd[0], str, strlen(str));
+
+		if (conf_p->extern_mail_on) {
+			/*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+			write(fd[0], "\n", 1);
+		}
+
+		/* Send data to fd[0] */
+		snprintf(str, sizeof(str), "%d/%d/%d %d:%d License: License Key has expired! System has been disabled! Please refer to Admin Guide to enable the system.\n\n", timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_year+1900,timeinfo->tm_hour, timeinfo->tm_min);
+		write(fd[0], str, strlen(str));
+	
+	} else if (flag == 1) {
+
+		/* Send the subject to fd[0] */
+		snprintf(str, sizeof(str), "Subject: License Key will expire soon! System will be disabled in %d day!\n", flag);
+		write(fd[0], str, strlen(str));
+
+		if (conf_p->extern_mail_on) {
+			/*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+			write(fd[0], "\n", 1);
+		}
+
+		/* Send data to fd[0] */
+		snprintf(str, sizeof(str), "%d/%d/%d %d:%d License: License Key will expire in %d day! System will be disabled in %d day! Please refer to Admin Guide.\n\n", timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_year+1900,timeinfo->tm_hour, timeinfo->tm_min, flag, flag);
+		write(fd[0], str, strlen(str));
+
+	} else if (flag == 2) {
+
+		/* Send the subject to fd[0] */
+		snprintf(str, sizeof(str), "Subject: License Key will expire soon! System will be disabled in %d days!\n", flag);
+		write(fd[0], str, strlen(str));
+
+		if (conf_p->extern_mail_on) {
+			/*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+			write(fd[0], "\n", 1);
+		}
+
+		/* Send data to fd[0] */
+		snprintf(str, sizeof(str), "%d/%d/%d %d:%d License: License Key will expire in %d days! System will be disabled in %d days! Please refer to Admin Guide.\n\n", timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_year+1900,timeinfo->tm_hour, timeinfo->tm_min, flag, flag);
+		write(fd[0], str, strlen(str));
+
+	} else if (flag == 3) {
+	
+		/* Send the subject to fd[0] */
+		snprintf(str, sizeof(str), "Subject: License Key will expire soon! System will be disabled in %d days!\n", flag);
+		write(fd[0], str, strlen(str));
+
+		if (conf_p->extern_mail_on) {
+			/*we need to insert a extra \n between subject and body if we use ssmtp tool*/
+			write(fd[0], "\n", 1);
+		}
+
+		/* Send data to fd[0] */
+		snprintf(str, sizeof(str), "%d/%d/%d %d:%d License: License Key will expire in %d days! System will be disabled in %d days! Please refer to Admin Guide.\n\n", timeinfo->tm_mon+1, timeinfo->tm_mday, timeinfo->tm_year+1900,timeinfo->tm_hour, timeinfo->tm_min, flag, flag);
+		write(fd[0], str, strlen(str));
+
+	}
+
+	snprintf(str, sizeof(str), "For system information, please refer to below:\n");
+	write(fd[0], str, strlen(str));
+
+	snprintf(str, sizeof(str), "\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
+	write(fd[0], str, strlen(str));
+
+
+	sprintf(cmd, "/ca/bin/backend -c \"show version\"`echo -e \"\\0374\"` | sed \"s/`echo -e \"\\0374\"`//g\"");
+	if ((fp = popen(cmd, "r")) == NULL){
+		printf ("cannot get show version \n");
+		tracker_detach_sys_mail_conf(conf_p);
+		return;
+	}
+
+	while (fgets(str, 300, fp) != NULL){
+		printf("%s", str);
+		write(fd[0], str, strlen(str));
+	}
+	pclose (fp);
+
+	/* send out all the dat a*/
+	close(fd[0]);
+	tracker_detach_sys_mail_conf(conf_p);
+}
+
+
+

Property changes on: src/bin/tracker/tracker.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/rel_avx_2_7_2/src/cli/Makefile
===================================================================
--- /branches/rel_avx_2_7_2/src/cli/Makefile	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/cli/Makefile	(working copy)
@@ -11,6 +11,7 @@
 		-L ../library/node_man -lnode \
 		-L ../library/ca_ui -lcaui \
 		-L ../library/ca_util -lcautil \
+		-L ../library/ca_mail -lcamail \
 		-lcrypt -L ../library/version -lversion \
 		-L ../library/management -lsuppress_print \
 		-L ../library/avx_log -lavxlog \
Index: /branches/rel_avx_2_7_2/src/cli/shell.c
===================================================================
--- /branches/rel_avx_2_7_2/src/cli/shell.c	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/cli/shell.c	(working copy)
@@ -37,6 +37,7 @@
 #include <sys/shm.h>
 #include "ca_util.h"
 #include "ca_ui.h"
+#include "../library/ca_mail/sys_mail.h"
 #include "node_sys.h"
 #include "getline/getline.h"
 #include "clickarray.h"
Index: /branches/rel_avx_2_7_2/src/generator/commands.pm
===================================================================
--- /branches/rel_avx_2_7_2/src/generator/commands.pm	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/generator/commands.pm	(working copy)
@@ -1796,6 +1796,68 @@
 		function_args => [],
 	},
 	{
+                obj_type => "ITEM",
+                name => "relay",
+                menu => "root_clear_system",
+                user_level => "CLI_LEVEL_CONFIG",
+                cmd_attribute => "CMD_ARRAYOS|CMD_SPROXY|CMD_NORMAL",
+                help_string => "Clear system mail relay configuration",
+                function_name => "clear_system_mail_relay",
+                function_args => [],
+        },
+        {
+                obj_type => "MENU",
+                name => "relay",
+                parent_menu => "root_no_system_mail",
+                uniq_name => "root_no_system_mail_relay",
+                user_level => "CLI_LEVEL_CONFIG",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+                help_string => "Delete a record of system mail relay server configuration",
+        },
+        {
+                obj_type => "MENU",
+                name => "external",
+                parent_menu => "root_no_system_mail",
+                uniq_name => "root_no_system_mail_external",
+                user_level => "CLI_LEVEL_CONFIG",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+                help_string => "Delete the configuration of the external SMTP mail server",
+        },
+        {
+                obj_type => "ITEM",
+                name => "server",
+                menu => "root_no_system_mail_external",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+                user_level => "CLI_LEVEL_CONFIG",
+                help_string => "Delete the external SMTP mail server",
+                function_name => "no_system_mail_external_server",
+                function_args => [],
+        },
+        {
+                obj_type => "ITEM",
+                name => "user",
+                menu => "root_no_system_mail_external",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+                user_level => "CLI_LEVEL_CONFIG",
+                help_string => "Delete the sender address on the external SMTP mail server",
+                function_name => "no_system_mail_external_user",
+                function_args => [],
+        },
+	{
+                obj_type => "ITEM",
+                name => "server",
+                menu => "root_no_system_mail_relay",
+                cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+                user_level => "CLI_LEVEL_CONFIG",
+                help_string => "Delete a system mail relay server",
+                function_name => "system_mail_relay_server_del",
+                function_args => [ {
+                                     type => "STRING",
+                                     help_string => "Hostname to del",
+                                     optional => "NO",
+                                   },],
+        },
+	{
 		obj_type => "MENU",
 		name => "admin",
 		parent_menu => "root_clear",
@@ -2351,6 +2413,128 @@
         user_level => "CLI_LEVEL_CONFIG",
         help_string => "Set system mail",
     },
+    {
+	obj_type => "MENU",
+        name => "external",
+        parent_menu => "root_system_mail",
+        uniq_name => "root_system_mail_external",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Configure external mail server",
+    },
+    {
+	obj_type => "ITEM",
+        name => "on",
+        parent_menu => "root_system_mail_external",
+        help_string => "Enable the external mail server to deliver the mail",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        function_name => "system_mail_external_on",
+        function_args => [],
+    },
+    {
+	obj_type => "ITEM",
+        name => "off",
+        parent_menu => "root_system_mail_external",
+        help_string => "Use the local mail server to deliver the mail",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        function_name => "system_mail_external_off",
+        function_args => [],
+    },
+    {
+	obj_type => "ITEM",
+        name => "server",
+	menu => "root_system_mail_external",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Configure the external SMTP mail server",
+        function_name => "system_mail_external_server",
+        function_args => [ {
+				type => "STRING",
+                                help_string => "External SMTP server name or External SMTP server ip",
+                                optional => "NO",
+                            },
+                            {
+                                type => "U16",
+                                help_string => "External SMTP server port, default value is 25",
+                                optional => "YES",
+                                default_value => "25",
+                            },
+                            {
+                                type => "U16",
+                                help_string => "External SMTP server use SSL/TLS connectivity or not(1-yes, 0-no), default value is 0",
+                                optional => "YES",
+                                default_value => "0",
+                            },],
+    },
+    {
+	obj_type => "ITEM",
+        name => "user",
+        menu => "root_system_mail_external",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_SPECIAL_LOG",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Configure the sender address on the external SMTP mail server",
+        function_name => "system_mail_external_user",
+        function_args => [ {
+				type => "STRING",
+				help_string => "User name on External SMTP server",
+                                optional => "NO",
+                            },
+                            {
+                                type => "STRING",
+                                help_string => "Password of this user",
+                                optional => "NO",
+                            },],
+    },
+    {
+        obj_type => "MENU",
+        name => "relay",
+        parent_menu => "root_system_mail",
+        uniq_name => "root_system_mail_relay",
+        user_level => "CLI_LEVEL_CONFIG",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        help_string => "System mail relay server configuration",
+    },
+    {
+        obj_type => "ITEM",
+        name => "on",
+        menu => "root_system_mail_relay",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Enable a relay server configuration",
+        function_name => "system_mail_relay_on",
+        function_args => [],
+    },
+    {
+	obj_type => "ITEM",
+        name => "off",
+        menu => "root_system_mail_relay",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Disable a relay server configuration",
+        function_name => "system_mail_relay_off",
+        function_args => [],
+    },
+    {
+        obj_type => "ITEM",
+        name => "server",
+        menu => "root_system_mail_relay",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "To config a relay server",
+        function_name => "system_mail_relay_server_add",
+        function_args => [ {
+				type => "STRING",
+                                help_string => "Hostname to relay",
+                                optional => "NO",
+                            },
+			    {
+                                type =>"STRING",
+                                help_string => "Relay server name or relay server ip",
+                                optional => "NO",
+                            },],
+    },
 	{
 		obj_type => "ITEM",
 		name => "from",
Index: /branches/rel_avx_2_7_2/src/library/Makefile
===================================================================
--- /branches/rel_avx_2_7_2/src/library/Makefile	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/library/Makefile	(working copy)
@@ -5,7 +5,7 @@
 
 include $(TOP)/Makefile.master
 
-SDIRS=avx_log avxssl node_man ca_ui ca_util version avxha management avxnet avxvainst avxresource
+SDIRS= ca_mail avx_log avxssl node_man ca_ui ca_util version avxha management avxnet avxvainst avxresource
 
 # since we are using some utils that might not be on the build machine
 # lets not fail the entire build, but still be noise about failing to
Index: /branches/rel_avx_2_7_2/src/library/ca_mail/Makefile
===================================================================
--- /branches/rel_avx_2_7_2/src/library/ca_mail/Makefile	(revision 0)
+++ /branches/rel_avx_2_7_2/src/library/ca_mail/Makefile	(working copy)
@@ -0,0 +1,35 @@
+TOP = ../../..
+
+include $(TOP)/Makefile.master
+
+FILES = sendmail.cf
+FILESDIR = /ca/etc
+
+LIB_NAME = libcamail
+STARGET = $(LIB_NAME).a
+SLIB = $(LIB_NAME).so
+
+CFILES = sys_mail.c
+HFILES = sys_mail.h
+OBJS = $(CFILES:.c=.o)
+
+CC = gcc
+AR = ar
+CFLAGS = -fPIC -Wformat -Wall -Wno-long-long -O
+LINK = -lnode -lsuppressprint
+
+all: $(STARGET) $(SLIB)
+
+%.o: %.c $(HFILES)
+	$(CC) $(CFLAGS) -c $< -o $@
+
+$(STARGET): $(OBJS)
+	$(AR) rs $(STARGET) $(OBJS)
+
+$(SLIB): $(OBJS)
+	$(CC) -shared -o $(SLIB) $(OBJS)
+
+clean:
+	/bin/rm -f *.o *.core *.out *.a 
+
+.PHONY: all clean
Index: /branches/rel_avx_2_7_2/src/library/ca_mail/sendmail.cf
===================================================================
--- /branches/rel_avx_2_7_2/src/library/ca_mail/sendmail.cf	(revision 0)
+++ /branches/rel_avx_2_7_2/src/library/ca_mail/sendmail.cf	(working copy)
@@ -0,0 +1,1843 @@
+#
+# Copyright (c) 1998-2004, 2009, 2010 Sendmail, Inc. and its suppliers.
+#	All rights reserved.
+# Copyright (c) 1983, 1995 Eric P. Allman.  All rights reserved.
+# Copyright (c) 1988, 1993
+#	The Regents of the University of California.  All rights reserved.
+#
+# By using this file, you agree to the terms and conditions set
+# forth in the LICENSE file which can be found at the top level of
+# the sendmail distribution.
+#
+#
+
+######################################################################
+######################################################################
+#####
+#####		SENDMAIL CONFIGURATION FILE
+#####
+######################################################################
+#####
+#####	DO NOT EDIT THIS FILE!  Only edit the source .mc file.
+#####
+######################################################################
+######################################################################
+
+#####  $Id: cfhead.m4,v 8.121 2010/01/07 18:20:19 ca Exp $  #####
+#####  $Id: cf.m4,v 8.32 1999/02/07 07:26:14 gshapiro Exp $  #####
+#####  setup for linux  #####
+#####  $Id: linux.m4,v 8.13 2000/09/17 17:30:00 gshapiro Exp $  #####
+
+
+
+#####  $Id: local_procmail.m4,v 8.22 2002/11/17 04:24:19 ca Exp $  #####
+
+
+#####  $Id: no_default_msa.m4,v 8.2 2001/02/14 05:03:22 gshapiro Exp $  #####
+
+#####  $Id: smrsh.m4,v 8.14 1999/11/18 05:06:23 ca Exp $  #####
+
+#####  $Id: mailertable.m4,v 8.25 2002/06/27 23:23:57 gshapiro Exp $  #####
+
+#####  $Id: virtusertable.m4,v 8.23 2002/06/27 23:23:57 gshapiro Exp $  #####
+
+#####  $Id: redirect.m4,v 8.15 1999/08/06 01:47:36 gshapiro Exp $  #####
+
+#####  $Id: always_add_domain.m4,v 8.11 2000/09/12 22:00:53 ca Exp $  #####
+
+#####  $Id: use_cw_file.m4,v 8.11 2001/08/26 20:58:57 gshapiro Exp $  #####
+
+
+#####  $Id: use_ct_file.m4,v 8.11 2001/08/26 20:58:57 gshapiro Exp $  #####
+
+
+#####  $Id: local_procmail.m4,v 8.22 2002/11/17 04:24:19 ca Exp $  #####
+
+#####  $Id: access_db.m4,v 8.27 2006/07/06 21:10:10 ca Exp $  #####
+
+#####  $Id: blacklist_recipients.m4,v 8.13 1999/04/02 02:25:13 gshapiro Exp $  #####
+
+#####  $Id: accept_unresolvable_domains.m4,v 8.10 1999/02/07 07:26:07 gshapiro Exp $  #####
+
+
+#####  $Id: proto.m4,v 8.760 2012/09/07 16:30:15 ca Exp $  #####
+
+# level 10 config file format
+V10/Berkeley
+
+# override file safeties - setting this option compromises system security,
+# addressing the actual file configuration problem is preferred
+# need to set this before any file actions are encountered in the cf file
+#O DontBlameSendmail=safe
+
+# default LDAP map specification
+# need to set this now before any LDAP maps are defined
+#O LDAPDefaultSpec=-h localhost
+
+##################
+#   local info   #
+##################
+
+# my LDAP cluster
+# need to set this before any LDAP lookups are done (including classes)
+#D{sendmailMTACluster}$m
+
+Cwlocalhost
+# file containing names of hosts for which we receive email
+Fw/etc/mail/local-host-names
+
+# my official domain name
+# ... define this only if sendmail cannot automatically determine your domain
+#Dj$w.Foo.COM
+Dj $w.alert_pseudo_domain
+
+# host/domain names ending with a token in class P are canonical
+CP.
+
+# "Smart" relay host (may be null)
+DS
+
+
+# operators that cannot be in local usernames (i.e., network indicators)
+CO @ % !
+
+# a class with just dot (for identifying canonical names)
+C..
+
+# a class with just a left bracket (for identifying domain literals)
+C[[
+
+# access_db acceptance class
+C{Accept}OK RELAY
+
+
+C{ResOk}OKR
+
+
+# Hosts for which relaying is permitted ($=R)
+FR-o /etc/mail/relay-domains
+
+# arithmetic map
+Karith arith
+# macro storage map
+Kmacro macro
+# possible values for TLS_connection in access map
+C{Tls}VERIFY ENCR
+
+
+
+
+
+# dequoting map
+Kdequote dequote
+
+# class E: names that should be exposed as from this host, even if we masquerade
+# class L: names that should be delivered locally, even if we have a relay
+# class M: domains that should be converted to $M
+# class N: domains that should not be converted to $M
+#CL root
+C{E}root
+C{w}localhost.localdomain
+
+
+
+# my name for error messages
+DnMAILER-DAEMON
+
+
+# Mailer table (overriding domains)
+Kmailertable hash -o /etc/mail/mailertable.db
+
+# Virtual user table (maps incoming users)
+Kvirtuser hash -o /etc/mail/virtusertable.db
+
+CPREDIRECT
+
+# Access list database (for spam stomping)
+Kaccess hash -T<TMPF> -o /etc/mail/access.db
+
+# Configuration version number
+DZ8.14.7
+
+
+###############
+#   Options   #
+###############
+
+# strip message body to 7 bits on input?
+O SevenBitInput=False
+
+# 8-bit data handling
+#O EightBitMode=pass8
+
+# DSCP marking of traffic (IP_TOS)
+#O InetQoS=none
+
+# wait for alias file rebuild (default units: minutes)
+O AliasWait=10
+
+# location of alias file
+O AliasFile=/etc/aliases
+
+# minimum number of free blocks on filesystem
+O MinFreeBlocks=100
+
+# maximum message size
+#O MaxMessageSize=0
+
+# substitution for space (blank) characters
+O BlankSub=.
+
+# avoid connecting to "expensive" mailers on initial submission?
+O HoldExpensive=False
+
+# checkpoint queue runs after every N successful deliveries
+#O CheckpointInterval=10
+
+# default delivery mode
+O DeliveryMode=background
+
+# error message header/file
+#O ErrorHeader=/etc/mail/error-header
+
+# error mode
+#O ErrorMode=print
+
+# save Unix-style "From_" lines at top of header?
+#O SaveFromLine=False
+
+# queue file mode (qf files)
+#O QueueFileMode=0600
+
+# temporary file mode
+O TempFileMode=0600
+
+# match recipients against GECOS field?
+#O MatchGECOS=False
+
+# maximum hop count
+#O MaxHopCount=25
+
+# location of help file
+O HelpFile=/etc/mail/helpfile
+
+# ignore dots as terminators in incoming messages?
+#O IgnoreDots=False
+
+# name resolver options
+#O ResolverOptions=+AAONLY
+
+# deliver MIME-encapsulated error messages?
+O SendMimeErrors=True
+
+# Forward file search path
+O ForwardPath=$z/.forward.$w:$z/.forward
+
+# open connection cache size
+O ConnectionCacheSize=2
+
+# open connection cache timeout
+O ConnectionCacheTimeout=5m
+
+# persistent host status directory
+#O HostStatusDirectory=.hoststat
+
+# single thread deliveries (requires HostStatusDirectory)?
+#O SingleThreadDelivery=False
+
+# use Errors-To: header?
+O UseErrorsTo=False
+
+# log level
+O LogLevel=9
+
+# send to me too, even in an alias expansion?
+#O MeToo=True
+
+# verify RHS in newaliases?
+O CheckAliases=False
+
+# default messages to old style headers if no special punctuation?
+O OldStyleHeaders=True
+
+# SMTP daemon options
+
+O DaemonPortOptions=Port=smtp,Addr=127.0.0.1, Name=MTA
+
+# SMTP client options
+#O ClientPortOptions=Family=inet, Address=0.0.0.0
+
+# Modifiers to define {daemon_flags} for direct submissions
+#O DirectSubmissionModifiers
+
+# Use as mail submission program? See sendmail/SECURITY
+#O UseMSP
+
+# privacy flags
+O PrivacyOptions=authwarnings,novrfy,noexpn,restrictqrun
+
+# who (if anyone) should get extra copies of error messages
+#O PostmasterCopy=Postmaster
+
+# slope of queue-only function
+#O QueueFactor=600000
+
+# limit on number of concurrent queue runners
+#O MaxQueueChildren
+
+# maximum number of queue-runners per queue-grouping with multiple queues
+#O MaxRunnersPerQueue=1
+
+# priority of queue runners (nice(3))
+#O NiceQueueRun
+
+# shall we sort the queue by hostname first?
+#O QueueSortOrder=priority
+
+# minimum time in queue before retry
+#O MinQueueAge=30m
+
+# how many jobs can you process in the queue?
+#O MaxQueueRunSize=0
+
+# perform initial split of envelope without checking MX records
+#O FastSplit=1
+
+# queue directory
+O QueueDirectory=/var/spool/mqueue
+
+# key for shared memory; 0 to turn off, -1 to auto-select
+#O SharedMemoryKey=0
+
+# file to store auto-selected key for shared memory (SharedMemoryKey = -1)
+#O SharedMemoryKeyFile
+
+# timeouts (many of these)
+#O Timeout.initial=5m
+O Timeout.connect=1m
+#O Timeout.aconnect=0s
+#O Timeout.iconnect=5m
+#O Timeout.helo=5m
+#O Timeout.mail=10m
+#O Timeout.rcpt=1h
+#O Timeout.datainit=5m
+#O Timeout.datablock=1h
+#O Timeout.datafinal=1h
+#O Timeout.rset=5m
+#O Timeout.quit=2m
+#O Timeout.misc=2m
+#O Timeout.command=1h
+O Timeout.ident=0
+#O Timeout.fileopen=60s
+#O Timeout.control=2m
+O Timeout.queuereturn=5d
+#O Timeout.queuereturn.normal=5d
+#O Timeout.queuereturn.urgent=2d
+#O Timeout.queuereturn.non-urgent=7d
+#O Timeout.queuereturn.dsn=5d
+O Timeout.queuewarn=4h
+#O Timeout.queuewarn.normal=4h
+#O Timeout.queuewarn.urgent=1h
+#O Timeout.queuewarn.non-urgent=12h
+#O Timeout.queuewarn.dsn=4h
+#O Timeout.hoststatus=30m
+#O Timeout.resolver.retrans=5s
+#O Timeout.resolver.retrans.first=5s
+#O Timeout.resolver.retrans.normal=5s
+#O Timeout.resolver.retry=4
+#O Timeout.resolver.retry.first=4
+#O Timeout.resolver.retry.normal=4
+#O Timeout.lhlo=2m
+#O Timeout.auth=10m
+#O Timeout.starttls=1h
+
+# time for DeliverBy; extension disabled if less than 0
+#O DeliverByMin=0
+
+# should we not prune routes in route-addr syntax addresses?
+#O DontPruneRoutes=False
+
+# queue up everything before forking?
+O SuperSafe=True
+
+# status file
+O StatusFile=/var/log/mail/statistics
+
+# time zone handling:
+#  if undefined, use system default
+#  if defined but null, use TZ envariable passed in
+#  if defined and non-null, use that info
+#O TimeZoneSpec=
+
+# default UID (can be username or userid:groupid)
+O DefaultUser=8:12
+
+# list of locations of user database file (null means no lookup)
+O UserDatabaseSpec=/etc/mail/userdb.db
+
+# fallback MX host
+#O FallbackMXhost=fall.back.host.net
+
+# fallback smart host
+#O FallbackSmartHost=fall.back.host.net
+
+# if we are the best MX host for a site, try it directly instead of config err
+O TryNullMXList=True
+
+# load average at which we just queue messages
+#O QueueLA=8
+
+# load average at which we refuse connections
+#O RefuseLA=12
+
+# log interval when refusing connections for this long
+#O RejectLogInterval=3h
+
+# load average at which we delay connections; 0 means no limit
+#O DelayLA=0
+
+# maximum number of children we allow at one time
+#O MaxDaemonChildren=0
+
+# maximum number of new connections per second
+#O ConnectionRateThrottle=0
+
+# Width of the window 
+#O ConnectionRateWindowSize=60s
+
+# work recipient factor
+#O RecipientFactor=30000
+
+# deliver each queued job in a separate process?
+#O ForkEachJob=False
+
+# work class factor
+#O ClassFactor=1800
+
+# work time factor
+#O RetryFactor=90000
+
+# default character set
+#O DefaultCharSet=unknown-8bit
+
+# service switch file (name hardwired on Solaris, Ultrix, OSF/1, others)
+#O ServiceSwitchFile=/etc/mail/service.switch
+
+# hosts file (normally /etc/hosts)
+#O HostsFile=/etc/hosts
+
+# dialup line delay on connection failure
+#O DialDelay=0s
+
+# action to take if there are no recipients in the message
+#O NoRecipientAction=none
+
+# chrooted environment for writing to files
+#O SafeFileEnvironment
+
+# are colons OK in addresses?
+#O ColonOkInAddr=True
+
+# shall I avoid expanding CNAMEs (violates protocols)?
+#O DontExpandCnames=False
+
+# SMTP initial login message (old $e macro)
+O SmtpGreetingMessage=$j Sendmail $v/$Z; $b
+
+# UNIX initial From header format (old $l macro)
+O UnixFromLine=From $g $d
+
+# From: lines that have embedded newlines are unwrapped onto one line
+#O SingleLineFromHeader=False
+
+# Allow HELO SMTP command that does not include a host name
+#O AllowBogusHELO=False
+
+# Characters to be quoted in a full name phrase (@,;:\()[] are automatic)
+#O MustQuoteChars=.
+
+# delimiter (operator) characters (old $o macro)
+O OperatorChars=.:%@!^/[]+
+
+# shall I avoid calling initgroups(3) because of high NIS costs?
+#O DontInitGroups=False
+
+# are group-writable :include: and .forward files (un)trustworthy?
+# True (the default) means they are not trustworthy.
+#O UnsafeGroupWrites=True
+
+
+# where do errors that occur when sending errors get sent?
+#O DoubleBounceAddress=postmaster
+
+# issue temporary errors (4xy) instead of permanent errors (5xy)?
+#O SoftBounce=False
+
+# where to save bounces if all else fails
+#O DeadLetterDrop=/var/tmp/dead.letter
+
+# what user id do we assume for the majority of the processing?
+#O RunAsUser=sendmail
+
+# maximum number of recipients per SMTP envelope
+#O MaxRecipientsPerMessage=0
+
+# limit the rate recipients per SMTP envelope are accepted
+# once the threshold number of recipients have been rejected
+#O BadRcptThrottle=0
+
+
+# shall we get local names from our installed interfaces?
+O DontProbeInterfaces=True
+
+# Return-Receipt-To: header implies DSN request
+#O RrtImpliesDsn=False
+
+# override connection address (for testing)
+#O ConnectOnlyTo=0.0.0.0
+
+# Trusted user for file ownership and starting the daemon
+#O TrustedUser=root
+
+# Control socket for daemon management
+#O ControlSocketName=/var/spool/mqueue/.control
+
+# Maximum MIME header length to protect MUAs
+#O MaxMimeHeaderLength=0/0
+
+# Maximum length of the sum of all headers
+#O MaxHeadersLength=32768
+
+# Maximum depth of alias recursion
+#O MaxAliasRecursion=10
+
+# location of pid file
+#O PidFile=/var/run/sendmail.pid
+
+# Prefix string for the process title shown on 'ps' listings
+#O ProcessTitlePrefix=prefix
+
+# Data file (df) memory-buffer file maximum size
+#O DataFileBufferSize=4096
+
+# Transcript file (xf) memory-buffer file maximum size
+#O XscriptFileBufferSize=4096
+
+# lookup type to find information about local mailboxes
+#O MailboxDatabase=pw
+
+# override compile time flag REQUIRES_DIR_FSYNC
+#O RequiresDirfsync=true
+
+# list of authentication mechanisms
+#O AuthMechanisms=EXTERNAL GSSAPI KERBEROS_V4 DIGEST-MD5 CRAM-MD5
+
+# Authentication realm
+#O AuthRealm
+
+# default authentication information for outgoing connections
+#O DefaultAuthInfo=/etc/mail/default-auth-info
+
+# SMTP AUTH flags
+O AuthOptions=A
+
+# SMTP AUTH maximum encryption strength
+#O AuthMaxBits
+
+# SMTP STARTTLS server options
+#O TLSSrvOptions
+
+
+# Input mail filters
+#O InputMailFilters
+
+
+# CA directory
+#O CACertPath
+# CA file
+#O CACertFile
+# Server Cert
+#O ServerCertFile
+# Server private key
+#O ServerKeyFile
+# Client Cert
+#O ClientCertFile
+# Client private key
+#O ClientKeyFile
+# File containing certificate revocation lists 
+#O CRLFile
+# DHParameters (only required if DSA/DH is used)
+#O DHParameters
+# Random data source (required for systems without /dev/urandom under OpenSSL)
+#O RandFile
+
+# Maximum number of "useless" commands before slowing down
+#O MaxNOOPCommands=20
+
+# Name to use for EHLO (defaults to $j)
+#O HeloName
+
+############################
+# QUEUE GROUP DEFINITIONS  #
+############################
+
+
+###########################
+#   Message precedences   #
+###########################
+
+Pfirst-class=0
+Pspecial-delivery=100
+Plist=-30
+Pbulk=-60
+Pjunk=-100
+
+#####################
+#   Trusted users   #
+#####################
+
+# this is equivalent to setting class "t"
+Ft/etc/mail/trusted-users
+Troot
+Tdaemon
+Tuucp
+
+#########################
+#   Format of headers   #
+#########################
+
+H?P?Return-Path: <$g>
+HReceived: $?sfrom $s $.$?_($?s$|from $.$_)
+	$.$?{auth_type}(authenticated$?{auth_ssf} bits=${auth_ssf}$.)
+	$.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version}
+	(version=${tls_version} cipher=${cipher} bits=${cipher_bits} verify=${verify})$.$?u
+	for $u; $|;
+	$.$b
+H?D?Resent-Date: $a
+H?D?Date: $a
+H?F?Resent-From: $?x$x <$g>$|$g$.
+H?F?From: $?x$x <$g>$|$g$.
+H?x?Full-Name: $x
+# HPosted-Date: $a
+# H?l?Received-Date: $b
+H?M?Resent-Message-Id: <$t.$i@$j>
+H?M?Message-Id: <$t.$i@$j>
+
+#
+######################################################################
+######################################################################
+#####
+#####			REWRITING RULES
+#####
+######################################################################
+######################################################################
+
+############################################
+###  Ruleset 3 -- Name Canonicalization  ###
+############################################
+Scanonify=3
+
+# handle null input (translate to <@> special case)
+R$@			$@ <@>
+
+# strip group: syntax (not inside angle brackets!) and trailing semicolon
+R$*			$: $1 <@>			mark addresses
+R$* < $* > $* <@>	$: $1 < $2 > $3			unmark <addr>
+R@ $* <@>		$: @ $1				unmark @host:...
+R$* [ IPv6 : $+ ] <@>	$: $1 [ IPv6 : $2 ]		unmark IPv6 addr
+R$* :: $* <@>		$: $1 :: $2			unmark node::addr
+R:include: $* <@>	$: :include: $1			unmark :include:...
+R$* : $* [ $* ]		$: $1 : $2 [ $3 ] <@>		remark if leading colon
+R$* : $* <@>		$: $2				strip colon if marked
+R$* <@>			$: $1				unmark
+R$* ;			   $1				strip trailing semi
+R$* < $+ :; > $*	$@ $2 :; <@>			catch <list:;>
+R$* < $* ; >		   $1 < $2 >			bogus bracketed semi
+
+# null input now results from list:; syntax
+R$@			$@ :; <@>
+
+# strip angle brackets -- note RFC733 heuristic to get innermost item
+R$*			$: < $1 >			housekeeping <>
+R$+ < $* >		   < $2 >			strip excess on left
+R< $* > $+		   < $1 >			strip excess on right
+R<>			$@ < @ >			MAIL FROM:<> case
+R< $+ >			$: $1				remove housekeeping <>
+
+# strip route address <@a,@b,@c:user@d> -> <user@d>
+R@ $+ , $+		$2
+R@ [ $* ] : $+		$2
+R@ $+ : $+		$2
+
+# find focus for list syntax
+R $+ : $* ; @ $+	$@ $>Canonify2 $1 : $2 ; < @ $3 >	list syntax
+R $+ : $* ;		$@ $1 : $2;			list syntax
+
+# find focus for @ syntax addresses
+R$+ @ $+		$: $1 < @ $2 >			focus on domain
+R$+ < $+ @ $+ >		$1 $2 < @ $3 >			move gaze right
+R$+ < @ $+ >		$@ $>Canonify2 $1 < @ $2 >	already canonical
+
+
+# convert old-style addresses to a domain-based address
+R$- ! $+		$@ $>Canonify2 $2 < @ $1 .UUCP >	resolve uucp names
+R$+ . $- ! $+		$@ $>Canonify2 $3 < @ $1 . $2 >		domain uucps
+R$+ ! $+		$@ $>Canonify2 $2 < @ $1 .UUCP >	uucp subdomains
+
+# if we have % signs, take the rightmost one
+R$* % $*		$1 @ $2				First make them all @s.
+R$* @ $* @ $*		$1 % $2 @ $3			Undo all but the last.
+R$* @ $*		$@ $>Canonify2 $1 < @ $2 >	Insert < > and finish
+
+# else we must be a local name
+R$*			$@ $>Canonify2 $1
+
+
+################################################
+###  Ruleset 96 -- bottom half of ruleset 3  ###
+################################################
+
+SCanonify2=96
+
+# handle special cases for local names
+R$* < @ localhost > $*		$: $1 < @ $j . > $2		no domain at all
+R$* < @ localhost . $m > $*	$: $1 < @ $j . > $2		local domain
+R$* < @ localhost . UUCP > $*	$: $1 < @ $j . > $2		.UUCP domain
+
+# check for IPv4/IPv6 domain literal
+R$* < @ [ $+ ] > $*		$: $1 < @@ [ $2 ] > $3		mark [addr]
+R$* < @@ $=w > $*		$: $1 < @ $j . > $3		self-literal
+R$* < @@ $+ > $*		$@ $1 < @ $2 > $3		canon IP addr
+
+
+
+
+
+# if really UUCP, handle it immediately
+
+# try UUCP traffic as a local address
+R$* < @ $+ . UUCP > $*		$: $1 < @ $[ $2 $] . UUCP . > $3
+R$* < @ $+ . . UUCP . > $*	$@ $1 < @ $2 . > $3
+
+# hostnames ending in class P are always canonical
+R$* < @ $* $=P > $*		$: $1 < @ $2 $3 . > $4
+R$* < @ $* $~P > $*		$: $&{daemon_flags} $| $1 < @ $2 $3 > $4
+R$* CC $* $| $* < @ $+.$+ > $*	$: $3 < @ $4.$5 . > $6
+R$* CC $* $| $*			$: $3
+# pass to name server to make hostname canonical
+R$* $| $* < @ $* > $*		$: $2 < @ $[ $3 $] > $4
+R$* $| $*			$: $2
+
+# local host aliases and pseudo-domains are always canonical
+R$* < @ $=w > $*		$: $1 < @ $2 . > $3
+R$* < @ $=M > $*		$: $1 < @ $2 . > $3
+R$* < @ $={VirtHost} > $* 	$: $1 < @ $2 . > $3
+R$* < @ $* . . > $*		$1 < @ $2 . > $3
+
+
+##################################################
+###  Ruleset 4 -- Final Output Post-rewriting  ###
+##################################################
+Sfinal=4
+
+R$+ :; <@>		$@ $1 :				handle <list:;>
+R$* <@>			$@				handle <> and list:;
+
+# strip trailing dot off possibly canonical name
+R$* < @ $+ . > $*	$1 < @ $2 > $3
+
+# eliminate internal code
+R$* < @ *LOCAL* > $*	$1 < @ $j > $2
+
+# externalize local domain info
+R$* < $+ > $*		$1 $2 $3			defocus
+R@ $+ : @ $+ : $+	@ $1 , @ $2 : $3		<route-addr> canonical
+R@ $*			$@ @ $1				... and exit
+
+# UUCP must always be presented in old form
+R$+ @ $- . UUCP		$2!$1				u@h.UUCP => h!u
+
+# delete duplicate local names
+R$+ % $=w @ $=w		$1 @ $2				u%host@host => u@host
+
+
+
+##############################################################
+###   Ruleset 97 -- recanonicalize and call ruleset zero   ###
+###		   (used for recursive calls)		   ###
+##############################################################
+
+SRecurse=97
+R$*			$: $>canonify $1
+R$*			$@ $>parse $1
+
+
+######################################
+###   Ruleset 0 -- Parse Address   ###
+######################################
+
+Sparse=0
+
+R$*			$: $>Parse0 $1		initial parsing
+R<@>			$#local $: <@>		special case error msgs
+R$*			$: $>ParseLocal $1	handle local hacks
+R$*			$: $>Parse1 $1		final parsing
+
+#
+#  Parse0 -- do initial syntax checking and eliminate local addresses.
+#	This should either return with the (possibly modified) input
+#	or return with a #error mailer.  It should not return with a
+#	#mailer other than the #error mailer.
+#
+
+SParse0
+R<@>			$@ <@>			special case error msgs
+R$* : $* ; <@>		$#error $@ 5.1.3 $: "553 List:; syntax illegal for recipient addresses"
+R@ <@ $* >		< @ $1 >		catch "@@host" bogosity
+R<@ $+>			$#error $@ 5.1.3 $: "553 User address required"
+R$+ <@>			$#error $@ 5.1.3 $: "553 Hostname required"
+R$*			$: <> $1
+R<> $* < @ [ $* ] : $+ > $*	$1 < @ [ $2 ] : $3 > $4
+R<> $* < @ [ $* ] , $+ > $*	$1 < @ [ $2 ] , $3 > $4
+R<> $* < @ [ $* ] $+ > $*	$#error $@ 5.1.2 $: "553 Invalid address"
+R<> $* < @ [ $+ ] > $*		$1 < @ [ $2 ] > $3
+R<> $* <$* : $* > $*	$#error $@ 5.1.3 $: "553 Colon illegal in host name part"
+R<> $*			$1
+R$* < @ . $* > $*	$#error $@ 5.1.2 $: "553 Invalid host name"
+R$* < @ $* .. $* > $*	$#error $@ 5.1.2 $: "553 Invalid host name"
+R$* < @ $* @ > $*	$#error $@ 5.1.2 $: "553 Invalid route address"
+R$* @ $* < @ $* > $*	$#error $@ 5.1.3 $: "553 Invalid route address"
+R$* , $~O $*		$#error $@ 5.1.3 $: "553 Invalid route address"
+
+
+# now delete the local info -- note $=O to find characters that cause forwarding
+R$* < @ > $*		$@ $>Parse0 $>canonify $1	user@ => user
+R< @ $=w . > : $*	$@ $>Parse0 $>canonify $2	@here:... -> ...
+R$- < @ $=w . >		$: $(dequote $1 $) < @ $2 . >	dequote "foo"@here
+R< @ $+ >		$#error $@ 5.1.3 $: "553 User address required"
+R$* $=O $* < @ $=w . >	$@ $>Parse0 $>canonify $1 $2 $3	...@here -> ...
+R$- 			$: $(dequote $1 $) < @ *LOCAL* >	dequote "foo"
+R< @ *LOCAL* >		$#error $@ 5.1.3 $: "553 User address required"
+R$* $=O $* < @ *LOCAL* >
+			$@ $>Parse0 $>canonify $1 $2 $3	...@*LOCAL* -> ...
+R$* < @ *LOCAL* >	$: $1
+
+#
+#  Parse1 -- the bottom half of ruleset 0.
+#
+
+SParse1
+
+# handle numeric address spec
+R$* < @ [ $+ ] > $*	$: $>ParseLocal $1 < @ [ $2 ] > $3	numeric internet spec
+R$* < @ [ $+ ] > $*	$: $1 < @ [ $2 ] : $S > $3	Add smart host to path
+R$* < @ [ $+ ] : > $*		$#esmtp $@ [$2] $: $1 < @ [$2] > $3	no smarthost: send
+R$* < @ [ $+ ] : $- : $*> $*	$#$3 $@ $4 $: $1 < @ [$2] > $5	smarthost with mailer
+R$* < @ [ $+ ] : $+ > $*	$#esmtp $@ $3 $: $1 < @ [$2] > $4	smarthost without mailer
+
+# handle virtual users
+R$+			$: <!> $1		Mark for lookup
+R<!> $+ < @ $={VirtHost} . > 	$: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
+R<!> $+ < @ $=w . > 	$: < $(virtuser $1 @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
+R<@> $+ + $+ < @ $* . >
+			$: < $(virtuser $1 + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
+R<@> $+ + $* < @ $* . >
+			$: < $(virtuser $1 + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
+R<@> $+ + $* < @ $* . >
+			$: < $(virtuser $1 @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
+R<@> $+ + $+ < @ $+ . >	$: < $(virtuser + + @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
+R<@> $+ + $* < @ $+ . >	$: < $(virtuser + * @ $3 $@ $1 $@ $2 $@ +$2 $: @ $) > $1 + $2 < @ $3 . >
+R<@> $+ + $* < @ $+ . >	$: < $(virtuser @ $3 $@ $1 $@ $2 $@ +$2 $: ! $) > $1 + $2 < @ $3 . >
+R<@> $+ < @ $+ . >	$: < $(virtuser @ $2 $@ $1 $: @ $) > $1 < @ $2 . >
+R<@> $+			$: $1
+R<!> $+			$: $1
+R< error : $-.$-.$- : $+ > $* 	$#error $@ $1.$2.$3 $: $4
+R< error : $- $+ > $* 	$#error $@ $(dequote $1 $) $: $2
+R< $+ > $+ < @ $+ >	$: $>Recurse $1
+
+# short circuit local delivery so forwarded email works
+
+
+R$=L < @ $=w . >	$#local $: @ $1			special local names
+R$+ < @ $=w . >		$#local $: $1			regular local name
+
+# not local -- try mailer table lookup
+R$* <@ $+ > $*		$: < $2 > $1 < @ $2 > $3	extract host name
+R< $+ . > $*		$: < $1 > $2			strip trailing dot
+R< $+ > $*		$: < $(mailertable $1 $) > $2	lookup
+R< $~[ : $* > $* 	$>MailerToTriple < $1 : $2 > $3		check -- resolved?
+R< $+ > $*		$: $>Mailertable <$1> $2		try domain
+
+# resolve remotely connected UUCP links (if any)
+
+# resolve fake top level domains by forwarding to other hosts
+
+
+
+# pass names that still have a host to a smarthost (if defined)
+R$* < @ $* > $*		$: $>MailerToTriple < $S > $1 < @ $2 > $3	glue on smarthost name
+
+# deal with other remote names
+R$* < @$* > $*		$#esmtp $@ $2 $: $1 < @ $2 > $3	user@host.domain
+
+# handle locally delivered names
+R$=L			$#local $: @ $1		special local names
+R$+			$#local $: $1			regular local names
+
+###########################################################################
+###   Ruleset 5 -- special rewriting after aliases have been expanded   ###
+###########################################################################
+
+SLocal_localaddr
+Slocaladdr=5
+R$+			$: $1 $| $>"Local_localaddr" $1
+R$+ $| $#ok		$@ $1			no change
+R$+ $| $#$*		$#$2
+R$+ $| $*		$: $1
+
+
+
+
+# deal with plussed users so aliases work nicely
+R$+ + *			$#local $@ $&h $: $1
+R$+ + $*		$#local $@ + $2 $: $1 + *
+
+# prepend an empty "forward host" on the front
+R$+			$: <> $1
+
+
+
+R< > $+			$: < > < $1 <> $&h >		nope, restore +detail
+
+R< > < $+ <> + $* >	$: < > < $1 + $2 >		check whether +detail
+R< > < $+ <> $* >	$: < > < $1 >			else discard
+R< > < $+ + $* > $*	   < > < $1 > + $2 $3		find the user part
+R< > < $+ > + $*	$#local $@ $2 $: @ $1		strip the extra +
+R< > < $+ >		$@ $1				no +detail
+R$+			$: $1 <> $&h			add +detail back in
+
+R$+ <> + $*		$: $1 + $2			check whether +detail
+R$+ <> $*		$: $1				else discard
+R< local : $* > $*	$: $>MailerToTriple < local : $1 > $2	no host extension
+R< error : $* > $*	$: $>MailerToTriple < error : $1 > $2	no host extension
+
+R< $~[ : $+ > $+	$: $>MailerToTriple < $1 : $2 > $3 < @ $2 >
+
+R< $+ > $+		$@ $>MailerToTriple < $1 > $2 < @ $1 >
+
+
+###################################################################
+###  Ruleset 90 -- try domain part of mailertable entry 	###
+###################################################################
+
+SMailertable=90
+R$* <$- . $+ > $*	$: $1$2 < $(mailertable .$3 $@ $1$2 $@ $2 $) > $4
+R$* <$~[ : $* > $*	$>MailerToTriple < $2 : $3 > $4		check -- resolved?
+R$* < . $+ > $* 	$@ $>Mailertable $1 . <$2> $3		no -- strip & try again
+R$* < $* > $*		$: < $(mailertable . $@ $1$2 $) > $3	try "."
+R< $~[ : $* > $*	$>MailerToTriple < $1 : $2 > $3		"." found?
+R< $* > $*		$@ $2				no mailertable match
+
+###################################################################
+###  Ruleset 95 -- canonify mailer:[user@]host syntax to triple	###
+###################################################################
+
+SMailerToTriple=95
+R< > $*				$@ $1			strip off null relay
+R< error : $-.$-.$- : $+ > $* 	$#error $@ $1.$2.$3 $: $4
+R< error : $- : $+ > $*		$#error $@ $(dequote $1 $) $: $2
+R< error : $+ > $*		$#error $: $1
+R< local : $* > $*		$>CanonLocal < $1 > $2
+R< $~[ : $+ @ $+ > $*<$*>$*	$# $1 $@ $3 $: $2<@$3>	use literal user
+R< $~[ : $+ > $*		$# $1 $@ $2 $: $3	try qualified mailer
+R< $=w > $*			$@ $2			delete local host
+R< $+ > $*			$#relay $@ $1 $: $2	use unqualified mailer
+
+###################################################################
+###  Ruleset CanonLocal -- canonify local: syntax		###
+###################################################################
+
+SCanonLocal
+# strip local host from routed addresses
+R< $* > < @ $+ > : $+		$@ $>Recurse $3
+R< $* > $+ $=O $+ < @ $+ >	$@ $>Recurse $2 $3 $4
+
+# strip trailing dot from any host name that may appear
+R< $* > $* < @ $* . >		$: < $1 > $2 < @ $3 >
+
+# handle local: syntax -- use old user, either with or without host
+R< > $* < @ $* > $*		$#local $@ $1@$2 $: $1
+R< > $+				$#local $@ $1    $: $1
+
+# handle local:user@host syntax -- ignore host part
+R< $+ @ $+ > $* < @ $* >	$: < $1 > $3 < @ $4 >
+
+# handle local:user syntax
+R< $+ > $* <@ $* > $*		$#local $@ $2@$3 $: $1
+R< $+ > $* 			$#local $@ $2    $: $1
+
+###################################################################
+###  Ruleset 93 -- convert header names to masqueraded form	###
+###################################################################
+
+SMasqHdr=93
+
+
+# do not masquerade anything in class N
+R$* < @ $* $=N . >	$@ $1 < @ $2 $3 . >
+
+R$* < @ *LOCAL* >	$@ $1 < @ $j . >
+
+###################################################################
+###  Ruleset 94 -- convert envelope names to masqueraded form	###
+###################################################################
+
+SMasqEnv=94
+R$* < @ *LOCAL* > $*	$: $1 < @ $j . > $2
+
+###################################################################
+###  Ruleset 98 -- local part of ruleset zero (can be null)	###
+###################################################################
+
+SParseLocal=98
+
+# addresses sent to foo@host.REDIRECT will give a 551 error code
+R$* < @ $+ .REDIRECT. >		$: $1 < @ $2 . REDIRECT . > < ${opMode} >
+R$* < @ $+ .REDIRECT. > <i>	$: $1 < @ $2 . REDIRECT. >
+R$* < @ $+ .REDIRECT. > < $- >	$#error $@ 5.1.1 $: "551 User has moved; please try " <$1@$2>
+
+
+
+
+
+
+######################################################################
+###  D: LookUpDomain -- search for domain in access database
+###
+###	Parameters:
+###		<$1> -- key (domain name)
+###		<$2> -- default (what to return if not found in db)
+###		<$3> -- mark (must be <(!|+) single-token>)
+###			! does lookup only with tag
+###			+ does lookup with and without tag
+###		<$4> -- passthru (additional data passed unchanged through)
+######################################################################
+
+SD
+R<$*> <$+> <$- $-> <$*>		$: < $(access $4:$1 $: ? $) > <$1> <$2> <$3 $4> <$5>
+R<?> <$+> <$+> <+ $-> <$*>	$: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4>
+R<?> <[$+.$-]> <$+> <$- $-> <$*>	$@ $>D <[$1]> <$3> <$4 $5> <$6>
+R<?> <[$+::$-]> <$+> <$- $-> <$*>	$: $>D <[$1]> <$3> <$4 $5> <$6>
+R<?> <[$+:$-]> <$+> <$- $-> <$*>	$: $>D <[$1]> <$3> <$4 $5> <$6>
+R<?> <$+.$+> <$+> <$- $-> <$*>	$@ $>D <$2> <$3> <$4 $5> <$6>
+R<?> <$+> <$+> <$- $-> <$*>	$@ <$2> <$5>
+R<$* <TMPF>> <$+> <$+> <$- $-> <$*>	$@ <<TMPF>> <$6>
+R<$*> <$+> <$+> <$- $-> <$*>	$@ <$1> <$6>
+
+######################################################################
+###  A: LookUpAddress -- search for host address in access database
+###
+###	Parameters:
+###		<$1> -- key (dot quadded host address)
+###		<$2> -- default (what to return if not found in db)
+###		<$3> -- mark (must be <(!|+) single-token>)
+###			! does lookup only with tag
+###			+ does lookup with and without tag
+###		<$4> -- passthru (additional data passed through)
+######################################################################
+
+SA
+R<$+> <$+> <$- $-> <$*>		$: < $(access $4:$1 $: ? $) > <$1> <$2> <$3 $4> <$5>
+R<?> <$+> <$+> <+ $-> <$*>	$: < $(access $1 $: ? $) > <$1> <$2> <+ $3> <$4>
+R<?> <$+::$-> <$+> <$- $-> <$*>		$@ $>A <$1> <$3> <$4 $5> <$6>
+R<?> <$+:$-> <$+> <$- $-> <$*>		$@ $>A <$1> <$3> <$4 $5> <$6>
+R<?> <$+.$-> <$+> <$- $-> <$*>		$@ $>A <$1> <$3> <$4 $5> <$6>
+R<?> <$+> <$+> <$- $-> <$*>	$@ <$2> <$5>
+R<$* <TMPF>> <$+> <$+> <$- $-> <$*>	$@ <<TMPF>> <$6>
+R<$*> <$+> <$+> <$- $-> <$*>	$@ <$1> <$6>
+
+######################################################################
+###  CanonAddr --	Convert an address into a standard form for
+###			relay checking.  Route address syntax is
+###			crudely converted into a %-hack address.
+###
+###	Parameters:
+###		$1 -- full recipient address
+###
+###	Returns:
+###		parsed address, not in source route form
+######################################################################
+
+SCanonAddr
+R$*			$: $>Parse0 $>canonify $1	make domain canonical
+
+
+######################################################################
+###  ParseRecipient --	Strip off hosts in $=R as well as possibly
+###			$* $=m or the access database.
+###			Check user portion for host separators.
+###
+###	Parameters:
+###		$1 -- full recipient address
+###
+###	Returns:
+###		parsed, non-local-relaying address
+######################################################################
+
+SParseRecipient
+R$*				$: <?> $>CanonAddr $1
+R<?> $* < @ $* . >		<?> $1 < @ $2 >			strip trailing dots
+R<?> $- < @ $* >		$: <?> $(dequote $1 $) < @ $2 >	dequote local part
+
+# if no $=O character, no host in the user portion, we are done
+R<?> $* $=O $* < @ $* >		$: <NO> $1 $2 $3 < @ $4>
+R<?> $*				$@ $1
+
+
+R<NO> $* < @ $* $=R >		$: <RELAY> $1 < @ $2 $3 >
+R<NO> $* < @ $+ >		$: $>D <$2> <NO> <+ To> <$1 < @ $2 >>
+R<$+> <$+>			$: <$1> $2
+
+
+
+R<RELAY> $* < @ $* >		$@ $>ParseRecipient $1
+R<$+> $*			$@ $2
+
+
+######################################################################
+###  check_relay -- check hostname/address on SMTP startup
+######################################################################
+
+
+
+SLocal_check_relay
+Scheck_relay
+R$*			$: $1 $| $>"Local_check_relay" $1
+R$* $| $* $| $#$*	$#$3
+R$* $| $* $| $*		$@ $>"Basic_check_relay" $1 $| $2
+
+SBasic_check_relay
+# check for deferred delivery mode
+R$*			$: < $&{deliveryMode} > $1
+R< d > $*		$@ deferred
+R< $* > $*		$: $2
+
+R$+ $| $+		$: $>D < $1 > <?> <+ Connect> < $2 >
+R   $| $+		$: $>A < $1 > <?> <+ Connect> <>	empty client_name
+R<?> <$+>		$: $>A < $1 > <?> <+ Connect> <>	no: another lookup
+R<?> <$*>		$: OK				found nothing
+R<$={Accept}> <$*>	$@ $1				return value of lookup
+R<REJECT> <$*>		$#error $@ 5.7.1 $: "550 Access denied"
+R<DISCARD> <$*>		$#discard $: discard
+R<QUARANTINE:$+> <$*>	$#error $@ quarantine $: $1
+R<ERROR:$-.$-.$-:$+> <$*>	$#error $@ $1.$2.$3 $: $4
+R<ERROR:$+> <$*>		$#error $: $1
+R<$* <TMPF>> <$*>		$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<$+> <$*>		$#error $: $1
+
+
+######################################################################
+###  check_mail -- check SMTP `MAIL FROM:' command argument
+######################################################################
+
+SLocal_check_mail
+Scheck_mail
+R$*			$: $1 $| $>"Local_check_mail" $1
+R$* $| $#$*		$#$2
+R$* $| $*		$@ $>"Basic_check_mail" $1
+
+SBasic_check_mail
+# check for deferred delivery mode
+R$*			$: < $&{deliveryMode} > $1
+R< d > $*		$@ deferred
+R< $* > $*		$: $2
+
+# authenticated?
+R$*			$: $1 $| $>"tls_client" $&{verify} $| MAIL
+R$* $| $#$+		$#$2
+R$* $| $*		$: $1
+
+R<>			$@ <OK>			we MUST accept <> (RFC 1123)
+R$+			$: <?> $1
+R<?><$+>		$: <@> <$1>
+R<?>$+			$: <@> <$1>
+R$*			$: $&{daemon_flags} $| $1
+R$* f $* $| <@> < $* @ $- >	$: < ? $&{client_name} > < $3 @ $4 >
+R$* u $* $| <@> < $* >	$: <?> < $3 >
+R$* $| $*		$: $2
+# handle case of @localhost on address
+R<@> < $* @ localhost >	$: < ? $&{client_name} > < $1 @ localhost >
+R<@> < $* @ [127.0.0.1] >
+			$: < ? $&{client_name} > < $1 @ [127.0.0.1] >
+R<@> < $* @ localhost.$m >
+			$: < ? $&{client_name} > < $1 @ localhost.$m >
+R<@> < $* @ localhost.localdomain >
+			$: < ? $&{client_name} > < $1 @ localhost.localdomain >
+R<@> < $* @ localhost.UUCP >
+			$: < ? $&{client_name} > < $1 @ localhost.UUCP >
+R<@> $*			$: $1			no localhost as domain
+R<? $=w> $*		$: $2			local client: ok
+R<? $+> <$+>		$#error $@ 5.5.4 $: "553 Real domain name required for sender address"
+R<?> $*			$: $1
+R$*			$: <?> $>CanonAddr $1		canonify sender address and mark it
+R<?> $* < @ $+ . >	<?> $1 < @ $2 >			strip trailing dots
+# handle non-DNS hostnames (*.bitnet, *.decnet, *.uucp, etc)
+R<?> $* < @ $* $=P >	$: <OKR> $1 < @ $2 $3 >
+R<?> $* < @ $j >	$: <OKR> $1 < @ $j >
+R<?> $* < @ $+ >	$: <OKR> $1 < @ $2 >		... unresolvable OK
+
+# check sender address: user@address, user@, address
+R<$+> $+ < @ $* >	$: @<$1> <$2 < @ $3 >> $| <F:$2@$3> <U:$2@> <D:$3>
+R<$+> $+		$: @<$1> <$2> $| <U:$2@>
+R@ <$+> <$*> $| <$+>	$: <@> <$1> <$2> $| $>SearchList <+ From> $| <$3> <>
+R<@> <$+> <$*> $| <$*>	$: <$3> <$1> <$2>		reverse result
+# retransform for further use
+R<?> <$+> <$*>		$: <$1> $2	no match
+R<$+> <$+> <$*>		$: <$1> $3	relevant result, keep it
+
+# handle case of no @domain on address
+R<?> $*			$: $&{daemon_flags} $| <?> $1
+R$* u $* $| <?> $*	$: <OKR> $3
+R$* $| $*		$: $2
+R<?> $*			$: < ? $&{client_addr} > $1
+R<?> $*			$@ <OKR>			...local unqualed ok
+R<? $+> $*		$#error $@ 5.5.4 $: "553 Domain name required for sender address " $&f
+							...remote is not
+# check results
+R<?> $*			$: @ $1		mark address: nothing known about it
+R<$={ResOk}> $*		$: @ $2		domain ok
+R<TEMP> $*		$#error $@ 4.1.8 $: "451 Domain of sender address " $&f " does not resolve"
+R<PERM> $*		$#error $@ 5.1.8 $: "553 Domain of sender address " $&f " does not exist"
+R<$={Accept}> $*	$# $1		accept from access map
+R<DISCARD> $*		$#discard $: discard
+R<QUARANTINE:$+> $*	$#error $@ quarantine $: $1
+R<REJECT> $*		$#error $@ 5.7.1 $: "550 Access denied"
+R<ERROR:$-.$-.$-:$+> $*		$#error $@ $1.$2.$3 $: $4
+R<ERROR:$+> $*		$#error $: $1
+R<<TMPF>> $*		$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<$+> $*		$#error $: $1		error from access db
+
+
+
+######################################################################
+###  check_rcpt -- check SMTP `RCPT TO:' command argument
+######################################################################
+
+SLocal_check_rcpt
+Scheck_rcpt
+R$*			$: $1 $| $>"Local_check_rcpt" $1
+R$* $| $#$*		$#$2
+R$* $| $*		$@ $>"Basic_check_rcpt" $1
+
+SBasic_check_rcpt
+# empty address?
+R<>			$#error $@ nouser $: "553 User address required"
+R$@			$#error $@ nouser $: "553 User address required"
+# check for deferred delivery mode
+R$*			$: < $&{deliveryMode} > $1
+R< d > $*		$@ deferred
+R< $* > $*		$: $2
+
+
+######################################################################
+R$*			$: $1 $| @ $>"Rcpt_ok" $1
+R$* $| @ $#TEMP $+	$: $1 $| T $2
+R$* $| @ $#$*		$#$2
+R$* $| @ RELAY		$@ RELAY
+R$* $| @ $*		$: O $| $>"Relay_ok" $1
+R$* $| T $+		$: T $2 $| $>"Relay_ok" $1
+R$* $| $#TEMP $+	$#error $2
+R$* $| $#$*		$#$2
+R$* $| RELAY		$@ RELAY
+R T $+ $| $*		$#error $1
+# anything else is bogus
+R$*			$#error $@ 5.7.1 $: "550 Relaying denied"
+
+
+######################################################################
+### Rcpt_ok: is the recipient ok?
+######################################################################
+SRcpt_ok
+R$*			$: $>ParseRecipient $1		strip relayable hosts
+
+
+
+# blacklist local users or any host from receiving mail
+R$*			$: <?> $1
+R<?> $+ < @ $=w >	$: <> <$1 < @ $2 >> $| <F:$1@$2> <U:$1@> <D:$2>
+R<?> $+ < @ $* >	$: <> <$1 < @ $2 >> $| <F:$1@$2> <D:$2>
+R<?> $+			$: <> <$1> $| <U:$1@>
+R<> <$*> $| <$+>	$: <@> <$1> $| $>SearchList <+ To> $| <$2> <>
+R<@> <$*> $| <$*>	$: <$2> <$1>		reverse result
+R<?> <$*>		$: @ $1		mark address as no match
+R<$={Accept}> <$*>	$: @ $2		mark address as no match
+
+R<REJECT> $*		$#error $@ 5.2.1 $: "550 Mailbox disabled for this recipient"
+R<DISCARD> $*		$#discard $: discard
+R<QUARANTINE:$+> $*	$#error $@ quarantine $: $1
+R<ERROR:$-.$-.$-:$+> $*		$#error $@ $1.$2.$3 $: $4
+R<ERROR:$+> $*		$#error $: $1
+R<<TMPF>> $*		$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<$+> $*		$#error $: $1		error from access db
+R@ $*			$1		remove mark
+
+# authenticated via TLS?
+R$*			$: $1 $| $>RelayTLS	client authenticated?
+R$* $| $# $+		$# $2			error/ok?
+R$* $| $*		$: $1			no
+
+R$*			$: $1 $| $>"Local_Relay_Auth" $&{auth_type}
+R$* $| $# $*		$# $2
+R$* $| NO		$: $1
+R$* $| $*		$: $1 $| $&{auth_type}
+R$* $|			$: $1
+R$* $| $={TrustAuthMech}	$# RELAY
+R$* $| $*		$: $1
+# anything terminating locally is ok
+R$+ < @ $=w >		$@ RELAY
+R$+ < @ $* $=R >	$@ RELAY
+R$+ < @ $+ >		$: $>D <$2> <?> <+ To> <$1 < @ $2 >>
+R<RELAY> $*		$@ RELAY
+R<$* <TMPF>> $*		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<$*> <$*>		$: $2
+
+
+
+# check for local user (i.e. unqualified address)
+R$*			$: <?> $1
+R<?> $* < @ $+ >	$: <REMOTE> $1 < @ $2 >
+# local user is ok
+R<?> $+			$@ RELAY
+R<$+> $*		$: $2
+
+######################################################################
+### Relay_ok: is the relay/sender ok?
+######################################################################
+SRelay_ok
+# anything originating locally is ok
+# check IP address
+R$*			$: $&{client_addr}
+R$@			$@ RELAY		originated locally
+R0			$@ RELAY		originated locally
+R127.0.0.1		$@ RELAY		originated locally
+RIPv6:::1		$@ RELAY		originated locally
+R$=R $*			$@ RELAY		relayable IP address
+R$*			$: $>A <$1> <?> <+ Connect> <$1>
+R<RELAY> $* 		$@ RELAY		relayable IP address
+
+R<<TMPF>> $*		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<$*> <$*>		$: $2
+R$*			$: [ $1 ]		put brackets around it...
+R$=w			$@ RELAY		... and see if it is local
+
+
+# check client name: first: did it resolve?
+R$*			$: < $&{client_resolve} >
+R<TEMP>			$#TEMP $@ 4.4.0 $: "450 Relaying temporarily denied. Cannot resolve PTR record for " $&{client_addr}
+R<FORGED>		$#error $@ 5.7.1 $: "550 Relaying denied. IP name possibly forged " $&{client_name}
+R<FAIL>			$#error $@ 5.7.1 $: "550 Relaying denied. IP name lookup failed " $&{client_name}
+R$*			$: <@> $&{client_name}
+# pass to name server to make hostname canonical
+R<@> $* $=P 		$:<?>  $1 $2
+R<@> $+			$:<?>  $[ $1 $]
+R$* .			$1			strip trailing dots
+R<?> $=w		$@ RELAY
+R<?> $* $=R			$@ RELAY
+R<?> $*			$: $>D <$1> <?> <+ Connect> <$1>
+R<RELAY> $*		$@ RELAY
+R<$* <TMPF>> $*		$#TEMP $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<$*> <$*>		$: $2
+
+
+
+######################################################################
+###  F: LookUpFull -- search for an entry in access database
+###
+###	lookup of full key (which should be an address) and
+###	variations if +detail exists: +* and without +detail
+###
+###	Parameters:
+###		<$1> -- key
+###		<$2> -- default (what to return if not found in db)
+###		<$3> -- mark (must be <(!|+) single-token>)
+###			! does lookup only with tag
+###			+ does lookup with and without tag
+###		<$4> -- passthru (additional data passed unchanged through)
+######################################################################
+
+SF
+R<$+> <$*> <$- $-> <$*>		$: <$(access $4:$1 $: ? $)> <$1> <$2> <$3 $4> <$5>
+R<?> <$+> <$*> <+ $-> <$*>	$: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4>
+R<?> <$+ + $* @ $+> <$*> <$- $-> <$*>
+			$: <$(access $6:$1+*@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7>
+R<?> <$+ + $* @ $+> <$*> <+ $-> <$*>
+			$: <$(access $1+*@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6>
+R<?> <$+ + $* @ $+> <$*> <$- $-> <$*>
+			$: <$(access $6:$1@$3 $: ? $)> <$1+$2@$3> <$4> <$5 $6> <$7>
+R<?> <$+ + $* @ $+> <$*> <+ $-> <$*>
+			$: <$(access $1@$3 $: ? $)> <$1+$2@$3> <$4> <+ $5> <$6>
+R<?> <$+> <$*> <$- $-> <$*>	$@ <$2> <$5>
+R<$+ <TMPF>> <$*> <$- $-> <$*>	$@ <<TMPF>> <$5>
+R<$+> <$*> <$- $-> <$*>		$@ <$1> <$5>
+
+######################################################################
+###  E: LookUpExact -- search for an entry in access database
+###
+###	Parameters:
+###		<$1> -- key
+###		<$2> -- default (what to return if not found in db)
+###		<$3> -- mark (must be <(!|+) single-token>)
+###			! does lookup only with tag
+###			+ does lookup with and without tag
+###		<$4> -- passthru (additional data passed unchanged through)
+######################################################################
+
+SE
+R<$*> <$*> <$- $-> <$*>		$: <$(access $4:$1 $: ? $)> <$1> <$2> <$3 $4> <$5>
+R<?> <$+> <$*> <+ $-> <$*>	$: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4>
+R<?> <$+> <$*> <$- $-> <$*>	$@ <$2> <$5>
+R<$+ <TMPF>> <$*> <$- $-> <$*>	$@ <<TMPF>> <$5>
+R<$+> <$*> <$- $-> <$*>		$@ <$1> <$5>
+
+######################################################################
+###  U: LookUpUser -- search for an entry in access database
+###
+###	lookup of key (which should be a local part) and
+###	variations if +detail exists: +* and without +detail
+###
+###	Parameters:
+###		<$1> -- key (user@)
+###		<$2> -- default (what to return if not found in db)
+###		<$3> -- mark (must be <(!|+) single-token>)
+###			! does lookup only with tag
+###			+ does lookup with and without tag
+###		<$4> -- passthru (additional data passed unchanged through)
+######################################################################
+
+SU
+R<$+> <$*> <$- $-> <$*>		$: <$(access $4:$1 $: ? $)> <$1> <$2> <$3 $4> <$5>
+R<?> <$+> <$*> <+ $-> <$*>	$: <$(access $1 $: ? $)> <$1> <$2> <+ $3> <$4>
+R<?> <$+ + $* @> <$*> <$- $-> <$*>
+			$: <$(access $5:$1+*@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6>
+R<?> <$+ + $* @> <$*> <+ $-> <$*>
+			$: <$(access $1+*@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5>
+R<?> <$+ + $* @> <$*> <$- $-> <$*>
+			$: <$(access $5:$1@ $: ? $)> <$1+$2@> <$3> <$4 $5> <$6>
+R<?> <$+ + $* @> <$*> <+ $-> <$*>
+			$: <$(access $1@ $: ? $)> <$1+$2@> <$3> <+ $4> <$5>
+R<?> <$+> <$*> <$- $-> <$*>	$@ <$2> <$5>
+R<$+ <TMPF>> <$*> <$- $-> <$*>	$@ <<TMPF>> <$5>
+R<$+> <$*> <$- $-> <$*>		$@ <$1> <$5>
+
+######################################################################
+###  SearchList: search a list of items in the access map
+###	Parameters:
+###		<exact tag> $| <mark:address> <mark:address> ... <>
+###	where "exact" is either "+" or "!":
+###	<+ TAG>	lookup with and w/o tag
+###	<! TAG>	lookup with tag
+###	possible values for "mark" are:
+###		D: recursive host lookup (LookUpDomain)
+###		E: exact lookup, no modifications
+###		F: full lookup, try user+ext@domain and user@domain
+###		U: user lookup, try user+ext and user (input must have trailing @)
+###	return: <RHS of lookup> or <?> (not found)
+######################################################################
+
+# class with valid marks for SearchList
+C{Src}E F D U 
+SSearchList
+# just call the ruleset with the name of the tag... nice trick...
+R<$+> $| <$={Src}:$*> <$*>	$: <$1> $| <$4> $| $>$2 <$3> <?> <$1> <>
+R<$+> $| <> $| <?> <>		$@ <?>
+R<$+> $| <$+> $| <?> <>		$@ $>SearchList <$1> $| <$2>
+R<$+> $| <$*> $| <$+> <>	$@ <$3>
+R<$+> $| <$+>			$@ <$2>
+
+
+######################################################################
+###  trust_auth: is user trusted to authenticate as someone else?
+###
+###	Parameters:
+###		$1: AUTH= parameter from MAIL command
+######################################################################
+
+SLocal_trust_auth
+Strust_auth
+R$*			$: $&{auth_type} $| $1
+# required by RFC 2554 section 4.
+R$@ $| $*		$#error $@ 5.7.1 $: "550 not authenticated"
+R$* $| $&{auth_authen}		$@ identical
+R$* $| <$&{auth_authen}>	$@ identical
+R$* $| $*		$: $1 $| $>"Local_trust_auth" $2
+R$* $| $#$*		$#$2
+R$*			$#error $@ 5.7.1 $: "550 " $&{auth_authen} " not allowed to act as " $&{auth_author}
+
+######################################################################
+###  Relay_Auth: allow relaying based on authentication?
+###
+###	Parameters:
+###		$1: ${auth_type}
+######################################################################
+SLocal_Relay_Auth
+
+######################################################################
+###  srv_features: which features to offer to a client?
+###	(done in server)
+######################################################################
+Ssrv_features
+R$*		$: $>D <$&{client_name}> <?> <! "Srv_Features"> <>
+R<?>$*		$: $>A <$&{client_addr}> <?> <! "Srv_Features"> <>
+R<?>$*		$: <$(access "Srv_Features": $: ? $)>
+R<?>$*		$@ OK
+R<$* <TMPF>>$*	$#temp
+R<$+>$*		$# $1
+
+######################################################################
+###  try_tls: try to use STARTTLS?
+###	(done in client)
+######################################################################
+Stry_tls
+R$*		$: $>D <$&{server_name}> <?> <! "Try_TLS"> <>
+R<?>$*		$: $>A <$&{server_addr}> <?> <! "Try_TLS"> <>
+R<?>$*		$: <$(access "Try_TLS": $: ? $)>
+R<?>$*		$@ OK
+R<$* <TMPF>>$*	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R<NO>$*		$#error $@ 5.7.1 $: "550 do not try TLS with " $&{server_name} " ["$&{server_addr}"]"
+
+######################################################################
+###  tls_rcpt: is connection with server "good" enough?
+###	(done in client, per recipient)
+###
+###	Parameters:
+###		$1: recipient
+######################################################################
+Stls_rcpt
+R$*			$: $(macro {TLS_Name} $@ $&{server_name} $) $1
+R$+			$: <?> $>CanonAddr $1
+R<?> $+ < @ $+ . >	<?> $1 <@ $2 >
+R<?> $+ < @ $+ >	$: $1 <@ $2 > $| <F:$1@$2> <U:$1@> <D:$2> <E:>
+R<?> $+			$: $1 $| <U:$1@> <E:>
+R$* $| $+	$: $1 $| $>SearchList <! "TLS_Rcpt"> $| $2 <>
+R$* $| <?>	$@ OK
+R$* $| <$* <TMPF>>	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R$* $| <$+>	$@ $>"TLS_connection" $&{verify} $| <$2>
+
+######################################################################
+###  tls_client: is connection with client "good" enough?
+###	(done in server)
+###
+###	Parameters:
+###		${verify} $| (MAIL|STARTTLS)
+######################################################################
+Stls_client
+R$*		$: $(macro {TLS_Name} $@ $&{client_name} $) $1
+R$* $| $*	$: $1 $| $>D <$&{client_name}> <?> <! "TLS_Clt"> <>
+R$* $| <?>$*	$: $1 $| $>A <$&{client_addr}> <?> <! "TLS_Clt"> <>
+R$* $| <?>$*	$: $1 $| <$(access "TLS_Clt": $: ? $)>
+R$* $| <$* <TMPF>>	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R$*		$@ $>"TLS_connection" $1
+
+######################################################################
+###  tls_server: is connection with server "good" enough?
+###	(done in client)
+###
+###	Parameter:
+###		${verify}
+######################################################################
+Stls_server
+R$*		$: $(macro {TLS_Name} $@ $&{server_name} $) $1
+R$*		$: $1 $| $>D <$&{server_name}> <?> <! "TLS_Srv"> <>
+R$* $| <?>$*	$: $1 $| $>A <$&{server_addr}> <?> <! "TLS_Srv"> <>
+R$* $| <?>$*	$: $1 $| <$(access "TLS_Srv": $: ? $)>
+R$* $| <$* <TMPF>>	$#error $@ 4.3.0 $: "451 Temporary system failure. Please try again later."
+R$*		$@ $>"TLS_connection" $1
+
+######################################################################
+###  TLS_connection: is TLS connection "good" enough?
+###
+###	Parameters:
+###		${verify} $| <Requirement> [<>]
+###		Requirement: RHS from access map, may be ? for none.
+######################################################################
+STLS_connection
+R$* $| <$*>$*			$: $1 $| <$2>
+# create the appropriate error codes
+R$* $| <PERM + $={Tls} $*>	$: $1 $| <503:5.7.0> <$2 $3>
+R$* $| <TEMP + $={Tls} $*>	$: $1 $| <403:4.7.0> <$2 $3>
+R$* $| <$={Tls} $*>		$: $1 $| <403:4.7.0> <$2 $3>
+# deal with TLS handshake failures: abort
+RSOFTWARE $| <$-:$+> $* 	$#error $@ $2 $: $1 " TLS handshake failed."
+RSOFTWARE $| $* 		$#error $@ 4.7.0 $: "403 TLS handshake failed."
+# deal with TLS protocol errors: abort
+RPROTOCOL $| <$-:$+> $* 	$#error $@ $2 $: $1 " STARTTLS failed."
+RPROTOCOL $| $* 		$#error $@ 4.7.0 $: "403 STARTTLS failed."
+R$* $| <$*> <VERIFY>		$: <$2> <VERIFY> <> $1
+R$* $| <$*> <VERIFY + $+>	$: <$2> <VERIFY> <$3> $1
+R$* $| <$*> <$={Tls}:$->$*	$: <$2> <$3:$4> <> $1
+R$* $| <$*> <$={Tls}:$- + $+>$*	$: <$2> <$3:$4> <$5> $1
+R$* $| $*			$@ OK
+# authentication required: give appropriate error
+# other side did authenticate (via STARTTLS)
+R<$*><VERIFY> <> OK		$@ OK
+R<$*><VERIFY> <$+> OK		$: <$1> <REQ:0> <$2>
+R<$*><VERIFY:$-> <$*> OK	$: <$1> <REQ:$2> <$3>
+R<$*><ENCR:$-> <$*> $*		$: <$1> <REQ:$2> <$3>
+R<$-:$+><VERIFY $*> <$*>	$#error $@ $2 $: $1 " authentication required"
+R<$-:$+><VERIFY $*> <$*> FAIL	$#error $@ $2 $: $1 " authentication failed"
+R<$-:$+><VERIFY $*> <$*> NO	$#error $@ $2 $: $1 " not authenticated"
+R<$-:$+><VERIFY $*> <$*> NOT	$#error $@ $2 $: $1 " no authentication requested"
+R<$-:$+><VERIFY $*> <$*> NONE	$#error $@ $2 $: $1 " other side does not support STARTTLS"
+R<$-:$+><VERIFY $*> <$*> $+	$#error $@ $2 $: $1 " authentication failure " $4
+R<$*><REQ:$-> <$*>		$: <$1> <REQ:$2> <$3> $>max $&{cipher_bits} : $&{auth_ssf}
+R<$*><REQ:$-> <$*> $-		$: <$1> <$2:$4> <$3> $(arith l $@ $4 $@ $2 $)
+R<$-:$+><$-:$-> <$*> TRUE	$#error $@ $2 $: $1 " encryption too weak " $4 " less than " $3
+R<$-:$+><$-:$-> <$*> $*		$: <$1:$2 ++ $5>
+R<$-:$+ ++ >			$@ OK
+R<$-:$+ ++ $+ >			$: <$1:$2> <$3>
+R<$-:$+> < $+ ++ $+ >		<$1:$2> <$3> <$4>
+R<$-:$+> $+			$@ $>"TLS_req" $3 $| <$1:$2>
+
+######################################################################
+###  TLS_req: check additional TLS requirements
+###
+###	Parameters: [<list> <of> <req>] $| <$-:$+>
+###		$-: SMTP reply code
+###		$+: Enhanced Status Code
+######################################################################
+STLS_req
+R $| $+		$@ OK
+R<CN> $* $| <$+>		$: <CN:$&{TLS_Name}> $1 $| <$2>
+R<CN:$&{cn_subject}> $* $| <$+>		$@ $>"TLS_req" $1 $| <$2>
+R<CN:$+> $* $| <$-:$+>	$#error $@ $4 $: $3 " CN " $&{cn_subject} " does not match " $1
+R<CS:$&{cert_subject}> $* $| <$+>	$@ $>"TLS_req" $1 $| <$2>
+R<CS:$+> $* $| <$-:$+>	$#error $@ $4 $: $3 " Cert Subject " $&{cert_subject} " does not match " $1
+R<CI:$&{cert_issuer}> $* $| <$+>	$@ $>"TLS_req" $1 $| <$2>
+R<CI:$+> $* $| <$-:$+>	$#error $@ $4 $: $3 " Cert Issuer " $&{cert_issuer} " does not match " $1
+ROK			$@ OK
+
+######################################################################
+###  max: return the maximum of two values separated by :
+###
+###	Parameters: [$-]:[$-]
+######################################################################
+Smax
+R:		$: 0
+R:$-		$: $1
+R$-:		$: $1
+R$-:$-		$: $(arith l $@ $1 $@ $2 $) : $1 : $2
+RTRUE:$-:$-	$: $2
+R$-:$-:$-	$: $2
+
+
+######################################################################
+###  RelayTLS: allow relaying based on TLS authentication
+###
+###	Parameters:
+###		none
+######################################################################
+SRelayTLS
+# authenticated?
+R$*			$: <?> $&{verify}
+R<?> OK			$: OK		authenticated: continue
+R<?> $*			$@ NO		not authenticated
+R$*			$: $&{cert_issuer}
+R$+			$: $(access CERTISSUER:$1 $)
+RRELAY			$# RELAY
+RSUBJECT		$: <@> $&{cert_subject}
+R<@> $+			$: <@> $(access CERTSUBJECT:$1 $)
+R<@> RELAY		$# RELAY
+R$*			$: NO
+
+######################################################################
+###  authinfo: lookup authinfo in the access map
+###
+###	Parameters:
+###		$1: {server_name}
+###		$2: {server_addr}
+######################################################################
+Sauthinfo
+R$*		$: $1 $| $>D <$&{server_name}> <?> <! AuthInfo> <>
+R$* $| <?>$*	$: $1 $| $>A <$&{server_addr}> <?> <! AuthInfo> <>
+R$* $| <?>$*	$: $1 $| <$(access AuthInfo: $: ? $)> <>
+R$* $| <?>$*	$@ no				no authinfo available
+R$* $| <$*> <>	$# $2
+
+
+
+
+
+#
+######################################################################
+######################################################################
+#####
+#####			MAIL FILTER DEFINITIONS
+#####
+######################################################################
+######################################################################
+
+#
+######################################################################
+######################################################################
+#####
+#####			MAILER DEFINITIONS
+#####
+######################################################################
+######################################################################
+
+#####################################
+###   SMTP Mailer specification   ###
+#####################################
+
+#####  $Id: smtp.m4,v 8.65 2006/07/12 21:08:10 ca Exp $  #####
+
+#
+#  common sender and masquerading recipient rewriting
+#
+SMasqSMTP
+R$* < @ $* > $*		$@ $1 < @ $2 > $3		already fully qualified
+R$+			$@ $1 < @ *LOCAL* >		add local qualification
+
+#
+#  convert pseudo-domain addresses to real domain addresses
+#
+SPseudoToReal
+
+# pass <route-addr>s through
+R< @ $+ > $*		$@ < @ $1 > $2			resolve <route-addr>
+
+# output fake domains as user%fake@relay
+
+# do UUCP heuristics; note that these are shared with UUCP mailers
+R$+ < @ $+ .UUCP. >	$: < $2 ! > $1			convert to UUCP form
+R$+ < @ $* > $*		$@ $1 < @ $2 > $3		not UUCP form
+
+# leave these in .UUCP form to avoid further tampering
+R< $&h ! > $- ! $+	$@ $2 < @ $1 .UUCP. >
+R< $&h ! > $-.$+ ! $+	$@ $3 < @ $1.$2 >
+R< $&h ! > $+		$@ $1 < @ $&h .UUCP. >
+R< $+ ! > $+		$: $1 ! $2 < @ $Y >		use UUCP_RELAY
+R$+ < @ $~[ $* : $+ >	$@ $1 < @ $4 >			strip mailer: part
+R$+ < @ >		$: $1 < @ *LOCAL* >		if no UUCP_RELAY
+
+
+#
+#  envelope sender rewriting
+#
+SEnvFromSMTP
+R$+			$: $>PseudoToReal $1		sender/recipient common
+R$* :; <@>		$@				list:; special case
+R$*			$: $>MasqSMTP $1		qualify unqual'ed names
+R$+			$: $>MasqEnv $1			do masquerading
+
+
+#
+#  envelope recipient rewriting --
+#  also header recipient if not masquerading recipients
+#
+SEnvToSMTP
+R$+			$: $>PseudoToReal $1		sender/recipient common
+R$+			$: $>MasqSMTP $1		qualify unqual'ed names
+R$* < @ *LOCAL* > $*	$: $1 < @ $j . > $2
+
+#
+#  header sender and masquerading header recipient rewriting
+#
+SHdrFromSMTP
+R$+			$: $>PseudoToReal $1		sender/recipient common
+R:; <@>			$@				list:; special case
+
+# do special header rewriting
+R$* <@> $*		$@ $1 <@> $2			pass null host through
+R< @ $* > $*		$@ < @ $1 > $2			pass route-addr through
+R$*			$: $>MasqSMTP $1		qualify unqual'ed names
+R$+			$: $>MasqHdr $1			do masquerading
+
+
+#
+#  relay mailer header masquerading recipient rewriting
+#
+SMasqRelay
+R$+			$: $>MasqSMTP $1
+R$+			$: $>MasqHdr $1
+
+Msmtp,		P=[IPC], F=mDFMuX, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
+		T=DNS/RFC822/SMTP,
+		A=TCP $h
+Mesmtp,		P=[IPC], F=mDFMuXa, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
+		T=DNS/RFC822/SMTP,
+		A=TCP $h
+Msmtp8,		P=[IPC], F=mDFMuX8, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
+		T=DNS/RFC822/SMTP,
+		A=TCP $h
+Mdsmtp,		P=[IPC], F=mDFMuXa%, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP, E=\r\n, L=990,
+		T=DNS/RFC822/SMTP,
+		A=TCP $h
+Mrelay,		P=[IPC], F=mDFMuXa8, S=EnvFromSMTP/HdrFromSMTP, R=MasqSMTP, E=\r\n, L=2040,
+		T=DNS/RFC822/SMTP,
+		A=TCP $h
+
+
+######################*****##############
+###   PROCMAIL Mailer specification   ###
+##################*****##################
+
+#####  $Id: procmail.m4,v 8.22 2001/11/12 23:11:34 ca Exp $  #####
+
+Mprocmail,	P=/usr/bin/procmail, F=DFMSPhnu9, S=EnvFromSMTP/HdrFromSMTP, R=EnvToSMTP/HdrFromSMTP,
+		T=DNS/RFC822/X-Unix,
+		A=procmail -Y -m $h $f $u
+
+
+##################################################
+###   Local and Program Mailer specification   ###
+##################################################
+
+#####  $Id: local.m4,v 8.59 2004/11/23 00:37:25 ca Exp $  #####
+
+#
+#  Envelope sender rewriting
+#
+SEnvFromL
+R<@>			$n			errors to mailer-daemon
+R@ <@ $*>		$n			temporarily bypass Sun bogosity
+R$+			$: $>AddDomain $1	add local domain if needed
+R$*			$: $>MasqEnv $1		do masquerading
+
+#
+#  Envelope recipient rewriting
+#
+SEnvToL
+R$+ < @ $* >		$: $1			strip host part
+
+#
+#  Header sender rewriting
+#
+SHdrFromL
+R<@>			$n			errors to mailer-daemon
+R@ <@ $*>		$n			temporarily bypass Sun bogosity
+R$+			$: $>AddDomain $1	add local domain if needed
+R$*			$: $>MasqHdr $1		do masquerading
+
+#
+#  Header recipient rewriting
+#
+SHdrToL
+R$+			$: $>AddDomain $1	add local domain if needed
+R$* < @ *LOCAL* > $*	$: $1 < @ $j . > $2
+
+#
+#  Common code to add local domain name (only if always-add-domain)
+#
+SAddDomain
+R$* < @ $* > $* 	$@ $1 < @ $2 > $3	already fully qualified
+
+R$+			$@ $1 < @ *LOCAL* >	add local qualification
+
+Mlocal,		P=/usr/bin/procmail, F=lsDFMAw5:/|@qSPfhn9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL,
+		T=DNS/RFC822/X-Unix,
+		A=procmail -t -Y -a $h -d $u
+Mprog,		P=/usr/sbin/smrsh, F=lsDFMoqeu9, S=EnvFromL/HdrFromL, R=EnvToL/HdrToL, D=$z:/,
+		T=X-Unix/X-Unix/X-Unix,
+		A=smrsh -c $u
+
Index: /branches/rel_avx_2_7_2/src/library/ca_mail/sys_mail.h
===================================================================
--- /branches/rel_avx_2_7_2/src/library/ca_mail/sys_mail.h	(revision 0)
+++ /branches/rel_avx_2_7_2/src/library/ca_mail/sys_mail.h	(working copy)
@@ -0,0 +1,110 @@
+#ifndef _SYS_MAIL_H_
+#define _SYS_MAIL_H_
+
+#define SYS_MAIL_SHM_MODE               SHM_R|SHM_W
+#define SYS_MAIL_SHM_SZ                	sizeof(sys_mail_conf_t)
+
+#define MAX_MAIL_FROM_LEN               256
+#define MAX_MAIL_HOSTNAME_LEN           128
+
+#define DEF_MAIL_FROM                   "%h<alert@log.domain>"
+#define DEF_MAIL_HOSTNAME               "%l.alert_pseudo_domain"
+
+#define SENDMAIL_HOSTNAME_DEF           "Dj"
+#define SENDMAIL_CONF_FILE              "/etc/mail/sendmail.cf"
+#define SENDMAIL_CONF_NEW_FILE          "/etc/mail/sendmail.cf.new"
+#define SENDMAIL_ORI_CONF_FILE          "/ca/etc/sendmail.cf"
+
+#ifdef UOS_X86
+#define SSMTP_SCRIPT                    "/ca/bin/msmtp_config.pl"
+#define SSMTP_CONF_DEF			        "/ca/etc/msmtp.conf.def"
+#define SSMTP_CONF			            "/etc/msmtprc"
+
+#else
+#define SSMTP_SCRIPT                    "/ca/bin/ssmtp_config.pl"
+#define SSMTP_CONF_DEF			        "/ca/etc/ssmtp.conf.def"
+#define SSMTP_CONF			            "/etc/ssmtp/ssmtp.conf"
+
+#endif
+
+
+
+
+/*
+* QinXing 2005-7-26 bug 10914
+* define mailertable file and path
+*/
+#define ERR_RELAY_ADD           "Error occurred when add a relay server!"
+#define ERR_RELAY_DEL           "Error occurred when delete a relay server!"
+#define MAILERTABLE_FILE        "/etc/mail/mailertable"
+#define MAILERTABLE_FILE_NEW    "/etc/mail/mailertable.new"
+#define MAILERTABLE_DB          "/etc/mail/mailertable.db"
+#define ENCRYPT_PASSWD_PREFIX	"XXXXXXXXX"
+#define ENCRYPT_PASSWD_PREFIX_LEN sizeof(ENCRYPT_PASSWD_PREFIX) - 1
+#define MAX_MAIL_RELAY_NUM      10
+#define MAX_MAIL_RELAY_HOSTNAME_LEN 50
+#define MAX_MAIL_RELAY_SERVER 30
+#define MAX_MAIL_EXTERN_SERVER_LEN 64
+#define MAX_MAIL_USER_LEN 32
+#define MAX_MAIL_PASSWD_LEN 64
+#define MAX_MAIL_ENCRPT_PASSWD_LEN ENCRYPT_PASSWD_PREFIX_LEN + 128
+
+/* end add define bug 10914 QinXing*/
+/*
+* QinXing 2005-7-26 bug 10914
+* add structs for relay server & status
+*/
+typedef struct _mail_relay_status_t{
+        int relay_status;
+        int relay_num;
+}mail_relay_status_t;
+
+typedef struct _mail_relay_server_t{
+        char hostname[MAX_MAIL_RELAY_HOSTNAME_LEN+1];
+        char relayserver[MAX_MAIL_RELAY_SERVER+1];
+}mail_relay_server_t;
+
+typedef struct _mail_extern_server_t{
+        char extern_server[MAX_MAIL_EXTERN_SERVER_LEN+1];
+        int port;
+        char user[MAX_MAIL_USER_LEN+1];
+        char passwd[MAX_MAIL_ENCRPT_PASSWD_LEN+1];
+        int use_ssl;
+}mail_extern_server_t;
+
+/*end 10914*/
+
+typedef struct sys_mail_conf {
+        char from[MAX_MAIL_FROM_LEN+1];
+        char hostname[MAX_MAIL_HOSTNAME_LEN+1];
+        unsigned int hostname_behavior;    /* bug73086, special case, 0 is default behavior on 8.6, 1 is keep pace with 8.5.*/
+        /*
+         * QinXing 2005-8-1 bug 10914
+         * Add structs for relay server % status
+         */
+        mail_relay_status_t mrelay_status;
+        mail_relay_server_t mrelay_server[MAX_MAIL_RELAY_NUM];
+        /* end add for 10914 */
+        int extern_mail_on;
+        mail_extern_server_t mextern_server; 
+} sys_mail_conf_t;
+
+int system_mail_external_on(void);
+
+/*
+* QinXing 2005-7-26 bug 10914
+* add new CLI reference function
+*/
+char *write_system_mail_relay(char *segment);
+int clear_system_mail_relay(void);
+int system_mail_relay_on(void);
+int system_mail_relay_off(void);
+int system_mail_relay_server_add(char *relayhostname, char *relayserver);
+int system_mail_relay_server_del(char *relayhostname);
+int show_system_mail_relay(void);
+
+char *write_system_mail_conf(char *segment);
+int clear_system_mail_conf(void);
+extern int sysmail_get_domainame(char * output, size_t len);
+
+#endif

Property changes on: src/library/ca_mail/sys_mail.h
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/rel_avx_2_7_2/src/library/ca_mail/sys_mail.c
===================================================================
--- /branches/rel_avx_2_7_2/src/library/ca_mail/sys_mail.c	(revision 0)
+++ /branches/rel_avx_2_7_2/src/library/ca_mail/sys_mail.c	(working copy)
@@ -0,0 +1,1523 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#if !defined(__linux__)
+#include <machine/param.h>
+#endif
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "../../proxy_shm.h"
+#include "sys_mail.h"
+#include "../management/suppress_print.h"
+#include "../ca_util/ca_util.h"
+
+extern int set_node_name(char *name, int id);
+
+sys_mail_conf_t *attach_sys_mail_conf(void);
+void detach_sys_mail_conf(sys_mail_conf_t *conf_p);
+int check_from_string(char *from_str);
+int check_hostname_string(char *hostname);
+int write_fqdn_to_file(void);
+int write_hostname_to_file(char *hostname);
+
+/*
+ * QinXing 2005-7-28 bug 10914
+ */
+int check_servername_relay(char *relayhostname);
+int check_ip_valid(char *address);
+char *system_mail_relay_get_config(void);
+int check_external_mail_string(char *name);
+int ssmtp_conf_file_update(sys_mail_conf_t *conf_p);
+
+#define RANDOM_KEY 	"sfG{[5+/au"
+#define WRITE_STR_LEN	1024
+
+#define CHARACTER_VALID		0
+#define CHARACTER_INVALID	1
+
+int
+check_servername_relay(char * relayserver)
+{
+    int i;
+    i = strlen(relayserver);
+    if( ((relayserver[i-1] < 48) || (relayserver[i-1]) > 57 ) && (relayserver[i-1] != '.')){
+        return 2;             
+    } else {
+        if(check_ip_valid(relayserver) != 0){
+                return -1;
+        }
+        return 1;
+    }
+}
+
+int 
+check_ip_valid(char *address)
+{
+    struct sockaddr_in ina;
+              
+    if( (ina.sin_addr.s_addr = inet_addr(address)) == -1){
+	if(cli_interactive()){
+        	printf("The address is invalid!\n");
+	}
+        return -1;
+    }
+        return 0;     
+} 
+
+int
+system_mail_relay_server_add(char *relayhostname, char *relayserver)
+{
+	FILE *mailertable_new_fpw;
+	sys_mail_conf_t *conf_p = attach_sys_mail_conf();
+	char *ptradd = system_mail_relay_get_config();
+	int i,j;
+
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not add mail relay config (Internal error - 1)\n");
+		}
+		if(ptradd){
+			free(ptradd);
+			ptradd = NULL;
+		}
+		return -1;
+	}
+
+	if( strlen(relayhostname) > MAX_MAIL_RELAY_HOSTNAME_LEN)	{
+		if(cli_interactive()){
+			printf("The length of hostname is over %d!\n", MAX_MAIL_RELAY_HOSTNAME_LEN);
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptradd){             
+                        free(ptradd);
+                        ptradd = NULL;
+                }
+		return -1;
+	}
+	if( strlen(relayserver) > MAX_MAIL_RELAY_SERVER){
+		if(cli_interactive()){
+			printf("The length of relayserver is over %d!\n", MAX_MAIL_RELAY_SERVER);
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptradd){             
+                        free(ptradd);
+                        ptradd = NULL;
+                }
+		return -1;
+	}	
+
+	for(i=0;i<MAX_MAIL_RELAY_NUM;i++){
+		if( strcasecmp(relayhostname, conf_p->mrelay_server[i].hostname) == 0)	{
+			if(cli_interactive()){
+				printf("The host is exist!\n");
+			}
+			detach_sys_mail_conf(conf_p);
+			if(ptradd){             
+        	                free(ptradd);
+                	        ptradd = NULL;
+               		}
+			return -1;
+		}
+		if( strlen(conf_p->mrelay_server[i].hostname) <= 0)	{
+			break;
+		}
+	}
+
+	j = check_servername_relay(relayserver);	
+
+	if( j == 1)	{
+		strcat(conf_p->mrelay_server[i].relayserver, "[");
+		strcat(conf_p->mrelay_server[i].relayserver, relayserver);
+		strcat(conf_p->mrelay_server[i].relayserver, "]");
+	}
+	if(j == 2)	{
+		strcpy( conf_p->mrelay_server[i].relayserver, relayserver);
+	}
+	if(j == -1){	
+		if(cli_interactive()){
+			printf("%s", ERR_RELAY_ADD);
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptradd){             
+        	        free(ptradd);
+                        ptradd = NULL;
+               	}
+		return -1;
+	}
+	
+	strcpy(conf_p->mrelay_server[i].hostname, relayhostname);
+	
+	if((mailertable_new_fpw = fopen(MAILERTABLE_FILE_NEW, "w")) == NULL){
+		if(cli_interactive()){
+			printf("Can not open file %s !", MAILERTABLE_FILE_NEW);
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptradd){             
+        	        free(ptradd);
+                        ptradd = NULL;
+               	}
+		return -1;
+	}
+
+	if(ptradd == NULL){
+		fprintf(mailertable_new_fpw, "%s     smtp:%s\n", conf_p->mrelay_server[i].hostname, conf_p->mrelay_server[i].relayserver);
+	}else {
+		for(i=0;i<MAX_MAIL_RELAY_NUM;i++){
+			if( strlen(conf_p->mrelay_server[i].hostname) <= 0)	{
+				break;
+			}
+			fprintf(mailertable_new_fpw, "%s     smtp:%s\n", conf_p->mrelay_server[i].hostname, conf_p->mrelay_server[i].relayserver);
+		}
+	} 
+	fclose(mailertable_new_fpw);
+
+	unlink(MAILERTABLE_FILE);
+	unlink(MAILERTABLE_DB);
+
+	if(rename(MAILERTABLE_FILE_NEW, MAILERTABLE_FILE) == -1){
+		detach_sys_mail_conf(conf_p);
+		if(ptradd){             
+        	        free(ptradd);
+                        ptradd = NULL;
+               	}
+		return -1;
+	}
+
+	if(conf_p->mrelay_status.relay_status == 1) {
+		/*printf("Mail relay module is on\n");*/
+		if( system("/usr/sbin/makemap hash " MAILERTABLE_DB " < " MAILERTABLE_FILE) != 0) {
+			detach_sys_mail_conf(conf_p);
+			if(ptradd) {
+				free(ptradd);
+				ptradd = NULL;
+			}
+			return -1;
+		}
+	}
+
+	conf_p->mrelay_status.relay_num += 1;
+
+	/*
+	i = strlen(relayserver) +50;
+	chadd = (char*)malloc(i*sizeof(char));
+	strcat(chadd, "The relay server ");
+	strcat(chadd, relayserver);
+	strcat(chadd, " was configured successfully!")
+	*/
+	if(ptradd) {
+		free(ptradd);
+		ptradd = NULL;
+	}
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+system_mail_relay_server_del(char * relayhostname)
+{
+	FILE *mailertable_new_fpw;
+	sys_mail_conf_t *conf_p = NULL;
+	char *ptrdel = system_mail_relay_get_config();
+	int i, j, k;
+	
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not del mail relay config (Internal error - 1)\n");
+		}
+		if(ptrdel){
+			free(ptrdel);
+			ptrdel = NULL;
+		}
+		return -1;
+	}
+
+	if(ptrdel == NULL){
+		if(cli_interactive()){
+			printf("Relay host %s was not configured", relayhostname);
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptrdel){
+			free(ptrdel);
+			ptrdel = NULL;
+		}
+		return -1;
+	}
+
+	if((mailertable_new_fpw = fopen(MAILERTABLE_FILE_NEW, "w")) == NULL){
+		if(cli_interactive()){
+			printf("Can not open file %s !", MAILERTABLE_FILE_NEW);
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptrdel){
+			free(ptrdel);
+			ptrdel = NULL;
+		}
+		return -1;
+	}
+
+	j = -1;
+	k = -1;
+	for( i = 0; i < MAX_MAIL_RELAY_NUM; i++ ){
+		if(strlen(conf_p->mrelay_server[i].hostname) <= 0){
+			if(j < 0){
+				if(cli_interactive()){
+					printf("Can not find the record, the relay host has not been configured!!");
+				}
+				detach_sys_mail_conf(conf_p);
+				return -1;
+			}
+			break;
+		}
+		if(strcasecmp(relayhostname, conf_p->mrelay_server[i].hostname) != 0){
+			fprintf(mailertable_new_fpw, "%s     smtp:%s\n", conf_p->mrelay_server[i].hostname, conf_p->mrelay_server[i].relayserver);
+			k++;
+		}else{
+			j = i;
+		}
+	}
+
+	fclose(mailertable_new_fpw);
+
+	unlink(MAILERTABLE_FILE);
+	unlink(MAILERTABLE_DB);
+
+	if(rename(MAILERTABLE_FILE_NEW, MAILERTABLE_FILE) == -1){
+		detach_sys_mail_conf(conf_p);
+		if(ptrdel){
+			free(ptrdel);
+			ptrdel = NULL;
+		}
+		return -1;
+	}
+
+	/*mailertable text is empty*/
+	if(k < 0) {
+		system_mail_relay_off();
+		conf_p->mrelay_status.relay_num = 0;
+		conf_p->mrelay_status.relay_status = 0;
+	}
+
+	if(conf_p->mrelay_status.relay_status == 1) {
+		/*printf("Mail relay module is on\n");*/
+		if( system("/usr/sbin/makemap hash " MAILERTABLE_DB " < " MAILERTABLE_FILE) != 0) {
+			detach_sys_mail_conf(conf_p);
+			if(ptrdel) {
+				free(ptrdel);
+				ptrdel = NULL;
+			}
+			return -1;
+		}
+	}
+
+	if(ptrdel)	{
+		free(ptrdel);
+		ptrdel = NULL;
+	}
+
+	/*
+	i = strlen(relayserver) +100;
+	chadd = (char*)malloc(i*sizeof(char));
+	strcat(chadd, "The relay configuration record ");
+	strcat(chadd, conf_p->mrelay_server[j].hostname);
+	strcat(chadd, " ");
+	strcat(chadd, conf_p->mrelay_server[j].relayserver);
+	strcat(chadd, " ");
+	strcat(chadd, " was deleted successfully!")
+	*/
+	
+	
+	detach_sys_mail_conf(conf_p);
+	return 0;
+	
+}
+
+char *
+write_system_mail_relay(char *segment)
+{
+	sys_mail_conf_t *conf_p = NULL;
+	char *ptrwri = system_mail_relay_get_config(); 
+	char *currptr, *saveptr;
+	char p[MAX_MAIL_RELAY_SERVER+1];
+	char *p1,*p2;
+	int i;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not write mail relay config (Internal error - 1)\n");
+		}
+		if(ptrwri){
+			free(ptrwri);
+			ptrwri = NULL;
+		}
+		return NULL;
+	}
+
+	saveptr = (char *) malloc(50*(sizeof(conf_p->mrelay_server) + 20) +30);
+	if (saveptr == NULL) {
+		if(cli_interactive()){
+			printf("malloc error\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptrwri){
+			free(ptrwri);
+			ptrwri = NULL;
+		}
+		return NULL;
+	}
+	currptr = saveptr;	
+
+	for( i = 0; i< MAX_MAIL_RELAY_NUM; i++)	{
+		if(strlen(conf_p->mrelay_server[i].hostname) <= 0){
+			break;
+		} else {
+			if(conf_p->mrelay_server[i].relayserver[0] != '[')	{
+				currptr += sprintf(currptr, "system mail relay server \"%s\" \"%s\"\n", conf_p->mrelay_server[i].hostname, conf_p->mrelay_server[i].relayserver);
+			}else{
+				p1 = &(conf_p->mrelay_server[i].relayserver[1]);
+				if ((p2 = strstr(conf_p->mrelay_server[i].relayserver, "]")) == NULL){
+					if(cli_interactive()){
+						printf("The relay server format is error!");
+					}
+					detach_sys_mail_conf(conf_p);
+					if(ptrwri){
+						free(ptrwri);
+						ptrwri = NULL;
+					}
+					/* Bug 17427, huangyf, 20071113 */
+					free(saveptr);
+					/* Bug 17427, end */
+					return NULL;
+				}else{
+					memcpy(p, p1, (p2 - p1));
+					p[p2-p1] = '\0';
+					currptr += sprintf(currptr, "system mail relay server \"%s\" \"%s\"\n", conf_p->mrelay_server[i].hostname, p);
+				/*	
+					if(p)
+					{
+						free(p);
+						p = NULL;
+					}
+					*/
+				}
+
+			}
+		}
+	}
+
+	if(conf_p->mrelay_status.relay_status == 1)	{
+		currptr += sprintf(currptr, "system mail relay %s\n", "on");
+	}else{
+		currptr += sprintf(currptr, "system mail relay %s\n", "off");
+
+	}
+
+	*currptr = '\0';
+	
+	if(ptrwri)	{
+		free(ptrwri);
+		ptrwri = NULL;
+	}
+	detach_sys_mail_conf(conf_p);		
+	return(saveptr);
+}
+
+int
+system_mail_relay_off(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not turn off mail relay (Internal error - 1)\n");
+		}
+		return -1;
+	}
+	if( system("rm -f " MAILERTABLE_DB) != 0){
+		if(cli_interactive()){
+			printf("Can not delete the db file for relay server!");
+		}
+		return -1;
+	}
+
+	conf_p->mrelay_status.relay_status = 0;
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+int
+system_mail_relay_on(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+	char *ptron = system_mail_relay_get_config();
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not turn on mail relay (Internal error - 1)\n");
+		}
+		if(ptron){
+			free(ptron);
+			ptron = NULL;
+		}
+		return -1;
+	}
+
+	if(ptron == NULL){
+		if(cli_interactive()){
+			printf("No configured relay server!\n");
+		}
+		conf_p->mrelay_status.relay_status = 0;
+		detach_sys_mail_conf(conf_p);
+		if(ptron){
+			free(ptron);
+			ptron = NULL;
+		}
+		return -1;
+	}
+	
+	if( system("/usr/sbin/makemap hash " MAILERTABLE_DB " < " MAILERTABLE_FILE) != 0) {
+		if(cli_interactive()){
+			printf("Can not enable the relay servers!\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		if(ptron){
+			free(ptron);
+			ptron = NULL;
+		}
+		return -1;
+	}
+
+	if(ptron)	{
+		free(ptron);
+		ptron = NULL;
+	}
+	
+	conf_p->mrelay_status.relay_status = 1;
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+system_mail_external_on(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not turn on external mail(Internal error - 1)\n");
+		}
+		return -1;
+	}
+
+	if (conf_p->mextern_server.extern_server[0] == '\0') {
+		if (cli_interactive()) {
+			printf("Please config an external mail server first.\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	}
+
+	conf_p->extern_mail_on = 1;
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+system_mail_external_off(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not turn off external mail(Internal error - 1)\n");
+		}
+		return -1;
+	}
+
+	conf_p->extern_mail_on = 0;
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+system_mail_external_server(char *server_addr, uint16_t port, uint16_t use_ssl)
+{
+	char tmp_addr[MAX_MAIL_EXTERN_SERVER_LEN + sizeof(":65535")];
+	sys_mail_conf_t *conf_p = NULL;
+
+	if (server_addr == NULL || server_addr[0] == '\0') {
+		if (cli_interactive()) {
+			printf("server_address can not be NULL or empty\n");
+		}
+		return -1;
+	}
+
+	if (strlen(server_addr) > MAX_MAIL_EXTERN_SERVER_LEN) {
+		if (cli_interactive()) {
+			printf("server_address exceeds the length limit: %d\n", MAX_MAIL_EXTERN_SERVER_LEN);
+		}
+		return -1;
+	}
+
+	if (check_external_mail_string(server_addr) == CHARACTER_INVALID) {
+		return -1;
+	}
+
+	if (snprintf(tmp_addr, sizeof(tmp_addr), "%s:%u", server_addr, port) >= sizeof(tmp_addr)) {
+		if (cli_interactive()) {
+			printf("server_address:port exceeds the length limit: %lu\n", sizeof(tmp_addr));
+		}
+		return -1;
+	}
+
+	if (use_ssl != 0 && use_ssl != 1) {
+		if (cli_interactive()) {
+			printf("This ssl flag can only be 0 or 1\n");
+		}
+		return -1;
+	}
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 1)\n");
+		}
+		return -1;
+	}
+	ssmtp_conf_file_update(conf_p);
+
+	char cmd[256];
+	#ifdef UOS_X86
+	snprintf(cmd, sizeof(cmd), "%s edit_server %s %hu %u", SSMTP_SCRIPT, server_addr, port, use_ssl);
+	#else
+	snprintf(cmd, sizeof(cmd), "%s edit_server %s %u", SSMTP_SCRIPT, tmp_addr, use_ssl);
+    #endif
+	
+	if (system(cmd)) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 2)\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	}
+
+	strcpy(conf_p->mextern_server.extern_server, server_addr);
+	conf_p->mextern_server.port = port;
+	conf_p->mextern_server.use_ssl = use_ssl;
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+system_mail_external_user(char *user, char *passwd)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	if (user == NULL || user[0] == '\0' || passwd == NULL || passwd[0] == '\0') {
+		if (cli_interactive()) {
+			printf("user and password can not be NULL or empty\n");
+		}
+		return -1;
+	}
+
+	if (strlen(user) > MAX_MAIL_USER_LEN) {
+		if (cli_interactive()) {
+			printf("user name %s exceeds the length limit: %d\n", user, MAX_MAIL_USER_LEN);
+		}
+		return -1;
+	}
+
+	if (check_external_mail_string(user) == CHARACTER_INVALID) {
+		return -1;
+	}
+
+	if (check_external_mail_string(passwd) == CHARACTER_INVALID) {
+		return -1;
+	}
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 1)\n");
+		}
+		return -1;
+	}
+	ssmtp_conf_file_update(conf_p);
+
+	int input_from_ca = 0;
+	char orig_passwd[MAX_MAIL_PASSWD_LEN + 1];
+	char mask_passwd[MAX_MAIL_ENCRPT_PASSWD_LEN + 1];
+	strcpy(mask_passwd, ENCRYPT_PASSWD_PREFIX);
+	char key[MAX_MAIL_USER_LEN + sizeof(RANDOM_KEY) + 3];
+	snprintf(key, sizeof(key), "%s@%s", user, RANDOM_KEY);
+	char cmd[256];
+
+	if (strncmp(passwd, ENCRYPT_PASSWD_PREFIX, ENCRYPT_PASSWD_PREFIX_LEN) == 0) {
+		/*We get password from ca.conf*/
+		input_from_ca = 1;
+		if (strlen(passwd) > MAX_MAIL_ENCRPT_PASSWD_LEN) {
+			/*This should never happen*/
+			if (cli_interactive()) {
+				printf("password %s exceeds the length limit: %lu\n", passwd, MAX_MAIL_ENCRPT_PASSWD_LEN);
+			}
+			detach_sys_mail_conf(conf_p);
+			return -1;
+		}
+
+		if (decrypt_passwd((unsigned char *)passwd + ENCRYPT_PASSWD_PREFIX_LEN, key, orig_passwd, sizeof(orig_passwd))) {
+			if (cli_interactive()) {
+				printf("password %s decrypt fail!\n", passwd);
+			}
+			detach_sys_mail_conf(conf_p);
+			return -1;
+		}
+
+		snprintf(cmd, sizeof(cmd), "%s edit_user %s %s", SSMTP_SCRIPT, user, orig_passwd);
+	} else {
+		/*we get password from user*/
+		if (strlen(passwd) > MAX_MAIL_PASSWD_LEN) {
+			if (cli_interactive()) {
+				printf("password %s exceeds the length limit: %d\n", passwd, MAX_MAIL_PASSWD_LEN);
+			}
+			detach_sys_mail_conf(conf_p);
+			return -1;
+		}
+
+		if (encrypt_passwd((unsigned char*)passwd, key, mask_passwd + ENCRYPT_PASSWD_PREFIX_LEN, sizeof(mask_passwd) - ENCRYPT_PASSWD_PREFIX_LEN)) {
+			if (cli_interactive()) {
+				printf("password %s encrypt fail!\n", passwd);
+			}
+			detach_sys_mail_conf(conf_p);
+			return -1;
+		}
+
+		snprintf(cmd, sizeof(cmd), "%s edit_user %s %s", SSMTP_SCRIPT, user, passwd);
+	}
+
+	if (system(cmd)) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 2)\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	}
+
+	strcpy(conf_p->mextern_server.user, user);
+	if (input_from_ca) {
+		strcpy(conf_p->mextern_server.passwd, passwd);
+	} else {
+		strcpy(conf_p->mextern_server.passwd, mask_passwd);
+	}
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+no_system_mail_external_server(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 1)\n");
+		}
+		return -1;
+	}
+
+	/*we turn off external server first*/
+	conf_p->extern_mail_on = 0;
+	conf_p->mextern_server.extern_server[0] = '\0';
+	conf_p->mextern_server.port = 0;
+	conf_p->mextern_server.use_ssl = 0;
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+no_system_mail_external_user(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 1)\n");
+		}
+		return -1;
+	}
+
+	char cmd[256];
+	snprintf(cmd, sizeof(cmd), "%s no_user", SSMTP_SCRIPT);
+
+	if (system(cmd)) {
+		if (cli_interactive()) {
+			printf("Could not config external mail server(Internal error - 2)\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	}
+
+
+	conf_p->mextern_server.user[0] = '\0';
+	conf_p->mextern_server.passwd[0] = '\0';
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+show_system_mail_relay(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+	char *str = system_mail_relay_get_config();
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not show mail relay config (Internal error - 1)\n");
+		}
+		if(str){
+			free(str);
+			str = NULL;
+		}
+		return -1;
+	}
+
+	if(str != NULL){
+		if(conf_p->mrelay_status.relay_status == 1){
+			printf("Mail relay module is on\n");
+		}
+		printf("%s", str);
+	}
+	if(conf_p->mrelay_status.relay_status == 0){
+		printf("Mail relay module is off\n");
+	}
+
+	if(str){
+		free(str);
+		str = NULL;
+	}
+	
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int 
+clear_system_mail_relay(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+	FILE *mailertable_fpw;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not clear mail relay config (Internal error - 1)\n");
+		}
+		return -1;
+	}
+
+	memset(conf_p->mrelay_server, 0x00, MAX_MAIL_RELAY_NUM*sizeof(mail_relay_server_t));
+
+	if( ( mailertable_fpw = fopen(MAILERTABLE_FILE_NEW, "w")) == NULL){
+		return -1;
+	}
+	
+	fprintf(mailertable_fpw, "%s", " ");
+	fclose(mailertable_fpw);
+
+	unlink(MAILERTABLE_FILE);
+	if(rename(MAILERTABLE_FILE_NEW, MAILERTABLE_FILE) == -1){
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	}
+	unlink(MAILERTABLE_DB);
+
+	conf_p->mrelay_status.relay_status = 0;
+	conf_p->mrelay_status.relay_num = 0;
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+char *
+system_mail_relay_get_config(void)
+{
+	FILE *mailertable_fpr;
+	char *line;
+	char *con_str;
+	sys_mail_conf_t *conf_p = NULL;
+	int i,j, linenr, linehr;
+	//int linelen;
+
+	i = 0;
+	linenr = 0;
+	linehr = 0;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not get system mail relay config "
+			       "(Internal error)\n");
+		}
+		return NULL;
+	}
+
+	memset(conf_p->mrelay_server, 0x00, MAX_MAIL_RELAY_NUM*sizeof(mail_relay_server_t));
+	/* bzero(conf_p->mrelay_server, MAX_MAIL_RELAY_NUM*sizeof(mail_relay_server_t));*/
+
+	if(( mailertable_fpr = fopen(MAILERTABLE_FILE, "r")) == NULL){
+		if(cli_interactive()){
+			printf("The mailertable file can not be opened or do not exist!\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		return NULL;
+	}
+
+	if((line = (char*)malloc(500*sizeof(char))) == NULL){
+		if(cli_interactive()){
+			printf("Can not malloc memory!\n");
+		}
+		detach_sys_mail_conf(conf_p);
+		/* Bug 17427, huangyf, 20071113 */
+		fclose(mailertable_fpr);
+		/* Bug 17427, end */
+		return NULL;
+	}
+	while( fgets(line, 500*sizeof(char), mailertable_fpr)){
+		linenr += 1;
+		//linelen = strlen(line);
+		if(line[0] == '#' ||(line[0] == ' ') || (line == NULL)){
+			continue;
+		}else{
+			if((strstr( line, "smtp")) == NULL){
+				continue;
+			}
+			i = 0;
+			while((line[i] != ' ') && (line[i]) != '\t'){
+				conf_p->mrelay_server[linehr].hostname[i] = line[i];
+				i +=1;
+			}
+			conf_p->mrelay_server[linehr].hostname[i] = '\0';
+
+			while(line[i] != ':'){
+				i += 1;
+			}
+			i += 1;
+/*
+			if(line[i] == '[')
+			{
+				i += 1;
+				j = 0;
+				while(line[i] != ']')
+				{
+					conf_p->mrelay_server[linehr].relayserver[j] = line[i];
+					i += 1;
+					j += 1;
+				}
+				conf_p->mrelay_server[linehr].relayserver[j] = '\0';
+			}
+*/
+			j = 0;
+			while(line[i] != '\0' && line[i] != '\n'){
+				conf_p->mrelay_server[linehr].relayserver[j] = line[i];
+				i += 1;
+				j += 1;
+			}
+			conf_p->mrelay_server[linehr].relayserver[j+1] = '\0';
+			linehr += 1;
+		}
+	}
+
+	conf_p->mrelay_status.relay_num = linehr;
+/*	if((conf_p->mrelay_status.relay_num > 0) && (conf_p->mrelay_status.relay_status == 0)){
+		conf_p->mrelay_status.relay_status = 1;
+	}
+*/
+	if(linehr < 1){
+		/*printf("No relay server has been configured!\n");*/
+		detach_sys_mail_conf(conf_p);
+		/* Bug 17427, huangyf, 20071114 */
+		fclose(mailertable_fpr);
+		free(line);
+		/* Bug 17427, end */
+		return NULL;
+	}
+	
+	con_str = (char*)malloc((linehr)*sizeof(mail_relay_server_t)+linehr*10);
+	bzero(con_str, ((linehr)*sizeof(mail_relay_server_t)+linehr*10));
+	for(i=0; i<conf_p->mrelay_status.relay_num; i++){
+		strcat(con_str, conf_p->mrelay_server[i].hostname);
+		strcat(con_str, "  ----->  ");
+		strcat(con_str, conf_p->mrelay_server[i].relayserver);
+		strcat(con_str, "\n");
+	}
+ 	detach_sys_mail_conf(conf_p);	
+        /* Bug 17427, huangyf, 20071113 */
+	fclose(mailertable_fpr);
+	free(line);
+	/* Bug 17427, end */
+	return con_str;
+}
+
+/* end add 10914 */
+
+int
+system_mail_from(char *from_string)
+{
+	int len = strlen(from_string);
+	sys_mail_conf_t *conf_p;
+
+	if (len == 0) {
+		printf("From string cannot be empty\n");
+		return 0;
+	}
+
+	if (len > MAX_MAIL_FROM_LEN) {
+		printf("Length of from string cannot be greater than %d\n",
+		       MAX_MAIL_FROM_LEN);
+		return 0;
+	}
+
+	if (check_from_string(from_string) == -1) {
+		return 0;
+	}
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		printf("Could not set from string (Internal error)\n");
+		return 0;
+	}
+
+	strcpy(conf_p->from, from_string);
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+system_mail_hostname(char *hostname, unsigned int hostname_behavior)
+{
+	int len = strlen(hostname);
+	sys_mail_conf_t *conf_p;
+
+	if (len == 0) {
+		printf("Hostname cannot be empty\n");
+		return 0;
+	}
+
+	if (len > MAX_MAIL_HOSTNAME_LEN) {
+		printf("Length of hostname cannot be greater than %d\n",
+		       MAX_MAIL_HOSTNAME_LEN);
+		return 0;
+	}
+	
+	if (strchr(hostname, '.') == NULL) {
+		printf("Hostname must be a fully qualified domain name (FQDN).\n");
+		return 0;
+	}
+
+	if (check_hostname_string(hostname) == -1) {
+		return 0;
+	}
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		printf("Could not set hostname (Internal error - 1)\n");
+		return 0;
+	}
+
+	strcpy(conf_p->hostname, hostname);
+	conf_p->hostname_behavior = hostname_behavior;
+	if (write_fqdn_to_file() == -1) {
+		printf("Could not set hostname (Internal error - 2)\n");
+		detach_sys_mail_conf(conf_p);
+		return 0;
+	}
+
+	/*rewrite sendmail.cf file, Dj domain.The Dj item is the domain name*/
+	if (write_hostname_to_file(conf_p->hostname) == -1) {
+		printf("Could not set hostname (Internal error - 2)\n");
+		detach_sys_mail_conf(conf_p);
+		return 0;
+	}
+	/*change sendmail.cf file, need to restart sendmail */
+	system("systemctl restart sendmail");
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+no_system_mail_from(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		printf("Could not set from string to default (Internal error)\n");
+		return 0;
+	}
+
+	strcpy(conf_p->from, DEF_MAIL_FROM);
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+no_system_mail_hostname(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		printf("Could not set hostname to default (Internal error - 1)\n");
+		return 0;
+	}
+
+	strcpy(conf_p->hostname, DEF_MAIL_HOSTNAME);
+	if (0 == conf_p->hostname_behavior) {
+		/* init sendmail.cf file. Dj $w.alert_pseudo_domain.The Dj item is the domain name*/
+		if (write_hostname_to_file(DEF_MAIL_HOSTNAME) == -1) {
+			printf("Could not set hostname to default (Internal error - 2)\n");
+			detach_sys_mail_conf(conf_p);
+			return 0;
+		}
+	
+		if (write_fqdn_to_file() == -1) {
+			printf("Could not set hostname to default (Internal error - 2)\n");
+			detach_sys_mail_conf(conf_p);
+			return 0;
+		}
+		/*change sendmail.cf file, need to restart sendmail */
+		system("systemctl restart sendmail"); 
+	}
+	/*reset hostname_behavior to default*/
+	conf_p->hostname_behavior = 0;
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+clear_system_mail_conf(void)
+{
+	sys_mail_conf_t *conf_p = NULL;
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not clear mail config (Internal error - 1)\n");
+		}
+		return 0;
+	}
+
+	strcpy(conf_p->hostname, DEF_MAIL_HOSTNAME);
+	if (0 == conf_p->hostname_behavior) {
+		if (write_hostname_to_file(DEF_MAIL_HOSTNAME) != 0) {
+			if (cli_interactive()) {
+				printf("Could not clear mail config (Internal error - 2)\n");
+			}
+
+			detach_sys_mail_conf(conf_p);
+			return 0;
+		}
+
+		if (write_fqdn_to_file() != 0) {
+			if (cli_interactive()) {
+				printf("Could not clear mail config (Internal error - 2)\n");
+			}
+
+			detach_sys_mail_conf(conf_p);
+			return 0;
+		}
+		/*change sendmail.cf file, need to restart sendmail */
+		system("systemctl restart sendmail");
+	}
+
+	strcpy(conf_p->from, DEF_MAIL_FROM);
+	conf_p->hostname_behavior = 0;
+	conf_p->extern_mail_on = 0;
+	memset(&conf_p->mextern_server, 0, sizeof(conf_p->mextern_server));
+	system("cp -f /etc/ssmtp/ssmtp.conf /var/run/ssmtp.conf");
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+int
+show_system_mail_conf(void)
+{
+	char *str = write_system_mail_conf("");
+
+	if (str) {
+		printf("%s", str);
+		free(str);
+	}
+
+	return 0;
+}
+
+char *
+write_system_mail_conf(char *segment)
+{
+	int n = 0;
+	char *str = NULL;
+	sys_mail_conf_t *conf_p = NULL;
+
+	str = (char *)malloc(WRITE_STR_LEN * sizeof(char));
+	if (str == NULL) {
+		return NULL;
+	}
+
+	conf_p = attach_sys_mail_conf();
+	if (conf_p == NULL) {
+		if (cli_interactive()) {
+			printf("Could not get system mail config "
+			       "(Internal error)\n");
+		}
+		free(str);
+		return NULL;
+	}
+
+	n += sprintf((str+n), "system mail from \"%s\"\n", conf_p->from);
+	n += sprintf((str+n), "system mail hostname \"%s\" %d\n", conf_p->hostname, conf_p->hostname_behavior);
+
+	if (conf_p->mextern_server.extern_server[0]) {
+		n += sprintf((str+n), "system mail external server \"%s\" %d %d\n",
+				conf_p->mextern_server.extern_server,
+				conf_p->mextern_server.port,
+				conf_p->mextern_server.use_ssl);
+	}
+
+	if (conf_p->mextern_server.user[0]) {
+		n += sprintf((str+n), "system mail external user \"%s\" \"%s\"\n",
+				conf_p->mextern_server.user,
+				conf_p->mextern_server.passwd);
+	}
+
+	if (conf_p->extern_mail_on) {
+		n += sprintf((str+n), "system mail external on\n");
+	} else {
+		n += sprintf((str+n), "system mail external off\n");
+	}
+
+	detach_sys_mail_conf(conf_p);
+	return str;
+}
+
+#define MAX_LINE_LEN                    1024
+
+int
+write_fqdn_to_file(void)
+{
+	char name[MAX_LONG_TOKEN_SIZE+1] = "";
+
+	gethostname(name, MAX_LONG_TOKEN_SIZE+1);
+	if (name[0] == 0) {
+		/* the hostname are not initialize */
+		return 0;
+	}
+
+	/* will upgrade the domain name at set_node_name() */
+	return set_node_name(name,0);
+}
+
+int
+write_hostname_to_file(char *hostname)
+{
+	int esc = 0, n = 0;
+	char *str = hostname;
+	char host[MAX_MAIL_HOSTNAME_LEN+MAX_LONG_TOKEN_SIZE+1];
+	char name[MAX_LONG_TOKEN_SIZE+1];
+	char buff[MAX_LINE_LEN+1];
+	FILE *fpr, *fpw;
+	char cmd[256] = {0};
+
+	bzero(host, (MAX_MAIL_HOSTNAME_LEN+1));
+	while (*str) {
+		if (esc == 1) {
+			esc = 0;
+			switch (*str) {
+			case 'h':
+				gethostname(name, MAX_LONG_TOKEN_SIZE+1);
+				n += sprintf((host+n), "%s", name);
+				break;
+
+			case 'l':
+				host[n++] = '$';
+				host[n++] = 'w';
+				break;
+
+			default:
+				break;
+			}
+		} else if (*str == '%') {
+			esc = 1;
+		} else {
+			host[n++] = *str;
+		}
+
+		str++;
+	}
+
+	if (access(SENDMAIL_CONF_FILE, F_OK) == 0) {
+		bzero(cmd, sizeof(cmd));
+		snprintf(cmd, sizeof(cmd), "rm -f %s", SENDMAIL_CONF_FILE);
+		system(cmd);
+	}
+	bzero(cmd, sizeof(cmd));
+	snprintf(cmd, sizeof(cmd), "/bin/cp %s %s", SENDMAIL_ORI_CONF_FILE, SENDMAIL_CONF_FILE);
+	system(cmd);
+
+	fpr = fopen(SENDMAIL_CONF_FILE, "r");
+	if (fpr == NULL) {
+		return -1;
+	}
+
+	fpw = fopen(SENDMAIL_CONF_NEW_FILE, "w");
+	if (fpw == NULL) {
+		fclose(fpr);
+		return -1;
+	}
+
+	while (fgets(buff, (MAX_LINE_LEN+1), fpr)) {
+		if (strstr(buff, SENDMAIL_HOSTNAME_DEF) == buff) {
+			fprintf(fpw, "%s %s\n", SENDMAIL_HOSTNAME_DEF, host);
+		} else {
+			fprintf(fpw, "%s", buff);
+		}
+	}
+
+	fclose(fpr); 
+	fclose(fpw);
+
+	if (rename(SENDMAIL_CONF_NEW_FILE, SENDMAIL_CONF_FILE) == -1) {
+		return -1;
+	}
+
+	return 0;
+}
+
+
+int
+sysmail_get_domainame(char * output, size_t len)
+{
+	int esc = 0, n = 0;
+	char *str, *p;
+	char host[MAX_MAIL_HOSTNAME_LEN+MAX_LONG_TOKEN_SIZE+1];
+	char name[MAX_LONG_TOKEN_SIZE+1];
+	//char buff[MAX_LINE_LEN+1];
+	sys_mail_conf_t *conf_p;
+
+	conf_p = attach_sys_mail_conf();	
+	if (conf_p == NULL) {
+		snprintf(output, len, "Unknown");
+		return -1;
+	}
+
+	if (conf_p->hostname_behavior) {
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	}
+
+	str = conf_p->hostname;
+	bzero(host, (MAX_MAIL_HOSTNAME_LEN+MAX_LONG_TOKEN_SIZE+1));
+	while (*str) {
+		if (esc == 1) {
+			esc = 0;
+			switch (*str) {
+			case 'h':
+				gethostname(name, MAX_LONG_TOKEN_SIZE+1);
+				n += sprintf((host+n), "%s", name);
+				break;
+
+			case 'l':
+				gethostname(name, MAX_LONG_TOKEN_SIZE+1);
+				p = name;	
+				while(*p && *p != '.') {
+					host[n++] = *p++;
+				}
+				break;
+
+			default:
+				break;
+			}
+		} else if (*str == '%') {
+			esc = 1;
+		} else {
+			host[n++] = *str;
+		}
+
+		str++;
+	}
+
+	if (strlen(host) > len) {
+		snprintf(output, len, "Unknown");
+		detach_sys_mail_conf(conf_p);
+		return -1;
+	} else {
+		strncpy(output, host, len);
+		host[len] = '\0';
+	}
+
+	detach_sys_mail_conf(conf_p);
+	return 0;
+}
+
+sys_mail_conf_t *
+attach_sys_mail_conf(void)
+{
+	int shm_id = 0;
+	sys_mail_conf_t *conf_p = NULL;
+
+	shm_id = shmget(SYS_MAIL_SHM_KEY, 0, 0);
+	if (shm_id == -1) {
+		return NULL;
+	}
+
+	conf_p = (sys_mail_conf_t *)shmat(shm_id, NULL, 0);
+	if (conf_p == (sys_mail_conf_t *)-1) {
+		return NULL;
+	}
+
+	return conf_p;
+}
+
+void
+detach_sys_mail_conf(sys_mail_conf_t *conf_p)
+{
+	shmdt(conf_p);
+}
+
+int
+check_from_string(char *from_str)
+{
+	int esc = 0;
+	char *str = from_str;
+
+	while (*str) {
+		if (esc == 1) {
+			esc = 0;
+			switch (*str) {
+			case 'h':
+			case 'q':
+			case '%':
+				break;
+
+			default:
+				printf("Unsupported escape sequence %%%c\n", *str);
+				return -1;
+			}
+		} else if (*str == '%') {
+			esc = 1;
+		}
+
+		str++;
+	}
+
+	if (esc == 1) {
+		printf("Unsupported escape sequence %%\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+check_hostname_string(char *hostname)
+{
+	int esc = 0, i = 0;
+	char *str = hostname;
+
+	while (*str) {
+		if (esc == 1) {
+			esc = 0;
+			switch (*str) {
+			case 'h':
+			case 'l':
+				break;
+
+			default:
+				printf("Unsupported escape sequence %%%c\n", *str);
+				return -1;
+			}
+		} else if (*str == '%') {
+			esc = 1;
+		} else {
+			for (i=0; host_unsupp_chars[i] != '\0'; i++) {
+				if (*str == host_unsupp_chars[i]) {
+					printf("Unsupported character '%c'\n", *str);
+					return -1;
+				}
+			}
+		}
+
+		str++;
+	}
+
+	if (esc == 1) {
+		printf("Unsupported escape sequence %%\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int
+check_external_mail_string(char *name)
+{
+	char *str = name;
+
+	while (*str) {
+		switch (*str) {
+			case '(':
+			case ')':
+			case '&':
+			case ';':
+			case '<':
+			case '>':
+			case '\'':
+				printf("Unsupported character '%c'\n", *str);
+				return CHARACTER_INVALID;
+
+			default:
+				break;
+		}
+		str++;
+	}
+
+	return CHARACTER_VALID;
+}
+
+int ssmtp_conf_file_update(sys_mail_conf_t *conf_p)
+{	
+	char cmd[128];
+	
+	if (!conf_p) {
+		return 0;
+	}
+
+	/*If extern server configed, do not update*/
+	if (conf_p->mextern_server.extern_server[0] || 
+		conf_p->mextern_server.user[0]) {
+		return 0;
+	}	
+	
+	/*We cover it with ssmtp.conf.def */
+	snprintf(cmd, sizeof(cmd) -1, "/usr/bin/cp %s %s", SSMTP_CONF_DEF, SSMTP_CONF);
+	system(cmd);
+
+	return 1;
+}
+

Property changes on: src/library/ca_mail/sys_mail.c
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: /branches/rel_avx_2_7_2/src/library/ca_util/ca_util.h
===================================================================
--- /branches/rel_avx_2_7_2/src/library/ca_util/ca_util.h	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/library/ca_util/ca_util.h	(working copy)
@@ -327,6 +327,10 @@
 extern long rand_num(void);
 /*extern int sleep_dot(int total, int interval);*/
 char * strrstr(char const *s1, char const *s2);
+
+int encrypt_passwd(unsigned char *decrypted_passwd, const char *key, char *encrypted_passwd, int output_len);
+int decrypt_passwd(unsigned char *encrypted_passwd, const char *key, char *decrypted_passwd, int output_len);
+
 const char* str_start_with(const char* haystack, const char* needle);
 const char* str_end_with(const char* haystack, const char* needle);
 const char* str_case_start_with(const char* haystack, const char* needle);
Index: /branches/rel_avx_2_7_2/src/library/node_man/node_cmd.c
===================================================================
--- /branches/rel_avx_2_7_2/src/library/node_man/node_cmd.c	(revision 8915)
+++ /branches/rel_avx_2_7_2/src/library/node_man/node_cmd.c	(working copy)
@@ -26,7 +26,7 @@
 #include "node_sys.h"
 #include "node_cmd.h"
 #include "clickarray.h"
-
+#include "../ca_mail/sys_mail.h"
 
 char host_unsupp_chars[] = { '$', '#', ',', '\0' };
 
