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

Defined functions

bzero defined in line 496; used 3 times
close_server defined in line 480; used 1 times
get_dnet_socket defined in line 293; used 1 times
get_server defined in line 445; used 3 times
get_tcp_socket defined in line 170; used 2 times
getserverbyfile defined in line 57; used 1 times
handle_server_response defined in line 370; never used
put_server defined in line 420; used 2 times
server_init defined in line 108; used 1 times

Defined variables

sccsid defined in line 2; never used

Defined macros

IPPORT_NNTP defined in line 30; used 1 times
index defined in line 26; used 7 times
Last modified: 1988-02-26
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4361
Valid CSS Valid XHTML 1.0 Strict