pop_updt.c
上传用户:dayuan858
上传日期:2007-01-04
资源大小:194k
文件大小:15k
源码类别:

网络编程

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1989 Regents of the University of California.
  3.  * All rights reserved.  The Berkeley software License Agreement
  4.  * specifies the terms and conditions for redistribution.
  5.  */
  6. /*
  7.  * Copyright (c) 1997 by Qualcomm Incorporated.
  8.  */
  9. #include <config.h>
  10. #include <errno.h>
  11. #include <stdio.h>
  12. #include <sys/types.h>
  13. # include <string.h>
  14. #if HAVE_UNISTD_H
  15. # include <unistd.h>
  16. #endif
  17. #include <flock.h>
  18. #if HAVE_STRINGS_H
  19. # include <strings.h>
  20. #endif
  21. #include <sys/stat.h>
  22. #include <sys/file.h>
  23. #include <popper.h>
  24. #ifdef MAILOCK
  25. # include <maillock.h>
  26. #endif
  27. #if !defined(L_XTND)
  28. #define L_XTND SEEK_END
  29. #endif
  30. #ifndef L_SET
  31. #define L_SET SEEK_SET
  32. #endif
  33. #if defined(HAVE_UNISTD_H)
  34. #include <unistd.h>
  35. #endif
  36. extern int      errno;
  37. #define BBSIZE 4096
  38. static char standard_error[] =
  39.     "Error updating primary drop. Mail left in temporary maildrop (%d)";
  40. /* 
  41.  *  updt:   Apply changes to a user's POP maildrop
  42.  */
  43. int pop_updt (p)
  44. POP     *   p;
  45. {
  46.     FILE                *   md;                     /*  Stream pointer for 
  47.                                                         the user's maildrop */
  48.     int                     mfd;                    /*  File descriptor for
  49.                                                         above */
  50.     char                    buffer[BBSIZE];         /*  Read buffer */
  51.     char     uidl_buf[128];     /*  UIDL header */
  52.     MsgInfoList         *   mp;                     /*  Pointer to message 
  53.                                                         info list */
  54.     register int            msg_num;                /*  Current message 
  55.                                                         counter */
  56.     register int            status_written;         /*  Status header field 
  57.                                                         written */
  58.     int                     nchar;                  /* Bytes read/written */
  59.     long                    offset;                 /* New mail offset */
  60.     char *   result;     /* fget and fputs status */
  61.     int     save_errno;     /* Save the error value we
  62.        are trying to print. */
  63.     struct stat             mybuf;                  /*  For fstat() */
  64. #ifdef DEBUG
  65.     if (p->debug) {
  66.         pop_log(p,POP_DEBUG,"Performing maildrop update...");
  67.         pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
  68.     }
  69. #endif
  70.     if (p->stats) {
  71.         pop_log(p,POP_PRIORITY,"Stats: %s %d %d %d %d",
  72.            p->user, p->msgs_deleted, p->bytes_deleted,
  73.            p->msg_count - p->msgs_deleted,
  74.            p->drop_size - p->bytes_deleted);
  75.     }
  76.     if (p->server_mode) {
  77. if (!p->dirty) {
  78. #ifndef KEEP_TEMP_DROP
  79.     /* Added code in pop_dropcopy.c makes unlink ok now. */
  80.     /* s-dorner@uiuc.edu, 12/91 */
  81.     (void)unlink(p->temp_drop);
  82. #endif
  83.     return(POP_SUCCESS);
  84. }
  85. #ifdef MAILOCK
  86. /* Use SVR4 mail locking */
  87. if (maillock(p->user, 1) != 0)
  88.     return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",p->temp_drop,errno));
  89. #endif
  90.     }
  91.     if (p->server_mode)
  92. fstat(fileno(p->drop), &mybuf);
  93.     if ((p->msgs_deleted == p->msg_count) &&
  94. (!p->server_mode || (mybuf.st_size == p->spool_end))) {
  95. /* Truncate before close, to avoid race condition.  */
  96. (void)ftruncate (fileno(p->drop), (OFF_T)0);
  97. #ifndef KEEP_TEMP_DROP
  98. /* Added code in pop_dropcopy.c makes unlink ok now. */
  99. /* s-dorner@uiuc.edu, 12/91 */
  100. (void)unlink(p->temp_drop);
  101. #endif
  102. (void)fclose(p->drop);
  103. if (p->server_mode) {
  104.     (void)fclose(p->hold);
  105. #ifdef MAILOCK
  106.     mailunlock();
  107. #endif
  108. }
  109.         return (POP_SUCCESS);
  110.     }
  111.     if (!p->server_mode) {
  112. #ifdef DEBUG
  113. if (p->debug) 
  114.     pop_log(p,POP_DEBUG,"Opening mail drop "%s"", p->drop_name);
  115. #endif
  116. #ifdef MAILOCK
  117. /* Use SVR4 mail locking */
  118. if (maillock(p->user, 1) != 0)
  119.     return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",
  120. p->drop_name, errno));
  121. #endif
  122. /*  Open the user's real maildrop */
  123. if ((mfd = open(p->drop_name,O_RDWR|O_CREAT,0660)) == -1 ||
  124.     (md = fdopen(mfd,"r+")) == NULL) {
  125. #ifdef MAILOCK
  126.     mailunlock();
  127. #endif
  128.     return pop_msg(p,POP_FAILURE, standard_error, errno);
  129. }
  130.     } else {
  131. #ifdef MAILOCK
  132. /* Use SVR4 mail locking */
  133. if (maillock(p->user, 1) != 0)
  134.     return(pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",
  135. p->drop_name, errno));
  136. #endif
  137. mfd = fileno(p->drop);
  138.     }
  139.     /*  Lock the user's real mail drop */
  140.     if ( flock(mfd,LOCK_EX) == -1 )
  141.     {
  142.         (void)fclose(md) ;
  143. #ifdef MAILOCK
  144. mailunlock();
  145. #endif
  146.         return pop_msg(p,POP_FAILURE, "flock: '%s': %s (%d)", p->drop_name,
  147.             (errno < sys_nerr) ? sys_errlist[errno] : "", errno);
  148.     }
  149.     if (!p->server_mode) {
  150. /* Go to the right places */
  151. (void)fseek(p->drop, 0, SEEK_END); 
  152. offset = ftell(p->drop); 
  153. /*  Append any messages that may have arrived during the session 
  154.     to the temporary maildrop */
  155. while ((nchar = read(mfd, buffer, BBSIZE)) > 0)
  156.     if ( nchar != write(fileno(p->drop), buffer, nchar) ) {
  157. nchar = -1;
  158. break ;
  159.     }
  160. if ( nchar != 0 ) {
  161.     save_errno = errno;
  162.     (void)fclose(md) ;
  163. #ifdef MAILOCK
  164.     mailunlock();
  165. #endif
  166.     (void)ftruncate(fileno(p->drop), (OFF_T)offset);
  167.     (void)fclose(p->drop) ;
  168. #ifdef EDQUOT
  169.     if (save_errno == EDQUOT) {
  170. pop_msg(p, POP_FAILURE,
  171. "Overquota: appending messages from mailspool to temporary drop (%d)",
  172. errno);
  173.     } else
  174. #endif
  175. pop_msg(p, POP_FAILURE,
  176.       "Error appending messages from mailspool to temporary drop (%d)",
  177.     errno);
  178. }
  179. fflush(md);
  180. rewind(md);
  181. (void)ftruncate(mfd, (OFF_T)0) ;
  182. (void)lseek(mfd, (OFF_T)0, L_SET);
  183. /* Synch stdio and the kernel for the POP drop */
  184. rewind(p->drop);
  185. (void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
  186. /*  Transfer messages not flagged for deletion from the temporary 
  187.     maildrop to the new maildrop */
  188. #ifdef DEBUG
  189. if (p->debug) 
  190.     pop_log(p,POP_DEBUG,"Creating new maildrop "%s" from "%s"",
  191.     p->drop_name,p->temp_drop);
  192. #endif
  193.     } else {
  194. /* Move this stuff later */
  195. fstat(fileno(p->drop), &mybuf);
  196. md = p->hold; /* Really the temp drop */
  197. mfd = fileno(md);
  198.     }
  199.     if (!p->server_mode || (p->msgs_deleted != p->msg_count)) {
  200. for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
  201.     int inheader;
  202.     int body_lines;
  203.     /*  Get a pointer to the message information list */
  204.     mp = &p->mlp[msg_num];
  205.     if (mp->del_flag) {
  206. #ifdef DEBUG
  207. if(p->debug)
  208.     pop_log(p,POP_DEBUG,
  209. "Message %d flagged for deletion.",mp->number);
  210. #endif
  211. continue;
  212.     }
  213.     (void)fseek(p->drop, mp->offset, SEEK_SET);
  214. #ifdef DEBUG
  215.     if(p->debug)
  216. pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
  217. #endif
  218.     /* Put the From line separator */
  219.     fgets(buffer, MAXMSGLINELEN, p->drop);
  220.     if (fputs(buffer, md) == EOF)
  221. break;
  222.     sprintf(buffer, "%s %s", "X-UIDL:", mp->uidl_str);
  223.     if (fputs(buffer, md) == EOF)
  224. break;
  225.     for(status_written=0,inheader=1;
  226.     fgets(buffer,MAXMSGLINELEN,p->drop);) {
  227. if (inheader) { /* Header */
  228.     /*  A blank line signals the end of the header. */
  229.     if (*buffer == 'n') {
  230. #ifndef NO_STATUS
  231. if (status_written == 0) {
  232.     if (mp->retr_flag) {
  233. (void)sprintf(buffer, "Status: ROnn");
  234.     } else {
  235. (void)sprintf(buffer, "Status: Unn");
  236.     }
  237. }
  238. #endif
  239. inheader = 0;
  240. body_lines = 1;
  241. status_written = 0;
  242.     } else if (!strncasecmp(buffer, "X-UIDL:", 7)) {
  243. continue; /* Skip all existing UIDL lines */
  244.     } else if (!strncasecmp(buffer,"Status:", 7)) {
  245. /*  Update the message status */
  246. if (mp->retr_flag)
  247.     sprintf(buffer, "Status: ROn");
  248. status_written++;
  249.     }
  250.     /*  Save another header line */
  251.     if (fputs(buffer, md) == EOF)
  252. break;
  253.     } else { /* Body */ 
  254. if (++body_lines > mp->body_lines)
  255.     break;
  256. if (fputs(buffer, md) == EOF)
  257.     break;
  258.     }
  259.     }
  260.     if (ferror(md)) {
  261. break;
  262.     }
  263.     if (p->mmdf_separator) {
  264. fputs(p->mmdf_separator, md);
  265.     }
  266. }
  267.     /* flush and check for errors now!  The new mail will writen
  268.        without stdio,  since we need not separate messages */
  269. if (ferror(md)) {
  270.     save_errno = errno;
  271.     (void)ftruncate(mfd, (OFF_T)0) ;
  272.     (void)fclose(md) ;
  273. #ifdef MAILOCK
  274.     mailunlock();
  275. #endif
  276.     (void)fclose(p->drop) ;
  277. #ifdef EDQUOT
  278.     if (save_errno == EDQUOT)
  279. return pop_msg(p, POP_FAILURE,
  280.     "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  281.     save_errno);
  282.     else
  283. #endif
  284. return pop_msg(p,POP_FAILURE, standard_error, errno);
  285. }
  286. (void)fflush(md) ;
  287. if (ferror(md)) {
  288.     int save_error = errno;
  289.     (void)ftruncate(mfd, (OFF_T)0) ;
  290.     (void)close(mfd) ;
  291. #ifdef MAILOCK
  292.     mailunlock();
  293. #endif
  294.     (void)fclose(p->drop);
  295. #ifdef EDQUOT
  296.     if (save_errno == EDQUOT)
  297. return pop_msg(p, POP_FAILURE,
  298.     "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  299.     save_errno);
  300.     else
  301. #endif
  302. return pop_msg(p,POP_FAILURE, standard_error, errno);
  303. }
  304.     } /* p->msgs_deleted != p->msg_count */
  305.     if (p->server_mode) {
  306. if (mybuf.st_size > p->spool_end) {
  307.     /* Go to the right places */
  308.     (void)lseek(fileno(p->drop), (OFF_T)p->spool_end, L_SET); 
  309.     /*  Append any messages that may have arrived during the session 
  310. to the temporary maildrop */
  311.     while ((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
  312. if ( nchar != write(mfd, buffer, nchar) ) {
  313.     nchar = -1;
  314.     break ;
  315. }
  316.     if ( nchar != 0 ) {
  317. #ifdef MAILOCK
  318. mailunlock();
  319. #endif
  320. (void)ftruncate(mfd, (OFF_T)0) ;
  321. (void)close(mfd) ;
  322. #ifdef EDQUOT
  323. if (errno == EDQUOT) {
  324.     pop_msg(p, POP_FAILURE,
  325. "Overquota: appending messages from mailspool to temporary drop (%d)",
  326.     errno);
  327. } else
  328. #endif
  329.     pop_msg(p, POP_FAILURE,
  330.     "Error appending messages from mailspool to temporary drop (%d)",
  331. errno);
  332.     }
  333. }
  334. rewind(p->drop);
  335. (void)ftruncate(fileno(p->drop), (OFF_T)0);
  336. (void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
  337. (void)lseek(mfd, (OFF_T)0, L_SET);
  338. while ((nchar = read(mfd, buffer, BBSIZE)) > 0)
  339.     if (nchar != write(fileno(p->drop), buffer, nchar)) {
  340. nchar = -1;
  341. break ;
  342.     }
  343. if ( nchar != 0 ) {
  344.     (void)ftruncate(fileno(p->drop), (OFF_T)0);
  345.     (void)fclose(p->drop);
  346. #ifdef MAILOCK
  347.     mailunlock();
  348. #endif
  349.     (void)fclose(md);
  350. #ifdef EDQUOT
  351.     if (errno == EDQUOT) {
  352. pop_msg(p, POP_FAILURE,
  353. "Overquota: copying messages back to mailspool (%d)", errno);
  354.     } else
  355. #endif
  356. pop_msg(p, POP_FAILURE,
  357.     "Error appending messages from temporary drop to mailspool (%d)",
  358. errno);
  359. }
  360. (void)fclose(md);
  361. #ifdef MAILOCK
  362. mailunlock();
  363. #endif
  364. (void)ftruncate(mfd, (OFF_T)0);
  365. #ifndef KEEP_TEMP_DROP
  366. /* Added code in pop_dropcopy.c makes unlink ok now. */
  367. /* s-dorner@uiuc.edu, 12/91 */
  368. (void)fclose(p->drop);
  369. #endif
  370. (void)unlink(p->temp_drop);
  371.     } else {
  372. /* Go to start of new mail if any */
  373. (void)lseek(fileno(p->drop), (OFF_T)offset, L_SET);
  374. /* Copy over any new mail that arrived while processing the pop drop */
  375. while((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
  376.     if ( nchar != write(mfd, buffer, nchar) ) {
  377. nchar = -1;
  378. break ;
  379.     }
  380. if ( nchar != 0 ) {
  381.     int save_error = errno;
  382.     (void)ftruncate(mfd, (OFF_T)0) ;
  383.     (void)fclose(md) ;
  384. #ifdef MAILOCK
  385.     mailunlock();
  386. #endif
  387.     (void)fclose(p->drop) ;
  388. #ifdef EDQUOT
  389.     if (save_errno == EDQUOT)
  390. return pop_msg(p, POP_FAILURE,
  391.     "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  392. save_errno);
  393.     else
  394. #endif
  395. return pop_msg(p,POP_FAILURE, standard_error, errno);
  396. }
  397. /*  Close the maildrop and empty temporary maildrop */
  398. (void)fclose(md);
  399. #ifdef MAILOCK
  400. mailunlock();
  401. #endif
  402. (void)ftruncate(fileno(p->drop), (OFF_T)0);
  403. #ifndef KEEP_TEMP_DROP
  404. /* Added code in pop_dropcopy.c makes unlink ok now. */
  405. /* s-dorner@uiuc.edu, 12/91 */
  406. (void)unlink(p->temp_drop);
  407. #endif
  408. (void)fclose(p->drop);
  409.     }
  410.     return(pop_quit(p));
  411. }
  412. int pop_restore (p)
  413. POP *p;
  414. {
  415.   FILE    *md;
  416.   int     mfd;
  417.   char    buffer[BBSIZE];
  418.   int     nchar;
  419.   long    offset;
  420.   int     save_errno;
  421. #ifdef DEBUG
  422.     if (p->debug)
  423.         pop_log(p,POP_DEBUG,"Performing maildrop restoration...");
  424. #endif
  425.     if (p->server_mode)
  426.     {
  427. #ifndef KEEP_TEMP_DROP        
  428.         (void) unlink(p->temp_drop);
  429. #endif        
  430.         return(POP_SUCCESS);
  431.     }
  432. #ifdef DEBUG
  433.     if (p->debug)
  434.         pop_log(p,POP_DEBUG,"Opening mail drop "%s"", p->drop_name);
  435. #endif
  436. #ifdef MAILOCK
  437.     if (maillock(p->user, 1))
  438.         return pop_msg(p,POP_FAILURE,"maillock: '%s' (%d)",p->drop_name, errno);
  439. #endif
  440.     if ((mfd = open(p->drop_name,O_RDWR | O_CREAT,0660)) == -1 ||
  441.         (md = fdopen(mfd, "r+")) == NULL)
  442.     {
  443. #ifdef MAILOCK
  444.         mailunlock();
  445. #endif
  446.         return pop_msg(p,POP_FAILURE, standard_error, errno);
  447.     }
  448.     if (flock(mfd, LOCK_EX) == -1)
  449.     {
  450.         (void) fclose(md);
  451. #ifdef MAILOCK
  452.         mailunlock();
  453. #endif
  454.         return pop_msg(p,POP_FAILURE, "flock: '%s': %s (%d)", p->drop_name,
  455.             (errno < sys_nerr) ? sys_errlist[errno]: "", errno);
  456.     }
  457.     (void)fseek(p->drop, 0, SEEK_END);
  458.     offset = ftell(p->drop);
  459.     /* Append any messages that may have arrived during the session 
  460.          to the temporary mail drop */
  461.     while ((nchar = read(mfd,buffer, BBSIZE)) > 0)
  462.         if ( nchar != write(fileno(p->drop), buffer, nchar))
  463.         {
  464.             nchar = -1;
  465.             break;
  466.         }
  467.         if ( nchar != 0)
  468.         {
  469.     save_errno = errno;
  470.             (void) fclose(md);
  471. #ifdef MAILOCK
  472.             mailunlock();
  473. #endif
  474.             (void)ftruncate(fileno(p->drop), (OFF_T)offset);
  475.             (void)fclose(p->drop);
  476. #ifdef EDQUOT
  477.             if (save_errno == EDQUOT)
  478.             {
  479.                 pop_msg(p, POP_FAILURE, 
  480.                   "Overquota: appending messages to temporary drop (%d)",
  481.                   errno);
  482.             }
  483.             else
  484. #endif
  485.             pop_msg(p, POP_FAILURE,
  486.                 "Error appending messages from mailspool to temporary drop (%d)",
  487.                  errno);
  488.        }
  489.        fflush(md);
  490.        rewind(md);
  491.        (void)ftruncate(mfd, (OFF_T)0);
  492.        (void)lseek(mfd, (OFF_T)0, L_SET);
  493.        rewind(p->drop);
  494.        (void)lseek(fileno(p->drop), (OFF_T)0, L_SET);
  495.        
  496.        while((nchar = read(fileno(p->drop), buffer, BBSIZE)) > 0)
  497.             if (nchar != write(mfd, buffer, nchar))
  498.             {
  499.                 nchar = -1;
  500.                 break;
  501.             }
  502.        if (nchar != 0)
  503.        {
  504.            save_errno = errno;
  505.            (void) ftruncate(mfd, (OFF_T)0);
  506.            (void) fclose(md);
  507. #ifdef MAILOCK
  508.            mailunlock();
  509. #endif
  510.            (void)fclose(p->drop);
  511. #ifdef EDQUOT
  512.            if (save_errno == EDQUOT)
  513.                return pop_msg(p, POP_FAILURE,
  514.                   "Overquota copying messages to Mailspool. Temp drop unchanged (%d)",
  515.                    save_errno);
  516.            else
  517. #endif
  518.            return pop_msg(p,POP_FAILURE, standard_error, errno);
  519.        }
  520.        (void) fclose(md);
  521. #ifdef MAILOCK
  522.        mailunlock();
  523. #endif
  524.        (void) ftruncate(fileno(p->drop), (OFF_T)0);
  525. #ifndef KEEP_TEMP_DROP
  526.        (void) unlink(p->temp_drop);
  527. #endif
  528.        (void) fclose(p->drop);
  529.        return pop_quit(p);
  530. }