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: #if !defined(lint) && defined(DOSCCS)
   8: static char copyright[] = "Copyright (c) 1990 Regents of the University of California.\nAll rights reserved.\n";
   9: static char SccsId[] = "@(#)@(#)pop_dropcopy.c	2.6.1  (2.11BSD) 1996/3/21";
  10: #endif not lint
  11: 
  12: #include <errno.h>
  13: #include <stdio.h>
  14: #include <sys/types.h>
  15: #include <strings.h>
  16: #include <sys/stat.h>
  17: #include <sys/file.h>
  18: #include <pwd.h>
  19: #include "popper.h"
  20: 
  21: /*
  22:  *  dropcopy:   Make a temporary copy of the user's mail drop and
  23:  *  save a stream pointer for it.
  24:  */
  25: 
  26: pop_dropcopy(p,pwp)
  27: POP     *   p;
  28: struct passwd   *   pwp;
  29: {
  30:     int                     mfd;                    /*  File descriptor for
  31:                                                         the user's maildrop */
  32:     int                     dfd;                    /*  File descriptor for
  33:                                                         the SERVER maildrop */
  34:     FILE            *tf;            /*  The temp file */
  35:     char            template[POP_TMPSIZE];  /*  Temp name holder */
  36:     char                    buffer[BUFSIZ];         /*  Read buffer */
  37:     long                    offset;                 /*  Old/New boundary */
  38:     int                     nchar;                  /*  Bytes written/read */
  39:     struct stat             mybuf;                  /*  For lstat() */
  40: 
  41:     /*  Create a temporary maildrop into which to copy the updated maildrop */
  42:     (void)sprintf(p->temp_drop,POP_DROP,p->user);
  43: 
  44: #ifdef DEBUG
  45:     if(p->debug)
  46:         pop_log(p,POP_DEBUG,"Creating temporary maildrop '%s'",
  47:             p->temp_drop);
  48: #endif DEBUG
  49: 
  50:     /* Here we work to make sure the user doesn't cause us to remove or
  51:      * write over existing files by limiting how much work we do while
  52:      * running as root.
  53:      */
  54: 
  55:     /* First create a unique file.  Would prefer mkstemp, but Ultrix...*/
  56:     strcpy(template,POP_TMPDROP);
  57:     (void) mktemp(template);
  58:     if ( (tf=fopen(template,"w+")) == NULL ) {  /* failure, bail out	*/
  59:         pop_log(p,POP_PRIORITY,
  60:             "Unable to create temporary temporary maildrop '%s': %s",template,
  61:                 strerror(errno));
  62:         return pop_msg(p,POP_FAILURE,
  63:         "System error, can't create temporary file.");
  64:     }
  65: 
  66:     /* Now give this file to the user	*/
  67:     (void) chown(template,pwp->pw_uid, pwp->pw_gid);
  68:     (void) chmod(template,0600);
  69: 
  70:     /* Now link this file to the temporary maildrop.  If this fails it
  71:      * is probably because the temporary maildrop already exists.  If so,
  72:      * this is ok.  We can just go on our way, because by the time we try
  73:      * to write into the file we will be running as the user.
  74:      */
  75:     (void) link(template,p->temp_drop);
  76:     (void) fclose(tf);
  77:     (void) unlink(template);
  78: 
  79:     /* Now we run as the user. */
  80:     (void) setuid(pwp->pw_uid);
  81:     (void) setgid(pwp->pw_gid);
  82: 
  83: #ifdef DEBUG
  84:     if(p->debug)pop_log(p,POP_DEBUG,"uid = %u, gid = %u",getuid(),getgid());
  85: #endif DEBUG
  86: 
  87:     /* Open for append,  this solves the crash recovery problem */
  88:     if ((dfd = open(p->temp_drop,O_RDWR|O_APPEND|O_CREAT,0600)) == -1){
  89:         pop_log(p,POP_PRIORITY,
  90:             "Unable to open temporary maildrop '%s': %s",p->temp_drop,
  91:                 strerror(errno));
  92:         return pop_msg(p,POP_FAILURE,
  93:         "System error, can't open temporary file, do you own it?");
  94:     }
  95: 
  96:     /*  Lock the temporary maildrop */
  97:     if ( flock (dfd, LOCK_EX|LOCK_NB) == -1 )
  98:     switch(errno) {
  99:         case EWOULDBLOCK:
 100:             return pop_msg(p,POP_FAILURE,
 101:                  "Maildrop lock busy!  Is another session active?");
 102:             /* NOTREACHED */
 103:         default:
 104:             return pop_msg(p,POP_FAILURE,"flock: '%s': %s", p->temp_drop,
 105:                 strerror(errno));
 106:             /* NOTREACHED */
 107:         }
 108: 
 109:     /* May have grown or shrunk between open and lock! */
 110:     offset = lseek(dfd,0L,L_XTND);
 111: 
 112:     /*  Open the user's maildrop, If this fails,  no harm in assuming empty */
 113:     if ((mfd = open(p->drop_name,O_RDWR)) > 0) {
 114: 
 115:         /*  Lock the maildrop */
 116:         if (flock (mfd,LOCK_EX) == -1) {
 117:             (void)close(mfd) ;
 118:             return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
 119:                 strerror(errno));
 120:         }
 121: 
 122:         /*  Copy the actual mail drop into the temporary mail drop */
 123:         while ( (nchar=read(mfd,buffer,BUFSIZ)) > 0 )
 124:             if ( nchar != write(dfd,buffer,nchar) ) {
 125:                 nchar = -1 ;
 126:                 break ;
 127:             }
 128: 
 129:         if ( nchar != 0 ) {
 130:             /* Error adding new mail.  Truncate to original size,
 131:                and leave the maildrop as is.  The user will not
 132:                see the new mail until the error goes away.
 133:                Should let them process the current backlog,  in case
 134:                the error is a quota problem requiring deletions! */
 135:             (void)ftruncate(dfd,offset) ;
 136:         } else {
 137:             /* Mail transferred!  Zero the mail drop NOW,  that we
 138:                do not have to do gymnastics to figure out what's new
 139:                and what is old later */
 140:             (void)ftruncate(mfd,0L) ;
 141:         }
 142: 
 143:         /*  Close the actual mail drop */
 144:         (void)close (mfd);
 145:     }
 146: 
 147:     /*  Acquire a stream pointer for the temporary maildrop */
 148:     if ( (p->drop = fdopen(dfd,"a+")) == NULL ) {
 149:         (void)close(dfd) ;
 150:         return pop_msg(p,POP_FAILURE,"Cannot assign stream for %s",
 151:             p->temp_drop);
 152:     }
 153: 
 154:     rewind (p->drop);
 155: 
 156:     return(POP_SUCCESS);
 157: }

Defined functions

pop_dropcopy defined in line 26; used 1 times

Defined variables

SccsId defined in line 9; never used
copyright defined in line 8; never used
Last modified: 1996-03-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3605
Valid CSS Valid XHTML 1.0 Strict