|
|
1.1 root 1: /* popsbr.c - POP client subroutines */
2:
3: /* LINTLIBRARY */
4:
5: #include "../h/strings.h"
6: #include <stdio.h>
7: #include <signal.h>
8:
9:
10: #define NOTOK (-1)
11: #define OK 0
12: #define DONE 1
13:
14: #define TRM "."
15: #define TRMLEN (sizeof TRM - 1)
16:
17: extern int errno;
18: extern int sys_nerr;
19: extern char *sys_errlist[];
20:
21: static int poprint = 0;
22: static int pophack = 0;
23:
24: char response[BUFSIZ];
25:
26: static FILE *input;
27: static FILE *output;
28:
29: /* */
30:
31: #ifndef RPOP
32: int pop_init (host, user, pass, snoop)
33: #else RPOP
34: int pop_init (host, user, pass, snoop, rpop)
35: int rpop;
36: #endif RPOP
37: char *host,
38: *user,
39: *pass;
40: int snoop;
41: {
42: int fd1,
43: fd2;
44: #ifndef RPOP
45: int rpop = 0;
46: #endif RPOP
47: char buffer[BUFSIZ];
48:
49: if ((fd1 = client (host, "tcp", "pop", rpop, response)) == NOTOK)
50: return NOTOK;
51:
52: if ((fd2 = dup (fd1)) == NOTOK) {
53: (void) sprintf (response, "unable to dup connection descriptor: %s",
54: errno > 0 && errno < sys_nerr ? sys_errlist[errno]
55: : "unknown error");
56: (void) close (fd1);
57: return NOTOK;
58: }
59: if (pop_set (fd1, fd2, snoop) == NOTOK)
60: return NOTOK;
61:
62: (void) signal (SIGPIPE, SIG_IGN);
63:
64: switch (getline (response, sizeof response, input)) {
65: case OK:
66: if (poprint)
67: fprintf (stderr, "<--- %s\n", response);
68: if (*response == '+'
69: && command ("USER %s", user) != NOTOK
70: && command ("%s %s", rpop ? "RPOP" : (pophack++, "PASS"),
71: pass) != NOTOK)
72: return OK;
73: if (*response != '+') {
74: (void) strcpy (buffer, response);
75: (void) command ("QUIT");
76: (void) strcpy (response, buffer);
77: } /* fall */
78:
79: case NOTOK:
80: case DONE:
81: if (poprint)
82: fprintf (stderr, "%s\n", response);
83: (void) fclose (input);
84: (void) fclose (output);
85: return NOTOK;
86: }
87: /* NOTREACHED */
88: }
89:
90: /* */
91:
92: int pop_set (in, out, snoop)
93: int in,
94: out,
95: snoop;
96: {
97: if ((input = fdopen (in, "r")) == NULL
98: || (output = fdopen (out, "w")) == NULL) {
99: (void) strcpy (response, "fdopen failed on connection descriptor");
100: if (input)
101: (void) fclose (input);
102: else
103: (void) close (in);
104: (void) close (out);
105: return NOTOK;
106: }
107:
108: poprint = snoop;
109:
110: return OK;
111: }
112:
113:
114: int pop_fd (in, out)
115: char *in,
116: *out;
117: {
118: (void) sprintf (in, "%d", fileno (input));
119: (void) sprintf (out, "%d", fileno (output));
120: return OK;
121: }
122:
123: /* */
124:
125: int pop_stat (nmsgs, nbytes)
126: int *nmsgs,
127: *nbytes;
128: {
129: if (command ("STAT") == NOTOK)
130: return NOTOK;
131:
132: *nmsgs = *nbytes = 0;
133: (void) sscanf (response, "+OK %d %d", nmsgs, nbytes);
134: return OK;
135: }
136:
137:
138: #ifndef BPOP
139: int pop_list (msgno, nmsgs, msgs, bytes)
140: #else BPOP
141: int pop_list (msgno, nmsgs, msgs, bytes, ids)
142: int *ids;
143: #endif BPOP
144: int msgno,
145: *nmsgs,
146: *msgs,
147: *bytes;
148: {
149: int i;
150: #ifndef BPOP
151: int *ids = NULL;
152: #endif not BPOP
153:
154: if (msgno) {
155: if (command ("LIST %d", msgno) == NOTOK)
156: return NOTOK;
157:
158: *msgs = *bytes = 0;
159: if (ids) {
160: *ids = 0;
161: (void) sscanf (response, "+OK %d %d %d", msgs, bytes, ids);
162: }
163: else
164: (void) sscanf (response, "+OK %d %d", msgs, bytes);
165: return OK;
166: }
167:
168: if (command ("LIST") == NOTOK)
169: return NOTOK;
170:
171: for (i = 0; i < *nmsgs; i++)
172: switch (multiline ()) {
173: case NOTOK:
174: return NOTOK;
175: case DONE:
176: *nmsgs = ++i;
177: return OK;
178: case OK:
179: *msgs = *bytes = 0;
180: if (ids) {
181: *ids = 0;
182: (void) sscanf (response, "%d %d %d",
183: msgs++, bytes++, ids++);
184: }
185: else
186: (void) sscanf (response, "%d %d", msgs++, bytes++);
187: break;
188: }
189: for (;;)
190: switch (multiline ()) {
191: case NOTOK:
192: return NOTOK;
193: case DONE:
194: return OK;
195: case OK:
196: break;
197: }
198: }
199:
200: /* */
201:
202: int pop_retr (msgno, action)
203: int msgno,
204: (*action) ();
205: {
206: return traverse (action, "RETR %d", msgno);
207: }
208:
209:
210: /* VARARGS2 */
211:
212: static int traverse (action, fmt, a, b, c, d)
213: int (*action) ();
214: char *fmt,
215: *a,
216: *b,
217: *c,
218: *d;
219: {
220: char buffer[sizeof response];
221:
222: if (command (fmt, a, b, c, d) == NOTOK)
223: return NOTOK;
224: (void) strcpy (buffer, response);
225:
226: for (;;)
227: switch (multiline ()) {
228: case NOTOK:
229: return NOTOK;
230:
231: case DONE:
232: (void) strcpy (response, buffer);
233: return OK;
234:
235: case OK:
236: (*action) (response);
237: break;
238: }
239: }
240:
241: /* */
242:
243: int pop_dele (msgno)
244: int msgno;
245: {
246: return command ("DELE %d", msgno);
247: }
248:
249:
250: int pop_noop () {
251: return command ("NOOP");
252: }
253:
254:
255: int pop_rset () {
256: return command ("RSET");
257: }
258:
259: /* */
260:
261: int pop_top (msgno, lines, action)
262: int msgno,
263: lines,
264: (*action) ();
265: {
266: return traverse (action, "TOP %d %d", msgno, lines);
267: }
268:
269:
270: #ifdef BPOP
271: int pop_xtnd (action, fmt, a, b, c, d)
272: int (*action) ();
273: char *fmt,
274: *a,
275: *b,
276: *c,
277: *d;
278: {
279: char buffer[BUFSIZ];
280:
281: (void) sprintf (buffer, "XTND %s", fmt);
282: return traverse (action, buffer, a, b, c, d);
283: }
284: #endif BPOP
285:
286: /* */
287:
288: int pop_quit () {
289: int i;
290:
291: i = command ("QUIT");
292: (void) pop_done ();
293:
294: return i;
295: }
296:
297:
298: int pop_done () {
299: (void) fclose (input);
300: (void) fclose (output);
301:
302: return OK;
303: }
304:
305: /* */
306:
307: /* VARARGS1 */
308:
309: static int command (fmt, a, b, c, d)
310: char *fmt,
311: *a,
312: *b,
313: *c,
314: *d;
315: {
316: char *cp,
317: buffer[BUFSIZ];
318:
319: (void) sprintf (buffer, fmt, a, b, c, d);
320: if (poprint)
321: if (pophack) {
322: if (cp = index (buffer, ' '))
323: *cp = NULL;
324: fprintf (stderr, "---> %s ********\n", buffer);
325: if (cp)
326: *cp = ' ';
327: pophack = 0;
328: }
329: else
330: fprintf (stderr, "---> %s\n", buffer);
331:
332: if (putline (buffer, output) == NOTOK)
333: return NOTOK;
334:
335: switch (getline (response, sizeof response, input)) {
336: case OK:
337: if (poprint)
338: fprintf (stderr, "<--- %s\n", response);
339: return (*response == '+' ? OK : NOTOK);
340:
341: case NOTOK:
342: case DONE:
343: if (poprint)
344: fprintf (stderr, "%s\n", response);
345: return NOTOK;
346: }
347: /* NOTREACHED */
348: }
349:
350: static int multiline () {
351: char buffer[BUFSIZ + TRMLEN];
352:
353: if (getline (buffer, sizeof buffer, input) != OK)
354: return NOTOK;
355: if (strncmp (buffer, TRM, TRMLEN) == 0) {
356: if (buffer[TRMLEN] == NULL)
357: return DONE;
358: else
359: (void) strcpy (response, buffer + TRMLEN);
360: }
361: else
362: (void) strcpy (response, buffer);
363:
364: return OK;
365: }
366:
367: /* */
368:
369: static int getline (s, n, iop)
370: char *s;
371: int n;
372: FILE * iop;
373: {
374: int c;
375: char *p;
376:
377: p = s;
378: while (--n > 0 && (c = fgetc (iop)) != EOF)
379: if ((*p++ = c) == '\n')
380: break;
381: if (ferror (iop)) {
382: (void) strcpy (response, "error on connection");
383: return NOTOK;
384: }
385: if (c == EOF && p == s) {
386: (void) strcpy (response, "connection closed by foreign host");
387: return DONE;
388: }
389: *p = NULL;
390: if (*--p == '\n')
391: *p = NULL;
392: if (*--p == '\r')
393: *p = NULL;
394:
395: return OK;
396: }
397:
398:
399: static putline (s, iop)
400: char *s;
401: FILE * iop;
402: {
403: (void) fprintf (iop, "%s\r\n", s);
404: (void) fflush (iop);
405: if (ferror (iop)) {
406: (void) strcpy (response, "lost connection");
407: return NOTOK;
408: }
409:
410: return OK;
411: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.