Annotation of 43BSD/contrib/nntp/xmit/remote.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.