bmutil.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:22k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  * Simple mail user interface for KA9Q IP/TCP package.
  3.  * A.D. Barksdale Garbee II, aka Bdale, N3EUA
  4.  * Copyright 1986 Bdale Garbee, All Rights Reserved.
  5.  * Permission granted for non-commercial copying and use, provided
  6.  * this notice is retained.
  7.  * Copyright 1987 1988 Dave Trulli NN2Z, All Rights Reserved.
  8.  * Permission granted for non-commercial copying and use, provided
  9.  * this notice is retained.
  10.  *
  11.  * Ported to NOS at 900120 by Anders Klemets SM0RGV.
  12.  */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <time.h>
  17. #include "global.h"
  18. #include "ftpserv.h"
  19. #include "smtp.h"
  20. #include "proc.h"
  21. #include "usock.h"
  22. #include "socket.h"
  23. #include "telnet.h"
  24. #include "timer.h"
  25. #include "session.h"
  26. #include "files.h"
  27. #define SETVBUF
  28. #if defined(UNIX) || defined(MICROSOFT)
  29. #include <sys/types.h>
  30. #endif
  31. /*
  32. #if defined(UNIX) || defined(MICROSOFT) || defined(__TURBOC__)
  33. #include <sys/stat.h>
  34. #endif
  35. #ifdef AZTEC
  36. #include <stat.h>
  37. #endif
  38. */
  39. #include <fcntl.h>
  40. #include "bm.h"
  41. #include "mailbox.h"
  42. #ifdef SETVBUF
  43. #define MYBUF 1024
  44. #endif
  45. extern long ftell();
  46. static char Badmsg[] = "Invalid Message number %dn";
  47. static char Nomail[] = "No messagesn";
  48. static char Noaccess[] = "Unable to access %sn";
  49. static int readnotes(struct mbx *m,FILE *ifile,int update);
  50. static long isnewmail(struct mbx *m);
  51. static int initnotes(struct mbx *m);
  52. static int lockit(struct mbx *m);
  53. static long fsize(char *name);
  54. static void mfclose(struct mbx *m);
  55. static int tkeywait(char *prompt,int flush);
  56. static int
  57. initnotes(m)
  58. struct mbx *m;
  59. {
  60. FILE *tmpfile();
  61. FILE *ifile;
  62. register struct let *cmsg;
  63. char buf[256];
  64. int  i, ret;
  65. sprintf(buf,"%s/%s.txt",Mailspool,m->area);
  66. if ((ifile = fopen(buf,READ_TEXT)) == NULL)
  67. return 0;
  68. fseek(ifile,0L,2);  /* go to end of file */
  69. m->mboxsize = ftell(ifile);
  70. rewind(ifile);
  71. if(!stricmp(m->area,m->name)) /* our private mail area */
  72. m->mysize = m->mboxsize;
  73. if ((m->mfile = tmpfile()) == NULL) {
  74. (void) fclose(ifile);
  75. return -1;
  76. }
  77. #ifdef SETVBUF
  78. if (m->stdinbuf == NULL)
  79. m->stdinbuf = mallocw(MYBUF);
  80. setvbuf(ifile, m->stdinbuf, _IOFBF, MYBUF);
  81. if (m->stdoutbuf == NULL)
  82. m->stdoutbuf = mallocw(MYBUF);
  83. setvbuf(m->mfile, m->stdoutbuf, _IOFBF, MYBUF);
  84. #endif
  85. m->nmsgs = 0;
  86. m->current = 0;
  87. m->change = 0;
  88. m->newmsgs = 0;
  89. m->anyread = 0;
  90. /* Allocate space for reading messages */
  91. free(m->mbox);
  92. m->mbox = (struct let *)callocw(Maxlet+1,sizeof(struct let));
  93. ret = readnotes(m,ifile,0);
  94. (void) fclose(ifile);
  95. #ifdef SETVBUF
  96. free(m->stdinbuf);
  97. m->stdinbuf = NULL;
  98. #endif
  99. if (ret != 0)
  100. return -1;
  101. for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++)  
  102. if ((cmsg->status & BM_READ) == 0) {
  103. m->newmsgs++;
  104. if (m->current == 0)
  105. m->current = i;
  106. }
  107. /* start at one if no new messages */
  108. if (m->current == 0)
  109. m->current++;
  110. return 0;
  111. }
  112. /* readnotes assumes that ifile is pointing to the first
  113.  * message that needs to be read.  For initial reads of a
  114.  * notesfile, this will be the beginning of the file.  For
  115.  * rereads when new mail arrives, it will be the first new
  116.  * message.
  117.  */
  118. static int
  119. readnotes(m,ifile,update)
  120. struct mbx *m;
  121. FILE *ifile ;
  122. int update; /* true if this is not the initial read of the notesfile */
  123. {
  124. char  tstring[LINELEN];
  125. long cpos;
  126. register struct let *cmsg;
  127. register char *line;
  128. cmsg = (struct let *)NULL;
  129. line = tstring;
  130. while(fgets(line,LINELEN,ifile) != NULL) {
  131. /* scan for begining of a message */
  132. if(strncmp(line,"From ",5) == 0) {
  133. kwait(NULL);
  134. cpos = ftell(m->mfile);
  135. fputs(line,m->mfile);
  136. if (m->nmsgs == Maxlet) {
  137. printf("Mail box full: > %d messagesn",Maxlet);
  138. mfclose(m);
  139. return -1;
  140. }
  141. m->nmsgs++;
  142. cmsg = &m->mbox[m->nmsgs];
  143. cmsg->start = cpos;
  144. if(!update)
  145. cmsg->status = 0;
  146. cmsg->size = strlen(line);
  147. while (fgets(line,LINELEN,ifile) != NULL) {
  148. if (*line == 'n') { /* done header part */
  149. cmsg->size++;
  150. putc(*line, m->mfile);
  151. break;
  152. }
  153. if (htype(line) == STATUS) {
  154. if (line[8] == 'R') 
  155. cmsg->status |= BM_READ;
  156. continue;
  157. }
  158. cmsg->size += strlen(line);
  159. if (fputs(line,m->mfile) == EOF) {
  160. printf("tmp file: %s",sys_errlist[errno]);
  161. mfclose(m);
  162. return -1;
  163. }
  164. }
  165. } else if (cmsg) {
  166. cmsg->size += strlen(line);
  167. fputs(line,m->mfile);
  168. }
  169. }
  170. return 0;
  171. }
  172. /* list headers of a notesfile a message */
  173. int
  174. dolistnotes(argc,argv,p)
  175. int argc;
  176. char *argv[];
  177. void *p;
  178. {
  179. struct mbx *m;
  180. register struct let *cmsg;
  181. register char *cp, *s;
  182. char smtp_date[SLINELEN], smtp_from[SLINELEN];
  183. char smtp_subject[SLINELEN], tstring[LINELEN], type;
  184. int start, stop;
  185. long size;
  186. char *area;
  187. m = (struct mbx *) p;
  188. if (m->mfile == NULL) {
  189. printf(Nomail);
  190. return 0;
  191. }
  192. area = strdup(m->area);
  193. while((cp = strchr(area,'/')) != NULL)
  194. *cp = '.';
  195. printf("Mail area: %s  %d message%s -  %d newnn",area,m->nmsgs,
  196. m->nmsgs == 1 ? " " : "s ", m->newmsgs);
  197. free(area);
  198. stop = m->nmsgs;
  199. if(m->stype == 'L') { /* LL (List Latest) command */
  200.      if(argc > 1)
  201.   start = stop - atoi(argv[1]) + 1;
  202.      else
  203.   start = stop;
  204. }
  205. else {
  206.      if(argc > 1)
  207.   start = atoi(argv[1]);
  208.      else
  209.   start = 1;
  210.      if(argc > 2)
  211.   stop = atoi(argv[2]);
  212. }
  213. if(stop > m->nmsgs)
  214. stop = m->nmsgs;
  215. if(start < 1 || start > stop) {
  216. printf("Invalid range.n");
  217. return 0;
  218. }
  219. for (cmsg = &m->mbox[start]; start <= stop; start++, cmsg++) {
  220. *smtp_date = '';
  221. *smtp_from = '';
  222. *smtp_subject = '';
  223. type = ' ';
  224. fseek(m->mfile,cmsg->start,0);
  225. size = cmsg->size;
  226. while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
  227.        != NULL) {
  228. if (*tstring == 'n') /* end of header */
  229. break;
  230. size -= strlen(tstring);
  231. rip(tstring);
  232. /* handle continuation later */
  233. if (*tstring == ' '|| *tstring == 't')
  234. continue;
  235. switch(htype(tstring)) {
  236. case FROM:
  237. cp = getaddress(tstring,0);
  238. sprintf(smtp_from,"%.30s",
  239. cp != NULL ? cp : "");
  240. break;
  241. case SUBJECT:
  242. sprintf(smtp_subject,"%.34s",&tstring[9]);
  243. break;
  244. case DATE:
  245. if ((cp = strchr(tstring,',')) == NULL)
  246. cp = &tstring[6];
  247. else
  248. cp++;
  249. /* skip spaces */
  250. while (*cp == ' ') cp++;
  251. if(strlen(cp) < 17)
  252. break;  /* not a valid length */
  253. s = smtp_date;
  254. /* copy day */
  255. if (atoi(cp) < 10 && *cp != '0') {
  256. *s++ = ' ';
  257. } else
  258. *s++ = *cp++;
  259. *s++ = *cp++;
  260. *s++ = ' ';
  261. *s = '';
  262. while (*cp == ' ')
  263. cp++;
  264. strncat(s,cp,3); /* copy month */
  265. cp += 3;
  266. while (*cp == ' ')
  267. cp++;
  268. /* skip year */
  269. while (isdigit(*cp))
  270. cp++;
  271. /* copy time */
  272. strncat(s,cp,6); /* space hour : min */
  273. break;
  274. case BBSTYPE:
  275. type = tstring[16];
  276. break;
  277. case NOHEADER:
  278. break;
  279. }
  280. }
  281. if((type == m->stype && m->stype != ' ') || m->stype == ' '
  282.    || m->stype == 'L')
  283.      printf("%c%c%c%3d %-27.27s %-12.12s %5ld %.25sn",
  284.      (start == m->current ? '>' : ' '),
  285.      (cmsg->status & BM_DELETE ? 'D' : ' '),
  286.      (cmsg->status & BM_READ ? 'Y' : 'N'),
  287.      start, smtp_from, smtp_date,
  288.      cmsg->size, smtp_subject);
  289. }
  290. return 0;
  291. }
  292. /*  save msg on stream - if noheader set don't output the header */
  293. int
  294. msgtofile(m,msg,tfile,noheader)
  295. struct mbx *m;
  296. int msg;
  297. FILE *tfile;   /* already open for write */
  298. int noheader;
  299. {
  300. char tstring[LINELEN];
  301. long  size;
  302. if (m->mfile == NULL) {
  303. printf(Nomail);
  304. return -1;
  305. }
  306. fseek(m->mfile,m->mbox[msg].start,0);
  307. size = m->mbox[msg].size;
  308. if (noheader) {
  309. /* skip header */
  310. while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
  311.        != NULL) {
  312. size -= strlen(tstring);
  313. if (*tstring == 'n')
  314. break;
  315. }
  316. }
  317. while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
  318.        != NULL) {
  319. size -= strlen(tstring);
  320. fputs(tstring,tfile);
  321. if (ferror(tfile)) {
  322. printf("Error writing mail filen");
  323. return -1;
  324. }
  325. }
  326. return 0;
  327. }
  328. /*  dodelmsg - delete message in current notesfile */
  329. int
  330. dodelmsg(argc,argv,p)
  331. int argc;
  332. char *argv[];
  333. void *p;
  334. {
  335. struct mbx *m;
  336. int msg,i;
  337. m = (struct mbx *) p;
  338. if (m->mfile == NULL) {
  339. printf(Nomail);
  340. return 0;
  341. }
  342. for(i = 1; i < argc; ++i) {
  343. msg = atoi(argv[i]);
  344. if(msg < 0 || msg > m->nmsgs) {
  345. printf(Badmsg,msg);
  346. continue;
  347. }
  348. /* Check if we have permission to delete others mail */
  349. if(!(m->privs & FTP_WRITE) && stricmp(m->area,m->name)) {
  350. printf(Noperm);
  351. return 0;
  352. }
  353. m->mbox[msg].status |= BM_DELETE;
  354. printf("Msg %d Killed.n", msg);
  355. m->change = 1;
  356. }
  357. return 0;
  358. }
  359. /* close the temp file while coping mail back to the mailbox */
  360. int
  361. closenotes(m)
  362. struct mbx *m;
  363. {
  364. register struct let *cmsg;
  365. register char *line;
  366. char tstring[LINELEN], buf[256];
  367. long size;
  368. int i, nostatus = 0, nodelete;
  369. FILE *nfile;
  370. if (m->mfile == NULL)
  371. return 0;
  372. if(!m->change) { /* no changes were made */
  373. mfclose(m);
  374. m->mboxsize = 0;
  375. return 0;
  376. }
  377. /* If this area is a public message area, then we will not add a
  378.  * Status line to indicate that the message has been read.
  379.  */
  380. nostatus = isarea(m->area);
  381. /* Don't delete messages from public message areas unless you are
  382.  * a BBS.
  383.  */
  384. if(nostatus)
  385. nodelete = !(m->privs & SYSOP_CMD);
  386. else
  387. nodelete = 0;
  388. /* See if any messages have been forwarded, otherwise just close
  389.  * the file and return since there is nothing to write back.
  390.  */
  391. if(nostatus && nodelete) {
  392. for(i=1; i <= m->nmsgs; ++i)
  393. if(m->mbox[i].status & BM_FORWARDED)
  394. break;
  395. if(i > m->nmsgs) {
  396. mfclose(m);
  397. m->mboxsize = 0;
  398. return 0;
  399. }
  400. }
  401. line = tstring;
  402. scanmail(m);
  403. if(lockit(m))
  404. return -1;
  405. sprintf(buf,"%s/%s.txt",Mailspool,m->area);
  406. if ((nfile = fopen(buf,WRITE_TEXT)) == NULL) {
  407. printf(Noaccess,buf);
  408. mfclose(m);
  409. m->mboxsize = 0;
  410. rmlock(Mailspool,m->area);
  411. return -1;
  412. }
  413. /* copy tmp file back to notes file */
  414. for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++) {
  415. fseek(m->mfile,cmsg->start,0);
  416. size = cmsg->size;
  417. /* It is not possible to delete messages if nodelete is set */
  418. if ((cmsg->status & BM_DELETE) && !nodelete)
  419. continue;
  420. /* copy the header */
  421. while (size > 0 && fgets(line,LINELEN,m->mfile) != NULL) {
  422. size -= strlen(line);
  423. if (*line == 'n') {
  424. if (cmsg->status & BM_FORWARDED)
  425. fprintf(nfile,"%s%sn",Hdrs[XFORWARD],
  426. m->name);
  427. if ((cmsg->status & BM_READ) != 0 && !nostatus)
  428. fprintf(nfile,"%sRn",Hdrs[STATUS]);
  429. fprintf(nfile,"n");
  430. break;
  431. }
  432. fputs(line,nfile);
  433. /* kwait(NULL);  can cause problems if exiting NOS */
  434. }
  435. while (size > 0 && fgets(line,LINELEN,m->mfile) != NULL) {
  436. fputs(line,nfile);
  437. size -= strlen(line);
  438. /* kwait(NULL);   dont want no damaged files */
  439. if (ferror(nfile)) {
  440. printf("Error writing mail filen");
  441. (void) fclose(nfile);
  442. mfclose(m);
  443. m->mboxsize = 0;
  444. rmlock(Mailspool,m->area);
  445. return -1;
  446. }
  447. }
  448. }
  449. m->nmsgs = 0;
  450. if (!stricmp(m->name,m->area))
  451. m->mysize = ftell(nfile); /* Update the size of our mailbox */
  452. /* remove a zero length file */
  453. if (ftell(nfile) == 0L)
  454. (void) unlink(buf);
  455. (void) fclose(nfile);
  456. mfclose(m);
  457. m->mboxsize = 0;
  458. rmlock(Mailspool,m->area);
  459. kwait(NULL);
  460. return 0;
  461. }
  462. /* Returns 1 if name is a public message Area, 0 otherwise */
  463. int
  464. isarea(name)
  465. char *name;
  466. {
  467. char buf[LINELEN], *cp;
  468. FILE *fp;
  469. if((fp = fopen(Arealist,READ_TEXT)) == NULL)
  470. return 0;
  471. while(fgets(buf,sizeof(buf),fp) != NULL) {
  472. /* The first word on each line is all that matters */
  473. if((cp = strchr(buf,' ')) == NULL)
  474. if((cp = strchr(buf,'t')) == NULL)
  475. continue;
  476. *cp = '';
  477. if((cp = strchr(buf,'t')) != NULL)
  478. *cp = '';
  479. if(stricmp(name,buf) == 0) { /* found it */
  480. fclose(fp);
  481. return 1;
  482. }
  483. }
  484. fclose(fp);
  485. return 0;
  486. }
  487. static int
  488. lockit(m)
  489. struct mbx *m;
  490. {
  491. int c, cnt = 0;
  492. while(mlock(Mailspool,m->area)) {
  493. ppause(1000L/MSPTICK); /* Wait one second */
  494. if(++cnt == 10) {
  495. cnt = 0;
  496. c = tkeywait("Mail file is busy, Abort or Retry ? ",1);
  497. if (c == 'A' || c == 'a' || c == EOF) {
  498. mfclose(m);
  499. return 1;
  500. }
  501. }
  502. }
  503. return 0;
  504. }
  505. /* read the next message or the current one if new */
  506. int
  507. doreadnext(argc,argv,p)
  508. int argc;
  509. char *argv[];
  510. void *p;
  511. {
  512. struct mbx *m;
  513. char buf[10], *newargv[2];
  514. m = (struct mbx *) p;
  515. if (m->mfile == NULL)
  516. return 0;
  517. if ((m->mbox[m->current].status & BM_READ) != 0) {
  518. if (m->current == 1 && m->anyread == 0)
  519. ;
  520. else if (m->current < m->nmsgs) {
  521. m->current++;
  522. } else {
  523. printf("Last messagen");
  524. return 0;
  525. }
  526. }
  527. sprintf(buf,"%d",m->current);
  528. newargv[0] = "read";
  529. newargv[1] = buf;
  530. m->anyread = 1;
  531. return doreadmsg(2,newargv,p);
  532. }
  533. /*  display message on the crt given msg number */
  534. int
  535. doreadmsg(argc,argv,p)
  536. int argc;
  537. char *argv[];
  538. void *p;
  539. {
  540. struct mbx *m;
  541. register int c, col, lin;
  542. char buf[MAXCOL+2], *cp, *cp2;
  543. int msg, cnt, i, usemore, verbose, mbxheader, pathcol;
  544. int header, lastheader;
  545. long  size;
  546. m = (struct mbx *) p;
  547. if (m->mfile == NULL) {
  548. printf(Nomail);
  549. return 0;
  550. }
  551. if(m->type == TELNET || m->type == TIP)
  552. usemore = 1; /* Display More prompt */
  553. else
  554. usemore = 0;
  555. lin = MAXLIN-1;
  556. for(i = 1; i < argc; ++i) {
  557. msg = atoi(argv[i]);
  558. if( msg < 1 || msg > m->nmsgs) {
  559. printf(Badmsg,msg);
  560. return 0;
  561. }
  562. fseek(m->mfile,m->mbox[msg].start,0);
  563. size = m->mbox[msg].size;
  564. m->current = msg;
  565. header = NOHEADER;
  566. mbxheader = 0;
  567. if(*argv[0] == 'v')
  568. verbose = 1; /* display all header lines */
  569. else
  570. verbose = 0;
  571. printf("Message #%d %sn", msg,
  572. m->mbox[msg].status & BM_DELETE ? "[Deleted]" : "");
  573. if ((m->mbox[msg].status & BM_READ) == 0) {
  574. m->mbox[msg].status |= BM_READ;
  575. m->change = 1;
  576. m->newmsgs--;
  577. }
  578. --lin;
  579. col = 0;
  580. while (!feof(m->mfile) && size > 0) {
  581. for (col = 0;  col < MAXCOL;) {
  582. c = getc(m->mfile);
  583. size--;
  584. if (feof(m->mfile) || size == 0) /* end this line */
  585. break;
  586. if (c == 't') {
  587. cnt = col + 8 - (col & 7);
  588. if (cnt >= MAXCOL) /* end this line */
  589. break;
  590. while (col < cnt)
  591. buf[col++] = ' ';
  592. } else {
  593. if (c == 'n')
  594. break;
  595. buf[col++] = c;
  596. }
  597. }
  598. if(col < MAXCOL)
  599. buf[col++] = 'n';
  600. buf[col] = '';
  601. if(mbxheader > 0) {
  602.      /* Digest R: lines and display as a Path: line */
  603.      if(strncmp(buf,"R:",2) != 0 ||
  604. (cp = strchr(buf,'@')) == NULL) {
  605.   putchar('n');
  606.   mbxheader = -1; /* don't get here again */
  607.   verbose = 1;
  608.      }
  609.      else {
  610.   if(*(++cp) == ':')
  611.        ++cp;
  612.   for(cp2 = cp; isalnum(*cp2); ++cp2)  ;
  613.   *cp2 = '';
  614.   if(mbxheader++ == 1) {
  615.        fputs("Path: ",stdout);
  616.        pathcol = 5;
  617.        --lin;
  618.   }
  619.   else {
  620.        putchar('!');
  621.        if(++pathcol + strlen(cp) > MAXCOL-3){
  622.     fputs("n      ",stdout);
  623.     pathcol = 5;
  624.     --lin;
  625.        }
  626.   }
  627.   fputs(cp,stdout);
  628.   pathcol += strlen(cp);
  629.   ++lin; /* to allow for not printing it later */
  630.      }
  631. }
  632. if(col == 1 && !verbose && !mbxheader)
  633.      /* last header line reached */
  634.      mbxheader = 1;
  635. if(verbose)
  636. fputs(buf,stdout);
  637. if(!verbose && !mbxheader){
  638. lastheader = header;
  639. if(!isspace(*buf))
  640. header = htype(buf);
  641. else
  642. header = lastheader;
  643. switch(header) {
  644. case TO:
  645. case CC:
  646. case FROM:
  647. case DATE:
  648. case SUBJECT:
  649. case APPARTO:
  650. case ORGANIZATION:
  651. fputs(buf,stdout);
  652. break;
  653. default:
  654. ++lin;
  655. }
  656. }
  657. col = 0;
  658. if(usemore && --lin == 0){
  659. c = tkeywait("--More--",0);
  660. lin = MAXLIN-1;
  661. if(c == -1 || c == 'q' || c == 'Q')
  662. break;
  663. if(c == 'n' || c == 'r')
  664. lin = 1;
  665. }
  666. }
  667. }
  668. return 0;
  669. }
  670. /* Set up m->to when replying to a message. The subject is returned in
  671.  * m->line.
  672.  */
  673. int
  674. mbx_reply(argc,argv,m,cclist,rhdr)
  675. int argc;
  676. char *argv[];
  677. struct mbx *m;
  678. struct list **cclist; /* Pointer to buffer for pointers to cc recipients */
  679. char **rhdr; /* Pointer to buffer for extra reply headers */
  680. {
  681. char subject[MBXLINE], *msgid = NULL, *date = NULL;
  682. char *cp;
  683. int msg, lastheader, header = NOHEADER;
  684. long size;
  685. /* Free anything that might be allocated
  686.  * since the last call to mbx_to() or mbx_reply()
  687.  */
  688. free(m->to);
  689. m->to = NULL;
  690. free(m->tofrom);
  691. m->tofrom = NULL;
  692. free(m->tomsgid);
  693. m->tomsgid = NULL;
  694. free(m->origto);
  695. m->origto = NULL;
  696. subject[0] = '';
  697. if(argc == 1)
  698.      msg = m->current;
  699. else
  700.      msg = atoi(argv[1]);
  701. if (m->mfile == NULL) {
  702.      if(m->sid & MBX_SID)
  703.   fputs("NO - ",stdout);
  704. puts(Nomail);
  705. return 0;
  706. }
  707. if(msg < 1 || msg > m->nmsgs) {
  708.      if(m->sid & MBX_SID)
  709.   fputs("NO - ",stdout);
  710.      puts(Badmsg);
  711.      return -1;
  712. }
  713. fseek(m->mfile,m->mbox[msg].start,0);
  714. size = m->mbox[msg].size;
  715. m->current = msg;
  716. while(size > 0 && fgets(m->line,MBXLINE-1,m->mfile) != NULL) {
  717.      size -= strlen(m->line);
  718.      if(m->line[0] == 'n') /* end of header */
  719.   break;
  720.      rip(m->line);
  721.      lastheader = header;
  722.      if(!isspace(m->line[0])) {
  723.   header = htype(m->line);
  724.   lastheader = NOHEADER;
  725.      }
  726.      switch(header) {
  727.      case SUBJECT:
  728.   if(strlen(m->line) > 11 && !strnicmp(&m->line[9],"Re:",3))
  729.        strcpy(subject,&m->line[9]);
  730.   else
  731.        sprintf(subject,"Re: %s",&m->line[9]);
  732.   break;
  733.      case FROM:
  734.   if(m->to == NULL && (cp = getaddress(m->line,0)) !=
  735.      NULL)
  736.        m->to = strdup(cp);
  737.   break;
  738.      case REPLYTO:
  739.   if((cp = getaddress(m->line,0)) != NULL) {
  740.        free(m->to);
  741.        m->to = strdup(cp);
  742.   }
  743.   break;
  744.      case MSGID:
  745.   free(msgid);
  746.   msgid = strdup(&m->line[12]);
  747.   break;
  748.      case DATE:
  749.   free(date);
  750.   date = strdup(&m->line[6]);
  751.   break;
  752.      case TO:
  753.      case CC:
  754.      case APPARTO:
  755.   /* Get addresses on To, Cc and Apparently-To lines */
  756.   cp = m->line;
  757.   m->line[strlen(cp)+1] = ''; /* add extra null at end */
  758.   for(;;) {
  759.        if((cp = getaddress(cp,lastheader == header ||
  760.    cp != m->line)) == NULL)
  761.     break;
  762.        addlist(cclist,cp,0);
  763.        /* skip to next address, if any */
  764.        cp += strlen(cp) + 1;
  765.   }
  766.   break;
  767.      }
  768. }
  769. if(msgid != NULL || date != NULL) {
  770.      *rhdr = mallocw(LINELEN);
  771.      sprintf(*rhdr,"In-Reply-To: your message ");
  772.      if(date != NULL) {
  773.   sprintf(m->line,"of %s.n",date);
  774.   strcat(*rhdr,m->line);
  775.   if(msgid != NULL)
  776.        strcat(*rhdr,"             ");
  777.      }
  778.      if(msgid != NULL) {
  779.   sprintf(m->line,"%sn",msgid);
  780.   strcat(*rhdr,m->line);
  781.      }
  782.      free(msgid);
  783.      free(date);
  784. }
  785. strcpy(m->line,subject);
  786. return 0;
  787. }
  788. void
  789. scanmail(m)  /* Get any new mail */
  790. struct mbx *m;
  791. {
  792. FILE *nfile;
  793. int ret, cnt;
  794. char buf[256];
  795. long diff;
  796. if ((diff = isnewmail(m)) == 0L)
  797. return;
  798. if(lockit(m))
  799. return;
  800. if(m->mfile == NULL || diff < 0L) {
  801. /* This is the first time scanmail is called, or the
  802.  * mail file size has decreased. In the latter case,
  803.  * any changes we did to this area will be lost, but this
  804.  * is not fatal.
  805.  */
  806. initnotes(m);
  807. rmlock(Mailspool,m->area);
  808. return;
  809. }
  810. sprintf(buf,"%s/%s.txt",Mailspool,m->area);
  811. if ((nfile = fopen(buf,READ_TEXT)) == NULL)
  812. printf(Noaccess,buf);
  813. else {
  814. /* rewind tempfile */
  815. fseek(m->mfile,0L,0);
  816. cnt = m->nmsgs;
  817. /* Reread all messages since size they may have changed
  818.  * in size after a X-Forwarded-To line was added.
  819.  */
  820. m->nmsgs = 0;
  821. ret = readnotes(m,nfile,1);   /* get the mail */
  822. m->newmsgs += m->nmsgs - cnt;
  823. m->mboxsize = ftell(nfile);
  824. if(!stricmp(m->name,m->area))
  825. m->mysize = m->mboxsize;
  826. (void) fclose(nfile);
  827. if (ret != 0)
  828. printf("Error updating mail filen");
  829. }
  830. rmlock(Mailspool,m->area);
  831. }
  832. /* Check the current mailbox to see if new mail has arrived.
  833.  * Returns the difference in size.
  834.  */
  835. static long
  836. isnewmail(m)
  837. struct mbx *m;
  838. {
  839. char buf[256];
  840. sprintf(buf,"%s/%s.txt",Mailspool,m->area);
  841. return fsize(buf) - m->mboxsize;
  842. }
  843. /* Check if the private mail area has changed */
  844. long
  845. isnewprivmail(m)
  846. struct mbx *m;
  847. {
  848. long cnt;
  849. char buf[256];
  850. sprintf(buf,"%s/%s.txt",Mailspool,m->name);
  851. cnt = m->mysize;
  852. m->mysize = fsize(buf);
  853. return m->mysize - cnt; /* != 0 not more than once */
  854. }
  855. /* This function returns the length of a file. The proper thing would be
  856.  * to use stat(), but it fails when using DesqView together with Turbo-C
  857.  * code.
  858.  */
  859. static long
  860. fsize(name)
  861. char *name;
  862. {
  863. long cnt;
  864. FILE *fp;
  865. if((fp = fopen(name,READ_TEXT)) == NULL)
  866. return -1L;
  867. fseek(fp,0L,2);
  868. cnt = ftell(fp);
  869. fclose(fp);
  870. return cnt;
  871. }
  872. /* close the temporary mail file */
  873. static void
  874. mfclose(m)
  875. struct mbx *m;
  876. {
  877. if(m->mfile != NULL)
  878. fclose(m->mfile);
  879. m->mfile = NULL;
  880. #ifdef SETVBUF
  881. free(m->stdoutbuf);
  882. m->stdoutbuf = NULL;
  883. #endif
  884. }
  885. /* Print prompt and read one character, telnet version */
  886. static int
  887. tkeywait(prompt,flush)
  888. char *prompt; /* Optional prompt */
  889. int flush; /* Flush queued input? */
  890. {
  891. int c, i, oldimode,oldomode;
  892. if(flush && socklen(fileno(stdin),0) != 0)
  893. recv_mbuf(fileno(stdin),NULL,0,NULL,0); /* flush */
  894. if(prompt == NULL)
  895. prompt = "Hit enter to continue"; 
  896. printf("%s%c%c%c",prompt,IAC,WILL,TN_ECHO);
  897. fflush(stdout);
  898. /* discard the response */
  899. oldimode = fmode(stdin,STREAM_BINARY);
  900. oldomode = fmode(stdout,STREAM_BINARY);
  901. while((c = getchar()) == IAC){
  902. c = getchar();
  903. if(c > 250 && c < 255)
  904. getchar();
  905. }
  906. fmode(stdout,oldomode);
  907. fmode(stdin,oldimode);
  908. /* Get rid of the prompt */
  909. for(i=strlen(prompt);i != 0;i--)
  910. putchar('b');
  911. for(i=strlen(prompt);i != 0;i--)
  912. putchar(' ');
  913. for(i=strlen(prompt);i != 0;i--)
  914. putchar('b');
  915. printf("%c%c%c",IAC,WONT,TN_ECHO);
  916. fflush(stdout);
  917. return c;
  918. }