13 #include "readwrite.h"
14 #include "timeoutread.h"
15 #include "timeoutwrite.h"
17 void die() { _exit(1); }
19 int saferead(fd
,buf
,len
) int fd
; char *buf
; int len
;
22 r
= timeoutread(1200,fd
,buf
,len
);
27 int safewrite(fd
,buf
,len
) int fd
; char *buf
; int len
;
30 r
= timeoutwrite(1200,fd
,buf
,len
);
36 substdio ssout
= SUBSTDIO_FDBUF(safewrite
,1,ssoutbuf
,sizeof ssoutbuf
);
39 substdio ssin
= SUBSTDIO_FDBUF(saferead
,0,ssinbuf
,sizeof ssinbuf
);
43 substdio_puts(&ssout
,s
);
47 substdio_flush(&ssout
);
57 void die_usage() { err("usage: popup hostname subprogram"); die(); }
58 void die_nomem() { err("out of memory"); die(); }
59 void die_pipe() { err("unable to open pipe"); die(); }
60 void die_write() { err("unable to write pipe"); die(); }
61 void die_fork() { err("unable to fork"); die(); }
62 void die_childcrashed() { err("aack, child crashed"); }
63 void die_badauth() { err("authorization failed"); }
65 void err_syntax() { err("syntax error"); }
66 void err_wantuser() { err("USER first"); }
67 void err_authoriz() { err("authorization first"); }
69 void okay() { puts("+OK \r\n"); flush(); }
70 void pop3_quit() { okay(); die(); }
73 char unique
[FMT_ULONG
+ FMT_ULONG
+ 3];
75 stralloc username
= {0};
82 void doanddie(user
,userlen
,pass
)
84 unsigned int userlen
; /* including 0 byte */
91 if (fd_copy(2,1) == -1) die_pipe();
93 if (pipe(pi
) == -1) die_pipe();
94 if (pi
[0] != 3) die_pipe();
95 switch(child
= fork()) {
101 execvp(*childargs
,childargs
);
105 substdio_fdbuf(&ssup
,write
,pi
[1],upbuf
,sizeof upbuf
);
106 if (substdio_put(&ssup
,user
,userlen
) == -1) die_write();
107 if (substdio_put(&ssup
,pass
,str_len(pass
) + 1) == -1) die_write();
108 if (substdio_puts(&ssup
,"<") == -1) die_write();
109 if (substdio_puts(&ssup
,unique
) == -1) die_write();
110 if (substdio_puts(&ssup
,hostname
) == -1) die_write();
111 if (substdio_put(&ssup
,">",2) == -1) die_write();
112 if (substdio_flush(&ssup
) == -1) die_write();
114 byte_zero(pass
,str_len(pass
));
115 byte_zero(upbuf
,sizeof upbuf
);
116 if (wait_pid(&wstat
,child
) == -1) die();
117 if (wait_crashed(wstat
)) die_childcrashed();
118 if (wait_exitcode(wstat
)) die_badauth();
125 s
+= fmt_uint(s
,getpid());
127 s
+= fmt_ulong(s
,(unsigned long) now());
136 void pop3_user(arg
) char *arg
;
138 if (!*arg
) { err_syntax(); return; }
141 if (!stralloc_copys(&username
,arg
)) die_nomem();
142 if (!stralloc_0(&username
)) die_nomem();
144 void pop3_pass(arg
) char *arg
;
146 if (!seenuser
) { err_wantuser(); return; }
147 if (!*arg
) { err_syntax(); return; }
148 doanddie(username
.s
,username
.len
,arg
);
150 void pop3_apop(arg
) char *arg
;
153 space
= arg
+ str_chr(arg
,' ');
154 if (!*space
) { err_syntax(); return; }
156 doanddie(arg
,space
- arg
,space
);
159 struct commands pop3commands
[] = {
160 { "user", pop3_user
, 0 }
161 , { "pass", pop3_pass
, 0 }
162 , { "apop", pop3_apop
, 0 }
163 , { "quit", pop3_quit
, 0 }
164 , { "noop", okay
, 0 }
165 , { 0, err_authoriz
, 0 }
176 if (!hostname
) die_usage();
177 childargs
= argv
+ 2;
178 if (!*childargs
) die_usage();
181 commands(&ssin
,pop3commands
);