1 /* $Id: nntpclient.c,v 3.0 1991/11/22 04:12:21 davison Trn $
2 */
3 /* The authors make no claims as to the fitness or correctness of this software
4  * for any use whatsoever, and it is provided as is. Any use of this software
5  * is at the user's own risk.
6  */
7 
8 #include "EXTERN.h"
9 #include "common.h"
10 
11 #ifdef USE_NNTP
12 
13 #include "INTERN.h"
14 #include "nntpclient.h"
15 
16 void finalize _((int));
17 #ifdef NNTP_HANDLE_TIMEOUT
18 char nntp_handle_timeout _((bool_int));
19 #endif
20 #ifdef NNTP_HANDLE_AUTH_ERR
21 char nntp_handle_auth_err _((bool_int));
22 #endif
23 
24 #define CANTPOST	\
25 	"NOTE:  This machine does not have permission to post articles.\n\n"
26 #define CANTUSE		\
27 	"This machine does not have permission to use the %s news server.\n\n"
28 
29 int
nntp_connect(verbose)30 nntp_connect(verbose)
31 bool_int verbose;
32 {
33     char *server, filebuf[128];
34     int response;
35 
36     if ((server = getenv("NNTPSERVER")) == Nullch)
37 	server = SERVER_NAME;
38     if (server[0] == '/') {
39 	register FILE *fp;
40 	if ((fp = fopen(server, "r")) != Nullfp) {
41 	    server = Nullch;
42 	    while (fgets(filebuf, sizeof filebuf, fp) != Nullch) {
43 		if (*filebuf == '\n' || *filebuf == '#')
44 		    continue;
45 		if ((server = index(filebuf, '\n')) != Nullch)
46 		    *server = '\0';
47 		server = filebuf;
48 		break;
49 	    }
50 	    fclose(fp);
51 	} else
52 	    server = Nullch;
53 	if (server == Nullch) {
54 	    sprintf(ser_line, "\
55 Couldn't get name of news server from %s\n\
56 Either fix this file, or put NNTPSERVER in your environment.\n", SERVER_NAME);
57 	    nntp_init_error(ser_line);
58 	    return 0;
59 	}
60     }
61 
62     switch (response = server_init(server)) {
63     case NNTP_GOODBYE_VAL:
64 	if (atoi(ser_line) == response) {
65 	    char tmpbuf[LBUFLEN];
66 	    sprintf(tmpbuf,"News server %s unavailable: %s\n",server,&ser_line[4]);
67 	    nntp_init_error(tmpbuf);
68 	    return 0;
69 	}
70     case -1:
71 	sprintf(ser_line,"News server %s unavailable, try again later.\n",server);
72 	nntp_init_error(ser_line);
73 	return 0;
74     case NNTP_ACCESS_VAL:
75 	sprintf(ser_line,CANTUSE,server);
76 	nntp_init_error(ser_line);
77 	return 0;
78     case NNTP_NOPOSTOK_VAL:
79 	if (verbose) {
80 	    nntp_advise(CANTPOST);
81 	}
82 	/* FALL THROUGH */
83     case NNTP_POSTOK_VAL:
84 	break;
85     default:
86 	sprintf(ser_line,"Unknown response code %d from %s.\n", response, server);
87 	nntp_init_error(ser_line);
88 	return 0;
89     }
90     return 1;
91 }
92 
93 void
nntp_command(buf)94 nntp_command(buf)
95 char *buf;
96 {
97 #if defined(DEBUG) && defined(FLUSH)
98     if (debug & DEB_NNTP)
99 	printf(">%s\n", buf) FLUSH;
100 #endif
101 #if defined(NNTP_HANDLE_TIMEOUT) || defined(NNTP_HANDLE_AUTH_ERR)
102     strcpy(last_command, buf);
103 #endif
104     fprintf(ser_wr_fp, "%s\r\n", buf);
105     fflush(ser_wr_fp);
106 }
107 
108 #ifdef NNTP_HANDLE_TIMEOUT
109 extern char *instr();
110 #endif
111 
112 char
nntp_check(strict)113 nntp_check(strict)
114 bool_int strict;
115 {
116     int n;
117 
118 #ifdef HAS_SIGHOLD
119     sighold(SIGINT);
120 #endif
121     n = (fgets(ser_line, sizeof ser_line, ser_rd_fp) == NULL)? -1 : 0;
122 #ifdef HAS_SIGHOLD
123     sigrelse(SIGINT);
124 #endif
125     if (n < 0) {
126 	nntp_close(FALSE);
127 	nntp_error("\nUnexpected close of server socket.\n");
128 #ifdef NNTP_ERROR_IS_FATAL
129 	finalize(1);
130 #else
131 	return NNTP_CLASS_FATAL;
132 #endif
133     }
134     n = strlen(ser_line);
135     if (n >= 2 && ser_line[n-1] == '\n' && ser_line[n-2] == '\r')
136 	ser_line[n-2] = '\0';
137 #if defined(DEBUG) && defined(FLUSH)
138     if (debug & DEB_NNTP)
139 	printf("<%s\n", ser_line) FLUSH;
140 #endif
141 #ifdef NNTP_HANDLE_AUTH_ERR
142     if (atoi(ser_line) == NNTP_AUTH_NEEDED_VAL) {
143 	return nntp_handle_auth_err(strict);
144     }
145 #endif
146 #ifdef NNTP_HANDLE_TIMEOUT
147     if (atoi(ser_line) == NNTP_TMPERR_VAL && instr(ser_line,"timeout",FALSE)) {
148 	/* See if this was really a timeout */
149 	return nntp_handle_timeout(strict);
150     }
151 #endif
152     if (strict && *ser_line == NNTP_CLASS_FATAL) {	/* Fatal error */
153 	char tmpbuf[LBUFLEN];
154 	sprintf(tmpbuf,"\n%s\n",ser_line);
155 	nntp_error(tmpbuf);
156 #ifdef NNTP_ERROR_IS_FATAL
157 	finalize(1);
158 #endif
159     }
160     return *ser_line;
161 }
162 
163 int
nntp_gets(buf,len)164 nntp_gets(buf, len)
165 char *buf;
166 int  len;
167 {
168     int n;
169 
170 #ifdef HAS_SIGHOLD
171     sighold(SIGINT);
172 #endif
173     n = (fgets(buf, len, ser_rd_fp) == NULL)? -1 : 0;
174 #ifdef HAS_SIGHOLD
175     sigrelse(SIGINT);
176 #endif
177     if (n < 0) {
178 	nntp_close(FALSE);
179 	nntp_error("\nUnexpected close of server socket.\n");
180 #ifdef NNTP_ERROR_IS_FATAL
181 	finalize(1);
182 #else
183 	return -1;
184 #endif
185     }
186     n = strlen(buf);
187     if (n >= 2 && buf[n-1] == '\n' && buf[n-2] == '\r') {
188 	buf[n-2] = '\0';
189 	return 1;
190     }
191     return 0;
192 }
193 
194 void
nntp_close(send_quit)195 nntp_close(send_quit)
196 bool_int send_quit;
197 {
198     if (send_quit && ser_wr_fp != NULL && ser_rd_fp != NULL) {
199 	nntp_command("QUIT");
200 	nntp_check(FALSE);
201     }
202     /* the nntp_check() above might have closed these already. */
203     if (ser_wr_fp != NULL && ser_rd_fp != NULL) {
204 	fclose(ser_wr_fp);
205 	ser_wr_fp = NULL;
206 	fclose(ser_rd_fp);
207 	ser_rd_fp = NULL;
208     }
209 }
210 
211 #endif /* USE_NNTP */
212