17 #include "readwrite.h"
21 int timeoutread(fd
,buf
,n
) int fd
; char *buf
; int n
;
25 r
= read(fd
,buf
,n
); saveerrno
= errno
;
27 errno
= saveerrno
; return r
;
31 substdio ssin
= SUBSTDIO_FDBUF(timeoutread
,0,ssinbuf
,sizeof(ssinbuf
));
34 void die() { _exit(1); }
37 if (substdio_puts(subfdoutsmall
,s
) == -1) die();
39 void outflush(s
) char *s
;
42 if (substdio_flush(subfdoutsmall
) == -1) die();
46 if (substdio_puts(subfdoutsmall
,"-ERR ") == -1) die();
47 if (substdio_puts(subfdoutsmall
,s
) == -1) die();
48 if (substdio_puts(subfdoutsmall
,"\r\n") == -1) die();
49 if (substdio_flush(subfdoutsmall
) == -1) die();
51 void die_usage() { err("usage: popup hostname subprogram"); die(); }
52 void die_nomem() { err("out of memory"); die(); }
53 void die_pipe() { err("unable to open pipe"); die(); }
54 void die_write() { err("unable to write pipe"); die(); }
55 void die_fork() { err("unable to fork"); die(); }
56 void die_childcrashed() { err("aack, child crashed"); }
57 void die_badauth() { err("authorization failed"); }
59 void err_syntax() { err("syntax error"); }
60 void err_wantuser() { err("USER first"); }
61 void err_authoriz() { err("authorization first"); }
63 void okay() { outflush("+OK \r\n"); }
66 char unique
[FMT_ULONG
+ FMT_ULONG
+ 3];
68 stralloc username
= {0};
75 void doanddie(user
,userlen
,pass
)
77 unsigned int userlen
; /* including 0 byte */
85 if (fd_copy(2,1) == -1) die_pipe();
87 if (pipe(pi
) == -1) die_pipe();
88 if (pi
[0] != 3) die_pipe();
89 switch(child
= fork())
96 execvp(*childargs
,childargs
);
100 substdio_fdbuf(&ssup
,write
,pi
[1],upbuf
,sizeof(upbuf
));
101 if (substdio_put(&ssup
,user
,userlen
) == -1) die_write();
102 if (substdio_put(&ssup
,pass
,str_len(pass
) + 1) == -1) die_write();
103 if (substdio_puts(&ssup
,"<") == -1) die_write();
104 if (substdio_puts(&ssup
,unique
) == -1) die_write();
105 if (substdio_puts(&ssup
,hostname
) == -1) die_write();
106 if (substdio_put(&ssup
,">",2) == -1) die_write();
107 if (substdio_flush(&ssup
) == -1) die_write();
109 for (i
= 0;pass
[i
];++i
) pass
[i
] = 0;
110 for (i
= 0;i
< sizeof(upbuf
);++i
) upbuf
[i
] = 0;
111 if (wait_pid(&wstat
,child
) == -1) die();
112 if (wait_crashed(wstat
)) die_childcrashed();
113 if (wait_exitcode(wstat
)) die_badauth();
120 s
+= fmt_uint(s
,getpid());
122 s
+= fmt_ulong(s
,(unsigned long) now());
131 void pop3_user(arg
) char *arg
;
133 if (!arg
) { err_syntax(); return; }
136 if (!stralloc_copys(&username
,arg
)) die_nomem();
137 if (!stralloc_0(&username
)) die_nomem();
139 void pop3_pass(arg
) char *arg
;
141 if (!seenuser
) { err_wantuser(); return; }
142 if (!arg
) { err_syntax(); return; }
143 doanddie(username
.s
,username
.len
,arg
);
145 void pop3_apop(arg
) char *arg
;
148 if (!arg
) { err_syntax(); return; }
149 space
= arg
+ str_chr(arg
,' ');
150 if (!*space
) { err_syntax(); return; }
152 doanddie(arg
,space
- arg
,space
);
155 void pop3_quit() { okay(); die(); }
157 static struct { void (*fun
)(); char *text
; } pop3cmd
[] = {
158 { pop3_user
, "user" }
159 , { pop3_pass
, "pass" }
160 , { pop3_apop
, "apop" }
161 , { pop3_quit
, "quit" }
173 for (i
= 0;pop3cmd
[i
].fun
;++i
)
175 for (j
= 0;ch
= pop3cmd
[i
].text
[j
];++j
)
176 if ((cmd
[j
] != ch
) && (cmd
[j
] != ch
- 32))
179 if (!cmd
[j
] || (cmd
[j
] == ' '))
181 while (cmd
[j
] == ' ') ++j
;
183 pop3cmd
[i
].fun((char *) 0);
185 pop3cmd
[i
].fun(cmd
+ j
);
196 static stralloc cmd
= {0};
203 if (!hostname
) die_usage();
204 childargs
= argv
+ 2;
205 if (!*childargs
) die_usage();
211 if (getln(&ssin
,&cmd
,&match
,'\n') == -1) die();
213 if (cmd
.len
== 0) die();
214 if (cmd
.s
[--cmd
.len
] != '\n') die();
215 if ((cmd
.len
> 0) && (cmd
.s
[cmd
.len
- 1] == '\r')) --cmd
.len
;
216 cmd
.s
[cmd
.len
++] = 0;