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.
10 static char standard_error
[] =
11 "Error error updating primary drop. Mailbox unchanged";
14 * updt: Apply changes to a user's POP maildrop
20 FILE * md
; /* Stream pointer for
21 the user's maildrop */
22 int mfd
; /* File descriptor for
24 char buffer
[BUFSIZ
]; /* Read buffer */
26 MsgInfoList
* mp
; /* Pointer to message
28 int msg_num
; /* Current message
30 int status_written
; /* Status header field
32 int nchar
; /* Bytes read/written */
34 long offset
; /* New mail offset */
40 pop_log(p
,POP_DEBUG
,"Performing maildrop update...");
41 pop_log(p
,POP_DEBUG
,"Checking to see if all messages were deleted");
46 return pop_maildir_update(p
);
48 if (p
->msgs_deleted
== p
->msg_count
) {
49 /* Truncate before close, to avoid race condition, DO NOT UNLINK!
50 Another process may have opened, and not yet tried to lock */
51 ftruncate ((int)fileno(p
->drop
),0);
58 pop_log(p
,POP_DEBUG
,"Opening mail drop \"%s\"",p
->drop_name
);
61 /* Open the user's real maildrop */
62 if ((mfd
= open(p
->drop_name
,O_RDWR
|O_CREAT
,0600)) == -1 ||
63 (md
= fdopen(mfd
,"r+")) == NULL
) {
64 return pop_msg(p
,POP_FAILURE
,standard_error
);
67 /* Lock the user's real mail drop */
68 if ( flock(mfd
, LOCK_EX
) == -1 ) {
70 return pop_msg(p
,POP_FAILURE
, "flock: '%s': %s", p
->temp_drop
,
74 /* Go to the right places */
75 offset
= lseek((int)fileno(p
->drop
),0,SEEK_END
) ;
77 /* Append any messages that may have arrived during the session
78 to the temporary maildrop */
79 while ((nchar
=read(mfd
,buffer
,BUFSIZ
)) > 0)
80 if ( nchar
!= write((int)fileno(p
->drop
),buffer
,nchar
) ) {
86 ftruncate((int)fileno(p
->drop
),(int)offset
) ;
88 return pop_msg(p
,POP_FAILURE
,standard_error
);
92 lseek(mfd
,0,SEEK_SET
);
95 /* Synch stdio and the kernel for the POP drop */
97 lseek((int)fileno(p
->drop
),0,SEEK_SET
);
99 /* Transfer messages not flagged for deletion from the temporary
100 maildrop to the new maildrop */
103 pop_log(p
,POP_DEBUG
,"Creating new maildrop \"%s\" from \"%s\"",
104 p
->drop_name
,p
->temp_drop
);
107 for (msg_num
= 0; msg_num
< p
->msg_count
; ++msg_num
) {
111 /* Get a pointer to the message information list */
112 mp
= &p
->mlp
[msg_num
];
114 if (mp
->flags
& DEL_FLAG
) {
118 "Message %d flagged for deletion.",mp
->number
);
123 fseek(p
->drop
,mp
->offset
,0);
127 pop_log(p
,POP_DEBUG
,"Copying message %d.",mp
->number
);
130 for(status_written
= doing_body
= 0 ;
131 fgets(buffer
,MAXMSGLINELEN
,p
->drop
);) {
133 if (doing_body
== 0) { /* Header */
135 /* Update the message status */
136 if (strncasecmp(buffer
,"Status:",7) == 0) {
137 if (mp
->flags
& RETR_FLAG
)
138 fputs("Status: RO\n",md
);
144 /* A blank line signals the end of the header. */
145 if (*buffer
== '\n') {
147 if (status_written
== 0) {
148 if (mp
->flags
& RETR_FLAG
)
149 fputs("Status: RO\n\n",md
);
151 fputs("Status: U\n\n",md
);
153 else fputs ("\n", md
);
156 /* Save another header line */
160 if (blank_line
&& strncmp(buffer
,"From ",5) == 0) break;
162 blank_line
= (*buffer
== '\n');
167 /* flush and check for errors now! The new mail will writen
168 without stdio, since we need not separate messages */
175 return pop_msg(p
,POP_FAILURE
,standard_error
);
178 /* Go to start of new mail if any */
179 lseek((int)fileno(p
->drop
),offset
,SEEK_SET
);
181 while((nchar
=read((int)fileno(p
->drop
),buffer
,BUFSIZ
)) > 0)
182 if ( nchar
!= write(mfd
,buffer
,nchar
) ) {
190 return pop_msg(p
,POP_FAILURE
,standard_error
);
193 /* Close the maildrop and empty temporary maildrop */
195 ftruncate((int)fileno(p
->drop
),0);