]>
diplodocus.org Git - nmh/blob - uip/popsbr.c
3 * popsbr.c -- POP client subroutines
10 extern int client(char *args
, char *protocol
, char *service
, int rproto
,
11 char *response
, int len_response
);
13 #if defined(NNTP) && !defined(PSHSBR)
17 #ifdef NNTP /* building pshsbr.o from popsbr.c */
21 #if !defined(NNTP) && defined(APOP)
26 #include <h/signals.h>
31 #define TRMLEN (sizeof TRM - 1)
33 static int poprint
= 0;
34 static int pophack
= 0;
36 char response
[BUFSIZ
];
43 #if !defined(NNTP) && defined(MPOP)
44 # define command pop_command
45 # define multiline pop_multiline
49 # ifdef BPOP /* stupid */
50 static int xtnd_last
= -1;
51 static int xtnd_first
= 0;
52 static char xtnd_name
[512]; /* INCREDIBLE HACK!! */
59 #if !defined(NNTP) && defined(APOP)
60 static char *pop_auth (char *, char *);
63 #if defined(NNTP) || !defined(MPOP)
64 /* otherwise they are not static functions */
65 static int command(const char *, ...);
66 static int multiline(void);
69 static int traverse (int (*)(), const char *, ...);
70 static int vcommand(const char *, va_list);
71 static int getline (char *, int, FILE *);
72 static int putline (char *, FILE *);
75 #if !defined(NNTP) && defined(APOP)
77 pop_auth (char *user
, char *pass
)
81 unsigned char *dp
, *ep
, digest
[16];
83 static char buffer
[BUFSIZ
];
85 if ((cp
= strchr (response
, '<')) == NULL
86 || (lp
= strchr (cp
, '>')) == NULL
) {
87 snprintf (buffer
, sizeof(buffer
), "APOP not available: %s", response
);
88 strncpy (response
, buffer
, sizeof(response
));
93 snprintf (buffer
, sizeof(buffer
), "%s%s", cp
, pass
);
96 MD5Update (&mdContext
, (unsigned char *) buffer
,
97 (unsigned int) strlen (buffer
));
98 MD5Final (digest
, &mdContext
);
101 buflen
= sizeof(buffer
);
103 snprintf (cp
, buflen
, "%s ", user
);
108 for (ep
= (dp
= digest
) + sizeof(digest
) / sizeof(digest
[0]); dp
< ep
; ) {
109 snprintf (cp
, buflen
, "%02x", *dp
++ & 0xff);
117 #endif /* !NNTP && APOP */
121 pop_init (char *host
, char *user
, char *pass
, int snoop
, int rpop
, int kpop
)
129 if ((apop
= rpop
) < 0)
136 snprintf (buffer
, sizeof(buffer
), "%s/%s", KPOP_PRINCIPAL
, "kpop");
137 if ((fd1
= client (host
, "tcp", buffer
, 0, response
, sizeof(response
))) == NOTOK
) {
142 if ((fd1
= client (host
, "tcp", POPSERVICE
, rpop
, response
, sizeof(response
))) == NOTOK
) {
149 if ((fd1
= client (host
, "tcp", "nntp", rpop
, response
, sizeof(response
))) == NOTOK
)
153 if ((fd2
= dup (fd1
)) == NOTOK
) {
156 if ((s
= strerror(errno
)))
157 snprintf (response
, sizeof(response
),
158 "unable to dup connection descriptor: %s", s
);
160 snprintf (response
, sizeof(response
),
161 "unable to dup connection descriptor: unknown error");
166 if (pop_set (fd1
, fd2
, snoop
) == NOTOK
)
168 if (pop_set (fd1
, fd2
, snoop
, (char *)0) == NOTOK
)
172 SIGNAL (SIGPIPE
, SIG_IGN
);
174 switch (getline (response
, sizeof response
, input
)) {
177 fprintf (stderr
, "<--- %s\n", response
);
179 if (*response
== '+') {
183 char *cp
= pop_auth (user
, pass
);
185 if (cp
&& command ("APOP %s", cp
) != NOTOK
)
190 if (command ("USER %s", user
) != NOTOK
191 && command ("%s %s", rpop
? "RPOP" : (pophack
++, "PASS"),
195 if (command ("USER %s", user
) != NOTOK
196 && command ("PASS %s", pass
) != NOTOK
)
201 if (*response
< CHAR_ERR
) {
202 command ("MODE READER");
206 strncpy (buffer
, response
, sizeof(buffer
));
208 strncpy (response
, buffer
, sizeof(response
));
214 fprintf (stderr
, "%s\n", response
);
220 return NOTOK
; /* NOTREACHED */
225 pop_set (int in
, int out
, int snoop
, char *myname
)
228 pop_set (int in
, int out
, int snoop
)
233 if (myname
&& *myname
) {
234 /* interface from bbc to msh */
235 strncpy (xtnd_name
, myname
, sizeof(xtnd_name
));
239 if ((input
= fdopen (in
, "r")) == NULL
240 || (output
= fdopen (out
, "w")) == NULL
) {
241 strncpy (response
, "fdopen failed on connection descriptor", sizeof(response
));
257 pop_fd (char *in
, int inlen
, char *out
, int outlen
)
259 snprintf (in
, inlen
, "%d", fileno (input
));
260 snprintf (out
, outlen
, "%d", fileno (output
));
266 * Find out number of messages available
267 * and their total size.
271 pop_stat (int *nmsgs
, int *nbytes
)
278 if (command ("STAT") == NOTOK
)
281 *nmsgs
= *nbytes
= 0;
282 sscanf (response
, "+OK %d %d", nmsgs
, nbytes
);
285 if (xtnd_last
< 0) { /* in msh, xtnd_name is set from myname */
286 if (command("GROUP %s", xtnd_name
) == NOTOK
)
289 ap
= brkstring (response
, " ", "\n"); /* "211 nart first last ggg" */
290 xtnd_first
= atoi (ap
[2]);
291 xtnd_last
= atoi (ap
[3]);
294 /* nmsgs is not the real nart, but an incredible simuation */
296 *nmsgs
= xtnd_last
- xtnd_first
+ 1; /* because of holes... */
299 *nbytes
= xtnd_first
; /* for subtracting offset in msh() */
307 pop_exists (int (*action
)())
309 #ifdef XMSGS /* hacked into NNTP 1.5 */
310 if (traverse (action
, "XMSGS %d-%d", (targ_t
) xtnd_first
, (targ_t
) xtnd_last
) == OK
)
313 /* provided by INN 1.4 */
314 if (traverse (action
, "LISTGROUP") == OK
)
316 return traverse (action
, "XHDR NONAME %d-%d", (targ_t
) xtnd_first
, (targ_t
) xtnd_last
);
323 pop_list (int msgno
, int *nmsgs
, int *msgs
, int *bytes
, int *ids
)
326 pop_list (int msgno
, int *nmsgs
, int *msgs
, int *bytes
)
336 if (command ("LIST %d", msgno
) == NOTOK
)
341 sscanf (response
, "+OK %d %d %d", msgs
, bytes
, ids
);
344 sscanf (response
, "+OK %d %d", msgs
, bytes
);
347 if (command ("STAT %d", msgno
) == NOTOK
)
357 if (command ("LIST") == NOTOK
)
360 for (i
= 0; i
< *nmsgs
; i
++)
361 switch (multiline ()) {
371 sscanf (response
, "%d %d %d",
372 msgs
++, bytes
++, ids
++);
375 sscanf (response
, "%d %d", msgs
++, bytes
++);
379 switch (multiline ()) {
394 pop_retr (int msgno
, int (*action
)())
397 return traverse (action
, "RETR %d", (targ_t
) msgno
);
399 return traverse (action
, "ARTICLE %d", (targ_t
) msgno
);
405 traverse (int (*action
)(), const char *fmt
, ...)
409 char buffer
[sizeof(response
)];
412 result
= vcommand (fmt
, ap
);
417 strncpy (buffer
, response
, sizeof(buffer
));
420 switch (multiline ()) {
425 strncpy (response
, buffer
, sizeof(response
));
429 (*action
) (response
);
438 return command ("DELE %d", msgno
);
445 return command ("NOOP");
449 #if defined(MPOP) && !defined(NNTP)
453 return command ("LAST");
461 return command ("RSET");
466 pop_top (int msgno
, int lines
, int (*action
)())
469 return traverse (action
, "TOP %d %d", (targ_t
) msgno
, (targ_t
) lines
);
471 return traverse (action
, "HEAD %d", (targ_t
) msgno
);
478 pop_xtnd (int (*action
)(), char *fmt
, ...)
490 /* needs to be fixed... va_end needs to be added */
491 snprintf (buffer
, sizeof(buffer
), "XTND %s", fmt
);
492 result
= traverse (action
, buffer
, a
, b
, c
, d
);
496 snprintf (buffer
, sizeof(buffer
), fmt
, a
, b
, c
, d
);
497 ap
= brkstring (buffer
, " ", "\n"); /* a hack, i know... */
499 if (!strcasecmp(ap
[0], "x-bboards")) { /* XTND "X-BBOARDS group */
500 /* most of these parameters are meaningless under NNTP.
501 * bbc.c was modified to set AKA and LEADERS as appropriate,
502 * the rest are left blank.
506 if (!strcasecmp (ap
[0], "archive") && ap
[1]) {
507 snprintf (xtnd_name
, sizeof(xtnd_name
), "%s", ap
[1]); /* save the name */
509 xtnd_first
= 1; /* setup to fail in pop_stat */
512 if (!strcasecmp (ap
[0], "bboards")) {
514 if (ap
[1]) { /* XTND "BBOARDS group" */
515 snprintf (xtnd_name
, sizeof(xtnd_name
), "%s", ap
[1]); /* save the name */
516 if (command("GROUP %s", xtnd_name
) == NOTOK
)
519 /* action must ignore extra args */
520 strncpy (buffer
, response
, sizeof(buffer
));
521 ap
= brkstring (response
, " ", "\n");/* "211 nart first last g" */
522 xtnd_first
= atoi (ap
[2]);
523 xtnd_last
= atoi (ap
[3]);
528 } else { /* XTND "BBOARDS" */
529 return traverse (action
, "LIST", a
, b
, c
, d
);
532 return NOTOK
; /* unknown XTND command */
543 i
= command ("QUIT");
560 #if !defined(MPOP) || defined(NNTP)
564 command(const char *fmt
, ...)
570 result
= vcommand(fmt
, ap
);
578 vcommand (const char *fmt
, va_list ap
)
580 char *cp
, buffer
[BUFSIZ
];
582 vsnprintf (buffer
, sizeof(buffer
), fmt
, ap
);
585 if ((cp
= strchr (buffer
, ' ')))
587 fprintf (stderr
, "---> %s ********\n", buffer
);
593 fprintf (stderr
, "---> %s\n", buffer
);
596 if (putline (buffer
, output
) == NOTOK
)
599 switch (getline (response
, sizeof response
, input
)) {
602 fprintf (stderr
, "<--- %s\n", response
);
604 return (*response
== '+' ? OK
: NOTOK
);
606 return (*response
< CHAR_ERR
? OK
: NOTOK
);
612 fprintf (stderr
, "%s\n", response
);
616 return NOTOK
; /* NOTREACHED */
620 #if defined(MPOP) && !defined(NNTP)
628 char buffer
[BUFSIZ
+ TRMLEN
];
630 if (getline (buffer
, sizeof buffer
, input
) != OK
)
634 fprintf (stderr
, "<--- %s\n", response
);
636 if (strncmp (buffer
, TRM
, TRMLEN
) == 0) {
637 if (buffer
[TRMLEN
] == 0)
640 strncpy (response
, buffer
+ TRMLEN
, sizeof(response
));
643 strncpy (response
, buffer
, sizeof(response
));
650 getline (char *s
, int n
, FILE *iop
)
656 while (--n
> 0 && (c
= fgetc (iop
)) != EOF
)
657 if ((*p
++ = c
) == '\n')
659 if (ferror (iop
) && c
!= EOF
) {
660 strncpy (response
, "error on connection", sizeof(response
));
663 if (c
== EOF
&& p
== s
) {
664 strncpy (response
, "connection closed by foreign host", sizeof(response
));
678 putline (char *s
, FILE *iop
)
680 fprintf (iop
, "%s\r\n", s
);
683 strncpy (response
, "lost connection", sizeof(response
));