/* popsbr.c - POP client subroutines */
static char ident
[] = "@(#)$Id: popsbr.c,v 2.4 1992/11/24 18:32:32 jromine Exp $";
#if defined(NNTP) && !defined(PSHSBR)
#include "../h/strings.h"
#ifdef NNTP /* building pshsbr.o from popsbr.c */
#define TRMLEN (sizeof TRM - 1)
extern char *sys_errlist
[];
static int traverse (int (*)(), const char*, char *, char *, char *, char *);
#if !defined(NNTP) && defined(MPOP)
#define command pop_command
#define multiline pop_multiline
int command(), multiline();
static int command(), multiline();
static int xtnd_last
= -1,
static char xtnd_name
[512]; /* INCREDIBLE HACK!! */
static char *pop_auth (user
, pass
)
register unsigned char *dp
;
static char buffer
[BUFSIZ
];
if ((cp
= index (response
, '<')) == NULL
|| (lp
= index (cp
, '>')) == NULL
) {
(void) sprintf (buffer
, "APOP not available: %s", response
);
(void) strcpy (response
, buffer
);
(void) sprintf (buffer
, "%s%s", cp
, pass
);
MD5Update (&mdContext
, (unsigned char *) buffer
,
(unsigned int) strlen (buffer
));
MD5Final (digest
, &mdContext
);
(void) sprintf (cp
= buffer
, "%s ", user
);
for (ep
= (dp
= digest
) + sizeof digest
/ sizeof digest
[0];
(void) sprintf (cp
, "%02x", *dp
++ & 0xff);
#if defined(RPOP) || defined(APOP)
int pop_init (host
, user
, pass
, snoop
, rpop
)
int pop_init (host
, user
, pass
, snoop
)
#ifndef RPOP /* !APOP && !RPOP */
if ((fd1
= client (host
, "tcp", POPSERVICE
, rpop
, response
)) == NOTOK
)
(void) sprintf (buffer
, "%s/%s", POPSERVICE
, "kpop");
if ((fd1
= client (host
, "tcp", buffer
, rpop
, response
)) == NOTOK
)
if ((fd1
= client (host
, "tcp", "nntp", rpop
, response
)) == NOTOK
)
if ((fd2
= dup (fd1
)) == NOTOK
) {
(void) sprintf (response
, "unable to dup connection descriptor: %s",
errno
> 0 && errno
< sys_nerr
? sys_errlist
[errno
]
if (pop_set (fd1
, fd2
, snoop
) == NOTOK
)
if (pop_set (fd1
, fd2
, snoop
, (char *)0) == NOTOK
)
(void) signal (SIGPIPE
, SIG_IGN
);
switch (getline (response
, sizeof response
, input
)) {
fprintf (stderr
, "<--- %s\n", response
);
char *cp
= pop_auth (user
, pass
);
if (cp
&& command ("APOP %s", cp
) != NOTOK
)
if (command ("USER %s", user
) != NOTOK
&& command ("%s %s", rpop
? "RPOP" : (pophack
++, "PASS"),
if (command ("USER %s", user
) != NOTOK
&& command ("PASS %s", pass
) != NOTOK
)
if (*response
< CHAR_ERR
)
(void) strcpy (buffer
, response
);
(void) strcpy (response
, buffer
);
fprintf (stderr
, "%s\n", response
);
int pop_set (in
, out
, snoop
)
int pop_set (in
, out
, snoop
, myname
)
strcpy (xtnd_name
, myname
); /* interface from bbc to msh */
if ((input
= fdopen (in
, "r")) == NULL
|| (output
= fdopen (out
, "w")) == NULL
) {
(void) strcpy (response
, "fdopen failed on connection descriptor");
(void) sprintf (in
, "%d", fileno (input
));
(void) sprintf (out
, "%d", fileno (output
));
int pop_stat (nmsgs
, nbytes
)
extern char **brkstring();
if (command ("STAT") == NOTOK
)
(void) sscanf (response
, "+OK %d %d", nmsgs
, nbytes
);
if (xtnd_last
< 0) { /* in msh, xtnd_name is set from myname */
if (command("GROUP %s", xtnd_name
) == NOTOK
)
ap
= brkstring (response
, " ", "\n"); /* "211 nart first last ggg" */
xtnd_first
= atoi (ap
[2]);
xtnd_last
= atoi (ap
[3]);
/* nmsgs is not the real nart, but an incredible simuation */
*nmsgs
= xtnd_last
- xtnd_first
+ 1; /* because of holes... */
*nbytes
= xtnd_first
; /* for subtracting offset in msh() */
if (traverse (action
, "XMSGS %d-%d",
(targ_t
)xtnd_first
, (targ_t
)xtnd_last
, 0, 0) == OK
)
return traverse (action
, "XHDR NONAME %d-%d",
(targ_t
)xtnd_first
, (targ_t
)xtnd_last
, 0, 0);
int pop_list (msgno
, nmsgs
, msgs
, bytes
)
int pop_list (msgno
, nmsgs
, msgs
, bytes
, ids
)
if (command ("LIST %d", msgno
) == NOTOK
)
(void) sscanf (response
, "+OK %d %d %d", msgs
, bytes
, ids
);
(void) sscanf (response
, "+OK %d %d", msgs
, bytes
);
if (command ("STAT %d", msgno
) == NOTOK
)
if (command ("LIST") == NOTOK
)
for (i
= 0; i
< *nmsgs
; i
++)
(void) sscanf (response
, "%d %d %d",
(void) sscanf (response
, "%d %d", msgs
++, bytes
++);
int pop_retr (msgno
, action
)
return traverse (action
, "RETR %d", (targ_t
)msgno
, 0, 0, 0);
return traverse (action
, "ARTICLE %d", (targ_t
)msgno
, 0, 0, 0);
static int traverse (action
, fmt
, a
, b
, c
, d
)
char buffer
[sizeof response
];
if (command (fmt
, a
, b
, c
, d
) == NOTOK
)
(void) strcpy (buffer
, response
);
(void) strcpy (response
, buffer
);
return command ("DELE %d", msgno
);
int pop_top (msgno
, lines
, action
)
return traverse (action
, "TOP %d %d", (targ_t
)msgno
, (targ_t
)lines
, 0, 0);
return traverse (action
, "HEAD %d", (targ_t
)msgno
, 0, 0, 0);
int pop_xtnd (action
, fmt
, a
, b
, c
, d
)
extern char **brkstring();
(void) sprintf (buffer
, "XTND %s", fmt
);
return traverse (action
, buffer
, a
, b
, c
, d
);
sprintf (buffer
, fmt
, a
, b
, c
, d
);
ap
= brkstring (buffer
, " ", "\n"); /* a hack, i know... */
if (uleq(ap
[0], "x-bboards")) { /* XTND "X-BBOARDS group */
/* most of these parameters are meaningless under NNTP.
* bbc.c was modified to set AKA and LEADERS as appropriate,
* the rest are left blank.
if (uleq (ap
[0], "archive") && ap
[1]) {
sprintf (xtnd_name
, "%s", ap
[1]); /* save the name */
xtnd_first
= 1; /* setup to fail in pop_stat */
if (uleq (ap
[0], "bboards")) {
if (ap
[1]) { /* XTND "BBOARDS group" */
sprintf (xtnd_name
, "%s", ap
[1]); /* save the name */
if (command("GROUP %s", xtnd_name
) == NOTOK
)
strcpy (buffer
, response
); /* action must ignore extra args */
ap
= brkstring (response
, " ", "\n");/* "211 nart first last g" */
xtnd_first
= atoi (ap
[2]);
xtnd_last
= atoi (ap
[3]);
} else { /* XTND "BBOARDS" */
return traverse (action
, "LIST", a
, b
, c
, d
);
return NOTOK
; /* unknown XTND command */
#if defined(MPOP) && !defined(NNTP)
int command (fmt
, a
, b
, c
, d
)
static int command (fmt
, a
, b
, c
, d
)
(void) sprintf (buffer
, fmt
, a
, b
, c
, d
);
if (cp
= index (buffer
, ' '))
fprintf (stderr
, "---> %s ********\n", buffer
);
fprintf (stderr
, "---> %s\n", buffer
);
if (putline (buffer
, output
) == NOTOK
)
switch (getline (response
, sizeof response
, input
)) {
fprintf (stderr
, "<--- %s\n", response
);
return (*response
== '+' ? OK
: NOTOK
);
return (*response
< CHAR_ERR
? OK
: NOTOK
);
fprintf (stderr
, "%s\n", response
);
#if defined(MPOP) && !defined(NNTP)
static int multiline () {
char buffer
[BUFSIZ
+ TRMLEN
];
if (getline (buffer
, sizeof buffer
, input
) != OK
)
fprintf (stderr
, "<--- %s\n", response
);
if (strncmp (buffer
, TRM
, TRMLEN
) == 0) {
(void) strcpy (response
, buffer
+ TRMLEN
);
(void) strcpy (response
, buffer
);
static int getline (s
, n
, iop
)
while (--n
> 0 && (c
= fgetc (iop
)) != EOF
)
if (ferror (iop
) && c
!= EOF
) {
(void) strcpy (response
, "error on connection");
if (c
== EOF
&& p
== s
) {
(void) strcpy (response
, "connection closed by foreign host");
(void) fprintf (iop
, "%s\r\n", s
);
(void) strcpy (response
, "lost connection");