Annotation of 43BSDTahoe/new/nntp/common/clientlib.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * NNTP client routines.
        !             3:  */
        !             4: 
        !             5: #ifndef lint
        !             6: static char    *sccsid = "@(#)clientlib.c      1.5     (Berkeley) 10/15/87";
        !             7: #endif
        !             8: 
        !             9: #include <stdio.h>
        !            10: #include <sys/types.h>
        !            11: #include <sys/socket.h>
        !            12: #include <netinet/in.h>
        !            13: #include <netdb.h>
        !            14: 
        !            15: #if defined(AF_DECnet) && defined(ultrix)
        !            16: # ifndef DECNET
        !            17: #  define DECNET
        !            18: # endif
        !            19: #endif
        !            20: 
        !            21: #ifdef DECNET
        !            22: #include <netdnet/dn.h>
        !            23: #include <netdnet/dnetdb.h>
        !            24: #endif
        !            25: 
        !            26: #include "response_codes.h"
        !            27: 
        !            28: FILE   *ser_rd_fp = NULL;
        !            29: FILE   *ser_wr_fp = NULL;
        !            30: 
        !            31: /*
        !            32:  * getserverbyfile     Get the name of a server from a named file.
        !            33:  *                     Handle white space and comments.
        !            34:  *                     Use NNTPSERVER environment variable if set.
        !            35:  *
        !            36:  *     Parameters:     "file" is the name of the file to read.
        !            37:  *
        !            38:  *     Returns:        Pointer to static data area containing the
        !            39:  *                     first non-ws/comment line in the file.
        !            40:  *                     NULL on error (or lack of entry in file).
        !            41:  *
        !            42:  *     Side effects:   None.
        !            43:  */
        !            44: 
        !            45: char *
        !            46: getserverbyfile(file)
        !            47: char   *file;
        !            48: {
        !            49:        register FILE   *fp;
        !            50:        register char   *cp;
        !            51:        static char     buf[256];
        !            52:        char            *index();
        !            53:        char            *getenv();
        !            54: 
        !            55:        if (cp = getenv("NNTPSERVER")) {
        !            56:                (void) strcpy(buf, cp);
        !            57:                return (buf);
        !            58:        }
        !            59: 
        !            60:        if (file == NULL)
        !            61:                return (NULL);
        !            62: 
        !            63:        fp = fopen(file, "r");
        !            64:        if (fp == NULL)
        !            65:                return (NULL);
        !            66: 
        !            67:        while (fgets(buf, sizeof (buf), fp) != NULL) {
        !            68:                if (*buf == '\n' || *buf == '#')
        !            69:                        continue;
        !            70:                cp = index(buf, '\n');
        !            71:                if (cp)
        !            72:                        *cp = '\0';
        !            73:                (void) fclose(fp);
        !            74:                return (buf);
        !            75:        }
        !            76: 
        !            77:        (void) fclose(fp);
        !            78:        return (NULL);                   /* No entry */
        !            79: }
        !            80: 
        !            81: 
        !            82: /*
        !            83:  * server_init  Get a connection to the remote news server.
        !            84:  *
        !            85:  *     Parameters:     "machine" is the machine to connect to.
        !            86:  *
        !            87:  *     Returns:        -1 on error
        !            88:  *                     server's initial response code on success.
        !            89:  *
        !            90:  *     Side effects:   Connects to server.
        !            91:  *                     "ser_rd_fp" and "ser_wr_fp" are fp's
        !            92:  *                     for reading and writing to server.
        !            93:  */
        !            94: 
        !            95: server_init(machine)
        !            96: char   *machine;
        !            97: {
        !            98:        int     sockt_rd, sockt_wr;
        !            99:        char    line[256];
        !           100:        char    *cp;
        !           101:        char    *index();
        !           102: 
        !           103: #ifdef DECNET
        !           104:        cp = index(machine, ':');
        !           105: 
        !           106:        if (cp && cp[1] == ':') {
        !           107:                *cp = '\0';
        !           108:                sockt_rd = get_dnet_socket(machine);
        !           109:        } else
        !           110:                sockt_rd = get_tcp_socket(machine);
        !           111: #else
        !           112:        sockt_rd = get_tcp_socket(machine);
        !           113: #endif
        !           114: 
        !           115:        if (sockt_rd < 0)
        !           116:                return (-1);
        !           117: 
        !           118:        /*
        !           119:         * Now we'll make file pointers (i.e., buffered I/O) out of
        !           120:         * the socket file descriptor.  Note that we can't just
        !           121:         * open a fp for reading and writing -- we have to open
        !           122:         * up two separate fp's, one for reading, one for writing.
        !           123:         */
        !           124: 
        !           125:        if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) {
        !           126:                perror("server_init: fdopen #1");
        !           127:                return (-1);
        !           128:        }
        !           129: 
        !           130:        sockt_wr = dup(sockt_rd);
        !           131:        if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL) {
        !           132:                perror("server_init: fdopen #2");
        !           133:                ser_rd_fp = NULL;               /* from above */
        !           134:                return (-1);
        !           135:        }
        !           136: 
        !           137:        /* Now get the server's signon message */
        !           138: 
        !           139:        (void) get_server(line, sizeof(line));
        !           140:        return (atoi(line));
        !           141: }
        !           142: 
        !           143: 
        !           144: /*
        !           145:  * get_tcp_socket -- get us a socket connected to the news server.
        !           146:  *
        !           147:  *     Parameters:     "machine" is the machine the server is running on.
        !           148:  *
        !           149:  *     Returns:        Socket connected to the news server if
        !           150:  *                     all is ok, else -1 on error.
        !           151:  *
        !           152:  *     Side effects:   Connects to server.
        !           153:  *
        !           154:  *     Errors:         Printed via perror.
        !           155:  */
        !           156: 
        !           157: get_tcp_socket(machine)
        !           158: char   *machine;
        !           159: {
        !           160:        int     s, x = 0;
        !           161:        register char **cp;
        !           162:        struct  sockaddr_in sin;
        !           163:        struct  servent *getservbyname(), *sp;
        !           164:        struct  hostent *gethostbyname(), *hp;
        !           165: 
        !           166:        if ((sp = getservbyname("nntp", "tcp")) ==  NULL) {
        !           167:                fprintf(stderr, "nntp/tcp: Unknown service.\n");
        !           168:                return (-1);
        !           169:        }
        !           170: 
        !           171:        if ((hp = gethostbyname(machine)) == NULL) {
        !           172:                fprintf(stderr, "%s: Unknown host.\n", machine);
        !           173:                return (-1);
        !           174:        }
        !           175: 
        !           176:        bzero((char *) &sin, sizeof(sin));
        !           177:        sin.sin_family = hp->h_addrtype;
        !           178:        sin.sin_port = sp->s_port;
        !           179: 
        !           180:        /*
        !           181:         * The following is kinda gross.  The name server under 4.3
        !           182:         * returns a list of addresses, each of which should be tried
        !           183:         * in turn if the previous one fails.  However, 4.2 hostent
        !           184:         * structure doesn't have this list of addresses.
        !           185:         * Under 4.3, h_addr is a #define to h_addr_list[0].
        !           186:         * We use this to figure out whether to include the NS specific
        !           187:         * code...
        !           188:         */
        !           189: 
        !           190: #ifdef h_addr
        !           191: 
        !           192:        /* get a socket and initiate connection -- use multiple addresses */
        !           193: 
        !           194:        for (cp = hp->h_addr_list; cp && *cp; cp++) {
        !           195:                s = socket(hp->h_addrtype, SOCK_STREAM, 0);
        !           196:                if (s < 0) {
        !           197:                        perror("socket");
        !           198:                        return (-1);
        !           199:                }
        !           200:                bcopy(*cp, (char *)&sin.sin_addr, hp->h_length);
        !           201:                
        !           202:                if (x < 0)
        !           203:                        fprintf(stderr, "trying %s\n", inet_ntoa(sin.sin_addr));
        !           204:                x = connect(s, (struct sockaddr *)&sin, sizeof (sin));
        !           205:                if (x == 0)
        !           206:                        break;
        !           207:                 fprintf(stderr, "connection to %s: ", inet_ntoa(sin.sin_addr));
        !           208:                perror("");
        !           209:                (void) close(s);
        !           210:        }
        !           211:        if (x < 0) {
        !           212:                fprintf(stderr, "giving up...\n");
        !           213:                return (-1);
        !           214:        }
        !           215: #else  /* no name server */
        !           216: 
        !           217:        if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { /* Get the socket */
        !           218:                perror("socket");
        !           219:                return (-1);
        !           220:        }
        !           221: 
        !           222:        /* And then connect */
        !           223: 
        !           224:        bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);
        !           225:        if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
        !           226:                perror("connect");
        !           227:                (void) close(s);
        !           228:                return (-1);
        !           229:        }
        !           230: 
        !           231: #endif
        !           232: 
        !           233:        return (s);
        !           234: }
        !           235: 
        !           236: #ifdef DECNET
        !           237: /*
        !           238:  * get_dnet_socket -- get us a socket connected to the news server.
        !           239:  *
        !           240:  *     Parameters:     "machine" is the machine the server is running on.
        !           241:  *
        !           242:  *     Returns:        Socket connected to the news server if
        !           243:  *                     all is ok, else -1 on error.
        !           244:  *
        !           245:  *     Side effects:   Connects to server.
        !           246:  *
        !           247:  *     Errors:         Printed via nerror.
        !           248:  */
        !           249: 
        !           250: get_dnet_socket(machine)
        !           251: char   *machine;
        !           252: {
        !           253:        int     s, area, node;
        !           254:        struct  sockaddr_dn sdn;
        !           255:        struct  nodeent *getnodebyname(), *np;
        !           256: 
        !           257:        bzero((char *) &sdn, sizeof(sdn));
        !           258: 
        !           259:        switch (s = sscanf( machine, "%d%*[.]%d", &area, &node )) {
        !           260:                case 1: 
        !           261:                        node = area;
        !           262:                        area = 0;
        !           263:                case 2: 
        !           264:                        node += area*1024;
        !           265:                        sdn.sdn_add.a_len = 2;
        !           266:                        sdn.sdn_family = AF_DECnet;
        !           267:                        sdn.sdn_add.a_addr[0] = node % 256;
        !           268:                        sdn.sdn_add.a_addr[1] = node / 256;
        !           269:                        break;
        !           270:                default:
        !           271:                        if ((np = getnodebyname(machine)) == NULL) {
        !           272:                                fprintf(stderr, 
        !           273:                                        "%s: Unknown host.\n", machine);
        !           274:                                return (-1);
        !           275:                        } else {
        !           276:                                bcopy(np->n_addr, 
        !           277:                                        (char *) sdn.sdn_add.a_addr, 
        !           278:                                        np->n_length);
        !           279:                                sdn.sdn_add.a_len = np->n_length;
        !           280:                                sdn.sdn_family = np->n_addrtype;
        !           281:                        }
        !           282:                        break;
        !           283:        }
        !           284:        sdn.sdn_objnum = 0;
        !           285:        sdn.sdn_flags = 0;
        !           286:        sdn.sdn_objnamel = strlen("NNTP");
        !           287:        bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel);
        !           288: 
        !           289:        if ((s = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) {
        !           290:                nerror("socket");
        !           291:                return (-1);
        !           292:        }
        !           293: 
        !           294:        /* And then connect */
        !           295: 
        !           296:        if (connect(s, (struct sockaddr *) &sdn, sizeof(sdn)) < 0) {
        !           297:                nerror("connect");
        !           298:                close(s);
        !           299:                return (-1);
        !           300:        }
        !           301: 
        !           302:        return (s);
        !           303: }
        !           304: #endif
        !           305: 
        !           306: 
        !           307: 
        !           308: /*
        !           309:  * handle_server_response
        !           310:  *
        !           311:  *     Print some informative messages based on the server's initial
        !           312:  *     response code.  This is here so inews, rn, etc. can share
        !           313:  *     the code.
        !           314:  *
        !           315:  *     Parameters:     "response" is the response code which the
        !           316:  *                     server sent us, presumably from "server_init",
        !           317:  *                     above.
        !           318:  *                     "server" is the news server we got the
        !           319:  *                     response code from.
        !           320:  *
        !           321:  *     Returns:        -1 if the error is fatal (and we should exit).
        !           322:  *                     0 otherwise.
        !           323:  *
        !           324:  *     Side effects:   None.
        !           325:  */
        !           326: 
        !           327: handle_server_response(response, server)
        !           328: int    response;
        !           329: char   *server;
        !           330: {
        !           331:     switch (response) {
        !           332:        case OK_NOPOST:         /* fall through */
        !           333:                printf(
        !           334:        "NOTE: This machine does not have permission to post articles.\n");
        !           335:                printf(
        !           336:        "      Please don't waste your time trying.\n\n");
        !           337: 
        !           338:        case OK_CANPOST:
        !           339:                return (0);
        !           340:                break;
        !           341: 
        !           342:        case ERR_ACCESS:
        !           343:                printf(
        !           344:    "This machine does not have permission to use the %s news server.\n",
        !           345:                server);
        !           346:                return (-1);
        !           347:                break;
        !           348: 
        !           349:        default:
        !           350:                printf("Unexpected response code from %s news server: %d\n",
        !           351:                        server, response);
        !           352:                return (-1);
        !           353:                break;
        !           354:     }
        !           355:        /*NOTREACHED*/
        !           356: }
        !           357: 
        !           358: 
        !           359: /*
        !           360:  * put_server -- send a line of text to the server, terminating it
        !           361:  * with CR and LF, as per ARPA standard.
        !           362:  *
        !           363:  *     Parameters:     "string" is the string to be sent to the
        !           364:  *                     server.
        !           365:  *
        !           366:  *     Returns:        Nothing.
        !           367:  *
        !           368:  *     Side effects:   Talks to the server.
        !           369:  *
        !           370:  *     Note:           This routine flushes the buffer each time
        !           371:  *                     it is called.  For large transmissions
        !           372:  *                     (i.e., posting news) don't use it.  Instead,
        !           373:  *                     do the fprintf's yourself, and then a final
        !           374:  *                     fflush.
        !           375:  */
        !           376: 
        !           377: void
        !           378: put_server(string)
        !           379: char *string;
        !           380: {
        !           381: #ifdef DEBUG
        !           382:        fprintf(stderr, ">>> %s\n", string);
        !           383: #endif
        !           384:        fprintf(ser_wr_fp, "%s\r\n", string);
        !           385:        (void) fflush(ser_wr_fp);
        !           386: }
        !           387: 
        !           388: 
        !           389: /*
        !           390:  * get_server -- get a line of text from the server.  Strips
        !           391:  * CR's and LF's.
        !           392:  *
        !           393:  *     Parameters:     "string" has the buffer space for the
        !           394:  *                     line received.
        !           395:  *                     "size" is the size of the buffer.
        !           396:  *
        !           397:  *     Returns:        -1 on error, 0 otherwise.
        !           398:  *
        !           399:  *     Side effects:   Talks to server, changes contents of "string".
        !           400:  */
        !           401: 
        !           402: get_server(string, size)
        !           403: char   *string;
        !           404: int    size;
        !           405: {
        !           406:        register char *cp;
        !           407:        char    *index();
        !           408: 
        !           409:        if (fgets(string, size, ser_rd_fp) == NULL)
        !           410:                return (-1);
        !           411: 
        !           412:        if ((cp = index(string, '\r')) != NULL)
        !           413:                *cp = '\0';
        !           414:        else if ((cp = index(string, '\n')) != NULL)
        !           415:                *cp = '\0';
        !           416: #ifdef DEBUG
        !           417:        fprintf(stderr, "<<< %s\n", string);
        !           418: #endif
        !           419: 
        !           420:        return (0);
        !           421: }
        !           422: 
        !           423: 
        !           424: /*
        !           425:  * close_server -- close the connection to the server, after sending
        !           426:  *             the "quit" command.
        !           427:  *
        !           428:  *     Parameters:     None.
        !           429:  *
        !           430:  *     Returns:        Nothing.
        !           431:  *
        !           432:  *     Side effects:   Closes the connection with the server.
        !           433:  *                     You can't use "put_server" or "get_server"
        !           434:  *                     after this routine is called.
        !           435:  */
        !           436: 
        !           437: void
        !           438: close_server()
        !           439: {
        !           440:        char    ser_line[256];
        !           441: 
        !           442:        if (ser_wr_fp == NULL || ser_rd_fp == NULL)
        !           443:                return;
        !           444: 
        !           445:        put_server("QUIT");
        !           446:        (void) get_server(ser_line, sizeof(ser_line));
        !           447: 
        !           448:        (void) fclose(ser_wr_fp);
        !           449:        (void) fclose(ser_rd_fp);
        !           450: }

unix.superglobalmegacorp.com

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