📄 bbssmtpd.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 + -