|
|
1.1 root 1: #include <stdio.h>
2: #include <ctype.h>
3: #include <setjmp.h>
4: #include <signal.h>
5: #include "get_tcp_conn.h"
6: #include "response_codes.h"
7: #include "nntpxmit.h"
8:
9: #define TRUE 1
10: #define FALSE 0
11:
12: static jmp_buf SFGstack;
13: FILE *rmt_rd;
14: FILE *rmt_wr;
15: char *sfgets();
16: char *rfgets();
17:
18: extern int errno;
19: extern char *pname;
20: extern char Debug;
21: extern char *errmsg();
22:
23: /*
24: ** send cmd to remote, terminated with a CRLF.
25: */
26: sendcmd(cmd)
27: char *cmd;
28: {
29: dprintf(stderr, "<<< %s\n", cmd); /* DEBUG */
30: (void) fprintf(rmt_wr, "%s\r\n", cmd);
31: (void) fflush(rmt_wr);
32: return(ferror(rmt_wr));
33: }
34:
35: /*
36: ** read a reply line from the remote server and return the code number
37: ** as an integer, and the message in a buffer supplied by the caller.
38: ** Returns FAIL if something went wrong.
39: */
40: readreply(buf, size)
41: register char *buf;
42: int size;
43: {
44: register char *cp;
45: register int len;
46:
47: /*
48: ** make sure it's invalid, unless we say otherwise
49: */
50: buf[0] = '\0';
51:
52: /*
53: ** read one line from the remote
54: */
55: if (sfgets(buf, size, rmt_rd) == NULL)
56: return(FAIL); /* error reading from remote */
57:
58: /*
59: ** Make sure that what the remote sent us had a CRLF at the end
60: ** of the line, and then null it out.
61: */
62: if ((len = strlen(buf)) > 2 && *(cp = &buf[len - 2]) == '\r' &&
63: *(cp + 1) == '\n')
64: {
65: *cp = '\0';
66: } else
67: return(FAIL); /* error reading from remote */
68:
69: dprintf(stderr, ">>> %s\n", buf); /* DEBUG */
70: /*
71: ** Skip any non-digits leading the response code
72: ** and then convert the code from ascii to integer for
73: ** return from this routine.
74: */
75: cp = buf;
76: while(*cp != '\0' && isascii(*cp) && !isdigit(*cp))
77: cp++; /* skip anything leading */
78:
79: if (*cp == '\0' || !isascii(*cp))
80: return(FAIL); /* error reading from remote */
81:
82: return(atoi(cp));
83: }
84:
85: /*
86: ** send a command to the remote, and wait for a response
87: ** returns the response code, and the message in the buffer
88: */
89: converse(buf, size)
90: char *buf;
91: int size;
92: {
93: register int resp;
94:
95: if (sendcmd(buf))
96: return(FAIL); /* Ooops! Something went wrong in xmit */
97: /*
98: ** Skip the silly 100 series messages, since they're not the
99: ** final response we can expect
100: */
101: while((resp = readreply(buf, size)) >= 100 && resp < 200)
102: continue;
103: return(resp);
104: }
105:
106: /*
107: ** Contact the remote server and set up the two global FILE pointers
108: ** to that socket.
109: */
110: hello(host)
111: char *host;
112: {
113: int socket0, socket1; /* to me (bad pun) */
114: static char *service = "nntp";
115: char buf[BUFSIZ];
116:
117: switch(socket0 = get_tcp_conn(host, service)) {
118: case NOHOST:
119: fprintf(stderr,"%s: no such host <%s>\n", pname, host);
120: return(FAIL);
121: case NOSERVICE:
122: fprintf(stderr,"%s: no such service <%s>\n", pname, service);
123: return(FAIL);
124: case FAIL:
125: fprintf(stderr,"%s: %s: %s\n", pname, host, errmsg(errno));
126: return(FAIL);
127: }
128:
129: if ((socket1 = dup(socket0)) < 0) {
130: close(socket0);
131: fprintf(stderr,"%s: dup(2): %s\n", pname, errmsg(errno));
132: return(FAIL);
133: }
134:
135: if ((rmt_rd = fdopen(socket0, "r")) == (FILE *)NULL) {
136: close(socket0);
137: close(socket1);
138: fprintf(stderr,"%s: fdopen(3): %s\n", pname, errmsg(errno));
139: return(FAIL);
140: }
141:
142: if ((rmt_wr = fdopen(socket1, "w")) == (FILE *)NULL) {
143: fclose(rmt_rd);
144: rmt_rd = (FILE *)NULL;
145: close(socket1);
146: fprintf(stderr,"%s: fdopen(3): %s\n", pname, errmsg(errno));
147: return(FAIL);
148: }
149:
150: switch(readreply(buf, sizeof(buf))) {
151: case OK_CANPOST:
152: case OK_NOPOST:
153: if (ferror(rmt_rd)) {
154: goodbye(DONT_WAIT);
155: return(FAIL);
156: }
157: break;
158: default:
159: if (buf[0] != '\0')
160: fprintf(stderr, "%s: %s\n", pname, buf);
161: goodbye(DONT_WAIT);
162: return(FAIL);
163: }
164: return(NULL);
165: }
166:
167: /*
168: ** Say goodbye to the nice remote server.
169: */
170: goodbye(wait)
171: int wait;
172: {
173: if (sendcmd("QUIT"))
174: wait = FALSE; /* override, something's wrong. */
175: /*
176: ** I don't care what they say to me; this is just being polite.
177: */
178: if (wait) {
179: char buf[BUFSIZ];
180:
181: (void) readreply(buf, sizeof(buf));
182: }
183: (void) fclose(rmt_rd);
184: rmt_rd = (FILE *)NULL;
185: (void) fclose(rmt_wr);
186: rmt_wr = (FILE *)NULL;
187: }
188:
189: static
190: to_sfgets()
191: {
192: longjmp(SFGstack, 1);
193: }
194:
195: /*
196: ** `Safe' fgets, ala sendmail. This fgets will timeout after some
197: ** period of time, on the assumption that if the remote did not
198: ** return, they're gone.
199: ** WARNING: contains a possibly unportable reference to stdio
200: ** error macros.
201: */
202: char *
203: sfgets(buf, size, fp)
204: char *buf;
205: int size;
206: FILE *fp;
207: {
208: register char *ret;
209:
210: if (setjmp(SFGstack)) {
211: alarm(0); /* reset alarm clock */
212: signal(SIGALRM, SIG_DFL); /* reset SIGALRM */
213: fp->_flag |= _IOERR; /* set stdio error */
214: return(NULL); /* bad read, remote time out */
215: }
216: signal(SIGALRM, to_sfgets);
217: alarm(TIMEOUT);
218: ret = fgets(buf, size, fp);
219: alarm(0); /* reset alarm clock */
220: signal(SIGALRM, SIG_DFL); /* reset SIGALRM */
221: return(ret);
222: }
223:
224: /*
225: ** Remote fgets - converts CRLF to \n, and returns NULL on `.' EOF from
226: ** the remote. Otherwise it returns its first argument, like fgets(3).
227: */
228: char *
229: rfgets(buf, size, fp)
230: char *buf;
231: int size;
232: FILE *fp;
233: {
234: register char *cp = buf;
235: register int len;
236:
237: *cp = '\0';
238: if (sfgets(buf, size, fp) == NULL)
239: return(NULL);
240:
241: /* <CRLF> => '\n' */
242: if ((len = strlen(buf)) > 2 && *(cp = &buf[len - 2]) == '\r') {
243: *cp++ = '\n';
244: *cp = '\0';
245: }
246:
247: /* ".\n" => EOF */
248: cp = buf;
249: if (*cp++ == '.' && *cp == '\n') {
250: return(NULL); /* EOF */
251: }
252:
253: /* Dot escaping */
254: if (buf[0] == '.') strcpy(&buf[0], &buf[1]);
255: return(buf);
256: }
257:
258: /*
259: ** send the contents of an open file descriptor to the remote,
260: ** with appropriate RFC822 filtering (e.g. CRLF line termination,
261: ** and dot escaping). Return FALSE if something went wrong.
262: */
263: sendfile(fp)
264: FILE *fp;
265: {
266: register int c;
267: register int nl = TRUE; /* assume we start on a new line */
268:
269: if (fp == (FILE *)NULL)
270: return(FALSE);
271:
272: while((c = fgetc(fp)) != EOF) {
273: switch(c) {
274: case '\n':
275: (void) fputc('\r', rmt_wr); /* \n -> \r\n */
276: (void) fputc(c, rmt_wr);
277: nl = TRUE; /* for dot escaping */
278: break;
279: case '.':
280: if (nl) {
281: (void) fputc(c, rmt_wr); /* add a dot */
282: nl = FALSE;
283: }
284: (void) fputc(c, rmt_wr);
285: break;
286: default:
287: (void) fputc(c, rmt_wr);
288: nl = FALSE;
289: break;
290: }
291: }
292: if (!nl) {
293: (void) fputs("\r\n", rmt_wr);
294: }
295: (void) fputs(".\r\n", rmt_wr); /* <CRLF>.<CRLF> termination */
296: (void) fflush(rmt_wr);
297: if (ferror(fp) || ferror(rmt_wr)) /* any errors? */
298: return(FALSE);
299: return(TRUE);
300: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.