No empty .Rs/.Re
[netbsd-mini2440.git] / crypto / dist / heimdal / appl / popper / pop_updt.c
blob993ab440a44e918406acdf0ff3792b76ad61e185
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("$Heimdal: pop_updt.c 4798 1998-04-23 18:39:20Z joda $"
9 "$NetBSD$");
11 static char standard_error[] =
12 "Error error updating primary drop. Mailbox unchanged";
14 /*
15 * updt: Apply changes to a user's POP maildrop
18 int
19 pop_updt (POP *p)
21 FILE * md; /* Stream pointer for
22 the user's maildrop */
23 int mfd; /* File descriptor for
24 above */
25 char buffer[BUFSIZ]; /* Read buffer */
27 MsgInfoList * mp; /* Pointer to message
28 info list */
29 int msg_num; /* Current message
30 counter */
31 int status_written; /* Status header field
32 written */
33 int nchar; /* Bytes read/written */
35 long offset; /* New mail offset */
37 int blank_line;
39 #ifdef DEBUG
40 if (p->debug) {
41 pop_log(p,POP_DEBUG,"Performing maildrop update...");
42 pop_log(p,POP_DEBUG,"Checking to see if all messages were deleted");
44 #endif /* DEBUG */
46 if(IS_MAILDIR(p))
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);
53 fclose(p->drop) ;
54 return (POP_SUCCESS);
57 #ifdef DEBUG
58 if (p->debug)
59 pop_log(p,POP_DEBUG,"Opening mail drop \"%s\"",p->drop_name);
60 #endif /* DEBUG */
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 ) {
70 fclose(md) ;
71 return pop_msg(p,POP_FAILURE, "flock: '%s': %s", p->temp_drop,
72 strerror(errno));
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) ) {
82 nchar = -1;
83 break ;
85 if ( nchar != 0 ) {
86 fclose(md) ;
87 ftruncate((int)fileno(p->drop),(int)offset) ;
88 fclose(p->drop) ;
89 return pop_msg(p,POP_FAILURE,standard_error);
92 rewind(md);
93 lseek(mfd,0,SEEK_SET);
94 ftruncate(mfd,0) ;
96 /* Synch stdio and the kernel for the POP drop */
97 rewind(p->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 */
102 #ifdef DEBUG
103 if (p->debug)
104 pop_log(p,POP_DEBUG,"Creating new maildrop \"%s\" from \"%s\"",
105 p->drop_name,p->temp_drop);
106 #endif /* DEBUG */
108 for (msg_num = 0; msg_num < p->msg_count; ++msg_num) {
110 int doing_body;
112 /* Get a pointer to the message information list */
113 mp = &p->mlp[msg_num];
115 if (mp->flags & DEL_FLAG) {
116 #ifdef DEBUG
117 if(p->debug)
118 pop_log(p,POP_DEBUG,
119 "Message %d flagged for deletion.",mp->number);
120 #endif /* DEBUG */
121 continue;
124 fseek(p->drop,mp->offset,0);
126 #ifdef DEBUG
127 if(p->debug)
128 pop_log(p,POP_DEBUG,"Copying message %d.",mp->number);
129 #endif /* DEBUG */
130 blank_line = 1;
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);
140 else
141 fputs(buffer, md);
142 status_written++;
143 continue;
145 /* A blank line signals the end of the header. */
146 if (*buffer == '\n') {
147 doing_body = 1;
148 if (status_written == 0) {
149 if (mp->flags & RETR_FLAG)
150 fputs("Status: RO\n\n",md);
151 else
152 fputs("Status: U\n\n",md);
154 else fputs ("\n", md);
155 continue;
157 /* Save another header line */
158 fputs (buffer, md);
160 else { /* Body */
161 if (blank_line && strncmp(buffer,"From ",5) == 0) break;
162 fputs (buffer, md);
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 */
171 fflush(md) ;
172 if (ferror(md)) {
173 ftruncate(mfd,0) ;
174 fclose(md) ;
175 fclose(p->drop) ;
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) ) {
184 nchar = -1;
185 break ;
187 if ( nchar != 0 ) {
188 ftruncate(mfd,0) ;
189 fclose(md) ;
190 fclose(p->drop) ;
191 return pop_msg(p,POP_FAILURE,standard_error);
194 /* Close the maildrop and empty temporary maildrop */
195 fclose(md);
196 ftruncate((int)fileno(p->drop),0);
197 fclose(p->drop);
199 return(pop_quit(p));