⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bbssmtpd.c

📁 linux下的BBS
💻 C
字号:
/* *  Thread BBS SMTP Daemon By rexchen@ug.ee.tku.edu.tw */#include <bbs.h>#include "smtpd.h"#define CMD_MSG(smtpduser, msg)       writeln(smtpduser->sockfd,msg);pthread_t *smtpd_thread_lib;int countsmtpduser=0;intsw_key(key)char *key;{        if ( strncmp(key,"From",4) == 0 )                return(KW_FROM);        if ( strncmp(key,"Received:",9) == 0 )                return(KW_RECV);        if ( strncmp(key,"by",2) == 0 )                return(KW_BY);        if ( strncmp(key,"From:",5) == 0 )                return(KW_2FROM);        if ( strncmp(key,"Message-Id:",11) == 0 )                return(KW_MSGID);        if ( strncmp(key,"To:",3) == 0 )                return(KW_TO);        if ( strncmp(key,"Subject:",8) == 0 )                return(KW_SUBJ);        if ( strncmp(key,"Date:",5) == 0 )                return(KW_DATE);        if ( strncmp(key,"Content-Length:",15) == 0 )                return(KW_LENG);        if ( strncmp(key,"Content-Transfer-Encoding:",26) == 0 )                return(KW_ENCODE);        if ( strncmp(key,"MIME-Version:",13) == 0 )                return(KW_MIME);        if ( strncmp(key,"Content-Type:",13) == 0 )                return(KW_CTYPE);        return(0);}intparse_header(smtpduser,buf,head)struct smtpdcs *smtpduser;char *buf;struct dirhead *head;{	int kw=0,ctype=0,mime=0;	char *part;	char from[MAILLEN];	char to[MAILLEN];	char sender[MAILLEN];	char relay[DOMAINLEN];	char client[DOMAINLEN];	char encode[STRLEN];        kw = sw_key(buf);        switch (kw) {                case KW_FROM:                        strncpy(from,buf+5,MAILLEN);                        str_tok(from," \r\n");//                        printf("From : %s\n",from);                        break;                case KW_RECV:                        strncpy(relay,buf+15,DOMAINLEN);                        str_tok(relay," ");                        part = strchr(buf,'[');                        if ( part != NULL )                                strncpy(client,part+1,DOMAINLEN);                        str_tok(client,"[]\r\n");//                        printf("Client : %s\n",client);//                        printf("Relay : %s\n",relay);                        break;                case KW_TO:                        part = strchr(buf,'<');                        if ( part != NULL ) {                                strncpy(to,part+1,MAILLEN);                        } else {                                if ( ( part = strchr(buf,'"') ) != NULL )                                        strncpy(to,part+1,MAILLEN);                                else                                        strncpy(to,buf+6,MAILLEN);                        }                        str_tok(to," <>\r\n\"");//                        printf("TO : %s\n",to);                        break;                case KW_2FROM:                        part = strchr(buf,'<');                        if ( part != NULL )                                strncpy(sender,part+1,MAILLEN);                        else                                strncpy(sender,buf+6,MAILLEN);                        str_tok(sender," <>\r\n");//                        printf("From : %s\n",sender);                        break;                case KW_SUBJ:                        strncpy(head->title,buf+9,TITLELEN);                        str_tok(head->title,"\r\n");                        break;                case KW_MSGID:                        strncpy(head->msgid,buf+12,MSGIDLEN);                        strtok(head->msgid," \r\n");                        break;                case KW_ENCODE:                        strncpy(encode,buf+27,STRLEN);                        str_tok(encode,"\r\n");                        break;                case KW_MIME:                        mime = 1;                        break;                case KW_CTYPE:                        if ( strstr(buf,"text/plain") != NULL )                                ctype = TYPE_TEXT;                        if ( strstr(buf,"text/html") != NULL )                                ctype = TYPE_HTML;                        if ( strstr(buf,"multipart") != NULL )                                ctype = TYPE_MIME;                        break;        }}intsmtpd_client_close (smtpduser)struct smtpdcs *smtpduser;{  int sock;  sock = smtpduser->sockfd;  shutdown (sock, 2);  close (sock);  xfree(smtpduser);  countsmtpduser--;  pthread_exit (0);}intsmtpd_cmd_help(smtpduser)struct smtpdcs *smtpduser;{  CMD_MSG(smtpduser,SMTPD_HELP_MSG);}intsmtpd_cmd_xxxx (smtpduser)struct smtpdcs *smtpduser;{  CMD_MSG (smtpduser,SMTPD_ERRCMD_MSG);}intsmtpd_cmd_noop (smtpduser)struct smtpdcs *smtpduser;{  CMD_MSG (smtpduser,SMTPD_NOOP_OK);}intsmtpd_cmd_helo (smtpduser)struct smtpdcs *smtpduser;{  CMD_MSG(smtpduser,SMTPD_HELO_MSG);}intsmtpd_cmd_mail (smtpduser)struct smtpdcs *smtpduser;{  char buf[MAILLEN];  char cmd[MAILLEN];  if (smtpduser->mode >= CM_MAIL) {    CMD_MSG(smtpduser, SMTPD_MAIL_HAVESENDER);    return;  }  if ( strchr(smtpduser->data,':') != NULL ) {	hack_addr(smtpduser->data, smtpduser->sender, smtpduser->smail , smtpduser->snick);        snprintf(cmd,MAILLEN,"<%s>",smtpduser->smail);        parse_addr(cmd, buf, smtpduser->sdomain);	if ( strchr(smtpduser->smail,'@') == NULL || smtpduser->sdomain[0] == '\0' ) {		CMD_MSG(smtpduser,SMTPD_MAIL_NULLDOMAIN);		return(-1);	}  	smtpduser->mode = CM_MAIL;	sockprintf(smtpduser->sockfd,"250 <%s> Sender ok\r\n",smtpduser->smail);  } else {    	sockprintf (smtpduser->sockfd, "501 Syntax error in parameters \"%s\"\r\n",smtpduser->data);  }}intsmtpd_cmd_rcpt (smtpduser)struct smtpdcs *smtpduser;{  extern char bbsdn[HOSTLEN]; //rexchen  char buf[MAILLEN]={0};  char cmd[MAILLEN];  if (smtpduser->mode < CM_MAIL) {    CMD_MSG(smtpduser, SMTPD_RCPT_NEEDMAIL);    return;  }  if (smtpduser->mode >= CM_RCPT) {    CMD_MSG(smtpduser, SMTPD_RCPT_MORERCPT);    return;  }  if ( strchr(smtpduser->data,':') != NULL ) {        hack_addr(smtpduser->data, smtpduser->recver, smtpduser->rmail , smtpduser->rnick);        snprintf(cmd,MAILLEN,"<%s>",smtpduser->rmail);        parse_addr(cmd, buf, smtpduser->rdomain);        if ( strchr(smtpduser->rmail,'@') == NULL || smtpduser->rdomain[0] == '\0') {                CMD_MSG(smtpduser,SMTPD_MAIL_NULLDOMAIN);		return(-1);        }	snprintf(cmd,MAILLEN,"%sbbs@%s",smtpduser->recver,bbsdn);	if ( str_ncmp( smtpduser->rmail , cmd , MAILLEN) == 0 ) {		str_tok(smtpduser->recver,".");		if ((smtpduser->uid = searchuid (smtpduser, smtpduser->recver)) < 0) {    			CMD_MSG (smtpduser, SMTPD_NOUSER_ERR );    			return;  		}	} else {		CMD_MSG(smtpduser,"551 we dont accept relayed mail\r\n");		return;	}        smtpduser->mode = CM_RCPT;        sockprintf(smtpduser->sockfd,"250 <%s> Recipient ok\r\n",smtpduser->rmail);  } else {        sockprintf (smtpduser->sockfd, "501 Syntax error in parameters \"%s\"\r\n",smtpduser->data);  }}intsmtpd_cmd_rset (smtpduser)struct smtpdcs *smtpduser;{  int sockfd=smtpduser->sockfd;  char ipaddr[IPLEN];  strncpy(ipaddr,smtpduser->ipaddr,IPLEN);  memset (smtpduser, 0,  sizeof (struct smtpdcs));  smtpduser->sockfd = sockfd;  strncpy(smtpduser->ipaddr,ipaddr,IPLEN);  smtpduser->mode = CM_RSET;  CMD_MSG(smtpduser,SMTPD_RSET_OK);}intsmtpd_cmd_data (smtpduser)struct smtpdcs *smtpduser;{  int pass = 0;  char fpath[PATHLEN] = { 0 };  char dpath[PATHLEN] = { 0 };  char str[RCVBUFSIZ];  struct dirhead tmp;  FILE *fp;  memset(&tmp,0,sizeof(struct dirhead));  if (smtpduser->mode < CM_MAIL) {    CMD_MSG(smtpduser, SMTPD_RCPT_NEEDMAIL);    return;  }  if (smtpduser->mode < CM_RCPT) {    CMD_MSG(smtpduser, SMTPD_DATA_NEEDRCPT);    return;  }  mail_path (smtpduser->uid, fpath);  file_new_path(dpath,fpath,DIR_FILE);  if ((char *) gen_fname (fpath, tmp.fname, NA) == NULL) {      CMD_MSG(smtpduser,SMTPD_DATA_NOTMP);      return ;  }  CMD_MSG(smtpduser,SMTPD_DATA_ENTERMAIL);  file_path(fpath,tmp.fname);  fp = fopen(fpath,"w");  if ( fp != NULL ) {    while (!readsock (smtpduser->sockfd, str, RCVBUFSIZ)) {	if ( strncmp(str,".\r\n",3) == 0 || strncmp(str,".\n",2) == 0) 		break;	if ( strncmp(str,"\r\n",2) == 0 || strncmp(str,"\n",1) == 0 )		pass = 1;	if (pass == 0)		parse_header(smtpduser,str,&tmp);	fprintf(fp,str);    }    fclose(fp);    strncpy(tmp.owner,smtpduser->sender,IDLEN);    strncpy(tmp.mail,smtpduser->smail,MAILLEN);    tmp.time = time(NULL);    rtime (&(tmp.time), tmp.date);    add_recs (dpath, &tmp, sizeof (struct dirhead), 1);    CMD_MSG(smtpduser,SMTPD_DATA_ACCEPT);  } else {      CMD_MSG(smtpduser,SMTPD_DATA_NOTMP);      return ;  }}intsmtpd_cmd_quit (smtpduser)struct smtpdcs *smtpduser;{  writeln (smtpduser->sockfd, SMTPD_BYE_MSG);  smtpd_client_close (smtpduser);}intsmtpd_client_serve (smtpduser)struct smtpdcs *smtpduser;{  char *cmd, *str;  struct smtpdcmd *pc;  cmd = smtpduser->data;  if (!cmd || !*cmd)    return;  for (pc = smtpdcmdlist; str = pc->cmd; pc++) {    if (!str_ncmp (cmd, str,4))      break;  }  (*pc->fun) (smtpduser);}intsmtpd_client_read (smtpduser)struct smtpdcs *smtpduser;{  int cc;  char buf[RCVBUFSIZ]={0};  char *str = buf;  if (!readsock (smtpduser->sockfd, str, RCVBUFSIZ)) {    while (cc = *str) {      switch (cc) {	case '\r':	case '\n':	  *str = '\0';	  strncpy(smtpduser->data,buf,RCVBUFSIZ);	  smtpd_client_serve (smtpduser);	  return 1;	case '\t':	  *str = ' ';      }      str++;    }    smtpd_client_close (smtpduser);  } else {    smtpd_client_close (smtpduser);  }}smtpds (smtpduser)struct smtpdcs *smtpduser;{  int nfds=0;  fd_set rset;  struct timeval tv;  tv.tv_sec = SMTPD_TIMEOUT;  tv.tv_usec = 0;  writeln (smtpduser->sockfd, SMTPD_DAEMON_OK);  FD_ZERO (&rset);  FD_SET (smtpduser->sockfd, &rset);  while (1) {    nfds = select (smtpduser->sockfd + 1, &rset, NULL, NULL, &tv);    if (nfds <= 0) {      smtpd_client_close (smtpduser);    }    smtpd_client_read (smtpduser);  }}intsmtpd_daemon (){  pthread_attr_t thr_attr;  struct sockaddr_in from, sin = { AF_INET };  int bid, sock, on = 1, i = 0, size = 0;  struct smtpdcs *smtpduser;  smtpd_thread_lib = calloc (sizeof (pthread_t), MAX_SMTPD_CLIENT);  smtpduser = calloc (sizeof (struct smtpdcs), MAX_SMTPD_CLIENT);  memset (smtpd_thread_lib, 0, sizeof (pthread_t) * MAX_SMTPD_CLIENT);  memset (smtpduser, 0, sizeof (struct smtpdcs) * MAX_SMTPD_CLIENT);  pthread_attr_init (&thr_attr);  pthread_attr_setscope (&thr_attr, PTHREAD_SCOPE_SYSTEM);  pthread_attr_setdetachstate (&thr_attr, PTHREAD_CREATE_DETACHED);  sin.sin_family = AF_INET;  sin.sin_addr.s_addr = INADDR_ANY;  sin.sin_port = htons (SMTP_PORT);  bid = socket (AF_INET, SOCK_STREAM, 0);  if (bid < 0)     return (-1);  setsockopt (bid, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on));  if (bind (bid, (struct sockaddr *) &sin, sizeof (sin)) < 0)     return (-1);  if (listen (bid, 20) < 0)     return (-1);  for (;;) {    size = sizeof (from);    sock = accept (bid, (struct sockaddr *) &from, &size);    if (sock < 0) {      bid = socket (AF_INET, SOCK_STREAM, 0);      setsockopt (bid, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on));      bind (bid, (struct sockaddr *) &sin, sizeof (sin));      listen (bid, 20);      continue;    } else {      smtpduser = malloc (sizeof (struct smtpdcs));      memset (smtpduser, 0, sizeof (struct smtpdcs));      smtpduser->sockfd = sock;      if ( ++countsmtpduser >= MAX_SMTPD_CLIENT ) {                shutdown (sock, 2);                close(sock);                xfree(smtpduser);		countsmtpduser--;                continue;      }      memcpy (smtpduser->ipaddr, (char *) inet_ntoa (from.sin_addr), IPLEN);      pthread_create (&smtpd_thread_lib[i], &thr_attr, (void *) smtpds, smtpduser);    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -