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.
8 __RCSID("$Heimdal: pop_updt.c 4798 1998-04-23 18:39:20Z joda $"
11 static char standard_error
[] =
12 "Error error updating primary drop. Mailbox unchanged";
15 * updt: Apply changes to a user's POP maildrop
21 FILE * md
; /* Stream pointer for
22 the user's maildrop */
23 int mfd
; /* File descriptor for
25 char buffer
[BUFSIZ
]; /* Read buffer */
27 MsgInfoList
* mp
; /* Pointer to message
29 int msg_num
; /* Current message
31 int status_written
; /* Status header field
33 int nchar
; /* Bytes read/written */
35 long offset
; /* New mail offset */
41 pop_log(p
,POP_DEBUG
,"Performing maildrop update...");
42 pop_log(p
,POP_DEBUG
,"Checking to see if all messages were deleted");
47 return pop_maildir_update(p
);
49 if (p
->msgs_deleted
== p
->msg_count
) {
50 /* Truncate before close, to avoid race condition, DO NOT UNLINK!
51 Another process may have opened, and not yet tried to lock */
52 ftruncate ((int)fileno(p
->drop
),0);
59 pop_log(p
,POP_DEBUG
,"Opening mail drop \"%s\"",p
->drop_name
);
62 /* Open the user's real maildrop */
63 if ((mfd
= open(p
->drop_name
,O_RDWR
|O_CREAT
,0600)) == -1 ||
64 (md
= fdopen(mfd
,"r+")) == NULL
) {
65 return pop_msg(p
,POP_FAILURE
,standard_error
);
68 /* Lock the user's real mail drop */
69 if ( flock(mfd
, LOCK_EX
) == -1 ) {
71 return pop_msg(p
,POP_FAILURE
, "flock: '%s': %s", p
->temp_drop
,
75 /* Go to the right places */
76 offset
= lseek((int)fileno(p
->drop
),0,SEEK_END
) ;
78 /* Append any messages that may have arrived during the session
79 to the temporary maildrop */
80 while ((nchar
=read(mfd
,buffer
,BUFSIZ
)) > 0)
81 if ( nchar
!= write((int)fileno(p
->drop
),buffer
,nchar
) ) {
87 ftruncate((int)fileno(p
->drop
),(int)offset
) ;
89 return pop_msg(p
,POP_FAILURE
,standard_error
);
93 lseek(mfd
,0,SEEK_SET
);
96 /* Synch stdio and the kernel for the POP drop */
98 lseek((int)fileno(p
->drop
),0,SEEK_SET
);
100 /* Transfer messages not flagged for deletion from the temporary
101 maildrop to the new maildrop */
104 pop_log(p
,POP_DEBUG
,"Creating new maildrop \"%s\" from \"%s\"",
105 p
->drop_name
,p
->temp_drop
);
108 for (msg_num
= 0; msg_num
< p
->msg_count
; ++msg_num
) {
112 /* Get a pointer to the message information list */
113 mp
= &p
->mlp
[msg_num
];
115 if (mp
->flags
& DEL_FLAG
) {
119 "Message %d flagged for deletion.",mp
->number
);
124 fseek(p
->drop
,mp
->offset
,0);
128 pop_log(p
,POP_DEBUG
,"Copying message %d.",mp
->number
);
131 for(status_written
= doing_body
= 0 ;
132 fgets(buffer
,MAXMSGLINELEN
,p
->drop
);) {
134 if (doing_body
== 0) { /* Header */
136 /* Update the message status */
137 if (strncasecmp(buffer
,"Status:",7) == 0) {
138 if (mp
->flags
& RETR_FLAG
)
139 fputs("Status: RO\n",md
);
145 /* A blank line signals the end of the header. */
146 if (*buffer
== '\n') {
148 if (status_written
== 0) {
149 if (mp
->flags
& RETR_FLAG
)
150 fputs("Status: RO\n\n",md
);
152 fputs("Status: U\n\n",md
);
154 else fputs ("\n", md
);
157 /* Save another header line */
161 if (blank_line
&& strncmp(buffer
,"From ",5) == 0) break;
163 blank_line
= (*buffer
== '\n');
168 /* flush and check for errors now! The new mail will writen
169 without stdio, since we need not separate messages */
176 return pop_msg(p
,POP_FAILURE
,standard_error
);
179 /* Go to start of new mail if any */
180 lseek((int)fileno(p
->drop
),offset
,SEEK_SET
);
182 while((nchar
=read((int)fileno(p
->drop
),buffer
,BUFSIZ
)) > 0)
183 if ( nchar
!= write(mfd
,buffer
,nchar
) ) {
191 return pop_msg(p
,POP_FAILURE
,standard_error
);
194 /* Close the maildrop and empty temporary maildrop */
196 ftruncate((int)fileno(p
->drop
),0);