s/qmail 4.2.29a
Next generation secure email transport
Loading...
Searching...
No Matches
qmail-pop3d.c
Go to the documentation of this file.
1#include <unistd.h>
2#include <sys/types.h>
3#include <sys/stat.h>
4#include "commands.h"
5#include "sig.h"
6#include "getln.h"
7#include "stralloc.h"
8#include "buffer.h"
9#include "alloc.h"
10#include "open.h"
11#include "prioq.h"
12#include "scan.h"
13#include "fmt.h"
14#include "str.h"
15#include "exit.h"
16#include "maildir.h"
17#include "timeout.h"
18
19#define FDIN 0
20#define FDOUT 1
21
22int rename(const char *,const char *); // stdio.h
23
24void die() { _exit(0); }
25
26ssize_t saferead(int fd,char *buf,int len)
27{
28 int r;
29 r = timeoutread(1200,fd,buf,len);
30 if (r <= 0) die();
31 return r;
32}
33
34ssize_t safewrite(int fd,char *buf,int len)
35{
36 int r;
37 r = timeoutwrite(1200,fd,buf,len);
38 if (r <= 0) die();
39 return r;
40}
41
42char outbuf[1024];
43buffer bo = BUFFER_INIT(safewrite,FDOUT,outbuf,sizeof(outbuf));
44
45char inbuf[128];
46buffer bi = BUFFER_INIT(saferead,FDIN,inbuf,sizeof(inbuf));
47
48void out(char *buf,int len)
49{
50 buffer_put(&bo,buf,len);
51}
52void outs(char *s)
53{
54 buffer_puts(&bo,s);
55}
56void flush()
57{
58 buffer_flush(&bo);
59}
60void err(char *s)
61{
62 outs("-ERR ");
63 outs(s);
64 outs("\r\n");
65 flush();
66}
67
68void die_nomem() { err("out of memory"); die(); }
69void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); }
70void die_scan() { err("unable to scan $HOME/Maildir"); die(); }
71
72void err_syntax() { err("syntax error"); }
73void err_unimpl() { err("unimplemented"); }
74void err_deleted() { err("already deleted"); }
75void err_nozero() { err("messages are counted from 1"); }
76void err_toobig() { err("not that many messages"); }
77void err_nosuch() { err("unable to open that message"); }
78void err_nounlink() { err("unable to unlink all deleted messages"); }
79
80void okay() { outs("+OK \r\n"); flush(); }
81
82void printfn(char *fn)
83{
84 fn += 4;
85 out(fn,str_chr(fn,':'));
86}
87
88char strnum[FMT_ULONG];
89stralloc line = {0};
90
91void blast(buffer *bf,unsigned long limit)
92{
93 int match;
94 int inheaders = 1;
95
96 for (;;) {
97 if (getln(bf,&line,&match,'\n') != 0) die();
98 if (!match && !line.len) break;
99 if (match) --line.len; /* no way to pass this info over POP */
100 if (limit) if (!inheaders) if (!--limit) break;
101 if (!line.len)
102 inheaders = 0;
103 else
104 if (line.s[0] == '.')
105 out(".",1);
106 out(line.s,line.len);
107 out("\r\n",2);
108
109 if (!match) break;
110 }
111 out("\r\n.\r\n",5);
112 flush();
113}
114
115stralloc filenames = {0};
116prioq pq = {0};
117
118struct message {
120 unsigned long size;
121 char *fn;
122} *m;
123
125int last = 0;
126
128{
129 struct prioq_elt pe;
130 struct stat st;
131 int i;
132
134 if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan();
135
136 numm = pq.p ? pq.len : 0;
137 m = (struct message *) alloc(numm * sizeof(struct message));
138 if (!m) die_nomem();
139
140 for (i = 0; i < numm; ++i) {
141 if (!prioq_min(&pq,&pe)) { numm = i; break; }
143 m[i].fn = filenames.s + pe.id;
144 m[i].flagdeleted = 0;
145 if (stat(m[i].fn,&st) == -1)
146 m[i].size = 0;
147 else
148 m[i].size = st.st_size;
149 }
150}
151
153{
154 int i;
155 unsigned long total;
156
157 total = 0;
158 for (i = 0; i < numm; ++i)
159 if (!m[i].flagdeleted) total += m[i].size;
160
161 outs("+OK ");
162 out(strnum,fmt_uint(strnum,numm));
163 outs(" ");
164 out(strnum,fmt_ulong(strnum,total));
165 outs("\r\n");
166 flush();
167}
168
170{
171 int i;
172
173 for (i = 0; i < numm; ++i)
174 m[i].flagdeleted = 0;
175 last = 0;
176 okay();
177}
178
180{
181 outs("+OK ");
182 out(strnum,fmt_uint(strnum,last));
183 outs("\r\n");
184 flush();
185}
186
188{
189 int i;
190
191 for (i = 0; i < numm; ++i)
192 if (m[i].flagdeleted) {
193 if (unlink(m[i].fn) == -1) err_nounlink();
194 } else {
195 if (str_start(m[i].fn,"new/")) {
196 if (!stralloc_copys(&line,"cur/")) die_nomem();
197 if (!stralloc_cats(&line,m[i].fn + 4)) die_nomem();
198 if (!stralloc_cats(&line,":2,")) die_nomem();
199 if (!stralloc_0(&line)) die_nomem();
200 rename(m[i].fn,line.s); /* if it fails, bummer */
201 }
202 }
203 okay();
204 die();
205}
206
207int msgno(char *arg)
208{
209 unsigned long u;
210
211 if (!scan_ulong(arg,&u)) { err_syntax(); return -1; }
212 if (!u) { err_nozero(); return -1; }
213 --u;
214 if (u >= numm) { err_toobig(); return -1; }
215 if (m[u].flagdeleted) { err_deleted(); return -1; }
216 return u;
217}
218
219void pop3_dele(char *arg)
220{
221 int i;
222
223 i = msgno(arg);
224 if (i == -1) return;
225 m[i].flagdeleted = 1;
226 if (i + 1 > last) last = i + 1;
227 okay();
228}
229
230void list(int i,int flaguidl)
231{
232 out(strnum,fmt_uint(strnum,i + 1));
233 outs(" ");
234 if (flaguidl) printfn(m[i].fn);
235 else out(strnum,fmt_ulong(strnum,m[i].size));
236 outs("\r\n");
237}
238
239void dolisting(char *arg,int flaguidl)
240{
241 unsigned int i;
242
243 if (*arg) {
244 i = msgno(arg);
245 if (i == -1) return;
246
247 outs("+OK ");
248 list(i,flaguidl);
249 } else {
250 okay();
251 for (i = 0; i < numm; ++i)
252 if (!m[i].flagdeleted) list(i,flaguidl);
253 outs(".\r\n");
254 }
255 flush();
256}
257
258void pop3_uidl(char *arg) { dolisting(arg,1); }
259void pop3_list(char *arg) { dolisting(arg,0); }
260
261char msgbuf[1024];
262buffer bm;
263
264void pop3_top(char *arg)
265{
266 int i;
267 unsigned long limit;
268 int fd;
269
270 i = msgno(arg);
271 if (i == -1) return;
272
273 arg += scan_ulong(arg,&limit);
274 while (*arg == ' ') ++arg;
275 if (scan_ulong(arg,&limit)) ++limit;
276 else limit = 0;
277
278 fd = open_read(m[i].fn);
279 if (fd == -1) { err_nosuch(); return; }
280 okay();
281 buffer_init(&bm,read,fd,msgbuf,sizeof(msgbuf));
282 blast(&bm,limit);
283 close(fd);
284}
285
287 { "quit", pop3_quit, 0 }
288, { "stat", pop3_stat, 0 }
289, { "list", pop3_list, 0 }
290, { "uidl", pop3_uidl, 0 }
291, { "dele", pop3_dele, 0 }
292, { "retr", pop3_top, 0 }
293, { "rset", pop3_rset, 0 }
294, { "last", pop3_last, 0 }
295, { "top", pop3_top, 0 }
296, { "noop", okay, 0 }
297, { 0, err_unimpl, 0 }
298} ;
299
300int main(int argc,char **argv)
301{
302 sig_alarmcatch(die);
303 sig_pipeignore();
304
305 if (!argv[1]) die_nomaildir();
306 if (chdir(argv[1]) == -1) die_nomaildir();
307
308 getlist();
309
310 okay();
312 die();
313}
int main()
Definition: chkshsgr.c:6
int stralloc_copys(stralloc *, char const *)
stralloc out
Definition: dnscname.c:12
void _exit()
char buf[100+FMT_ULONG]
Definition: hier.c:10
int maildir_scan(prioq *, stralloc *, int, int)
Definition: maildir.c:83
void maildir_clean(stralloc *)
Definition: maildir.c:27
int match
Definition: matchup.c:195
void prioq_delmin()
int prioq_min()
int fd
char msgbuf[1024]
Definition: qmail-pop3d.c:261
void die()
Definition: qmail-pop3d.c:24
ssize_t saferead(int fd, char *buf, int len)
Definition: qmail-pop3d.c:26
void err_nosuch()
Definition: qmail-pop3d.c:77
void die_scan()
Definition: qmail-pop3d.c:70
stralloc filenames
Definition: qmail-pop3d.c:115
char inbuf[128]
Definition: qmail-pop3d.c:45
void die_nomem()
Definition: qmail-pop3d.c:68
void pop3_quit()
Definition: qmail-pop3d.c:187
void pop3_last()
Definition: qmail-pop3d.c:179
char strnum[FMT_ULONG]
Definition: qmail-pop3d.c:88
int rename(const char *, const char *)
void pop3_top(char *arg)
Definition: qmail-pop3d.c:264
void err(char *s)
Definition: qmail-pop3d.c:60
char outbuf[1024]
Definition: qmail-pop3d.c:42
void okay()
Definition: qmail-pop3d.c:80
void die_nomaildir()
Definition: qmail-pop3d.c:69
void err_nounlink()
Definition: qmail-pop3d.c:78
void getlist()
Definition: qmail-pop3d.c:127
int last
Definition: qmail-pop3d.c:125
struct message * m
prioq pq
Definition: qmail-pop3d.c:116
void printfn(char *fn)
Definition: qmail-pop3d.c:82
void pop3_list(char *arg)
Definition: qmail-pop3d.c:259
void dolisting(char *arg, int flaguidl)
Definition: qmail-pop3d.c:239
int numm
Definition: qmail-pop3d.c:124
void err_nozero()
Definition: qmail-pop3d.c:75
void pop3_rset()
Definition: qmail-pop3d.c:169
void list(int i, int flaguidl)
Definition: qmail-pop3d.c:230
stralloc line
Definition: qmail-pop3d.c:89
buffer bi
Definition: qmail-pop3d.c:46
#define FDOUT
Definition: qmail-pop3d.c:20
void pop3_dele(char *arg)
Definition: qmail-pop3d.c:219
void err_unimpl()
Definition: qmail-pop3d.c:73
void err_deleted()
Definition: qmail-pop3d.c:74
void err_syntax()
Definition: qmail-pop3d.c:72
buffer bm
Definition: qmail-pop3d.c:262
void pop3_stat()
Definition: qmail-pop3d.c:152
#define FDIN
Definition: qmail-pop3d.c:19
buffer bo
Definition: qmail-pop3d.c:43
void flush()
Definition: qmail-pop3d.c:56
void pop3_uidl(char *arg)
Definition: qmail-pop3d.c:258
void err_toobig()
Definition: qmail-pop3d.c:76
struct commands pop3commands[]
Definition: qmail-pop3d.c:286
int msgno(char *arg)
Definition: qmail-pop3d.c:207
void outs(char *s)
Definition: qmail-pop3d.c:52
stralloc fn
Definition: qmail-qmaint.c:483
unsigned long size
Definition: qmail-qread.c:55
void blast()
Definition: qmail-remote.c:375
buffer bf
Definition: qmail-remote.c:315
ssize_t safewrite()
unsigned long size
Definition: qmail-pop3d.c:120
int flagdeleted
Definition: qmail-pop3d.c:119
char * fn
Definition: qmail-pop3d.c:121
Definition: prioq.h:7
unsigned long id
Definition: prioq.h:7