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: }

Defined functions

converse defined in line 89; used 1 times
goodbye defined in line 170; used 5 times
hello defined in line 110; used 1 times
readreply defined in line 40; used 4 times
rfgets defined in line 228; used 1 times
  • in line 16
sendcmd defined in line 26; used 2 times
sendfile defined in line 263; used 1 times
sfgets defined in line 202; used 3 times
to_sfgets defined in line 189; used 1 times

Defined variables

SFGstack defined in line 12; used 2 times

Defined macros

FALSE defined in line 10; used 5 times
TRUE defined in line 9; used 3 times
Last modified: 1986-03-21
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1713
Valid CSS Valid XHTML 1.0 Strict