📄 bbspop3d.c
字号:
/* * Thread BBS POP3 Daemon By rexchen@ug.ee.tku.edu.tw */#include <bbs.h>#include "pop3d.h"#define CMD_MSG(pop3user, msg) writeln(pop3user->sockfd,msg);pthread_t *pop3_thread_lib;int countpop3user =0;intpop3d_client_close (pop3user)struct pop3cs *pop3user;{ int sock; if (pop3user->mode >= CM_LOGIN) if (pop3user->cache != NULL) free (pop3user->cache); sock = pop3user->sockfd; shutdown (sock, 2); close (sock); xfree(pop3user); countpop3user--; pthread_exit (0);}intpop3d_cmd_xxxx (pop3user)struct pop3cs *pop3user;{ CMD_MSG (pop3user, POP3D_ERRCMD_MSG);}static char *parse_token (pop3user, str, lower)struct pop3cs *pop3user;char *str;int lower;{ char *token; int ch; if (str == NULL) { str = pop3user->trail_token; if (str == NULL) return NULL; } token = NULL; while (ch = *str) { if (ch == ' ') { if (token) { *str++ = '\0'; break; } } else { if (token == NULL) token = str; if (lower && ch >= 'A' && ch <= 'Z') *str = ch | 0x20; } str++; } pop3user->trail_token = str; return token;}intmbox_open (pop3user)struct pop3cs *pop3user;{ int i = 0; char fpath[PATHLEN] = { 0 }, fname[PATHLEN] = { 0}; pop3user->pcount = pop3user->pbytes = 0; mail_path (pop3user->uid, fpath); file_path (fpath, DIR_FILE); pop3user->pcount = statf (fpath, F_SIZE) / sizeof (struct dirhead); if (pop3user->pcount <= 0) return; pop3user->cache = (struct dirhead *) calloc (sizeof (struct dirhead), pop3user->pcount); get_recs (fpath, pop3user->cache, sizeof (struct dirhead), 0, pop3user->pcount); mail_path (pop3user->uid, fpath); for (i = 0; i < pop3user->pcount; i++) { file_new_path (fname, fpath, pop3user->cache[i].fname); pop3user->pbytes = pop3user->pbytes + statf (fname, F_SIZE); }}intmbox_read (pop3user, phdr)struct pop3cs *pop3user;struct dirhead *phdr;{ char fpath[PATHLEN] = { 0 }; FILE *fp = NULL; char buf[512] = { 0 }; mail_path (pop3user->uid, fpath); file_path (fpath, phdr->fname); sockprintf (pop3user->sockfd, "+OK %d octets\r\n", statf (fpath, F_SIZE)); fp = fopen (fpath, "r"); if (fp != NULL) { while (fgets (buf, sizeof (buf), fp) != NULL) { if (strncmp (buf, ".\n", 2) == 0) { writeln (pop3user->sockfd, "..\r\n"); memset (buf, 0, sizeof (buf)); continue; } if (strncmp (buf, "\n", 1) == 0) { writeln (pop3user->sockfd, "\r\n"); memset (buf, 0, sizeof (buf)); continue; } str_tok (buf, "\r\n"); writeln (pop3user->sockfd, buf); writeln (pop3user->sockfd, "\r\n"); memset (buf, 0, sizeof (buf)); } fclose (fp); } writeln (pop3user->sockfd, ".\r\n");}intmbox_close (pop3user)struct pop3cs *pop3user;{ int i = 0; char dpath[PATHLEN] = { 0 }; char fpath[PATHLEN] = { 0 }; char mpath[PATHLEN] = { 0 }; mail_path (pop3user->uid, mpath); file_new_path (dpath, mpath, DIR_FILE); for (i = pop3user->pcount; i > 0; i--) { if (pop3user->cache[i - 1].mark & HEAD_DELE) { file_new_path (fpath, mpath, pop3user->cache[i - 1].fname); unlink (fpath); del_recs (dpath, sizeof (struct dirhead), i - 1, 1); } }}intdo_argument (pop3user)struct pop3cs *pop3user;{ CMD_MSG (pop3user, POP3D_ERRARG_MSG);}intdo_number (pop3user, n)struct pop3cs *pop3user;int n;{ char *cmd; if (pop3user->mode < CM_LOGIN) { pop3d_cmd_xxxx (pop3user); return 0; } cmd = parse_token (pop3user, NULL, 0); if (!cmd || !*cmd) { if (n == 0) do_argument (pop3user); return n; } n = atoi (cmd); if (n <= 0 || n > pop3user->pcount) { CMD_MSG (pop3user, POP3D_ERRNUM_MSG); return 0; } return n;}intpop3d_cmd_noop (pop3user)struct pop3cs *pop3user;{ CMD_MSG (pop3user, POP3D_NOOP_OK);}intpop3d_cmd_user (pop3user)struct pop3cs *pop3user;{ extern struct account *acc; char *userid; if (pop3user->mode >= CM_LOGIN) { pop3d_cmd_xxxx (pop3user); return; } userid = parse_token (pop3user, NULL, 1); if (!userid || !*userid) { do_argument (pop3user); return; } if (!strstr (userid, ".bbs")) { sockprintf (pop3user->sockfd, "-ERR %s has no mail here\r\n", userid); return; } str_tok (userid, ".\r\n"); if (strlen (userid) > IDLEN) { writeln (pop3user->sockfd, POP3D_NOUSER_ERR); return; } if ((pop3user->uid = searchuid (pop3user, userid)) < 0) { writeln (pop3user->sockfd, POP3D_NOUSER_ERR); return; } strncpy (pop3user->userid, userid, IDLEN); memcpy (pop3user->passwd, acc[pop3user->uid].passwd, PASSLEN); sockprintf (pop3user->sockfd, "+OK Password required for %s.bbs\r\n", userid);}intpop3d_cmd_passwd (pop3user)struct pop3cs *pop3user;{ char *cmd; if (pop3user->mode >= CM_LOGIN) { pop3d_cmd_xxxx (pop3user); return; } if (!*(pop3user->passwd)) { CMD_MSG (pop3user, POP3D_NEEDUSER); return; } cmd = pop3user->trail_token; if (!cmd || !*cmd) { do_argument (pop3user); return; } if (check_bad_uid_ip (pop3user->uid, pop3user->ipaddr)) { CMD_MSG (pop3user, POP3D_PASSWD_ERR); pop3d_client_close (pop3user); } if (!chk_passwd (pop3user->passwd, cmd)) { *pop3user->passwd = '\0'; insert_bad_uid_ip (pop3user->uid, pop3user->ipaddr); CMD_MSG (pop3user, POP3D_PASSWD_ERR); return; } mbox_open (pop3user); sockprintf (pop3user->sockfd, "+OK %s has %d messages (%d octets)\r\n", pop3user->userid, pop3user->pcount, pop3user->pbytes); pop3user->mode = CM_LOGIN;}intpop3d_cmd_stat (pop3user)struct pop3cs *pop3user;{ if (pop3user->mode < CM_LOGIN) { pop3d_cmd_xxxx (pop3user); return; } sockprintf (pop3user->sockfd, "+OK %d %d\r\n", pop3user->pcount, pop3user->pbytes);}intpop3d_cmd_last (pop3user)struct pop3cs *pop3user;{ if (pop3user->mode < CM_LOGIN) { pop3d_cmd_xxxx (pop3user); return; } sockprintf (pop3user->sockfd, "+OK %d\r\n", pop3user->pcount);}intpop3d_cmd_reset (pop3user)struct pop3cs *pop3user;{ int n; n = pop3user->mode; if (n < CM_LOGIN) { pop3d_cmd_xxxx (pop3user); return; } if (n == CM_DIRTY) { for (n = 0; n < pop3user->pcount; n++) pop3user->cache[n].mark = 0; } sockprintf (pop3user->sockfd, "+OK mail reset %d messages %d octets\r\n", pop3user->pcount, pop3user->pbytes); pop3user->mode = CM_LOGIN;}intpop3d_cmd_retrive (pop3user)struct pop3cs *pop3user;{ int n; n = do_number (pop3user, 0); if (!n) return; if (pop3user->cache[n - 1].mark & HEAD_DELE) { CMD_MSG (pop3user, POP3D_DELETE_MSG); return; } mbox_read (pop3user, &(pop3user->cache[n - 1]));}intpop3d_cmd_top (pop3user)struct pop3cs *pop3user;{ int n; char *cmd; n = do_number (pop3user, 0); if (!n) return; if (pop3user->cache[n - 1].mark & HEAD_DELE) { CMD_MSG (pop3user, POP3D_DELETE_MSG); return; } cmd = parse_token (pop3user, NULL, 0); if (!cmd || !*cmd) { do_argument (pop3user); return; } n = atoi (cmd); if (n < 0) { CMD_MSG (pop3user, POP3D_ERRNUM_MSG); return; } mbox_read (pop3user, &(pop3user->cache[n - 1]));}intpop3d_cmd_delete (pop3user)struct pop3cs *pop3user;{ int n; if (!(n = do_number (pop3user, 0))) return; if (pop3user->cache[n - 1].mark & HEAD_DELE) { CMD_MSG (pop3user, POP3D_DELETE_MSG); return; } pop3user->cache[n - 1].mark = HEAD_DELE; pop3user->mode = CM_DIRTY; CMD_MSG (pop3user, POP3D_DELETE_OK);}intpop3d_cmd_list (pop3user)struct pop3cs *pop3user;{ int n = 0, i = 0; char fpath[PATHLEN] = { 0 }; n = do_number (pop3user, -1); if (n < 0) { sockprintf (pop3user->sockfd, "+OK %d messages (%d octets)\r\n", pop3user->pcount, pop3user->pbytes); for (i = 0; i < pop3user->pcount; i++) { mail_path (pop3user->uid, fpath); file_path (fpath, pop3user->cache[i].fname); sockprintf (pop3user->sockfd, "%d %d\r\n", i + 1, statf (fpath, F_SIZE)); } writeln (pop3user->sockfd, ".\r\n"); } else if (n > 0) { if (pop3user->cache[n - 1].mark & HEAD_DELE) { CMD_MSG (pop3user, POP3D_DELETE_MSG); } else { mail_path (pop3user->uid, fpath); file_path (fpath, pop3user->cache[n - 1].fname); sockprintf (pop3user->sockfd, "+OK %d %d\r\n", n, statf (fpath, F_SIZE)); } }}intpop3d_cmd_uidl (pop3user)struct pop3cs *pop3user;{ int n, i; n = do_number (pop3user, -1); if (n < 0) { writeln (pop3user->sockfd, POP3D_UIDL_OK); for (i = 0; i < pop3user->pcount; i++) { sockprintf (pop3user->sockfd, "%d %d.%03d\r\n", i + 1, pop3user->cache[i].time, str_nhash (pop3user->cache[i].msgid, MSGIDLEN, 3) % 1000); } writeln (pop3user->sockfd, ".\r\n"); } else if (n > 0) { if (pop3user->cache[n - 1].mark & HEAD_DELE) { CMD_MSG (pop3user, POP3D_DELETE_MSG); } else { sockprintf (pop3user->sockfd, "+OK %d %d.%03d", n, pop3user->cache[n - 1].time, str_nhash (pop3user->cache[n - 1].msgid, MSGIDLEN, 3) % 1000); } }}intpop3d_cmd_quit (pop3user)struct pop3cs *pop3user;{ if (pop3user->mode >= CM_DIRTY) { mbox_close (pop3user); } writeln (pop3user->sockfd, POP3D_BYE_MSG); pop3d_client_close (pop3user);}intpop3d_client_serve (pop3user, run)struct pop3cs *pop3user;char *run;{ char *cmd, *str; struct pop3dcmd *pc; cmd = parse_token (pop3user, run, 1); if (!cmd || !*cmd) return; for (pc = pop3dcmdlist; str = pc->cmd; pc++) { if (!str_ncmp (cmd, str, 4)) break; } (*pc->fun) (pop3user);}intpop3d_client_read (pop3user)struct pop3cs *pop3user;{ int cc; char buf[RCVBUFSIZ]; char *str = buf; if (!readsock (pop3user->sockfd, str, RCVBUFSIZ)) { while (cc = *str) { switch (cc) { case '\r': case '\n': *str = '\0'; pop3d_client_serve (pop3user, buf); return 1; case '\t': *str = ' '; } str++; } pop3d_client_close (pop3user); } else { pop3d_client_close (pop3user); }}pop3s (pop3user)struct pop3cs *pop3user;{ int nfds = 0; fd_set rset; struct timeval tv; tv.tv_sec = POP3D_TIMEOUT; tv.tv_usec = 0; writeln (pop3user->sockfd, POP3D_DAEMON_OK); FD_ZERO (&rset); FD_SET (pop3user->sockfd, &rset); while (1) { nfds = select (pop3user->sockfd + 1, &rset, NULL, NULL, &tv); if (nfds <= 0) { pop3d_client_close (pop3user); } pop3d_client_read (pop3user); }}intpop3d_daemon (){ pthread_attr_t thr_attr; struct sockaddr_in from, sin = { AF_INET }; int bid, sock, on = 1, i = 0, size = 0; struct pop3cs *pop3user; pop3_thread_lib = calloc (sizeof (pthread_t), MAX_POP3D_CLIENT); pop3user = calloc (sizeof (struct pop3cs), MAX_POP3D_CLIENT); memset (pop3_thread_lib, 0, sizeof (pthread_t) * MAX_POP3D_CLIENT); memset (pop3user, 0, sizeof (struct pop3cs) * MAX_POP3D_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 (POP3_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 { pop3user = malloc (sizeof (struct pop3cs)); memset (pop3user, 0, sizeof (struct pop3cs)); pop3user->sockfd = sock; if ( ++countpop3user >= MAX_POP3D_CLIENT ) { shutdown (sock, 2); close(sock); xfree(pop3user); countpop3user--; continue; } memcpy (pop3user->ipaddr, (char *) inet_ntoa (from.sin_addr), IPLEN); pthread_create (&pop3_thread_lib[i], &thr_attr, (void *) pop3s, pop3user); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -