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