1 /* popsbr.c - POP client subroutines */
3 static char ident[] = "@(#)$Id: popsbr.c,v 2.7 1994/04/19 20:12:14 jromine Exp shettich $";
6 #if defined(NNTP) && !defined(PSHSBR)
12 #include "../h/strings.h"
13 #ifdef NNTP /* building pshsbr.o from popsbr.c */
14 #include "../h/nntp.h"
20 #define POPSERVICE "pop"
28 #define TRMLEN (sizeof TRM - 1)
33 extern char *sys_errlist[];
36 static int poprint = 0;
37 static int pophack = 0;
39 char response[BUFSIZ];
45 static int traverse (int (*)(), const char*, char *, char *, char *, char *);
48 static int traverse();
52 #if !defined(NNTP) && defined(MPOP)
53 #define command pop_command
54 #define multiline pop_multiline
55 int command(), multiline();
57 static int command(), multiline();
64 #ifdef BPOP /* stupid */
65 static int xtnd_last = -1,
67 static char xtnd_name[512]; /* INCREDIBLE HACK!! */
77 static char *pop_auth (user, pass)
83 register unsigned char *dp;
87 static char buffer[BUFSIZ];
89 if ((cp = index (response, '<')) == NULL
90 || (lp = index (cp, '>')) == NULL) {
91 (void) sprintf (buffer, "APOP not available: %s", response);
92 (void) strcpy (response, buffer);
97 (void) sprintf (buffer, "%s%s", cp, pass);
100 MD5Update (&mdContext, (unsigned char *) buffer,
101 (unsigned int) strlen (buffer));
102 MD5Final (digest, &mdContext);
104 (void) sprintf (cp = buffer, "%s ", user);
106 for (ep = (dp = digest) + sizeof digest / sizeof digest[0];
109 (void) sprintf (cp, "%02x", *dp++ & 0xff);
120 int pop_init (host, user, pass, snoop)
122 int pop_init (host, user, pass, snoop)
139 if ((fd1 = client (host, "tcp", POPSERVICE, response)) == NOTOK)
141 (void) sprintf (buffer, "%s/%s", POPSERVICE, "kpop");
142 if ((fd1 = client (host, "tcp", buffer, response)) == NOTOK)
145 if ((fd1 = client (host, "tcp", "nntp", response)) == NOTOK)
149 if ((fd2 = dup (fd1)) == NOTOK) {
150 (void) sprintf (response, "unable to dup connection descriptor: %s",
151 errno > 0 && errno < sys_nerr ? sys_errlist[errno]
157 if (pop_set (fd1, fd2, snoop) == NOTOK)
159 if (pop_set (fd1, fd2, snoop, (char *)0) == NOTOK)
163 (void) signal (SIGPIPE, SIG_IGN);
165 switch (getline (response, sizeof response, input)) {
168 fprintf (stderr, "<--- %s\n", response);
170 if (*response == '+') {
174 char *cp = pop_auth (user, pass);
176 if (cp && command ("APOP %s", cp) != NOTOK)
181 if (command ("USER %s", user) != NOTOK
182 && command ("%s %s", (pophack++, "PASS"),
186 if (command ("USER %s", user) != NOTOK
187 && command ("PASS %s", pass) != NOTOK)
192 if (*response < CHAR_ERR) {
193 (void) command ("MODE READER");
195 if (getenv("NEWSAUTH")) /* special for IDENT protocol */
196 command("MODE IDENTIFY");
201 (void) strcpy (buffer, response);
202 (void) command ("QUIT");
203 (void) strcpy (response, buffer);
209 fprintf (stderr, "%s\n", response);
210 (void) fclose (input);
211 (void) fclose (output);
219 int pop_set (in, out, snoop)
221 int pop_set (in, out, snoop, myname)
229 if (myname && *myname)
230 strcpy (xtnd_name, myname); /* interface from bbc to msh */
233 if ((input = fdopen (in, "r")) == NULL
234 || (output = fdopen (out, "w")) == NULL) {
235 (void) strcpy (response, "fdopen failed on connection descriptor");
237 (void) fclose (input);
254 (void) sprintf (in, "%d", fileno (input));
255 (void) sprintf (out, "%d", fileno (output));
261 int pop_stat (nmsgs, nbytes)
267 extern char **brkstring();
271 if (command ("STAT") == NOTOK)
274 *nmsgs = *nbytes = 0;
275 (void) sscanf (response, "+OK %d %d", nmsgs, nbytes);
278 if (xtnd_last < 0) { /* in msh, xtnd_name is set from myname */
279 if (command("GROUP %s", xtnd_name) == NOTOK)
282 ap = brkstring (response, " ", "\n"); /* "211 nart first last ggg" */
283 xtnd_first = atoi (ap[2]);
284 xtnd_last = atoi (ap[3]);
287 /* nmsgs is not the real nart, but an incredible simuation */
289 *nmsgs = xtnd_last - xtnd_first + 1; /* because of holes... */
292 *nbytes = xtnd_first; /* for subtracting offset in msh() */
299 int pop_exists (action)
302 #ifdef XMSGS /* hacked into NNTP 1.5 */
303 if (traverse (action, "XMSGS %d-%d",
304 (targ_t)xtnd_first, (targ_t)xtnd_last, 0, 0) == OK)
307 if (traverse (action, "LISTGROUP", /* provided by INN 1.4 */
310 return traverse (action, "XHDR NONAME %d-%d",
311 (targ_t)xtnd_first, (targ_t)xtnd_last, 0, 0);
316 int pop_list (msgno, nmsgs, msgs, bytes)
318 int pop_list (msgno, nmsgs, msgs, bytes, ids)
333 if (command ("LIST %d", msgno) == NOTOK)
338 (void) sscanf (response, "+OK %d %d %d", msgs, bytes, ids);
341 (void) sscanf (response, "+OK %d %d", msgs, bytes);
344 if (command ("STAT %d", msgno) == NOTOK)
354 if (command ("LIST") == NOTOK)
357 for (i = 0; i < *nmsgs; i++)
358 switch (multiline ()) {
368 (void) sscanf (response, "%d %d %d",
369 msgs++, bytes++, ids++);
372 (void) sscanf (response, "%d %d", msgs++, bytes++);
376 switch (multiline ()) {
391 int pop_retr (msgno, action)
396 return traverse (action, "RETR %d", (targ_t)msgno, 0, 0, 0);
398 return traverse (action, "ARTICLE %d", (targ_t)msgno, 0, 0, 0);
405 static int traverse (action, fmt, a, b, c, d)
417 char buffer[sizeof response];
419 if (command (fmt, a, b, c, d) == NOTOK)
421 (void) strcpy (buffer, response);
424 switch (multiline ()) {
429 (void) strcpy (response, buffer);
433 (*action) (response);
443 return command ("DELE %d", msgno);
448 return command ("NOOP");
455 return command ("LAST");
461 return command ("RSET");
466 int pop_top (msgno, lines, action)
472 return traverse (action, "TOP %d %d", (targ_t)msgno, (targ_t)lines, 0, 0);
474 return traverse (action, "HEAD %d", (targ_t)msgno, 0, 0, 0);
480 int pop_xtnd (action, fmt, a, b, c, d)
490 extern char **brkstring();
495 (void) sprintf (buffer, "XTND %s", fmt);
496 return traverse (action, buffer, a, b, c, d);
498 sprintf (buffer, fmt, a, b, c, d);
499 ap = brkstring (buffer, " ", "\n"); /* a hack, i know... */
501 if (uleq(ap[0], "x-bboards")) { /* XTND "X-BBOARDS group */
502 /* most of these parameters are meaningless under NNTP.
503 * bbc.c was modified to set AKA and LEADERS as appropriate,
504 * the rest are left blank.
508 if (uleq (ap[0], "archive") && ap[1]) {
509 sprintf (xtnd_name, "%s", ap[1]); /* save the name */
511 xtnd_first = 1; /* setup to fail in pop_stat */
514 if (uleq (ap[0], "bboards")) {
516 if (ap[1]) { /* XTND "BBOARDS group" */
517 sprintf (xtnd_name, "%s", ap[1]); /* save the name */
518 if (command("GROUP %s", xtnd_name) == NOTOK)
521 strcpy (buffer, response); /* action must ignore extra args */
522 ap = brkstring (response, " ", "\n");/* "211 nart first last g" */
523 xtnd_first = atoi (ap[2]);
524 xtnd_last = atoi (ap[3]);
529 } else { /* XTND "BBOARDS" */
530 return traverse (action, "LIST", a, b, c, d);
533 return NOTOK; /* unknown XTND command */
543 i = command ("QUIT");
551 (void) fclose (input);
552 (void) fclose (output);
561 #if defined(MPOP) && !defined(NNTP)
562 int command (fmt, a, b, c, d)
564 static int command (fmt, a, b, c, d)
575 (void) sprintf (buffer, fmt, a, b, c, d);
578 if (cp = index (buffer, ' '))
580 fprintf (stderr, "---> %s ********\n", buffer);
586 fprintf (stderr, "---> %s\n", buffer);
588 if (putline (buffer, output) == NOTOK)
591 switch (getline (response, sizeof response, input)) {
594 fprintf (stderr, "<--- %s\n", response);
596 return (*response == '+' ? OK : NOTOK);
598 return (*response < CHAR_ERR ? OK : NOTOK);
604 fprintf (stderr, "%s\n", response);
610 #if defined(MPOP) && !defined(NNTP)
613 static int multiline () {
615 char buffer[BUFSIZ + TRMLEN];
617 if (getline (buffer, sizeof buffer, input) != OK)
621 fprintf (stderr, "<--- %s\n", response);
623 if (strncmp (buffer, TRM, TRMLEN) == 0) {
624 if (buffer[TRMLEN] == 0)
627 (void) strcpy (response, buffer + TRMLEN);
630 (void) strcpy (response, buffer);
637 static int getline (s, n, iop)
646 while (--n > 0 && (c = fgetc (iop)) != EOF)
647 if ((*p++ = c) == '\n')
649 if (ferror (iop) && c != EOF) {
650 (void) strcpy (response, "error on connection");
653 if (c == EOF && p == s) {
654 (void) strcpy (response, "connection closed by foreign host");
667 static putline (s, iop)
671 (void) fprintf (iop, "%s\r\n", s);
674 (void) strcpy (response, "lost connection");