Annotation of 43BSDTahoe/new/nntp/xmit/remote.c, revision 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.