📄 clientlib.c
字号:
#ifndef lintstatic char *sccsid = "@(#)clientlib.c 1.11 (Berkeley) 10/27/89";#endif/* * NNTP client routines. *//* * Include configuration parameters only if we're made in the nntp tree. */#ifdef HAVE_CONFIG_H#include "../config.h"#endif#include <stdio.h>#ifndef FOR_NN#include <sys/types.h>#endif#include <sys/socket.h>#ifdef FOR_NN#if !defined(NETWORK_DATABASE) || defined(NETWORK_BYTE_ORDER)#include <netinet/in.h>#endif#else#include <netinet/in.h>#endif#ifndef EXCELAN# include <netdb.h>#endif/* * __FP__ includes */#ifdef STDC_HEADERS#include <stdlib.h>#include <string.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif#ifdef EXCELAN# define IPPORT_NNTP 119#endif#ifdef DECNET#include <netdnet/dn.h>#include <netdnet/dnetdb.h>#endif#include "nntp.h"FILE *ser_rd_fp = NULL;FILE *ser_wr_fp = NULL;/* * getserverbyfile Get the name of a server from a named file. * Handle white space and comments. * Use NNTPSERVER environment variable if set. * * Parameters: "file" is the name of the file to read. * * Returns: Pointer to static data area containing the * first non-ws/comment line in the file. * NULL on error (or lack of entry in file). * * Side effects: None. */char *getserverbyfile(file)char *file;{ register FILE *fp; register char *cp; static char buf[256]; if (cp = getenv("NNTPSERVER")) { (void) strcpy(buf, cp); return (buf); } if (cp = getenv("NNTP_SERVER")) { (void) strcpy (buf, cp); return (buf); } /* * may define NNTPSERVER at compile time __FP__ */#ifdef NNTPSERVER if (NNTPSERVER[0]) { (void) strcpy (buf, NNTPSERVER); return buf; }#endif if (file == NULL) return (NULL); fp = fopen(file, "r"); if (fp == NULL) return (NULL); while (fgets(buf, sizeof (buf), fp) != NULL) { if (*buf == '\n' || *buf == '#') continue; cp = strchr(buf, '\n'); if (cp) *cp = '\0'; (void) fclose(fp); return (buf); } (void) fclose(fp); return (NULL); /* No entry */}/* * server_init Get a connection to the remote news server. * * Parameters: "machine" is the machine to connect to. * * Returns: -1 on error * server's initial response code on success. * * Side effects: Connects to server. * "ser_rd_fp" and "ser_wr_fp" are fp's * for reading and writing to server. */server_init(machine)char *machine;{ int sockt_rd, sockt_wr; char line[256];#ifdef DECNET char *cp; cp = strchr(machine, ':'); if (cp && cp[1] == ':') { *cp = '\0'; sockt_rd = get_dnet_socket(machine); } else sockt_rd = get_tcp_socket(machine);#else sockt_rd = get_tcp_socket(machine);#endif if (sockt_rd < 0) return (-1); /* * Now we'll make file pointers (i.e., buffered I/O) out of * the socket file descriptor. Note that we can't just * open a fp for reading and writing -- we have to open * up two separate fp's, one for reading, one for writing. */ if ((ser_rd_fp = fdopen(sockt_rd, "r")) == NULL) { perror("server_init: fdopen #1"); return (-1); } sockt_wr = dup(sockt_rd); if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL) { perror("server_init: fdopen #2"); ser_rd_fp = NULL; /* from above */ return (-1); } /* Now get the server's signon message */ (void) get_server(line, sizeof(line)); return (atoi(line));}/* * get_tcp_socket -- get us a socket connected to the news server. * * Parameters: "machine" is the machine the server is running on. * * Returns: Socket connected to the news server if * all is ok, else -1 on error. * * Side effects: Connects to server. * * Errors: Printed via perror. */get_tcp_socket(machine)char *machine;{ int s; struct sockaddr_in sin;#ifndef EXCELAN struct servent *getservbyname(), *sp; struct hostent *gethostbyname(), *hp;#ifdef h_addr int x = 0; register char **cp;#endif if ((sp = getservbyname("nntp", "tcp")) == NULL) { fprintf(stderr, "nntp/tcp: Unknown service.\n"); return (-1); } /* * Name resolution doesn't quite go as far as it should. Take things * one stage further to allow nnn.nnn.nnn.nnn addresses if all else * fails. */ if( (hp = gethostbyname( machine ) ) == NULL ) { unsigned long inet_addr(); static struct hostent def; static struct in_addr defaddr; static char *alist[1]; static char namebuf[ 256 ]; defaddr.s_addr = inet_addr( machine ); if( defaddr.s_addr != -1 ) { strcpy( namebuf, machine ); def.h_name = namebuf;#ifdef h_addr def.h_addr_list = alist;#endif def.h_addr = (char *)&defaddr; def.h_length = sizeof( struct in_addr ); def.h_addrtype = AF_INET; def.h_aliases = 0; hp = &def; } } if (hp == NULL) { fprintf(stderr, "%s: Unknown host.\n", machine); return (-1); } memset (&sin, '\0', sizeof(sin)); sin.sin_family = hp->h_addrtype; sin.sin_port = sp->s_port;#else memset (&sin, '\0', sizeof(sin)); sin.sin_family = AF_INET; sin.sin_port = htons(IPPORT_NNTP);#endif /* * The following is kinda gross. The name server under 4.3 * returns a list of addresses, each of which should be tried * in turn if the previous one fails. However, 4.2 hostent * structure doesn't have this list of addresses. * Under 4.3, h_addr is a #define to h_addr_list[0]. * We use this to figure out whether to include the NS specific * code... */#ifdef h_addr /* get a socket and initiate connection -- use multiple addresses */ for (cp = hp->h_addr_list; cp && *cp; cp++) { s = socket(hp->h_addrtype, SOCK_STREAM, 0); if (s < 0) { perror("socket"); return (-1); } memcpy ((char *)&sin.sin_addr, *cp, hp->h_length);/* bcopy(*cp, (char *)&sin.sin_addr, hp->h_length);*/ if (x < 0) fprintf(stderr, "trying %s\n", inet_ntoa(sin.sin_addr)); x = connect(s, (struct sockaddr *)&sin, sizeof (sin)); if (x == 0) break; fprintf(stderr, "connection to %s: ", inet_ntoa(sin.sin_addr)); perror(""); (void) close(s); } if (x < 0) { fprintf(stderr, "giving up...\n"); return (-1); }#else /* no name server */#ifdef EXCELAN if ((s = rresvport(SO_KEEPALIVE)) < 0) { /* Get the socket */ perror("socket"); return (-1); } /* set up addr for the connect */ sin.sin_addr.s_addr = rhost(machine); if (sin.sin_addr.s_addr < 0){ fprintf(stderr, "%s: Unknown host.\n", machine); return (-1); } /* And then connect */ if (connect(s, &sin) < 0) { perror("connect"); (void) close(s); return (-1); }#else if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket"); return (-1); } /* And then connect *//* bcopy(hp->h_addr, (char *) &sin.sin_addr, hp->h_length);*/ memcpy ((char *)&sin.sin_addr, hp->h_addr, hp->h_length); if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) { perror("connect"); (void) close(s); return (-1); }#endif#endif return (s);}#ifdef DECNET/* * get_dnet_socket -- get us a socket connected to the news server. * * Parameters: "machine" is the machine the server is running on. * * Returns: Socket connected to the news server if * all is ok, else -1 on error. * * Side effects: Connects to server. * * Errors: Printed via nerror. */get_dnet_socket(machine)char *machine;{ int s, area, node; struct sockaddr_dn sdn; struct nodeent *getnodebyname(), *np; memset (&sdn, '\0', sizeof(sdn)); switch (s = sscanf( machine, "%d%*[.]%d", &area, &node )) { case 1: node = area; area = 0; case 2: node += area*1024; sdn.sdn_add.a_len = 2; sdn.sdn_family = AF_DECnet; sdn.sdn_add.a_addr[0] = node % 256; sdn.sdn_add.a_addr[1] = node / 256; break; default: if ((np = getnodebyname(machine)) == NULL) { fprintf(stderr, "%s: Unknown host.\n", machine); return (-1); } else { /* bcopy(np->n_addr, (char *) sdn.sdn_add.a_addr, np->n_length); */ memcpy ((char *) sdn.sdn_add.a_addr, np->n_addr, np->n_length); sdn.sdn_add.a_len = np->n_length; sdn.sdn_family = np->n_addrtype; } break; } sdn.sdn_objnum = 0; sdn.sdn_flags = 0; sdn.sdn_objnamel = strlen("NNTP");/* bcopy("NNTP", &sdn.sdn_objname[0], sdn.sdn_objnamel); */ memcpy (&sdn.sdn_objname[0], "NNTP", sdn.sdn_objnamel); if ((s = socket(AF_DECnet, SOCK_STREAM, 0)) < 0) { nerror("socket"); return (-1); } /* And then connect */ if (connect(s, (struct sockaddr *) &sdn, sizeof(sdn)) < 0) { nerror("connect"); close(s); return (-1); } return (s);}#endif/* * handle_server_response * * Print some informative messages based on the server's initial * response code. This is here so inews, rn, etc. can share * the code. * * Parameters: "response" is the response code which the * server sent us, presumably from "server_init", * above. * "server" is the news server we got the * response code from. * * Returns: -1 if the error is fatal (and we should exit). * 0 otherwise. * * Side effects: None. */handle_server_response(response, server)int response;char *server;{ switch (response) { case OK_NOPOST: /* fall through */ printf( "NOTE: This machine does not have permission to post articles.\n"); printf( " Please don't waste your time trying.\n\n"); case OK_CANPOST: return (0); break; case ERR_ACCESS: printf( "This machine does not have permission to use the %s news server.\n", server); return (-1); break; default: printf("Unexpected response code from %s news server: %d\n", server, response); return (-1); break; } /*NOTREACHED*/}/* * put_server -- send a line of text to the server, terminating it * with CR and LF, as per ARPA standard. * * Parameters: "string" is the string to be sent to the * server. * * Returns: Nothing. * * Side effects: Talks to the server. * * Note: This routine flushes the buffer each time * it is called. For large transmissions * (i.e., posting news) don't use it. Instead, * do the fprintf's yourself, and then a final * fflush. */voidput_server(string)char *string;{#ifdef DEBUG fprintf(stderr, ">>> %s\n", string);#endif fprintf(ser_wr_fp, "%s\r\n", string); (void) fflush(ser_wr_fp);}/* * get_server -- get a line of text from the server. Strips * CR's and LF's. * * Parameters: "string" has the buffer space for the * line received. * "size" is the size of the buffer. * * Returns: -1 on error, 0 otherwise. * * Side effects: Talks to server, changes contents of "string". */get_server(string, size)char *string;int size;{ register char *cp; if (fgets(string, size, ser_rd_fp) == NULL) return (-1); if ((cp = strchr(string, '\r')) != NULL) *cp = '\0'; else if ((cp = strchr(string, '\n')) != NULL) *cp = '\0';#ifdef DEBUG fprintf(stderr, "<<< %s\n", string);#endif return (0);}/* * close_server -- close the connection to the server, after sending * the "quit" command. * * Parameters: None. * * Returns: Nothing. * * Side effects: Closes the connection with the server. * You can't use "put_server" or "get_server" * after this routine is called. */voidclose_server(){ char ser_line[256]; if (ser_wr_fp == NULL || ser_rd_fp == NULL) return; put_server("QUIT"); (void) get_server(ser_line, sizeof(ser_line)); (void) fclose(ser_wr_fp); (void) fclose(ser_rd_fp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -