daemon.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:19k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /*
  2.  * daemon.c -- a standalone server of this project
  3.  *
  4.  * A part of BBS Express Project
  5.  *
  6.  * Copyright (c) 1998, 1999, Edward Ping-Da Chuang <edwardc@edwardc.dhs.org>
  7.  * of BBS Express Project, All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  19.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  22.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  24.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28.  * SUCH DAMAGE.
  29.  *
  30.  * CVS: $Id: daemon.c,v 1.1 2000/01/15 01:45:32 edwardc Exp $
  31.  */
  32.         
  33. #include <sys/ioctl.h>
  34. #include "bbs.h"
  35. #include <sys/wait.h>
  36. #include <netinet/in.h>
  37. #include <sys/socket.h>
  38. #include <netdb.h>
  39. #include <sys/termios.h>
  40. static const char daemon_c[] =
  41.    "$Id: daemon.c,v 1.1 2000/01/15 01:45:32 edwardc Exp $";
  42. /* Edit these lines to fit the configuration of your server */
  43. #define DEF_PORT  2000
  44. #define BBSUID      9999
  45. #define BBSGID      99
  46. #define BUFSIZE     1024
  47. #ifndef BBSHOME
  48.   #define BBSHOME     "/service/bbs"
  49. #endif
  50. #define BBSPASSWDS  BBSHOME"/.PASSWDS"
  51. /* You needn't modify any lines below unless you know what you're doing */
  52. struct fileheader currentmail;
  53. struct userec   currentuser;
  54. char            LowUserid[20];
  55. char            hostname[80];
  56. #define QLEN            5
  57. #define S_CONNECT       1
  58. #define S_LOGIN         2
  59. #define STRN_CPY(d,s,l) { strncpy((d),(s),(l)); (d)[(l)-1] = 0; }
  60. #define ANY_PORT        0
  61. #define RFC931_PORT     113
  62. #define RFC931_TIMEOUT  20
  63. #define POP3_TIMEOUT    1200
  64. static jmp_buf  timebuf;
  65. int             State;
  66. int             msock, sock; /* master server socket */
  67. static int      reaper();
  68. char            fromhost[STRLEN];
  69. char            inbuf[BUFSIZE];
  70. char            remote_userid[STRLEN];
  71. FILE           *cfp;
  72. char           *msg, *cmd;
  73. int             fd;
  74. struct fileheader *fcache;
  75. int             totalnum, totalbyte, markdel, idletime;
  76. int            *postlen;
  77. int             loginok = 0;
  78. void            log_usies();
  79. int             Quit(), User(), Pass(), Conf(), Stat(), List(), Retr(), Rset();
  80. int             Last(), Dele(), Dump(), Upld(), Mtag(), Grup(), Version(), Mget();
  81. struct commandlist {
  82. char           *name;
  83. int             (*fptr) ();
  84. }               cmdlists[] = {
  85. "retr", Retr,
  86. "dele", Dele,
  87. "user", User,
  88. "pass", Pass,
  89. "stat", Stat,
  90. "list", List,
  91. "dump", Dump,
  92. "quit", Quit,
  93. "rset", Rset,
  94. "last", Last,
  95. "conf", Conf,
  96. "upld", Upld,
  97. "mtag", Mtag,
  98. "group", Grup,
  99. "version", Version,
  100. "mget", Mget,
  101. NULL, NULL
  102. };
  103. char           *crypt();
  104. int
  105. checkpasswd(passwd, test)
  106. char           *passwd, *test;
  107. {
  108. static char     pwbuf[14];
  109. char           *pw;
  110. strncpy(pwbuf, test, 14);
  111. pw = crypt(pwbuf, passwd);
  112. return (!strcmp(pw, passwd));
  113. }
  114. static int
  115. abort_server()
  116. {
  117. log_usies("ABORT SERVER");
  118. close(msock);
  119. close(sock);
  120. exit(1);
  121. }
  122. int
  123. dokill()
  124. {
  125. return kill(0, SIGKILL);
  126. }
  127. static FILE    *
  128. fsocket(domain, type, protocol)
  129. int             domain;
  130. int             type;
  131. int             protocol;
  132. {
  133. int             s;
  134. FILE           *fp;
  135. if ((s = socket(domain, type, protocol)) < 0) {
  136. return (0);
  137. } else {
  138. if ((fp = fdopen(s, "r+")) == 0) {
  139. close(s);
  140. }
  141. return (fp);
  142. }
  143. }
  144. void
  145. outs(str)
  146. char           *str;
  147. {
  148. char            sendbuf[BUFSIZE];
  149. (void) bzero(sendbuf, sizeof(sendbuf));
  150. (void) sprintf(sendbuf, "%srn", str);
  151. (void) write(sock, sendbuf, strlen(sendbuf));
  152. }
  153. /* timeout - handle timeouts */
  154. static void
  155. timeout(sig)
  156. int             sig;
  157. {
  158. longjmp(timebuf, sig);
  159. }
  160. void
  161. rfc931(rmt_sin, our_sin, dest)
  162. struct sockaddr_in *rmt_sin;
  163. struct sockaddr_in *our_sin;
  164. char           *dest;
  165. {
  166. unsigned        rmt_port;
  167. unsigned        our_port;
  168. struct sockaddr_in rmt_query_sin;
  169. struct sockaddr_in our_query_sin;
  170. char            user[256];
  171. char            buffer[512];
  172. char           *cp;
  173. FILE           *fp;
  174. char           *result = "unknown";
  175. struct hostent *hp;
  176. /*
  177.  * Use one unbuffered stdio stream for writing to and for reading
  178.  * from the RFC931 etc. server. This is done because of a bug in the
  179.  * SunOS 4.1.x stdio library. The bug may live in other stdio
  180.  * implementations, too. When we use a single, buffered,
  181.  * bidirectional stdio stream ("r+" or "w+" mode) we read our own
  182.  * output. Such behaviour would make sense with resources that
  183.  * support random-access operations, but not with   sockets.
  184.  */
  185. if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
  186. setbuf(fp, (char *) 0);
  187. /*
  188.  * Set up a timer so we won't get stuck while waiting for the
  189.  * server.
  190.  */
  191. if (setjmp(timebuf) == 0) {
  192. signal(SIGALRM, (void *) timeout);
  193. alarm(RFC931_TIMEOUT);
  194. /*
  195.  * Bind the local and remote ends of the query socket
  196.  * to the same IP addresses as the connection under
  197.  * investigation. We go through all this trouble
  198.  * because the local or remote system might have more
  199.  * than one network address. The RFC931 etc.  client
  200.  * sends only port numbers; the server takes the IP
  201.  * addresses from the query socket.
  202.  */
  203. our_query_sin = *our_sin;
  204. our_query_sin.sin_port = htons(ANY_PORT);
  205. rmt_query_sin = *rmt_sin;
  206. rmt_query_sin.sin_port = htons(RFC931_PORT);
  207. if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
  208.  sizeof(our_query_sin)) >= 0 &&
  209.     connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
  210.     sizeof(rmt_query_sin)) >= 0) {
  211. /*
  212.  * Send query to server. Neglect the risk
  213.  * that a 13-byte write would have to be
  214.  * fragmented by the local system and cause
  215.  * trouble with buggy System V stdio
  216.  * libraries.
  217.  */
  218. fprintf(fp, "%u,%urn",
  219. ntohs(rmt_sin->sin_port),
  220. ntohs(our_sin->sin_port));
  221. fflush(fp);
  222. /*
  223.  * Read response from server. Use
  224.  * fgets()/sscanf() so we can work around
  225.  * System V stdio libraries that incorrectly
  226.  * assume EOF when a read from a socket
  227.  * returns less than requested.
  228.  */
  229. if (fgets(buffer, sizeof(buffer), fp) != 0
  230.     && ferror(fp) == 0 && feof(fp) == 0
  231.     && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  232.     &rmt_port, &our_port, user) == 3
  233.     && ntohs(rmt_sin->sin_port) == rmt_port
  234.   && ntohs(our_sin->sin_port) == our_port) {
  235. /*
  236.  * Strip trailing carriage return. It
  237.  * is part of the protocol, not part
  238.  * of the data.
  239.  */
  240. if (cp = strchr(user, 'r'))
  241. *cp = 0;
  242. result = user;
  243. }
  244. }
  245. alarm(0);
  246. }
  247. fclose(fp);
  248. }
  249. STRN_CPY(dest, result, 60);
  250. if (strcmp(dest, "unknown") == 0)
  251. strcpy(dest, "");
  252. else
  253. strcat(dest, "@");
  254. hp = gethostbyaddr((char *) &rmt_sin->sin_addr, sizeof(struct in_addr),
  255.    rmt_sin->sin_family);
  256. if (hp)
  257. strcat(dest, hp->h_name);
  258. else
  259. strcat(dest, (char *) inet_ntoa(rmt_sin->sin_addr));
  260. }
  261. int
  262. Isspace(ch)
  263. char            ch;
  264. {
  265. return (ch == ' ' || ch == 't' || ch == 10 || ch == 13);
  266. }
  267. char           *
  268. nextwordlower(str)
  269. char          **str;
  270. {
  271. char           *p;
  272. while (Isspace(**str))
  273. (*str)++;
  274. p = (*str);
  275. while (**str && !Isspace(**str)) {
  276. **str = tolower(**str);
  277. (*str)++;
  278. }
  279. if (**str) {
  280. **str = '';
  281. (*str)++;
  282. }
  283. return p;
  284. }
  285. char           *
  286. nextword(str)
  287. char          **str;
  288. {
  289. char           *p;
  290. while (Isspace(**str))
  291. (*str)++;
  292. p = (*str);
  293. while (**str && !Isspace(**str))
  294. (*str)++;
  295. if (**str) {
  296. **str = '';
  297. (*str)++;
  298. }
  299. return p;
  300. }
  301. void
  302. Init()
  303. {
  304. State = S_CONNECT;
  305. LowUserid[0] = '';
  306. markdel = 0;
  307. idletime = 0;
  308. (void) gethostname(hostname, 80);
  309. }
  310. void
  311. Login_init()
  312. {
  313. int             fd, i;
  314. char           *ptr;
  315. struct stat     st;
  316. totalnum = totalbyte = 0;
  317. sprintf(genbuf, "mail/%c/%s/.DIR", toupper(*LowUserid), LowUserid);
  318. if (stat(genbuf, &st) == -1 || st.st_size == 0) {
  319. return;
  320. }
  321. totalnum = st.st_size / sizeof(struct fileheader);
  322. fcache = (struct fileheader *) malloc(st.st_size);
  323. postlen = (int *) malloc(sizeof(int) * totalnum);
  324. fd = open(genbuf, O_RDONLY);
  325. read(fd, fcache, st.st_size);
  326. close(fd);
  327. for (i = 0; i < totalnum; i++) {
  328. if (index(fcache[i].owner, '@') == NULL) {
  329. if (ptr = strchr(fcache[i].owner, ' '))
  330. *ptr = '';
  331. sprintf(genbuf, ".bbs@%s", hostname);
  332. strcat(fcache[i].owner, genbuf);
  333. }
  334. sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid, fcache[i].filename);
  335. if (stat(genbuf, &st) == -1)
  336. st.st_size = 0;
  337. postlen[i] = st.st_size + strlen(fcache[i].owner) + 10 + strlen(fcache[i].title)
  338. + 10 + 40;
  339. totalbyte += postlen[i];
  340. fcache[i].accessed[0] = ' ';
  341. }
  342. }
  343. void
  344. pop3_timeout()
  345. {
  346. idletime++;
  347. if (idletime > 5) {
  348. log_usies("ABORT - TIMEOUT");
  349. fclose(cfp);
  350. close(sock);
  351. exit(1);
  352. }
  353. alarm(POP3_TIMEOUT);
  354. }
  355. main(argc, argv)
  356. int             argc;
  357. char          **argv;
  358. {
  359. struct sockaddr_in fsin, our;
  360. int             on, alen, len, i, n;
  361. char           *str;
  362. int             portnum;
  363. int             childpid;
  364. if ( argc == 1 )
  365. portnum = (int) DEF_PORT;
  366. else
  367. portnum = atoi(argv[1]);
  368. if (fork())
  369. exit(0);
  370. fprintf(stderr,"nexpress[%d] at port %d startedn",getpid(),portnum);
  371. for (n = 0; n < 10; n++)
  372. close(n);
  373. open("/dev/null", O_RDONLY);
  374. dup2(0, 1);
  375. dup2(0, 2);
  376. if ((n = open("/dev/tty", O_RDWR)) > 0) {
  377. ioctl(n, TIOCNOTTY, 0);
  378. close(n);
  379. }
  380. if ((msock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  381. exit(1);
  382. }
  383. setsockopt(msock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on));
  384. bzero((char *) &fsin, sizeof(fsin));
  385. fsin.sin_family = AF_INET;
  386. fsin.sin_addr.s_addr = htonl(INADDR_ANY);
  387. fsin.sin_port = htons(portnum);
  388. if (bind(msock, (struct sockaddr *) & fsin, sizeof(fsin)) < 0) {
  389. exit(1);
  390. }
  391. signal(SIGHUP, (void *) abort_server);
  392. signal(SIGCHLD, (void *) reaper);
  393. listen(msock, QLEN);
  394. while (1) {
  395. alen = sizeof(fsin);
  396. sock = accept(msock, (struct sockaddr *) & fsin, &alen);
  397. if ((sock < 0) && (errno == EINTR))
  398. continue;
  399. if ((childpid = fork()) < 0) {
  400. exit(1);
  401. }
  402. switch (childpid) {
  403. case 0: /* child process */
  404. close(msock);
  405. setgid(BBSGID);
  406. setuid(BBSUID);
  407. strcpy(fromhost, (char *) inet_ntoa(fsin.sin_addr));
  408. len = sizeof our;
  409. getsockname(sock, (struct sockaddr *) & our, &len);
  410. Init();
  411. rfc931(&fsin, &our, remote_userid);
  412. cfp = fdopen(sock, "r+");
  413. setbuf(cfp, (char *) 0);
  414. sprintf(genbuf, "200 BlueWave Express server at %s starting, nice to see you.", hostname);
  415. outs(genbuf);
  416. chdir(BBSHOME);
  417. log_usies("CONNECT");
  418. alarm(0);
  419. signal(SIGALRM, (void *) pop3_timeout);
  420. alarm(POP3_TIMEOUT);
  421. while (fgets(inbuf, sizeof(inbuf), cfp) != 0) {
  422. idletime = 0;
  423. msg = inbuf;
  424. inbuf[strlen(inbuf) - 1] = '';
  425. if (inbuf[strlen(inbuf) - 1] == 'r')
  426. inbuf[strlen(inbuf) - 1] = '';
  427. cmd = nextwordlower(&msg);
  428. if (*cmd == 0)
  429. continue;
  430. i = 0;
  431. while ((str = cmdlists[i].name) != NULL) {
  432. if (strcmp(cmd, str) == 0)
  433. break;
  434. i++;
  435. }
  436. if (str == NULL) {
  437. sprintf(genbuf, "500 Unknown command: "%s".", cmd);
  438. outs(genbuf);
  439. } else
  440. (*cmdlists[i].fptr) ();
  441. }
  442. if (State == S_LOGIN) {
  443. free(fcache);
  444. free(postlen);
  445. }
  446. log_usies("ABORT");
  447. fclose(cfp);
  448. close(sock);
  449. exit(0);
  450. break;
  451. default: /* parent process */
  452. close(sock);
  453. break;
  454. }
  455. }
  456. }
  457. static int
  458. reaper()
  459. {
  460. int             state, pid;
  461. while ((pid = waitpid(-1, &state, WNOHANG | WUNTRACED)) > 0);
  462. return 0;
  463. }
  464. int
  465. Conf()
  466. {
  467. if (State != S_LOGIN) {
  468. outs("999 Unknown command: "conf".");
  469. return -1;
  470. }
  471. b_create();
  472. return 0;
  473. }
  474. int
  475. Grup()
  476. {
  477. if (State != S_LOGIN) {
  478. outs("999 Unknown command: "group".");
  479. return -1;
  480. }
  481. return(group());
  482. }
  483. int
  484. Version()
  485. {
  486. extern char c_express_c[], mmencode_c[], stuff_c[], bigfile_c[];
  487. sprintf(genbuf, "200 %s",daemon_c);
  488. outs(genbuf);
  489. sprintf(genbuf, "200 %s",c_express_c);
  490. outs(genbuf);
  491. sprintf(genbuf, "200 %s",mmencode_c);
  492. outs(genbuf);
  493. sprintf(genbuf, "200 %s",stuff_c);
  494. outs(genbuf);
  495. sprintf(genbuf, "200 %s",bigfile_c);
  496. outs(genbuf);
  497. }
  498. int
  499. Mtag()
  500. {
  501. if (!loginok) {
  502. outs("402 USER assign first.");
  503. return -1;
  504. }
  505. tagmail();
  506. return 0;
  507. }
  508. int
  509. get_userdata(user)
  510. char           *user;
  511. {
  512. FILE           *rec;
  513. int             found = 0;
  514. if ((rec = fopen(BBSPASSWDS, "rb")) == NULL)
  515. return -1;
  516. while (1) {
  517. if (fread(&currentuser, sizeof(currentuser), 1, rec) <= 0)
  518. break;
  519. if (currentuser.numlogins <= 0)
  520. continue;
  521. /* edwardc.990111 it may case insensetive */
  522. if (strcasecmp(user, currentuser.userid) == 0 ) {
  523. found = 1;
  524. break;
  525. }
  526. }
  527. fclose(rec);
  528. return found;
  529. }
  530. int
  531. User()
  532. {
  533. if (State == S_LOGIN) {
  534. outs("999 Unknown command: "user".");
  535. return -1;
  536. }
  537. cmd = nextwordlower(&msg);
  538. if ( strcasecmp(cmd, "guest") == 0 ) {
  539. sprintf(genbuf, "501 Unknown user "%s".", cmd);
  540. outs(genbuf);
  541. return -1;
  542. }
  543. if (get_userdata(cmd) == 1) {
  544. strcpy(LowUserid, cmd);
  545. sprintf(genbuf, "300 Password required for [%s]", currentuser.userid);
  546. outs(genbuf);
  547. return 0;
  548. } else {
  549. sprintf(genbuf, "501 Unknown user: "%s".", cmd);
  550. outs(genbuf);
  551. return -1;
  552. }
  553. }
  554. void
  555. log_usies(buf)
  556. char           *buf;
  557. {
  558. FILE           *fp;
  559. if ((fp = fopen("reclog/express.log", "a")) != NULL) {
  560. time_t          now;
  561. struct tm      *p;
  562. time(&now);
  563. p = localtime(&now);
  564. fprintf(fp, "%02d/%02d/%02d %02d:%02d:%02d [%s](%s) %sn",
  565. p->tm_year, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min,
  566.     p->tm_sec, currentuser.userid ? currentuser.userid : "",
  567. remote_userid ? remote_userid : "", buf);
  568. fflush(fp);
  569. fclose(fp);
  570. }
  571. }
  572. int
  573. Retr()
  574. {
  575. if (State != S_LOGIN) {
  576. outs("999 Unknown command: "retr".");
  577. return -1;
  578. }
  579. compress();
  580. }
  581. int
  582. Stat()
  583. {
  584. if (State != S_LOGIN) {
  585. outs("999 Unknown command: "stat".");
  586. return -1;
  587. }
  588. cmd = nextword(&msg);
  589. if ( *cmd == 0 ) {
  590.      sprintf(genbuf, "200 %d %d", totalnum, totalbyte);
  591.    outs(genbuf);
  592. } else if ( strcasecmp(cmd, "blist") == 0 ) {
  593.    statblist();
  594. } else {
  595.    outs("511 unknow parameter for "stat"");
  596. }
  597. return 0;
  598. }
  599. int
  600. Rset()
  601. {
  602. int             i;
  603. if (State != S_LOGIN) {
  604. outs("999 Unknown command: "rset".");
  605. return -1;
  606. }
  607. for (i = 0; i < totalnum; i++) {
  608. fcache[i].accessed[0] = ' ';
  609. }
  610. markdel = 0;
  611. sprintf(genbuf, "204 Maildrop has %d messages (%d octets)", totalnum, totalbyte);
  612. outs(genbuf);
  613. return 0;
  614. }
  615. int
  616. List()
  617. {
  618. int             i;
  619. if (State != S_LOGIN) {
  620. outs("999 Unknown command: "list".");
  621. return -1;
  622. }
  623. cmd = nextword(&msg);
  624. if (*cmd == 0) {
  625. sprintf(genbuf, "205 %d messages (%d octets)", totalnum, totalbyte);
  626. outs(genbuf);
  627. for (i = 0; i < totalnum; i++) {
  628. if (fcache[i].accessed[0] == ' ') {
  629. sprintf(genbuf, "%d %d", i + 1, postlen[i]);
  630. outs(genbuf);
  631. }
  632. }
  633. outs(".");
  634. } else {
  635. i = atoi(cmd);
  636. if (i <= 0 || totalnum < i) {
  637. sprintf(genbuf, "503 Message %d does not exist.", i);
  638. outs(genbuf);
  639. return -1;
  640. } else if (fcache[i - 1].accessed[0] == 'X') {
  641. sprintf(genbuf, "504 Message %d has been deleted.", i);
  642. outs(genbuf);
  643. return -1;
  644. }
  645. sprintf(genbuf, "205 %d %d", i, postlen[i - 1]);
  646. outs(genbuf);
  647. }
  648. return 0;
  649. }
  650. int
  651. Dump()
  652. {
  653. if (State != S_LOGIN) {
  654. outs("999 Unknown command: "uidl".");
  655. return -1;
  656. }
  657. cmd = nextword(&msg);
  658. outs("250 Data follow up");
  659. if ( strcasecmp(cmd, "boards") == 0 )
  660. boardlist();
  661. else {
  662. outs("250 Data follow up");
  663. dumplist();
  664. }
  665. return 0;
  666. }
  667. int
  668. Pass()
  669. {
  670. if (State == S_LOGIN) {
  671. outs("-ERR Unknown command: "pass".");
  672. return -1;
  673. }
  674. cmd = nextword(&msg);
  675. if (*cmd == 0) {
  676. outs("-ERR Too few arguments for the pass command.");
  677. return -1;
  678. }
  679. if (LowUserid[0] == '') {
  680. outs("-ERR need a USER");
  681. return -1;
  682. }
  683. if (!checkpasswd(currentuser.passwd, cmd)) {
  684. sprintf(genbuf, "-ERR Password supplied for "%s.bbs" is incorrect.", LowUserid);
  685. outs(genbuf);
  686. LowUserid[0] = '';
  687. log_usies("ERROR PASSWD");
  688. return -1;
  689. }
  690. if (State == S_CONNECT) {
  691. log_usies("ENTER");
  692. State = S_LOGIN;
  693. }
  694. Login_init();
  695. loginok = 1;
  696. express();
  697. return 0;
  698. }
  699. int
  700. Last()
  701. {
  702. if (State != S_LOGIN) {
  703. outs("-ERR Unknown command: "last".");
  704. return -1;
  705. }
  706.  
  707. cmd = nextword(&msg);
  708. tagnew();
  709. }
  710. int
  711. Upld()
  712. {
  713. if (State != S_LOGIN) {
  714. outs("-ERR Unknown command: "Upld".");
  715. return -1;
  716. }
  717. }
  718. int
  719. Dele()
  720. {
  721. int             num;
  722. if (State != S_LOGIN) {
  723. outs("-ERR Unknown command: "dele".");
  724. return -1;
  725. }
  726. cmd = nextword(&msg);
  727. if (*cmd == 0) {
  728. outs("-ERR Too few arguments for the dele command.");
  729. return -1;
  730. }
  731. num = atoi(cmd);
  732. if (num <= 0 || totalnum < num) {
  733. sprintf(genbuf, "-ERR Message %d does not exist.", num);
  734. outs(genbuf);
  735. return -1;
  736. } else if (fcache[num - 1].accessed[0] == 'X') {
  737. sprintf(genbuf, "-ERR Message %d has already been deleted.", num);
  738. outs(genbuf);
  739. return -1;
  740. }
  741. fcache[num-1].accessed[0] = 'X';
  742. markdel++;
  743. sprintf(genbuf, "+OK Message %d has been deleted.", num);
  744. outs(genbuf);
  745. return 0;
  746. }
  747. int
  748. do_delete()
  749. {
  750. int             i, fdr, fdw, count;
  751. char            fpath[80], fnew[80];
  752. sprintf(fpath, "mail/%c/%s/.DIR", toupper(*LowUserid), LowUserid);
  753. sprintf(fnew, "mail/%c/%s/pop3.DIR", toupper(*LowUserid), LowUserid);
  754. if ((fdr = open(fpath, O_RDONLY)) == -1)
  755. return -1;
  756. if ((fdw = open(fnew, O_RDWR | O_CREAT, 0644)) == -1)
  757. return -1;
  758. i = count = 0;
  759. while (read(fdr, &currentmail, sizeof(currentmail))) {
  760. if (i >= totalnum || fcache[i].accessed[0] == ' ') {
  761. write(fdw, &currentmail, sizeof(currentmail));
  762. count++;
  763. } else {
  764. sprintf(genbuf, "mail/%c/%s/%s", toupper(*LowUserid), LowUserid,
  765. currentmail.filename);
  766. unlink(genbuf);
  767. }
  768. i++;
  769. }
  770. close(fdr);
  771. close(fdw);
  772. unlink(fpath);
  773. if (count) {
  774. rename(fnew, fpath);
  775. } else
  776. unlink(fnew);
  777. return 0;
  778. }
  779. int
  780. Fatal()
  781. {
  782. Quit();
  783. }
  784. int
  785. Mget()
  786. {
  787. maxget();
  788. }
  789. int
  790. Quit()
  791. {
  792. if (State == S_LOGIN) {
  793. free(fcache);
  794. free(postlen);
  795. if (markdel)
  796. do_delete();
  797. }
  798. log_usies("EXIT");
  799. sprintf(genbuf, "200 BlueWave Express server at %s signing off, bye bye.", hostname);
  800. outs(genbuf);
  801. fclose(cfp);
  802. close(sock);
  803. exit(0);
  804. }
  805. void
  806. oouts(int status, char *str, int havereturn)
  807. {
  808. char            sendbuf[200];
  809. (void) bzero(sendbuf, sizeof(sendbuf));
  810. (void) sprintf(sendbuf, "%d %sr%s", status, str, (havereturn == 0) ? "n" : "");
  811. (void) write(sock, sendbuf, strlen(sendbuf));
  812. }