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;