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

📄 bbspop3d.c

📁 linux下的BBS
💻 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 + -