22575: Remove extra ;, From Dennis Davis.
[heimdal.git] / appl / popper / pop_updt.c
blob16102fa52abdd4c15d5fd698084773daf8ce843f
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 */
7 #include <popper.h>
8 RCSID("$Id$");
10 static char standard_error[] =
11 "Error error updating primary drop. Mailbox unchanged";
13 /*
14 * updt: Apply changes to a user's POP maildrop
17 int
18 pop_updt (POP *p)
20 FILE * md; /* Stream pointer for
21 the user's maildrop */
22 int mfd; /* File descriptor for
23 above */
24 char buffer[BUFSIZ]; /* Read buffer */
26 MsgInfoList * mp; /* Pointer to message
27 info list */
28 int msg_num; /* Current message
29 counter */
30 int status_written; /* Status header field
31 written */
32 int nchar; /* Bytes read/written */
34 long offset; /* New mail offset */
36 int blank_line;
38 #ifdef DEBUG
39 if (p->debug) {
40 pop_log(p,POP_DEBUG,"Performing maildrop update...");
41 pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
43 #endif /* DEBUG */
45 if(IS_MAILDIR(p))
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);
52 fclose(p->drop) ;
53 return (POP_SUCCESS);
56 #ifdef DEBUG
57 if (p->debug)
58 pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name);
59 #endif /* DEBUG */
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 ) {
69 fclose(md) ;
70 return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
71 strerror(errno));
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) ) {
81 nchar = -1;
82 break ;
84 if ( nchar != 0 ) {
85 fclose(md) ;
86 ftruncate((int)fileno(p->drop),(int)offset) ;
87 fclose(p->drop) ;
88 return pop_msg(p,POP_FAILURE,standard_error);
91 rewind(md);
92 lseek(mfd,0,SEEK_SET);
93 ftruncate(mfd,0) ;
95 /* Synch stdio and the kernel for the POP drop */
96 rewind(p->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 */
101 #ifdef DEBUG
102 if (p->debug)
103 pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"",
104 p->drop_name,p->temp_drop);
105 #endif /* DEBUG */
107 for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
109 int doing_body;
111 /* Get a pointer to the message information list */
112 mp = &p->mlp[msg_num];
114 if (mp->flags & DEL_FLAG) {
115 #ifdef DEBUG
116 if(p->debug)
117 pop_log(p,POP_DEBUG,
118 "Message %d flagged for deletion.",mp->number);
119 #endif /* DEBUG */
120 continue;
123 fseek(p->drop,mp->offset,0);
125 #ifdef DEBUG
126 if(p->debug)
127 pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
128 #endif /* DEBUG */
129 blank_line = 1;
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);
139 else
140 fputs(buffer, md);
141 status_written++;
142 continue;
144 /* A blank line signals the end of the header. */
145 if (*buffer == '\n') {
146 doing_body = 1;
147 if (status_written == 0) {
148 if (mp->flags & RETR_FLAG)
149 fputs("Status: RO\n\n",md);
150 else
151 fputs("Status: U\n\n",md);
153 else fputs ("\n", md);
154 continue;
156 /* Save another header line */
157 fputs (buffer, md);
159 else { /* Body */
160 if (blank_line && strncmp(buffer,"From ",5) == 0) break;
161 fputs (buffer, md);
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 */
170 fflush(md) ;
171 if (ferror(md)) {
172 ftruncate(mfd,0) ;
173 fclose(md) ;
174 fclose(p->drop) ;
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) ) {
183 nchar = -1;
184 break ;
186 if ( nchar != 0 ) {
187 ftruncate(mfd,0) ;
188 fclose(md) ;
189 fclose(p->drop) ;
190 return pop_msg(p,POP_FAILURE,standard_error);
193 /* Close the maildrop and empty temporary maildrop */
194 fclose(md);
195 ftruncate((int)fileno(p->drop),0);
196 fclose(p->drop);
198 return(pop_quit(p));