Annotation of 43BSDTahoe/new/nntp/common/clientlib.c, revision 1.1.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.