1 /* $Id: clientlib.c 10365 2020-05-10 12:58:37Z iulius $
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 "inn/libinn.h"
10 #include "inn/nntp.h"
11
12
13 FILE *ser_rd_fp = NULL;
14 FILE *ser_wr_fp = NULL;
15 char ser_line[NNTP_MAXLEN_COMMAND + 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 *
getserverbyfile(char * file UNUSED)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
server_init(char * host,int port)37 server_init(char *host, int port)
38 {
39 char line2[NNTP_MAXLEN_COMMAND];
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,
48 sizeof(ser_line)) < 0) {
49 if (ser_line[0] == '\0')
50 /* I/O problem. */
51 return -1;
52
53 /* Server rejected connection; return it's reply code. */
54 return atoi(ser_line);
55 }
56
57 /* Send the INN command; if understood, use that reply. */
58 put_server("MODE READER");
59 if (get_server(line2, (int)sizeof line2) < 0)
60 return -1;
61 if (atoi(line2) != NNTP_ERR_COMMAND)
62 strlcpy(ser_line, line2, sizeof(ser_line));
63
64 /* Connected; return server's reply code. */
65 return atoi(ser_line);
66 }
67
68
69 #define CANTPOST \
70 "NOTE: This machine does not have permission to post articles"
71 #define CANTUSE \
72 "This machine does not have permission to use the %s news server.\n"
73 /*
74 ** Print a message based on the the server's initial response.
75 ** Return -1 if server wants us to go away.
76 */
77 int
handle_server_response(int response,char * host)78 handle_server_response(int response, char *host)
79 {
80 char *p;
81
82 switch (response) {
83 default:
84 printf("Unknown response code %d from %s.\n", response, host);
85 return -1;
86 case NNTP_FAIL_TERMINATING:
87 if (atoi(ser_line) == response) {
88 size_t ser_line_len = strlen(ser_line);
89 if (ser_line_len > 4) {
90 p = &ser_line[ser_line_len - 1];
91 if (*p == '\n' && *--p == '\r')
92 *p = '\0';
93 if (p > &ser_line[3]) {
94 printf("News server %s unavailable: %s\n", host,
95 &ser_line[4]);
96 return -1;
97 }
98 }
99 }
100 printf("News server %s unavailable, try later.\n", host);
101 return -1;
102 case NNTP_ERR_ACCESS:
103 printf(CANTUSE, host);
104 return -1;
105 case NNTP_OK_BANNER_NOPOST:
106 printf("%s.\n", CANTPOST);
107 /* FALLTHROUGH */
108 case NNTP_OK_BANNER_POST:
109 break;
110 }
111 return 0;
112 }
113
114
115 /*
116 ** Send a line of text to the server.
117 */
118 void
put_server(const char * buff)119 put_server(const char *buff)
120 {
121 fprintf(ser_wr_fp, "%s\r\n", buff);
122 fflush(ser_wr_fp);
123 }
124
125
126 /*
127 ** Get a line of text from the server, strip trailing \r\n.
128 ** Return -1 on error.
129 */
130 int
get_server(char * buff,int buffsize)131 get_server(char *buff, int buffsize)
132 {
133 char *p;
134
135 if (fgets(buff, buffsize, ser_rd_fp) == NULL)
136 return -1;
137 p = &buff[strlen(buff)];
138 if (p >= &buff[2] && p[-2] == '\r' && p[-1] == '\n')
139 p[-2] = '\0';
140 return 0;
141 }
142
143
144 /*
145 ** Send QUIT and close the server.
146 */
147 void
close_server(void)148 close_server(void)
149 {
150 char buff[NNTP_MAXLEN_COMMAND];
151
152 if (ser_wr_fp != NULL && ser_rd_fp != NULL) {
153 put_server("QUIT");
154 fclose(ser_wr_fp);
155 ser_wr_fp = NULL;
156
157 get_server(buff, (int)sizeof buff);
158 fclose(ser_rd_fp);
159 ser_rd_fp = NULL;
160 }
161 }
162