chiark / gitweb /
Merge branch 'running' of login.chiark.greenend.org.uk:public-git/inn-innduct
[innduct.git] / lib / clientlib.c
1 /*  $Id: clientlib.c 6155 2003-01-19 19:58:25Z rra $
2 **
3 **  Routines compatible with the NNTP "clientlib" routines.
4 */
5 #include "config.h"
6 #include "clibrary.h"
7
8 #include "inn/innconf.h"
9 #include "libinn.h"
10 #include "nntp.h"
11
12
13 FILE    *ser_rd_fp = NULL;
14 FILE    *ser_wr_fp = NULL;
15 char    ser_line[NNTP_STRLEN + 2];
16
17
18 /*
19 **  Get the name of the NNTP server.  Ignore the filename; we use
20 **  our own configuration stuff.  Return pointer to static data.
21 */
22 char *
23 getserverbyfile(char *file UNUSED)
24 {
25     static char buff[256];
26
27     strlcpy(buff, innconf->server, sizeof(buff));
28     return buff;
29 }
30
31
32 /*
33 **  Get a connection to the remote news server.  Return server's reply
34 **  code or -1 on error.
35 */
36 int
37 server_init(char *host, int port)
38 {
39     char        line2[NNTP_STRLEN];
40
41     /* This interface may be used by clients that assume C News behavior and
42        won't read inn.conf themselves. */
43     if (innconf == NULL)
44         if (!innconf_read(NULL))
45             return -1;
46
47     if (NNTPconnect(host, port, &ser_rd_fp, &ser_wr_fp, ser_line) < 0) {
48         if (ser_line[0] == '\0')
49             /* I/O problem. */
50             return -1;
51
52         /* Server rejected connection; return it's reply code. */
53         return atoi(ser_line);
54     }
55
56     /* Send the INN command; if understood, use that reply. */
57     put_server("mode reader");
58     if (get_server(line2, (int)sizeof line2) < 0)
59         return -1;
60     if (atoi(line2) != NNTP_BAD_COMMAND_VAL)
61         strlcpy(ser_line, line2, sizeof(ser_line));
62
63     /* Connected; return server's reply code. */
64     return atoi(ser_line);
65 }
66
67
68 #define CANTPOST        \
69     "NOTE:  This machine does not have permission to post articles"
70 #define CANTUSE         \
71         "This machine does not have permission to use the %s news server.\n"
72 /*
73 **  Print a message based on the the server's initial response.
74 **  Return -1 if server wants us to go away.
75 */
76 int
77 handle_server_response(int response, char *host)
78 {
79     char        *p;
80
81     switch (response) {
82     default:
83         printf("Unknown response code %d from %s.\n", response, host);
84         return -1;
85      case NNTP_GOODBYE_VAL:
86         if (atoi(ser_line) == response) {
87             p = &ser_line[strlen(ser_line) - 1];
88             if (*p == '\n' && *--p == '\r')
89                 *p = '\0';
90             if (p > &ser_line[3]) {
91                 printf("News server %s unavailable: %s\n", host,
92                         &ser_line[4]);
93                 return -1;
94             }
95         }
96         printf("News server %s unavailable, try later.\n", host);
97         return -1;
98     case NNTP_ACCESS_VAL:
99         printf(CANTUSE, host);
100         return -1;
101     case NNTP_NOPOSTOK_VAL:
102         printf("%s.\n", CANTPOST);
103         /* FALLTHROUGH */
104     case NNTP_POSTOK_VAL:
105         break;
106     }
107     return 0;
108 }
109
110
111 /*
112 **  Send a line of text to the server.
113 */
114 void
115 put_server(const char *buff)
116 {
117     fprintf(ser_wr_fp, "%s\r\n", buff);
118     fflush(ser_wr_fp);
119 }
120
121
122 /*
123 **  Get a line of text from the server, strip trailing \r\n.
124 **  Return -1 on error.
125 */
126 int
127 get_server(char *buff, int buffsize)
128 {
129     char        *p;
130
131     if (fgets(buff, buffsize, ser_rd_fp) == NULL)
132         return -1;
133     p = &buff[strlen(buff)];
134     if (p >= &buff[2] && p[-2] == '\r' && p[-1] == '\n')
135         p[-2] = '\0';
136     return 0;
137 }
138
139
140 /*
141 **  Send QUIT and close the server.
142 */
143 void
144 close_server(void)
145 {
146     char        buff[NNTP_STRLEN];
147
148     if (ser_wr_fp != NULL && ser_rd_fp != NULL) {
149         put_server("QUIT");
150         fclose(ser_wr_fp);
151         ser_wr_fp = NULL;
152
153         get_server(buff, (int)sizeof buff);
154         fclose(ser_rd_fp);
155         ser_rd_fp = NULL;
156     }
157 }