19 #include "readwrite.h"
24 substdio ssout = SUBSTDIO_FDBUF(write,1,ssoutbuf,sizeof(ssoutbuf));
26 int timeoutread(fd,buf,n) int fd; char *buf; int n;
30 r = read(fd,buf,n); saveerrno = errno;
32 errno = saveerrno; return r;
36 substdio ssin = SUBSTDIO_FDBUF(timeoutread,0,ssinbuf,sizeof(ssinbuf));
39 void die() { _exit(0); }
42 if (substdio_puts(&ssout,s) == -1) die();
46 if (substdio_flush(&ssout) == -1) die();
53 if (substdio_flush(&ssout) == -1) die();
55 void die_nomem() { err("out of memory"); die(); }
56 void die_prot() { err("protection problem"); die(); }
57 void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); }
59 void err_syntax() { err("syntax error"); }
60 void err_unimpl() { err("unimplemented"); }
61 void err_deleted() { err("already deleted"); }
62 void err_nozero() { err("messages are counted from 1"); }
63 void err_toobig() { err("not that many messages"); }
64 void err_nosuch() { err("unable to open that message"); }
65 void err_nounlink() { err("unable to unlink all deleted messages"); }
67 void okay() { puts("+OK \r\n"); flush(); }
68 void pop3_last() { puts("+OK 0\r\n"); flush(); }
71 stralloc dataline = {0};
73 stralloc filenames = {0};
75 stralloc newname = {0};
86 substdio ssmsg; char ssmsgbuf[1024];
89 void blast(ssfrom,limit)
98 if (getln(ssfrom,&dataline,&match,'\n') != 0) die();
99 if (!match && !dataline.len) break;
100 if (match) --dataline.len; /* no way to pass this info over POP */
101 if (limit) if (!inheaders) if (!--limit) break;
105 if (dataline.s[0] == '.')
106 substdio_put(&ssout,".",1);
107 if (substdio_put(&ssout,dataline.s,dataline.len) == -1) die();
108 if (substdio_put(&ssout,"\r\n",2) == -1) die();
111 if (substdio_put(&ssout,"\r\n.\r\n",5) == -1) die();
112 if (substdio_flush(&ssout) == -1) die();
129 if (dir = opendir("tmp"))
131 while (d = readdir(dir))
133 if (str_equal(d->d_name,".")) continue;
134 if (str_equal(d->d_name,"..")) continue;
135 if (!stralloc_copys(&newname,"tmp/")) die_nomem();
136 if (!stralloc_cats(&newname,d->d_name)) die_nomem();
137 if (!stralloc_0(&newname)) die_nomem();
138 if (stat(newname.s,&st) == 0)
139 if (time > st.st_atime + 129600)
145 if (!stralloc_copys(&filenames,"")) die_nomem();
147 if (dir = opendir("new"))
149 while (d = readdir(dir))
151 if (str_equal(d->d_name,".")) continue;
152 if (str_equal(d->d_name,"..")) continue;
154 if (!stralloc_cats(&filenames,"new/")) die_nomem();
155 if (!stralloc_cats(&filenames,d->d_name)) die_nomem();
156 if (!stralloc_0(&filenames)) die_nomem();
157 if (stat(filenames.s + pos,&st) == 0)
161 if (!prioq_insert(&pq,&pe)) die_nomem();
168 if (dir = opendir("cur"))
170 while (d = readdir(dir))
172 if (str_equal(d->d_name,".")) continue;
173 if (str_equal(d->d_name,"..")) continue;
175 if (!stralloc_cats(&filenames,"cur/")) die_nomem();
176 if (!stralloc_cats(&filenames,d->d_name)) die_nomem();
177 if (!stralloc_0(&filenames)) die_nomem();
178 if (stat(filenames.s + pos,&st) == 0)
182 if (!prioq_insert(&pq,&pe)) die_nomem();
189 m = (struct message *) alloc(numm * sizeof(struct message));
192 for (i = 0;i < numm;++i)
194 if (!prioq_min(&pq,&pe)) { numm = i; break; }
196 m[i].fn = filenames.s + pe.id;
197 m[i].flagdeleted = 0;
198 if (stat(m[i].fn,&st) == -1)
201 m[i].size = st.st_size;
207 void printint(u) unsigned int u;
209 foo[fmt_uint(foo,u)] = 0;
214 void printlong(u) unsigned long u;
216 foo[fmt_uint(foo,u)] = 0;
221 void printfn(fn) char *fn;
233 for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size;
243 for (i = 0;i < numm;++i) m[i].flagdeleted = 0;
250 for (i = 0;i < numm;++i)
251 if (m[i].flagdeleted)
252 if (unlink(m[i].fn) == -1) err_nounlink();
257 int msgno(arg) char *arg;
260 if (!arg) { err_syntax(); return -1; }
261 if (!scan_ulong(arg,&u)) { err_syntax(); return -1; }
262 if (!u) { err_nozero(); return -1; }
264 if (u >= numm) { err_toobig(); return -1; }
265 if (m[u].flagdeleted) { err_deleted(); return -1; }
269 void pop3_dele(arg) char *arg;
275 m[i].flagdeleted = 1;
279 void dolisting(arg,flaguidl) char *arg; int flaguidl;
289 if (flaguidl) printfn(m[i].fn); else printlong(m[i].size);
295 for (i = 0;i < numm;++i)
296 if (!m[i].flagdeleted)
299 if (flaguidl) printfn(m[i].fn); else printlong(m[i].size);
306 void pop3_uidl(arg) char *arg; { dolisting(arg,1); }
307 void pop3_list(arg) char *arg; { dolisting(arg,0); }
309 void pop3_top(arg) char *arg;
318 arg += scan_ulong(arg,&limit);
319 while (*arg == ' ') ++arg;
320 if (scan_ulong(arg,&limit)) ++limit; else limit = 0;
322 fd = open_read(m[i].fn);
323 if (fd == -1) { err_nosuch(); return; }
325 substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf));
330 static struct { void (*fun)(); char *text; } pop3cmd[] = {
331 { pop3_quit, "quit" }
332 , { pop3_stat, "stat" }
333 , { pop3_list, "list" }
334 , { pop3_uidl, "uidl" }
335 , { pop3_dele, "dele" }
336 , { pop3_top, "retr" }
337 , { pop3_rset, "rset" }
338 , { pop3_last, "last" }
339 , { pop3_top, "top" }
351 for (i = 0;pop3cmd[i].fun;++i)
353 for (j = 0;ch = pop3cmd[i].text[j];++j)
354 if ((cmd[j] != ch) && (cmd[j] != ch - 32))
357 if (!cmd[j] || (cmd[j] == ' '))
359 while (cmd[j] == ' ') ++j;
361 pop3cmd[i].fun((char *) 0);
363 pop3cmd[i].fun(cmd + j);
374 static stralloc cmd = {0};
380 if (!argv[1]) die_nomaildir();
381 if (chdir(argv[1]) == -1) die_nomaildir();
389 if (getln(&ssin,&cmd,&match,'\n') == -1) die();
391 if (cmd.len == 0) die();
392 if (cmd.s[--cmd.len] != '\n') die();
393 if ((cmd.len > 0) && (cmd.s[cmd.len - 1] == '\r')) --cmd.len;
394 cmd.s[cmd.len++] = 0;