This is clientlib.c in view mode; [Download] [Up]
/* -*- mode: C; mode: fold */
/*
* This software is Copyright 1991 by Stan Barber.
*
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction or this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
*
* The author make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
*
*/
/* Modified 'server_init' by John E. Davis for use by slrn. */
/*
* NNTP client routines.
*/
/*
* Include configuration parameters only if we're made in the nntp tree.
*/
#if 0
# define DEBUG_FILE "slrn.log"
#endif
#include "config.h"
#include "features.h"
#include <stdio.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
#include <sys/types.h>
#ifdef VMS
/*{{{ VMS includes */
# include <signal.h>
# ifdef MULTINET
# include "multinet_root:[multinet.include.vms]inetiodef.h"
# include "multinet_root:[multinet.include.sys]types.h"
# else
# if NETLIB
# include <descrip.h>
# include <types.h>
# include <iodef.h>
# include <stsdef.h>
# include "netlib_dir:netlibdef.h"
# define NNTP_PORT 119
# define INIT_SDESC(dsc, len, ptr) {(dsc).dsc$b_dtype = DSC$K_DTYPE_T;\
(dsc).dsc$b_class = DSC$K_CLASS_S; (dsc).dsc$w_length = (len);\
(dsc).dsc$a_pointer = (ptr);}
# else
# include <types.h>
# include <iodef.h>
# define NNTP_PORT 119
# endif
# endif
/*}}}*/
#endif
#include <ctype.h>
#ifdef TLI
/*{{{ TLI includes */
# include <fcntl.h>
# include <tiuser.h>
# include <stropts.h>
# include <sys/socket.h>
# define SLRN_LOADED_SYS_SOCKET_H
# ifdef WIN_TCP
# include <sys/in.h>
# else
# include <netinet/in.h>
# define SLRN_LOADED_NETINET_IN_H
# endif
# define IPPORT_NNTP ((unsigned short) 119)
# include <netdb.h> /* All TLI implementations may not have this */
/*}}}*/
#else /* !TLI */
# ifdef VMS
/*{{{ More VMS includes */
# ifdef MULTINET
# include "multinet_root:[multinet.include]netdb.h"
# include "multinet_root:[multinet.include.sys]socket.h"
# include "multinet_root:[multinet.include.netinet]in.h"
# define SLRN_LOADED_NETINET_IN_H
# define SLRN_LOADED_SYS_SOCKET_H
# endif
# ifdef NETLIB
# include <descrip.h>
# include "netlib_dir:netlibdef.h"
# endif
# ifdef UCX
# include <netdb.h>
# include <socket.h>
# include <in.h>
# endif
/*}}}*/
# else /* !VMS */
# include <sys/socket.h>
# include <netinet/in.h>
# define SLRN_LOADED_NETINET_IN_H
# define SLRN_LOADED_SYS_SOCKET_H
# ifndef EXCELAN
# include <netdb.h>
# endif /* !EXCELAN */
# endif /* !VMS */
#endif /* !TLI */
#ifdef HAVE_SYS_SOCKET_H
# ifndef SLRN_LOADED_SYS_SOCKET_H
# include <sys/socket.h>
# define SLRN_LOADED_SYS_SOCKET_H
# endif
#endif
#ifdef HAVE_NETINET_IN_H
# ifndef SLRN_LOADED_NETINET_IN_H
# include <netinet/in.h>
# define SLRN_LOADED_NETINET_IN_H
# endif
#endif
#ifdef HAVE_ARPA_INET_H
# ifndef SLRN_LOADED_ARPA_INET_H
# include <arpa/inet.h>
# define SLRN_LOADED_ARPA_INET_H
# endif
#endif
#ifdef VMS
/*{{{ VMS #defines */
# ifdef MULTINET
# define netread socket_read
# define sock_write socket_write
# define netclose socket_close
# else
# if NETLIB
# define netread netlib_read
# define sock_write netlib_write
# define netclose netlib_close
# else
# define netread read
# define sock_write write
# define netclose close
# endif
# endif
/*}}}*/
# endif /* VMS */
#ifndef NETLIB
# define SERVER_READ_FP ser_rd_fp
# define SERVER_WRITE_FP ser_wr_fp
#else
# define SERVER_READ_FP ipctx
# define SERVER_WRITE_FP ipctx
#endif
#ifdef EXCELAN
/*{{{ EXCELAN defines */
# define NNTP_PORT ((unsigned short) 119)
# if __STDC__
int connect(int, struct sockaddr *);
unsigned short htons(unsigned short);
unsigned long rhost(char **);
int rresvport( int );
int socket( int, struct sockproto *, struct sockaddr_in *, int );
# endif
/*}}}*/
#endif
#ifdef DECNET
# include <netdnet/dn.h>
# include <netdnet/dnetdb.h>
#endif /* DECNET */
#include "server.h"
#include "misc.h"
#ifndef NNTP_PORT
# define NNTP_PORT 119
#endif
#ifdef NEEDS_EXTERN_DECLARATIONS
# define DECLARE_EXTERN(x) extern x;
#else
# define DECLARE_EXTERN(x)
#endif
#ifdef VMS
# ifdef NETLIB
static void *ipctx;
# else
static int ser_rd_fp = -1, ser_wr_fp = -1;
# endif
#else
static FILE *ser_rd_fp = NULL;
static FILE *ser_wr_fp = NULL;
#endif
#ifdef DEBUG_FILE
static FILE *Debug_Fp;
#endif
static int Server_Has_Been_Closed = 1;
static void client_close_server(void);
static int client_get_server(char *, int);
static int get_tcp_socket(char *, int);
/*{{{ client_server_init */
/*
* client_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.
*/
static int client_server_init(char *machine, int port, char *line, int len)
{
int sockt_rd, sockt_wr;
#ifdef DECNET
char *cp;
if (Server_Has_Been_Closed == 0)
client_close_server ();
cp = slrn_strchr(machine, ':');
if (cp && cp[1] == ':')
{
*cp = '\0';
sockt_rd = get_dnet_socket(machine);
}
else
sockt_rd = get_tcp_socket(machine, port);
#else
if (Server_Has_Been_Closed == 0)
client_close_server ();
sockt_rd = get_tcp_socket (machine, port);
#endif
if (sockt_rd < 0)
return (-1);
#ifdef VMS
# ifndef NETLIB
ser_rd_fp = ser_wr_fp = sockt_rd;
# endif
#else
/*
* 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("client_server_init: fdopen #1");
return (-1);
}
sockt_wr = dup(sockt_rd);
# ifdef TLI
if (t_sync(sockt_rd) < 0)
{
/* Sync up new fd with TLI */
t_error("client_server_init: t_sync");
ser_rd_fp = NULL; /* from above */
return (-1);
}
# endif
if ((ser_wr_fp = fdopen(sockt_wr, "w")) == NULL)
{
perror("client_server_init: fdopen #2");
ser_rd_fp = NULL; /* from above */
return (-1);
}
#endif /* VMS */
/* Now get the server's signon message */
#ifdef DEBUG_FILE
Debug_Fp = fopen (DEBUG_FILE, "w");
#endif
Server_Has_Been_Closed = 0;
(void) client_get_server(line, len);
return (atoi(line));
}
/*}}}*/
/*{{{ get_tcp_socket */
/*
* 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.
*/
static int get_tcp_socket(char *machine, int nntpport)
{
#ifndef NETLIB
int s = -1;
struct sockaddr_in s_in;
#endif
#ifdef TLI
char *t_alloc();
struct t_call *callptr;
/*
* Create a TCP transport endpoint.
*/
if ((s = t_open("/dev/tcp", O_RDWR, (struct t_info*) 0)) < 0)
{
t_error("t_open: can't t_open /dev/tcp");
return(-1);
}
if(t_bind(s, (struct t_bind *)0, (struct t_bind *)0) < 0)
{
t_error("t_bind");
t_close(s);
return(-1);
}
memset ((char *) &s_in, 0, sizeof(s_in));
s_in.sin_family = AF_INET;
if (nntpport < 0) nntpport = NNTP_PORT;
s_in.sin_port = htons((unsigned short) nntpport);
if (!isdigit(*machine) ||
(long)(s_in.sin_addr.s_addr = inet_addr(machine)) == -1)
{
struct hostent *gethostbyname(), *hp;
if((hp = gethostbyname(machine)) == NULL)
{
fprintf(stderr,"gethostbyname: %s: host unknown\n",
machine);
t_close(s);
return(-1);
}
memcpy ((char *) &s_in.sin_addr, hp->h_addr, hp->h_length);
}
/*
* Allocate a t_call structure and initialize it.
* Let t_alloc() initialize the addr structure of the t_call structure.
*/
if ((callptr = (struct t_call *) t_alloc(s,T_CALL,T_ADDR)) == NULL)
{
t_error("t_alloc");
t_close(s);
return(-1);
}
callptr->addr.maxlen = sizeof(s_in);
callptr->addr.len = sizeof(s_in);
callptr->addr.buf = (char *) &s_in;
callptr->opt.len = 0; /* no options */
callptr->udata.len = 0; /* no user data with connect */
/*
* Connect to the server.
*/
if (t_connect(s, callptr, (struct t_call *) 0) < 0)
{
t_error("t_connect");
t_close(s);
return(-1);
}
/*
* Now replace the timod module with the tirdwr module so that
* standard read() and write() system calls can be used on the
* descriptor.
*/
if (ioctl(s, I_POP, (char *) 0) < 0)
{
perror("I_POP(timod)");
t_close(s);
return(-1);
}
if (ioctl(s, I_PUSH, "tirdwr") < 0)
{
perror("I_PUSH(tirdwr)");
t_close(s);
return(-1);
}
#else /* !TLI */
# ifdef NETLIB
unsigned short port, nntp_port;
struct dsc$descriptor ndsc, dsc;
struct INADDRDEF addr;
struct SINDEF s_in;
unsigned int rc, size;
if (nntpport < 0) nntpport = NNTP_PORT;
nntp_port = (unsigned short) nntpport;
port = netlib_hton_word(&nntp_port);
rc = netlib_socket(&ipctx);
if (!$VMS_STATUS_SUCCESS(rc))
return(-1);
if (isdigit(*machine))
{
INIT_SDESC(dsc, strlen(machine), machine);
rc = netlib_strtoaddr(&dsc, &addr);
if (!$VMS_STATUS_SUCCESS(rc))
return(-1);
s_in.sin_w_family = NETLIB_K_AF_INET;
s_in.sin_w_port = netlib_hton_word(&nntp_port);
s_in.sin_x_addr.inaddr_l_addr = addr.inaddr_l_addr;
memset(&s_in.sin_x_mbz, 0, 8);
size = sizeof(struct SINDEF);
rc = netlib_connect(&ipctx, &s_in, &size, 0,0,0);
if (!$VMS_STATUS_SUCCESS(rc))
{
netlib_close(&ipctx);
return(-1);
}
}
else
{
INIT_SDESC(ndsc, strlen(machine), machine);
rc = netlib_connect_by_name(&ipctx, &ndsc, &nntp_port);
if (!$VMS_STATUS_SUCCESS(rc))
{
netlib_close(&ipctx);
return(-1);
}
}
return(0);
# else
# ifndef EXCELAN
struct servent *sp;
struct hostent *hp;
# ifdef VMS
# else
DECLARE_EXTERN(struct servent *getservbyname())
DECLARE_EXTERN(struct hostent *gethostbyname())
# endif
# ifdef h_addr
int x = 0;
register char **cp;
static char *alist[1];
# endif /* h_addr */
static struct hostent def;
static struct in_addr defaddr;
static char namebuf[ 256 ];
DECLARE_EXTERN(unsigned long inet_addr())
# ifndef UCX
struct servent sp_buffer;
if (nntpport >= 0)
{
sp = &sp_buffer;
memset ((char *) sp, 0, sizeof (struct servent));
sp->s_port = htons((unsigned short)nntpport);
}
else
{
if ((sp = getservbyname("nntp", "tcp")) == NULL)
{
fprintf(stderr, "nntp/tcp: Unknown service.\n");
return (-1);
}
}
# else
if (nntpport < 0) nntpport = NNTP_PORT;
sp = (struct servent *)malloc(sizeof(struct servent));
sp->s_port = htons((unsigned short)nntpport);
# endif
/* If not a raw ip address, try nameserver */
if (!isdigit(*machine) ||
(long)(defaddr.s_addr = inet_addr(machine)) == -1)
hp = gethostbyname(machine);
else
{
/* Raw ip address, fake */
(void) 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 ((char *) &s_in, 0, sizeof(s_in));
s_in.sin_family = hp->h_addrtype;
s_in.sin_port = sp->s_port;
# else /* EXCELAN */
memset ((char *) &s_in, 0, sizeof(s_in));
s_in.sin_family = AF_INET;
# endif /* EXCELAN */
/*
* 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 *)&s_in.sin_addr, *cp, hp->h_length);
if (x < 0)
fprintf(stderr, "trying %s\n",
(char *) inet_ntoa(s_in.sin_addr));
x = connect(s, (struct sockaddr *)&s_in, sizeof (s_in));
if (x == 0)
break;
fprintf(stderr, "connection to %s: ",
(char *) inet_ntoa(s_in.sin_addr));
perror("");
(void) close(s);
}
if (x < 0)
{
fprintf(stderr, "giving up...\n");
return (-1);
}
# else /* no name server */
# ifdef EXCELAN
if ((s = socket(SOCK_STREAM,(struct sockproto *)NULL,&s_in,SO_KEEPALIVE)) < 0)
{
/* Get the socket */
perror("socket");
return (-1);
}
memset ((char *) &s_in, 0, sizeof(s_in));
s_in.sin_family = AF_INET;
if (nntpport < 0) nntpport = NNTP_PORT;
s_in.sin_port = htons((unsigned short) nntpport);
/* set up addr for the connect */
if ((s_in.sin_addr.s_addr = rhost(&machine)) == -1)
{
fprintf(stderr, "%s: Unknown host.\n", machine);
return (-1);
}
/* And then connect */
if (connect(s, (struct sockaddr *)&s_in) < 0)
{
perror("connect");
(void) close(s);
return (-1);
}
# else /* not EXCELAN */
if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket");
return (-1);
}
/* And then connect */
memcpy ((char *) &s_in.sin_addr, hp->h_addr, hp->h_length);
if (connect(s, (struct sockaddr *) &s_in, sizeof(s_in)) < 0)
{
perror("connect");
(void) close(s);
return (-1);
}
# endif /* !EXCELAN */
# endif /* !h_addr */
# endif /* !NETLIB */
#endif /* !TLI */
#ifndef NETLIB
return (s);
#endif
}
/*}}}*/
#ifdef DECNET
/*{{{ get_dnet_socket */
/*
* 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 ((char *) &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
{
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");
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
/*{{{ client_put_server */
/*
* client_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.
*/
static int
client_put_server(char *string)
{
#ifdef VMS
char *cp;
# ifdef NETLIB
int rc;
struct dsc$descriptor dsc;
unsigned short retlen;
# endif
#endif
if (Server_Has_Been_Closed)
return -1;
#ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, ">>> %s\n", string);
#endif
#ifdef VMS
# ifndef NETLIB
cp = (char *)malloc(strlen(string)+4);
sprintf(cp, "%s\r\n", string);
netwrite(SERVER_WRITE_FP, cp, strlen(cp));
/* sock_write(ser_wr_fp, cp, strlen(cp)); */
free(cp);
# else
INIT_SDESC(dsc, strlen(string), string);
rc = netlib_writeline(&ipctx, &dsc);
if (!(rc & 1)) return(-1);
# endif /* !NETLIB */
#else
if ((EOF == fputs (string, ser_wr_fp))
|| (EOF == fputs ("\r\n", ser_wr_fp))
|| (EOF == fflush(ser_wr_fp)))
return -1;
#endif
return 0;
}
/*}}}*/
/*{{{ client_get_server */
/*
* client_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".
*/
#if defined(VMS) && !defined(NETLIB)
/*{{{ client_get_server (vms version) */
static void cancel_read (int sig_unused)
{
slrn_exit_error("\nCANCEL_READ: NNTP read failed.");
}
# define TIMEOUT 60
# define BUFSIZE 8192
static char buffer[BUFSIZE];
static int bufread = 0;
static int client_get_server(char *string, int size)
{
register char *cp;
int status, nb, len, count;
struct
{
unsigned short status;
unsigned short count;
unsigned int undef;
}
r_iosb;
if (Server_Has_Been_Closed) return -1;
if (!bufread)
{
signal(SIGALRM,cancel_read);
alarm(TIMEOUT);
nb = netread(SERVER_READ_FP, buffer, BUFSIZE);
alarm(0);
if (nb <= 0)
return(-1);
bufread = nb;
buffer[bufread] = '\0';
# ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, "<<<<< %s\n", buffer);
# endif
}
*string = '\0';
count=0;
while (((cp = strstr(buffer, "\r\n")) == NULL) && (count < 5))
{
count++;
strncpy(string, buffer, strlen(buffer));
string[strlen(buffer)] = '\0';
bufread=0;
memset(buffer, 0, BUFSIZE);
signal(SIGALRM,cancel_read);
alarm(TIMEOUT);
nb = netread(SERVER_READ_FP, buffer, BUFSIZE);
alarm(0);
if (nb <= 0)
{
# ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, "**** %s\n", string);
# endif
return(0);
}
bufread = nb;
buffer[bufread] = '\0';
}
/* while */
*cp = '\0'; cp += 2;
bufread = strlen(cp);
strcat(string, buffer);
if (bufread > 0)
{
memmove(buffer, cp, bufread);
buffer[bufread] = '\0';
}
else
memset(buffer, 0, BUFSIZE);
# ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, "<<< %s\n", string);
# endif
return (0);
}
/*}}}*/
#else /* !VMS || NETLIB */
# ifdef NETLIB
/*{{{ client_get_server (NETLIB) */
# define TIMEOUT 60
static int client_get_server(char *string, int size)
{
register char *cp;
int rc;
struct dsc$descriptor dsc;
unsigned short retlen;
INIT_SDESC(dsc, size, string);
if (Server_Has_Been_Closed) return -1;
rc = netlib_readline(&ipctx, &dsc, &retlen, 0, 0);
if (!(rc & 1))
return (-1);
string[retlen] = '\0';
# ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, "<<< %s\n", string);
# endif
return (0);
}
/*}}}*/
# else /* !VMS && !NETLIB */
/*{{{ client_get_server (Unix, OS/2) */
static int client_get_server(char *string, int size)
{
register char *cp;
if (Server_Has_Been_Closed) return -1;
if (fgets(string, size, ser_rd_fp) == NULL)
return (-1);
if ((cp = slrn_strchr(string, '\r')) != NULL)
*cp = '\0';
else if ((cp = slrn_strchr(string, '\n')) != NULL)
*cp = '\0';
# ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, "<<< %s\n", string);
# endif
return (0);
}
/*}}}*/
# endif /* !NETLIB */
#endif /* !VMS || NETLIB */
/*}}}*/
/*{{{ client_close_server */
/*
* client_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 "client_put_server" or "client_get_server"
* after this routine is called.
*/
static void
client_close_server(void)
{
char ser_line[256];
if (Server_Has_Been_Closed) return;
#ifdef VMS
# ifndef NETLIB
if (ser_wr_fp <= 0 || ser_rd_fp <= 0) return;
# else
if (ipctx == NULL) return;
# endif
#else
if (ser_wr_fp == NULL || ser_rd_fp == NULL)
return;
#endif
if (-1 != client_put_server("QUIT"))
(void) client_get_server(ser_line, sizeof(ser_line));
#ifdef NETLIB
netclose(&ipctx);
#else
# ifdef VMS
netclose(ser_rd_fp);
netclose(ser_wr_fp);
# else
(void) fclose(ser_wr_fp);
(void) fclose(ser_rd_fp);
# endif
#endif
Server_Has_Been_Closed = 1;
}
/*}}}*/
#ifdef VMS
/*{{{ VMS netwrite */
# ifdef NETLIB
static int netwrite(void *sockt, char *string, int len)
{
struct dsc$descriptor dsc;
int rc;
struct NETLIBIOSBDEF iosb;
INIT_SDESC(dsc, len, string);
netlib_write(&sockt, &dsc, 0,0, &iosb,0,0);
if ($VMS_STATUS_SUCCESS(rc))
{
return(iosb.iosb_w_count);
}
else
return(-1);
}
# else
static int netwrite(int sockt, char *string, int len)
{
# ifdef DEBUG_FILE
if (Debug_Fp != NULL) fprintf(Debug_Fp, ">>> %s\n", string);
# endif
return(sock_write(sockt, string, len));
}
# endif /* !NETLIB */
/*}}}*/
#endif /* VMS */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.