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.
11 * Run as the user in `pwd'
15 changeuser(POP
*p
, struct passwd
*pwd
)
17 if(setgid(pwd
->pw_gid
) < 0) {
18 pop_log (p
, POP_PRIORITY
,
19 "Unable to change to gid %u: %s",
20 (unsigned)pwd
->pw_gid
,
22 return pop_msg (p
, POP_FAILURE
,
23 "Unable to change gid");
25 if(setuid(pwd
->pw_uid
) < 0) {
26 pop_log (p
, POP_PRIORITY
,
27 "Unable to change to uid %u: %s",
28 (unsigned)pwd
->pw_uid
,
30 return pop_msg (p
, POP_FAILURE
,
31 "Unable to change uid");
35 pop_log(p
, POP_DEBUG
,"uid = %u, gid = %u",
43 * dropcopy: Make a temporary copy of the user's mail drop and
44 * save a stream pointer for it.
48 pop_dropcopy(POP
*p
, struct passwd
*pwp
)
50 int mfd
; /* File descriptor for
51 the user's maildrop */
52 int dfd
; /* File descriptor for
53 the SERVER maildrop */
54 FILE *tf
; /* The temp file */
55 char template[POP_TMPSIZE
]; /* Temp name holder */
56 char buffer
[BUFSIZ
]; /* Read buffer */
57 long offset
; /* Old/New boundary */
58 int nchar
; /* Bytes written/read */
59 int tf_fd
; /* fd for temp file */
62 /* Create a temporary maildrop into which to copy the updated maildrop */
63 snprintf(p
->temp_drop
, sizeof(p
->temp_drop
), POP_DROP
,p
->user
);
67 pop_log(p
,POP_DEBUG
,"Creating temporary maildrop '%s'",
71 /* Here we work to make sure the user doesn't cause us to remove or
72 * write over existing files by limiting how much work we do while
76 strlcpy(template, POP_TMPDROP
, sizeof(template));
77 if ((tf_fd
= mkstemp(template)) < 0 ||
78 (tf
= fdopen(tf_fd
, "w+")) == NULL
) {
79 pop_log(p
,POP_PRIORITY
,
80 "Unable to create temporary temporary maildrop '%s': %s",template,
82 return pop_msg(p
,POP_FAILURE
,
83 "System error, can't create temporary file.");
86 /* Now give this file to the user */
87 chown(template, pwp
->pw_uid
, pwp
->pw_gid
);
88 chmod(template, 0600);
90 /* Now link this file to the temporary maildrop. If this fails it
91 * is probably because the temporary maildrop already exists. If so,
92 * this is ok. We can just go on our way, because by the time we try
93 * to write into the file we will be running as the user.
95 link(template,p
->temp_drop
);
99 ret
= changeuser(p
, pwp
);
100 if (ret
!= POP_SUCCESS
)
103 /* Open for append, this solves the crash recovery problem */
104 if ((dfd
= open(p
->temp_drop
,O_RDWR
|O_APPEND
|O_CREAT
,0600)) == -1){
105 pop_log(p
,POP_PRIORITY
,
106 "Unable to open temporary maildrop '%s': %s",p
->temp_drop
,
108 return pop_msg(p
,POP_FAILURE
,
109 "System error, can't open temporary file, do you own it?");
112 /* Lock the temporary maildrop */
113 if ( flock (dfd
, (LOCK_EX
| LOCK_NB
)) == -1 )
116 return pop_msg(p
,POP_FAILURE
,
117 "%sMaildrop lock busy! Is another session active?",
118 (p
->flags
& POP_FLAG_CAPA
) ? "[IN-USE] " : "");
121 return pop_msg(p
,POP_FAILURE
,"flock: '%s': %s", p
->temp_drop
,
126 /* May have grown or shrunk between open and lock! */
127 offset
= lseek(dfd
,0, SEEK_END
);
129 /* Open the user's maildrop, If this fails, no harm in assuming empty */
130 if ((mfd
= open(p
->drop_name
,O_RDWR
)) > 0) {
132 /* Lock the maildrop */
133 if (flock (mfd
, LOCK_EX
) == -1) {
135 return pop_msg(p
,POP_FAILURE
, "flock: '%s': %s", p
->temp_drop
,
139 /* Copy the actual mail drop into the temporary mail drop */
140 while ( (nchar
=read(mfd
,buffer
,BUFSIZ
)) > 0 )
141 if ( nchar
!= write(dfd
,buffer
,nchar
) ) {
147 /* Error adding new mail. Truncate to original size,
148 and leave the maildrop as is. The user will not
149 see the new mail until the error goes away.
150 Should let them process the current backlog, in case
151 the error is a quota problem requiring deletions! */
152 ftruncate(dfd
,(int)offset
) ;
154 /* Mail transferred! Zero the mail drop NOW, that we
155 do not have to do gymnastics to figure out what's new
156 and what is old later */
160 /* Close the actual mail drop */
164 /* Acquire a stream pointer for the temporary maildrop */
165 if ( (p
->drop
= fdopen(dfd
,"a+")) == NULL
) {
167 return pop_msg(p
,POP_FAILURE
,"Cannot assign stream for %s",