# 2.11BSD#431 - /usr/src/libexec/popper/pop_dropcopy.c

##### Functions

    pop_dropcopy      X

       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

- in /usr/src/libexec/popper/pop_pass.c line 48

#### 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: 1731 |