Annotation of 43BSD/contrib/nntp/xmit/nntpxmit.c, revision 1.1

1.1     ! root        1: /*
        !             2: ** nntpxmit - transmit netnews articles across the internet with nntp
        !             3: **
        !             4: ** This program is for transmitting netnews between sites that offer the
        !             5: ** NNTP service, internet style.  Ideally, there are two forms of
        !             6: ** transmission that can be used in this environment, since the
        !             7: ** communication is interactive (and relatively immediate, when compared
        !             8: ** with UUCP).  They are:  passive poll (what have you gotten lately?) and
        !             9: ** active send (I have `x', do you want it?).  The USENET as a whole
        !            10: ** uniformly uses active send, and where the communication is batched
        !            11: ** (e.g. UUCP, or electronic mail) the software sends without even asking,
        !            12: ** unless it can determine that the article has already been to some site.
        !            13: **
        !            14: ** It turns out that when you implement passive poll, you have to be
        !            15: ** *very* careful about what you (the server) tell the client, because
        !            16: ** something that you might wish to restrict distribution of (either
        !            17: ** internal newsgroups, or material posted in the international groups in
        !            18: ** local distributions) will otherwise leak out.  It is the case that if
        !            19: ** the server doesn't tell the client that article `x' is there, the
        !            20: ** client won't ask for it.  If the server tells about an article which
        !            21: ** would otherwise stay within some restricted distribution, the onus is
        !            22: ** then on the client to figure out that the article is not appropriate to
        !            23: ** post on its local system.  Of course, at that point, we have already
        !            24: ** wasted the network bandwidth in transferring the article...
        !            25: **
        !            26: ** This is a roundabout way of saying that this program only implements
        !            27: ** active send.  There will have to be once-over done on the NNTP spec
        !            28: ** before passive poll goes in, because of the problems that I have cited.
        !            29: **
        !            30: ** Erik E. Fair        <ucbvax!fair>, Oct 14, 1985
        !            31: */
        !            32: 
        !            33: #include <stdio.h>
        !            34: #include <sys/types.h>
        !            35: #include <sys/file.h>
        !            36: #include <syslog.h>
        !            37: #include <sysexits.h>
        !            38: #include "defs.h"
        !            39: #include "header.h"
        !            40: #include "response_codes.h"
        !            41: #include "nntpxmit.h"
        !            42: 
        !            43: char   *pname;
        !            44: char   Debug = FALSE;
        !            45: char   Do_Stats = TRUE;
        !            46: char   *USAGE = "USAGE: nntpxmit [-s] hostname:file [hostname:file ...]";
        !            47: FILE   *getfp();
        !            48: 
        !            49: struct Stats {
        !            50:        u_long  offered;
        !            51:        u_long  accepted;
        !            52:        u_long  rejected;
        !            53:        u_long  failed;
        !            54: } Stats = {0L, 0L, 0L, 0L};
        !            55: 
        !            56: extern int     errno;
        !            57: extern char    *rindex();
        !            58: extern char    *index();
        !            59: extern char    *errmsg();
        !            60: 
        !            61: main(ac,av)
        !            62: int    ac;
        !            63: char   *av[];
        !            64: {
        !            65:        register int    i;
        !            66:        char    *host, *file;
        !            67: 
        !            68:        pname = ((pname = rindex(av[0],'/')) ? pname + 1 : av[0]);
        !            69:        
        !            70:        if (ac < 2) {
        !            71:                fprintf(stderr,"%s: %s\n", pname, USAGE);
        !            72:                exit(EX_USAGE);
        !            73:        }
        !            74: 
        !            75:        /* note that 4.2 BSD openlog has only two args */
        !            76:        (void) openlog(pname, LOG_PID, LOG_LOCAL7);
        !            77: 
        !            78:        for(i = 1; i < ac; i++) {
        !            79:                if (av[i][0] == '-') {
        !            80:                        switch(av[i][1]) {
        !            81:                        case 's':
        !            82:                                Do_Stats = FALSE;
        !            83:                                break;
        !            84:                        case 'd':
        !            85:                                Debug++;
        !            86:                                break;
        !            87:                        default:
        !            88:                                fprintf(stderr,"%s: no such option: -%c\n",
        !            89:                                        pname, av[i][1]);
        !            90:                                fprintf(stderr,"%s: %s\n", pname, USAGE);
        !            91:                                exit(EX_USAGE);
        !            92:                        }
        !            93:                        continue;
        !            94:                }
        !            95: 
        !            96:                /*
        !            97:                ** OK, it wasn't an option, therefore it must be a
        !            98:                ** hostname, filename pair.
        !            99:                */
        !           100:                host = av[i];
        !           101:                if ((file = index(host, ':')) != (char *)NULL) {
        !           102:                        *file++ = '\0';
        !           103:                } else {
        !           104:                        fprintf(stderr,"%s: illegal hostname:file pair: <%s>\n",
        !           105:                                pname, host);
        !           106:                        continue;
        !           107:                }
        !           108: 
        !           109:                bzero(&Stats, sizeof(Stats));
        !           110:                if (sendnews(host, file) && Do_Stats) {
        !           111:                        syslog(LOG_INFO,
        !           112:                                "%s stats %d offered %d accepted %d rejected %d failed\n",
        !           113:                                host, Stats.offered, Stats.accepted, Stats.rejected, Stats.failed);
        !           114:                }
        !           115:        }
        !           116:        exit(EX_OK);
        !           117: }
        !           118: 
        !           119: /*
        !           120: ** Given a hostname to connect to, and a file of filenames (which contain
        !           121: ** netnews articles), send those articles to the named host using NNTP.
        !           122: */
        !           123: sendnews(host, file)
        !           124: char   *host, *file;
        !           125: {
        !           126:        register int    code;
        !           127:        register FILE   *filefile = fopen(file, "r");
        !           128:        register FILE   *fp;
        !           129:        char    buf[BUFSIZ];
        !           130: 
        !           131:        /*
        !           132:        ** if no news to send, return
        !           133:        */
        !           134:        if (filefile == (FILE *)NULL) {
        !           135:                dprintf(stderr, "%s: %s: %s\n", pname, file, errmsg(errno));
        !           136:                return(FALSE);
        !           137:        }
        !           138: 
        !           139:        if (hello(host) == FAIL) {
        !           140:                fclose(filefile);
        !           141:                return(FALSE);
        !           142:        }
        !           143: 
        !           144:        while((fp = getfp(filefile)) != (FILE *)NULL) {
        !           145:                switch(code = ihave(fp)) {
        !           146:                case CONT_XFER:
        !           147:                        if (!sendfile(fp)) {
        !           148:                                fprintf(stderr, "%s: %s: article transmission failed.\n", pname, host);
        !           149:                                if (Do_Stats) Stats.failed++;
        !           150:                                fclose(filefile);
        !           151:                                fclose(fp);
        !           152:                                goodbye(DONT_WAIT);
        !           153:                                return(TRUE);
        !           154:                        }
        !           155:                        fclose(fp);
        !           156:                        /*
        !           157:                        ** Here I read the reply from the remote about the
        !           158:                        ** transferred article, and I throw it away. I
        !           159:                        ** should probably try and record the article
        !           160:                        ** filename and append it back to the batchfile
        !           161:                        ** again in the name of reliability, but that's
        !           162:                        ** messy, and it's easier to assume that the guy
        !           163:                        ** will have redundant feeds.
        !           164:                        */
        !           165:                        code = readreply(buf, sizeof(buf));
        !           166:                        if (Do_Stats && code != OK_XFERED) Stats.failed++;
        !           167:                        break;
        !           168:                case ERR_GOTIT:
        !           169:                        fclose(fp);
        !           170:                        break;
        !           171:                default:
        !           172:                        fprintf(stderr,"%s: %s gave an improper response to IHAVE: %d\n", pname, host, code);
        !           173:                        fclose(filefile);
        !           174:                        fclose(fp);
        !           175:                        goodbye(DONT_WAIT);
        !           176:                        return(TRUE);
        !           177:                }
        !           178:        }
        !           179:        fclose(filefile);
        !           180:        if (unlink(file) < 0) {
        !           181:                fprintf(stderr,"%s: unable to unlink(%s): %s\n", pname, file, errmsg(errno));
        !           182:        }
        !           183:        goodbye(WAIT);
        !           184:        return(TRUE);
        !           185: }
        !           186: 
        !           187: /*
        !           188: ** Read the header of a netnews article, snatch the message-id therefrom,
        !           189: ** and ask the remote if they have that one already.
        !           190: */
        !           191: ihave(fp)
        !           192: FILE   *fp;
        !           193: {
        !           194:        struct hbuf     header;
        !           195:        char    scr[LBUFLEN];
        !           196: 
        !           197:        bzero(&header, sizeof(header));
        !           198:        if (rfc822read(&header, fp, scr)) {
        !           199:                register int    code;
        !           200:                char    buf[BUFSIZ];
        !           201: 
        !           202:                /*
        !           203:                ** If an article shows up without a message-id,
        !           204:                ** we scream bloody murder. That's one in
        !           205:                ** the `can't ever happen' category.
        !           206:                */
        !           207:                if (header.ident[0] == '\0') {
        !           208:                        fprintf(stderr, "%s: article w/o message-id!\n", pname);
        !           209:                        return(ERR_GOTIT);
        !           210:                }
        !           211:                sprintf(buf, "IHAVE %s", header.ident);
        !           212:                if (Do_Stats) Stats.offered++;
        !           213: 
        !           214:                switch(code = converse(buf, sizeof(buf))) {
        !           215:                case CONT_XFER:
        !           216:                        if (Do_Stats) Stats.accepted++;
        !           217:                        rewind(fp);
        !           218:                        return(code);
        !           219:                default:
        !           220:                        if (Do_Stats) Stats.rejected++;
        !           221:                        return(code);
        !           222:                }
        !           223:        }
        !           224:        /*
        !           225:        ** something botched locally with the article
        !           226:        ** so we don't send it, but we don't break off
        !           227:        ** communications with the remote either.
        !           228:        */
        !           229:        return(ERR_GOTIT);
        !           230: }
        !           231: 
        !           232: /*
        !           233: ** Given that fp points to an open file containing filenames,
        !           234: ** open and return a file pointer to the next filename in the file.
        !           235: ** Don't you love indirection?
        !           236: */
        !           237: FILE *
        !           238: getfp(fp)
        !           239: FILE   *fp;
        !           240: {
        !           241:        register FILE   *newfp = NULL;
        !           242:        register char   *cp;
        !           243:        char    filename[BUFSIZ];
        !           244: 
        !           245:        while(newfp == NULL) {
        !           246:                if (fgets(filename, sizeof(filename), fp) == NULL)
        !           247:                        return(NULL);           /* EOF, tell caller */
        !           248:                
        !           249:                /* zap \n char */
        !           250:                if (*(cp = &filename[strlen(filename) - 1]) == '\n')
        !           251:                        *cp = '\0';
        !           252: 
        !           253:                if ((newfp = fopen(filename, "r")) == NULL)
        !           254:                        perror(filename);       /* tell 'em why it failed */
        !           255:        }
        !           256:        dprintf(stderr, "FILE: %s\n", filename);        /* DEBUG */
        !           257:        return(newfp);
        !           258: }

unix.superglobalmegacorp.com

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