|
|
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.