Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / pshsbr.c
1 /* pshsbr.c - NNTP client subroutines */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: pshsbr.c,v 2.4 1993/08/25 17:27:12 jromine Exp shettich $";
4 #endif  lint
5
6 /* LINTLIBRARY */
7
8 #include "../h/strings.h"
9 #include "../h/nntp.h"
10 #include <stdio.h>
11 #include <signal.h>
12
13
14 #define NOTOK   (-1)
15 #define OK      0
16 #define DONE    1
17
18 #define TRM     "."
19 #define TRMLEN  (sizeof TRM - 1)
20
21 extern int  errno;
22 #ifndef BSD44
23 extern int  sys_nerr;
24 extern char *sys_errlist[];
25 #endif
26
27 static int  poprint = 0;
28 static int  pophack = 0;
29
30 char    response[BUFSIZ];
31
32 static FILE *input;
33 static FILE *output;
34
35 #ifdef  BPOP    /* stupid */
36 static  int     xtnd_last = -1,
37                 xtnd_first = 0;
38 static char     xtnd_name[512]; /* INCREDIBLE HACK!! */
39 #endif
40
41 #define command pop_command
42 #define multiline pop_multiline
43
44 static int    traverse(), getline();
45 static                putline();
46 /* \f */
47
48 int     pop_init (host, user, pass, snoop)
49 #else   RPOP
50 char   *host,
51        *user,
52        *pass;
53 int     snoop;
54 {
55     int     fd1,
56             fd2;
57     char    buffer[BUFSIZ];
58
59     if ((fd1 = client (host, "tcp", "nntp", response)) == NOTOK)
60         return NOTOK;
61
62     if ((fd2 = dup (fd1)) == NOTOK) {
63         (void) sprintf (response, "unable to dup connection descriptor: %s",
64                 errno > 0 && errno < sys_nerr ? sys_errlist[errno]
65                 : "unknown error");
66         (void) close (fd1);
67         return NOTOK;
68     }
69     if (pop_set (fd1, fd2, snoop, (char *)0) == NOTOK)
70         return NOTOK;
71
72     (void) signal (SIGPIPE, SIG_IGN);
73
74     switch (getline (response, sizeof response, input)) {
75         case OK: 
76             if (poprint)
77                 fprintf (stderr, "<--- %s\n", response);
78             if (*response < CHAR_ERR)
79                 return OK;
80             else {
81                 (void) strcpy (buffer, response);
82                 (void) command ("QUIT");
83                 (void) strcpy (response, buffer);
84             }                   /* fall */
85
86         case NOTOK: 
87         case DONE: 
88             if (poprint)            
89                 fprintf (stderr, "%s\n", response);
90             (void) fclose (input);
91             (void) fclose (output);
92             return NOTOK;
93     }
94 /* NOTREACHED */
95 }
96
97 /* \f */
98
99 int     pop_set (in, out, snoop, myname)
100 int     in,
101         out,
102         snoop;
103 char   *myname;
104 {
105     if (myname && *myname)
106         strcpy (xtnd_name, myname);     /* interface from bbc to msh */
107
108     if ((input = fdopen (in, "r")) == NULL
109             || (output = fdopen (out, "w")) == NULL) {
110         (void) strcpy (response, "fdopen failed on connection descriptor");
111         if (input)
112             (void) fclose (input);
113         else
114             (void) close (in);
115         (void) close (out);
116         return NOTOK;
117     }
118
119     poprint = snoop;
120
121     return OK;
122 }
123
124
125 int     pop_fd (in, out)
126 char   *in,
127        *out;
128 {
129     (void) sprintf (in, "%d", fileno (input));
130     (void) sprintf (out, "%d", fileno (output));
131     return OK;
132 }
133
134 /* \f */
135
136 int     pop_stat (nmsgs, nbytes)
137 int    *nmsgs,
138        *nbytes;
139 {
140     char **ap;
141     extern char **brkstring();
142
143     if (xtnd_last < 0) {        /* in msh, xtnd_name is set from myname */
144         if (command("GROUP %s", xtnd_name) == NOTOK)
145             return NOTOK;
146
147         ap = brkstring (response, " ", "\n"); /* "211 nart first last ggg" */
148         xtnd_first = atoi (ap[2]);
149         xtnd_last  = atoi (ap[3]);
150     }
151
152     /* nmsgs is not the real nart, but an incredible simuation */
153     if (xtnd_last > 0)
154         *nmsgs = xtnd_last - xtnd_first + 1;    /* because of holes... */
155     else
156         *nmsgs = 0;
157     *nbytes = xtnd_first;       /* for subtracting offset in msh() */
158
159     return OK;
160 }
161
162 int     pop_exists (action)
163 int     (*action) ();
164 {
165     if (traverse (action, "XMSGS %d-%d", xtnd_first, xtnd_last) == OK)
166         return OK;
167
168     return traverse (action, "XHDR NONAME %d-%d", xtnd_first, xtnd_last);
169 }
170
171
172 #ifndef BPOP
173 int     pop_list (msgno, nmsgs, msgs, bytes)
174 #else   BPOP
175 int     pop_list (msgno, nmsgs, msgs, bytes, ids)
176 int    *ids;
177 #endif  BPOP
178 int     msgno,
179        *nmsgs,
180        *msgs,
181        *bytes;
182 {
183     int     i;
184 #ifndef BPOP
185     int    *ids = NULL;
186 #endif  not BPOP
187
188     if (msgno) {
189         *msgs = *bytes = 0;
190         if (command ("STAT %d", msgno) == NOTOK) 
191             return NOTOK;
192
193         if (ids) {
194             *ids = msgno;
195         }
196         return OK;
197     }
198     return NOTOK;
199 }
200
201 /* \f */
202
203 /* VARARGS2 */
204
205 static int  traverse (action, fmt, a, b, c, d)
206 int     (*action) ();
207 char   *fmt,
208        *a,
209        *b,
210        *c,
211        *d;
212 {
213     char    buffer[sizeof response];
214
215     if (command (fmt, a, b, c, d) == NOTOK)
216         return NOTOK;
217     (void) strcpy (buffer, response);
218
219     for (;;)
220         switch (multiline ()) {
221             case NOTOK: 
222                 return NOTOK;
223
224             case DONE: 
225                 (void) strcpy (response, buffer);
226                 return OK;
227
228             case OK: 
229                 (*action) (response);
230                 break;
231         }
232 }
233
234 /* \f */
235
236 int     pop_dele (msgno)
237 int     msgno;
238 {
239     return command ("DELE %d", msgno);
240 }
241
242
243 int     pop_noop () {
244     return command ("NOOP");
245 }
246
247
248 int     pop_rset () {
249     return command ("RSET");
250 }
251
252 /* \f */
253
254 int     pop_top (msgno, lines, action)
255 int     msgno,
256         lines,          /* sadly, ignored */
257         (*action) ();
258 {
259     return traverse (action, "HEAD %d", msgno);
260 }
261
262
263 int     pop_retr (msgno, action)
264 int     msgno,
265         (*action) ();
266 {
267     return traverse (action, "ARTICLE %d", msgno);
268 }
269
270
271 #ifdef  BPOP
272
273 int     pop_xtnd (action, fmt, a, b, c, d)
274 int     (*action) ();
275 char   *fmt, *a, *b, *c, *d;
276 {
277     extern char **brkstring();
278     char  buffer[BUFSIZ], **ap;
279
280     sprintf (buffer, fmt, a, b, c, d);
281     ap = brkstring (buffer, " ", "\n"); /* a hack, i know... */
282
283     if (uleq(ap[0], "x-bboards")) {     /* XTND "X-BBOARDS group */
284         /* most of these parameters are meaningless under NNTP. 
285          * bbc.c was modified to set AKA and LEADERS as appropriate,
286          * the rest are left blank.
287          */
288         return OK;
289     }
290     if (uleq (ap[0], "archive") && ap[1]) {
291         sprintf (xtnd_name, "%s", ap[1]);               /* save the name */
292         xtnd_last = 0;
293         xtnd_first = 1;         /* setup to fail in pop_stat */
294         return OK;
295     }
296     if (uleq (ap[0], "bboards")) {
297
298         if (ap[1]) {                    /* XTND "BBOARDS group" */
299             sprintf (xtnd_name, "%s", ap[1]);           /* save the name */
300             if (command("GROUP %s", xtnd_name) == NOTOK)
301                 return NOTOK;
302
303             strcpy (buffer, response);  /* action must ignore extra args */
304             ap = brkstring (response, " ", "\n");/* "211 nart first last g" */
305             xtnd_first = atoi (ap[2]);
306             xtnd_last  = atoi (ap[3]);
307
308             (*action) (buffer);         
309             return OK;
310
311         } else {                /* XTND "BBOARDS" */
312             return traverse (action, "LIST", a, b, c, d);
313         }
314     }
315     return NOTOK;       /* unknown XTND command */
316 }
317 #endif  BPOP
318
319 /* \f */
320
321 int     pop_quit () {
322     int     i;
323
324     i = command ("QUIT");
325     (void) pop_done ();
326
327     return i;
328 }
329
330
331 int     pop_done () {
332     (void) fclose (input);
333     (void) fclose (output);
334
335     return OK;
336 }
337
338 /* \f */
339
340 /* VARARGS1 */
341
342 int  command (fmt, a, b, c, d)
343 char   *fmt,
344        *a,
345        *b,
346        *c,
347        *d;
348 {
349     char   *cp,
350             buffer[BUFSIZ];
351
352     (void) sprintf (buffer, fmt, a, b, c, d);
353     if (poprint)
354         if (pophack) {
355             if (cp = index (buffer, ' '))
356                 *cp = NULL;
357             fprintf (stderr, "---> %s ********\n", buffer);
358             if (cp)
359                 *cp = ' ';
360             pophack = 0;
361         }
362         else
363             fprintf (stderr, "---> %s\n", buffer);
364
365     if (putline (buffer, output) == NOTOK)
366         return NOTOK;
367
368     switch (getline (response, sizeof response, input)) {
369         case OK: 
370             if (poprint)
371                 fprintf (stderr, "<--- %s\n", response);
372             return (*response < CHAR_ERR ? OK : NOTOK);
373
374         case NOTOK: 
375         case DONE: 
376             if (poprint)            
377                 fprintf (stderr, "%s\n", response);
378             return NOTOK;
379     }
380 /* NOTREACHED */
381 }
382
383 int  multiline () {
384     char    buffer[BUFSIZ + TRMLEN];
385
386     if (getline (buffer, sizeof buffer, input) != OK)
387         return NOTOK;
388 #ifdef  DEBUG
389     if (poprint)
390         fprintf (stderr, "<--- %s\n", response);
391 #endif  DEBUG
392     if (strncmp (buffer, TRM, TRMLEN) == 0) {
393         if (buffer[TRMLEN] == NULL)
394             return DONE;
395         else
396             (void) strcpy (response, buffer + TRMLEN);
397     }
398     else
399         (void) strcpy (response, buffer);
400
401     return OK;
402 }
403
404 /* \f */
405
406 static int  getline (s, n, iop)
407 char   *s;
408 int     n;
409 FILE * iop;
410 {
411     int     c;
412     char   *p;
413
414     p = s;
415     while (--n > 0 && (c = fgetc (iop)) != EOF)
416         if ((*p++ = c) == '\n')
417             break;
418     if (ferror (iop) && c != EOF) {
419         (void) strcpy (response, "error on connection");
420         return NOTOK;
421     }
422     if (c == EOF && p == s) {
423         (void) strcpy (response, "connection closed by foreign host");
424         return DONE;
425     }
426     *p = NULL;
427     if (*--p == '\n')
428         *p = NULL;
429     if (*--p == '\r')
430         *p = NULL;
431
432     return OK;
433 }
434
435
436 static  putline (s, iop)
437 char   *s;
438 FILE * iop;
439 {
440     (void) fprintf (iop, "%s\r\n", s);
441     (void) fflush (iop);
442     if (ferror (iop)) {
443         (void) strcpy (response, "lost connection");
444         return NOTOK;
445     }
446
447     return OK;
448 }