head	1.27;
access;
symbols
	release_4_2:1.27
	aix_ok:1.24
	Version_2_1:1.12;
locks; strict;
comment	@ * @;


1.27
date	94.02.09.00.12.24;	author aoki;	state Exp;
branches;
next	1.26;

1.26
date	94.02.07.11.56.57;	author aoki;	state Exp;
branches;
next	1.25;

1.25
date	94.01.13.17.26.12;	author jiangwu;	state Exp;
branches;
next	1.24;

1.24
date	93.08.13.22.05.01;	author aoki;	state Exp;
branches;
next	1.23;

1.23
date	93.06.23.22.02.36;	author aoki;	state Exp;
branches;
next	1.22;

1.22
date	93.06.16.05.05.24;	author aoki;	state Exp;
branches;
next	1.21;

1.21
date	93.01.05.02.31.00;	author aoki;	state Exp;
branches;
next	1.20;

1.20
date	93.01.01.18.46.26;	author marc;	state Exp;
branches;
next	1.19;

1.19
date	92.12.29.01.37.09;	author aoki;	state Exp;
branches;
next	1.18;

1.18
date	92.04.21.13.13.53;	author clarsen;	state Exp;
branches;
next	1.17;

1.17
date	92.04.13.19.08.45;	author mer;	state Exp;
branches;
next	1.16;

1.16
date	92.02.25.15.29.53;	author clarsen;	state Exp;
branches;
next	1.15;

1.15
date	91.11.11.23.19.20;	author hong;	state Exp;
branches;
next	1.14;

1.14
date	91.08.12.21.55.41;	author mao;	state Exp;
branches;
next	1.13;

1.13
date	91.08.12.21.40.31;	author mao;	state Exp;
branches;
next	1.12;

1.12
date	91.03.09.16.45.19;	author kemnitz;	state Exp;
branches;
next	1.11;

1.11
date	91.03.08.19.55.56;	author kemnitz;	state Exp;
branches;
next	1.10;

1.10
date	91.03.08.00.36.54;	author kemnitz;	state Exp;
branches;
next	1.9;

1.9
date	91.03.07.23.21.32;	author kemnitz;	state Exp;
branches;
next	1.8;

1.8
date	91.03.07.02.03.58;	author kemnitz;	state Exp;
branches;
next	1.7;

1.7
date	91.03.05.13.00.02;	author mao;	state Exp;
branches;
next	1.6;

1.6
date	91.02.28.17.01.59;	author mer;	state Exp;
branches;
next	1.5;

1.5
date	91.02.28.10.45.09;	author mer;	state Exp;
branches;
next	1.4;

1.4
date	91.02.22.17.07.40;	author mer;	state Exp;
branches;
next	1.3;

1.3
date	91.02.20.00.39.13;	author cimarron;	state Exp;
branches;
next	1.2;

1.2
date	91.02.19.14.00.56;	author cimarron;	state Exp;
branches;
next	1.1;

1.1
date	91.02.09.20.43.56;	author cimarron;	state Exp;
branches;
next	;


desc
@reorganization of libpq routines to provide
PQexec and PQfn functionality from both the front
end applications and the postgres backend.
@


1.27
log
@POSIX signal fixup.  actually use sigaction instead of trying
to do old SVID1-style signal handler reinstall (i keep missing
one signal or another..)
@
text
@/* ----------------------------------------------------------------
 *   FILE
 *	pqcomm.c
 *	
 *   DESCRIPTION
 *	Communication functions between the Frontend and the Backend
 *
 *   INTERFACE ROUTINES
 *	pq_gettty 	- return the name of the tty in the given buffer
 *	pq_getport 	- return the PGPORT setting
 *	pq_close 	- close input / output connections
 *	pq_flush 	- flush pending output
 *	pq_getstr 	- get a null terminated string from connection
 *	pq_getnchar 	- get n characters from connection
 *	pq_getint 	- get an integer from connection
 *	pq_putstr 	- send a null terminated string to connection
 *	pq_putnchar 	- send n characters to connection
 *	pq_putint 	- send an integer to connection
 *	pq_getinaddr 	- initialize address from host and port number
 *	pq_getinserv 	- initialize address from host and service name
 *	pq_connect 	- create remote input / output connection
 *	pq_accept 	- accept remote input / output connection
 *      pq_async_notify - receive notification from backend.
 *
 *   NOTES
 * 	These functions are used by both frontend applications and
 *	the postgres backend.
 *
 *   IDENTIFICATION
 *	$Header: /faerie/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.26 1994/02/07 11:56:57 aoki Exp aoki $
 * ----------------------------------------------------------------
 */

#include "libpq/pqsignal.h"	/* substitute for <signal.h> */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>		/* for ttyname() */

#ifdef PORTNAME_linux
#ifndef SOMAXCONN
#define SOMAXCONN 5		/* from Linux listen(2) man page */
#endif /* SOMAXCONN */
#endif /* PORTNAME_linux */

#include "libpq/auth.h"
#include "tmp/c.h"
#include "tmp/libpq.h"
#include "tmp/pqcomm.h"
#include "utils/log.h"

RcsId ("$Header: /faerie/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.26 1994/02/07 11:56:57 aoki Exp aoki $");

/* ----------------
 *	declarations
 * ----------------
 */
FILE *Pfout, *Pfin;
int PQAsyncNotifyWaiting;	/* for async. notification */

/* forward declarations */
void pq_regoob ARGS((void (*fptr )()));
void pq_unregoob ARGS((void ));
void pq_async_notify ARGS((void ));


/* --------------------------------
 *	pq_init - open portal file descriptors
 * --------------------------------
 */
void
pq_init(fd)
    int fd;
{
    Pfin = fdopen(fd, "r");
    Pfout = fdopen(dup(fd), "w");
    if (!Pfin || !Pfout)
	elog(FATAL, "pq_init: Couldn't initialize socket connection");
    PQnotifies_init();
}

/* --------------------------------
 *	pq_gettty - return the name of the tty in the given buffer
 * --------------------------------
 */
void
pq_gettty(tp)
    char *tp;
{	
    (void) strncpy(tp, ttyname(0), 19);
}

/* --------------------------------
 *	pq_getport - return the PGPORT setting
 * --------------------------------
 */
int
pq_getport()
{
    char *envport = getenv("PGPORT");

    if (envport)
	return(atoi(envport));
    return(atoi(POSTPORT));
}

/* --------------------------------
 *	pq_close - close input / output connections
 * --------------------------------
 */
void
pq_close()
{
    if (Pfin) {
	fclose(Pfin);
	Pfin = NULL;
    }
    if (Pfout) {
	fclose(Pfout);
	Pfout = NULL;
    }
    PQAsyncNotifyWaiting = 0;
    PQnotifies_init();
    pq_unregoob();
}

/* --------------------------------
 *	pq_flush - flush pending output
 * --------------------------------
 */
void
pq_flush()
{
    if (Pfout)
	fflush(Pfout);
}

/* --------------------------------
 *	pq_getstr - get a null terminated string from connection
 * --------------------------------
 */
int
pq_getstr(s, maxlen)
    char *s;
    int	 maxlen;
{
    int	c;

    if (Pfin == (FILE *) NULL) {
	elog(DEBUG, "Input descriptor is null");
	return(EOF);
    }

    while (maxlen-- && (c = getc(Pfin)) != EOF && c)
	*s++ = c;
    *s = '\0';

    /* -----------------
     *     If EOF reached let caller know.
     *     (This will only happen if we hit EOF before the string
     *     delimiter is reached.)
     * -----------------
     */
    if (c == EOF)
	return(EOF);
    return(!EOF);
}

/*
 * USER FUNCTION - gets a newline-terminated string from the backend.
 * 
 * Chiefly here so that applications can use "COPY <rel> to stdout"
 * and read the output string.  Returns a null-terminated string in s.
 *
 * PQgetline reads up to maxlen-1 characters (like fgets(3)) but strips
 * the terminating \n (like gets(3)).
 *
 * RETURNS:
 *	EOF if it is detected or invalid arguments are given
 *	0 if EOL is reached (i.e., \n has been read)
 *		(this is required for backward-compatibility -- this
 *		 routine used to always return EOF or 0, assuming that
 *		 the line ended within maxlen bytes.)
 *	1 in other cases
 */

int
PQgetline(s, maxlen)
    char *s;
    int maxlen;
{
    int c = '\0';

    if (!Pfin || !s || maxlen <= 1)
	return(EOF);

    for (; maxlen > 1 && (c = getc(Pfin)) != '\n' && c != EOF; --maxlen) {
	*s++ = c;
    }
    *s = '\0';

    if (c == EOF) {
	return(EOF);		/* error -- reached EOF before \n */
    } else if (c == '\n') {
	return(0);		/* done with this line */
    }
    return(1);			/* returning a full buffer */
}

/*
 * USER FUNCTION - sends a string to the backend.
 * 
 * Chiefly here so that applications can use "COPY <rel> from stdin".
 *
 * RETURNS:
 *	0 in all cases.
 */

int
PQputline(s)
    char *s;
{
    if (Pfout) {
	(void) fputs(s, Pfout);
	fflush(Pfout);
    }
    return(0);
}

/* --------------------------------
 *	pq_getnchar - get n characters from connection
 * --------------------------------
 */
int
pq_getnchar(s, off, maxlen)
    char *s;
    int	 off, maxlen;
{
    int	c;

    if (Pfin == (FILE *) NULL) {
	elog(DEBUG, "Input descriptor is null");
	return(EOF);
    }

    s += off;
    while (maxlen-- && (c = getc(Pfin)) != EOF)
	*s++ = c;

    /* -----------------
     *     If EOF reached let caller know
     * -----------------
     */
    if (c == EOF)
	return(EOF);
    return(!EOF);
}

/* --------------------------------
 *	pq_getint - get an integer from connection
 * --------------------------------
 */
int
pq_getint(b)
    int	b;
{
    int	n, c, p;

    if (Pfin == (FILE *) NULL) {
	elog(DEBUG, "pq_getint: Input descriptor is null");
	return(EOF);
    }

    n = p = 0;
    while (b-- && (c = getc(Pfin)) != EOF && p < 32) {
	n |= (c & 0xff) << p;
	p += 8;
    }

    return(n);
}

/* --------------------------------
 *	pq_putstr - send a null terminated string to connection
 * --------------------------------
 */
void
pq_putstr(s)
    char *s;
{
    int status;

    if (Pfout) {
	status = fputs(s, Pfout);
	if (status == EOF) {
	    (void) sprintf(PQerrormsg,
			   "FATAL: pq_putstr: fputs() failed: errno=%d\n",
			   errno);
	    fputs(PQerrormsg, stderr);
	    pqdebug("%s", PQerrormsg);
	}
	status = fputc('\0', Pfout);
	if (status == EOF) {
	    (void) sprintf(PQerrormsg,
			   "FATAL: pq_putstr: fputc() failed: errno=%d\n",
			   errno);
	    fputs(PQerrormsg, stderr);
	    pqdebug("%s", PQerrormsg);
	}
    }
}

/* --------------------------------
 *	pq_putnchar - send n characters to connection
 * --------------------------------
 */
void
pq_putnchar(s, n)
    char *s;
    int n;
{
    int status;

    if (Pfout) {
	while (n--) {
	    status = fputc(*s++, Pfout);
	    if (status == EOF) {
		(void) sprintf(PQerrormsg,
			       "FATAL: pq_putnchar: fputc() failed: errno=%d\n",
			       errno);
		fputs(PQerrormsg, stderr);
		pqdebug("%s", PQerrormsg);
	    }
	}
    }
}

/* --------------------------------
 *	pq_putint - send an integer to connection
 * --------------------------------
 */
void
pq_putint(i, b)
    int	i, b;
{
    int status;

    if (b > 4)
	b = 4;

    if (Pfout) {
	while (b--) {
	    status = fputc(i & 0xff, Pfout);
	    i >>= 8;
	    if (status == EOF) {
		(void) sprintf(PQerrormsg,
			       "FATAL: pq_putint: fputc() failed: errno=%d\n",
			       errno);
		fputs(PQerrormsg, stderr);
		pqdebug("%s", PQerrormsg);
	    }
	}
    }
}

/* ---
 *     pq_sendoob - send a string over the out-of-band channel
 *     pq_recvoob - receive a string over the oob channel
 *  NB: Fortunately, the out-of-band channel doesn't conflict with
 *      buffered I/O because it is separate from regular com. channel.
 * ---
 */
int
pq_sendoob(msg,len)
    char *msg;
    int len;
{
    int fd = fileno(Pfout);

    return(send(fd,msg,len,MSG_OOB));
}

int
pq_recvoob(msgPtr,lenPtr)
    char *msgPtr;
    int *lenPtr;
{
    int fd = fileno(Pfout);
    int len = 0, n;

    len = recv(fd,msgPtr+len,*lenPtr,MSG_OOB);
    *lenPtr = len;
    return(len);
}

/* --------------------------------
 *	pq_getinaddr - initialize address from host and port number
 * --------------------------------
 */
int
pq_getinaddr(sin, host, port)
    struct	sockaddr_in *sin;
    char	*host;
    int		port;
{
    struct hostent	*hs;

    bzero((char *) sin, sizeof(*sin));

    if (host) {
	if (*host >= '0' && *host <= '9')
	    sin->sin_addr.s_addr = inet_addr(host);
	else {
	    if (!(hs = gethostbyname(host))) {
		perror(host);
		return(1);
	    }
	    if (hs->h_addrtype != AF_INET) {
		(void) sprintf(PQerrormsg,
			       "FATAL: pq_getinaddr: %s not on Internet\n",
			       host);
		fputs(PQerrormsg, stderr);
		pqdebug("%s", PQerrormsg);
		return(1);
	    }
	    bcopy(hs->h_addr, (char *) &sin->sin_addr, hs->h_length);
	}
    }
    sin->sin_family = AF_INET;
    sin->sin_port = htons(port);
    return(0);
}

/* --------------------------------
 *	pq_getinserv - initialize address from host and servive name
 * --------------------------------
 */
int
pq_getinserv(sin, host, serv)
    struct sockaddr_in *sin;
    char *host, *serv;
{
    struct servent *ss;

    if (*serv >= '0' && *serv <= '9')
	return(pq_getinaddr(sin, host, atoi(serv)));
    if (!(ss = getservbyname(serv, NULL))) {
	(void) sprintf(PQerrormsg,
		       "FATAL: pq_getinserv: unknown service: %s\n",
		       serv);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(1);
    }
    return(pq_getinaddr(sin, host, ntohs(ss->s_port)));
}

#ifdef FRONTEND
/* ----------------------------------------
 * pq_connect  -- initiate a communication link between client and
 *	POSTGRES backend via postmaster.
 *
 * RETURNS: STATUS_ERROR, if arguments are wrong or local communication
 *	status is screwed up (can't create socket, etc).  STATUS_OK
 *	otherwise.
 *
 * SIDE_EFFECTS: initiates connection.  
 *               SIGURG handler is set (async notification)
 *
 * NOTE: we don't wait for any error messages from the backend/postmaster.
 *	That means that if the fork fails or the startup message is corrupted,
 *	we won't find out until the first Send/Receive message cal.
 * ----------------------------------------
 */
int
pq_connect(dbname,user,args,hostName,debugTty,execFile,portName)
    char	*dbname;
    char	*user;
    char	*args;
    char	*hostName;
    char	*debugTty;
    char	*execFile;
    short	portName;
{
    /*
     * This data structure is used for the seq-packet protocol.  It
     * describes the frontend-backend connection.
     */
    Connection		*MyConn = NULL;
    Port			*SendPort = NULL; /* This is a TCP or UDP socket */
    StartupPacket		startup;
    int			status;
    MsgType		msgtype;

    /*
     * Initialize the startup packet.  Packet fields defined in comm.h
     */
    strncpy(startup.database,dbname,sizeof(startup.database));
    strncpy(startup.user,user,sizeof(startup.user));
    strncpy(startup.options,args,sizeof(startup.options));
    strncpy(startup.tty,debugTty,sizeof(startup.tty));
    if (execFile != NULL) {
	strncpy(startup.execFile, execFile, sizeof(startup.execFile));
    } else {
	strncpy(startup.execFile, "", sizeof(startup.execFile));
    }

    /* If no port  was suggested grab the default or PGPORT value */
    if (!portName)
	portName = pq_getport();
    /*
     * initialize connection structure.  This is really needed
     * only for the sequenced packet protocol, but these initializations
     * are important to the packet.c library.
     */
    MyConn = (Connection *) malloc(sizeof(Connection));
    bzero(MyConn, sizeof(Connection));
    MyConn->id = INVALID_ID;
    MyConn->seqno = INITIAL_SEQNO;

    /*
     * Open a connection to postmaster/backend.
     */
    SendPort = (Port *) malloc(sizeof(Port));
    bzero((char *) SendPort, sizeof(Port));
    status = StreamOpen(hostName, portName, SendPort);
    if (status != STATUS_OK)
	/* StreamOpen already set PQerrormsg */
	return(STATUS_ERROR);

    /* initialize */
    msgtype = fe_getauthsvc();
    status = PacketSend(SendPort, MyConn, &startup, msgtype,
			sizeof(startup), BLOCKING);

    /* authenticate as required */
    if (fe_sendauth(msgtype, SendPort, hostName) != STATUS_OK) {
	(void) sprintf(PQerrormsg,
		       "FATAL: pq_connect: authentication failed with %s\n",
		       hostName);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }

    /* set up the socket file descriptors */
    Pfout = fdopen(SendPort->sock, "w");
    Pfin = fdopen(dup(SendPort->sock), "r");
    if (!Pfout && !Pfin) {
	(void) sprintf(PQerrormsg,
		       "FATAL: pq_connect: fdopen() failed: errno=%d\n",
		       errno);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }

    PQAsyncNotifyWaiting = 0;
    PQnotifies_init();
/*    pq_regoob(pq_async_notify);*/

    if (status != STATUS_OK)
	/* PacketSend already set PQerrormsg */
	return(STATUS_ERROR);

    return(STATUS_OK);
}
#endif /* FRONTEND */

/*
 * register an out-of-band listener proc--at most one allowed.
 * This is used for receiving async. notification from the backend.
 */
void 
pq_regoob(fptr)
    void (*fptr)();
{
    int fd = fileno(Pfout);
#ifdef PORTNAME_hpux
    ioctl(fd, FIOSSAIOOWN, getpid());
#else /* PORTNAME_hpux */
    fcntl(fd, F_SETOWN, getpid());
#endif /* PORTNAME_hpux */
    (void) signal(SIGURG,fptr);
}

void pq_unregoob()
{
    signal(SIGURG,SIG_DFL);
}


void
pq_async_notify() {
    char msg[20];
/*    int len = sizeof(msg);*/
    int len = 20;

    if (pq_recvoob(msg,&len) >= 0) {
	/* debugging */
	printf("received notification: %s\n",msg);
	PQAsyncNotifyWaiting = 1;
	/*	PQappendNotify(msg+1);*/
    } else {
	extern int errno;
	printf("SIGURG but no data: len = %d, err=%d\n",len,errno);
    }
}

/*
 * Streams -- wrapper around Unix socket system calls
 *
 *
 *	Stream functions are used for vanilla TCP connection protocol.
 */

/*
 * StreamServerPort -- open a sock stream "listening" port.
 *
 * This initializes the Postmaster's connection
 *	accepting port.  
 *
 * ASSUME: that this doesn't need to be non-blocking because
 *	the Postmaster uses select() to tell when the socket
 *	is ready.
 *
 * RETURNS: STATUS_OK or STATUS_ERROR
 */
StreamServerPort(hostName,portName,fdP)
    char	*hostName;
    short	portName;
    int	*fdP;
{
    struct sockaddr_in	sin;
    int			fd;
    struct hostent	*hp;

    if (! hostName)
	hostName = "localhost";

    bzero((char *)&sin, sizeof sin);

    if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	(void) sprintf(PQerrormsg,
		       "FATAL: StreamServerPort: socket() failed: errno=%d\n",
		       errno);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }

    sin.sin_family = AF_INET;
    sin.sin_port = htons(portName);

    if (bind(fd, (struct sockaddr *)&sin, sizeof sin) < 0) {
	(void) sprintf(PQerrormsg,
		       "FATAL: StreamServerPort: bind() failed: errno=%d\n",
		       errno);
	pqdebug("%s", PQerrormsg);
	(void) strcat(PQerrormsg, "\tIs another postmaster already running on that port?\n");
	(void) strcat(PQerrormsg, "\tIf not, wait a few seconds and retry.\n");
	fputs(PQerrormsg, stderr);
	return(STATUS_ERROR);
    }

    listen(fd, SOMAXCONN);

    /* MS: I took this code from Dillon's version.  It makes the 
     * listening port non-blocking.  That is not necessary (and
     * may tickle kernel bugs).

     (void) fcntl(fd, F_SETFD, 1);
     (void) fcntl(fd, F_SETFL, FNDELAY);
     */

    *fdP = fd;
    return(STATUS_OK);
}

/*
 * StreamConnection -- create a new connection with client using
 *	server port.
 *
 * This one should be non-blocking.
 * 
 * RETURNS: STATUS_OK or STATUS_ERROR
 */
StreamConnection(server_fd, port)
    int	server_fd;
    Port *port;
{
    int	addrlen;

    /* accept connection (and fill in the client (remote) address) */
    addrlen = sizeof(struct sockaddr_in);
    if ((port->sock = accept(server_fd,
			     (struct sockaddr *) &port->raddr,
			     &addrlen)) < 0) {
	elog(WARN, "postmaster: StreamConnection: accept: %m");
	return(STATUS_ERROR);
    }

    /* fill in the server (local) address */
    addrlen = sizeof(struct sockaddr_in);
    if (getsockname(port->sock, (struct sockaddr *) &port->laddr,
		    &addrlen) < 0) {
	elog(WARN, "postmaster: StreamConnection: getsockname: %m");
	return(STATUS_ERROR);
    }

    port->sock = port->sock;
    port->mask = 1 << port->sock;

    /* reset to non-blocking */
    fcntl(port->sock, F_SETFL, 1);	

    return(STATUS_OK);
}

/* 
 * StreamClose -- close a client/backend connection
 */
StreamClose(sock)
    int	sock;
{
    (void) close(sock); 
}

/* ---------------------------
 * StreamOpen -- From client, initiate a connection with the 
 *	server (Postmaster).
 *
 * RETURNS: STATUS_OK or STATUS_ERROR
 *
 * NOTE: connection is NOT established just because this
 *	routine exits.  Local state is ok, but we haven't
 *	spoken to the postmaster yet.
 * ---------------------------
 */
StreamOpen(hostName, portName, port)
    char	*hostName;
    short	portName;
    Port	*port;
{
    struct hostent	*hp;
    int			laddrlen = sizeof(struct sockaddr_in);
    extern int		errno;

    if (!hostName)
	hostName = "localhost";

    /* set up the server (remote) address */
    if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET) {
	(void) sprintf(PQerrormsg,
		       "FATAL: StreamOpen: unknown hostname: %s\n",
		       hostName);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }
    bzero((char *) &port->raddr, sizeof(port->raddr));
    bcopy((char *) hp->h_addr, (char *) &(port->raddr.sin_addr),
	  hp->h_length);
    port->raddr.sin_family = AF_INET;
    port->raddr.sin_port = htons(portName);

    /* connect to the server */
    if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
	(void) sprintf(PQerrormsg,
		       "FATAL: StreamOpen: socket() failed: errno=%d\n",
		       errno);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }
    if (connect(port->sock, (struct sockaddr *)&port->raddr,
		sizeof(port->raddr)) < 0) {
	(void) sprintf(PQerrormsg,
		       "FATAL: StreamOpen: connect() failed: errno=%d\n",
		       errno);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }

    /* fill in the client address */
    if (getsockname(port->sock, (struct sockaddr *) &port->laddr,
		    &laddrlen) < 0) {
	(void) sprintf(PQerrormsg,
		       "FATAL: StreamOpen: getsockname() failed: errno=%d\n",
		       errno);
	fputs(PQerrormsg, stderr);
	pqdebug("%s", PQerrormsg);
	return(STATUS_ERROR);
    }

    return(STATUS_OK);
}
@


1.26
log
@proto fixes
@
text
@d30 1
a30 1
 *	$Header: /import/faerie/faerie/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.25 1994/01/13 17:26:12 jiangwu Exp aoki $
d34 1
a42 1
#include <signal.h>
d57 1
a57 1
RcsId ("$Header: /import/faerie/faerie/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.25 1994/01/13 17:26:12 jiangwu Exp aoki $");
@


1.25
log
@Turned off the SIGURG handler since it is never used.
-- jw, 1/13/94
@
text
@d30 1
a30 1
 *	$Header: /private/src/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.24 1993/08/13 22:05:01 aoki Exp jiangwu $
d57 1
a57 1
RcsId ("$Header: /private/src/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.24 1993/08/13 22:05:01 aoki Exp jiangwu $");
d93 1
a93 1
    char tp[20];
@


1.24
log
@removed many bogosities.
there was no way to tell if you were at the end of a line,
which is a problem when the COPY protocol is line-sensitive.
(still returns 0 if ok, EOF at EOF, but also returns 1 if not done)
fixed problem with argument-checking.
@
text
@d30 1
a30 1
 *	$Header: /home2/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.23 1993/06/23 22:02:36 aoki Exp aoki $
d57 1
a57 1
RcsId ("$Header: /home2/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.23 1993/06/23 22:02:36 aoki Exp aoki $");
d565 1
a565 1
    pq_regoob(pq_async_notify);
d601 2
a602 1
    int len = sizeof(msg);
@


1.23
log
@changed __linux__ to PORTNAME_linux
hpux doesn't have fcntl(...F_SETOWN...) so i changed it to the
appropriate ioctl
@
text
@d30 1
a30 1
 *	$Header: /home2/aoki/master/src/backend/libpq/RCS/pqcomm.c,v 1.22 1993/06/16 05:05:24 aoki Exp $
d57 1
a57 1
RcsId ("$Header: /home2/aoki/master/src/backend/libpq/RCS/pqcomm.c,v 1.22 1993/06/16 05:05:24 aoki Exp $");
d177 13
a189 3
 * Chiefly here so that applications can use "COPY <rel> () from stdin"
 * and read the output string.  Returns a null-terminated string in s and
 * EOF if it is detected.
d197 1
a197 1
    int c;
d199 1
a199 1
    if (Pfin == (FILE *) NULL)
d202 1
a202 1
    while (maxlen-- && (c = getc(Pfin)) != '\n' && c != EOF) {
d207 6
a212 7
    /* -----------------
     *     If EOF reached let caller know
     * -----------------
     */
    if (c == EOF)
	return(EOF);
    return(!EOF);
d218 4
a221 3
 * Chiefly here so that applications can use "COPY <rel> () to stdout"
 * and read the output string.  Returns a null-terminated string in s and
 * EOF if it is detected.
@


1.22
log
@killed some bogus extern decls
added some linux compat #define's
now uses string POSTPORT
i/o routines now return error conditions and set PQerrormsg
@
text
@d30 1
a30 1
 *	$Header: /home2/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.21 1993/01/05 02:31:00 aoki Exp aoki $
d45 1
a45 1
#ifdef __linux__
d49 1
a49 1
#endif /* __linux__ */
d57 1
a57 1
RcsId ("$Header: /home2/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.21 1993/01/05 02:31:00 aoki Exp aoki $");
d574 5
a578 1
    fcntl(fd,F_SETOWN,getpid());
@


1.21
log
@fe/be is now conditionally compiled.
@
text
@d10 1
a10 1
 *	pq_getport 	- return the PGPORT setting or 4321 if not set
d30 1
a30 1
 *	$Header: /home2/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.19 1992/12/29 01:37:09 aoki Exp aoki $
d35 1
d38 1
d43 1
d45 6
d53 1
d57 1
a57 1
RcsId ("$Header: /home2/aoki/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.19 1992/12/29 01:37:09 aoki Exp aoki $");
a62 4
extern char **environ;
char **ep;
char *dp;

a64 3
extern char PQerrormsg[];

char *strcpy(), *ttyname();
d83 1
a83 1
	elog(FATAL, "Couldn't initialize socket connection");
d95 1
a95 1
    strcpy(tp, ttyname(0));
d99 1
a99 1
 *	pq_getport - return the PGPORT setting or 4321 if not set
d105 5
a109 12
    char *env, *getenv();
    int  port_no;
    
    env = getenv("PGPORT");
    
    if (env) {
	port_no = atoi(env);
    } else
	port_no = 4321;
    
    return
	port_no;
d144 1
a144 1
 *	pq_getstr - get a null terminateed string from connection
d153 2
a154 3
    
    if (Pfin == (FILE *) NULL)
    {
d156 1
a156 1
	return (EOF);
d164 3
a166 1
     *     If EOF reached let caller know
d170 2
a171 3
	return EOF;
    else
	return !EOF;
d184 2
a185 4

char *s;
int maxlen;

d190 1
a190 1
	return (EOF);
d192 3
a194 4
    while (maxlen-- && (c = getc(Pfin)) != '\n' && c != EOF)
	{
		*s++ = c;
	}
d202 2
a203 3
	return EOF;
    else
	return !EOF;
d216 1
a216 3

char *s;

d222 1
d235 2
a236 3
    
    if (Pfin == (FILE *) NULL)
    {
d238 1
a238 1
	return (EOF);
d250 2
a251 5
    {
	return EOF;
    }
    else
	return !EOF;
d263 4
a266 5
    
    if (Pfin == (FILE *) NULL)
    {
	elog(DEBUG, "Input descriptor is null");
	return (EOF);
d275 1
a275 1
    return n;
d290 6
a295 4
	if (status == EOF)
	{
	    strcpy(PQerrormsg,"pq_putstr: write to backend failed\n");
	    fprintf(stderr, PQerrormsg);
d298 6
a303 4
	if (status == EOF)
	{
	    strcpy(PQerrormsg, "pq_putstr: write to backend failed\n");
	    fprintf(stderr, PQerrormsg);
d320 1
a320 2
	while (n--)
	{
d322 6
a327 4
	    if (status == EOF)
	    {
		strcpy(PQerrormsg, "pq_putnchar: write to backend failed\n");
		fprintf(stderr, PQerrormsg);
d345 1
a345 1
    
d350 6
a355 4
	    if (status == EOF)
	    {
		strcpy(PQerrormsg, "pq_putint: write to backend failed\n");
		fprintf(stderr, PQerrormsg);
d370 2
a371 2
     char *msg;
     int len;
d374 2
a375 1
    return send(fd,msg,len,MSG_OOB);
d380 2
a381 2
     char *msgPtr;
     int *lenPtr;
d385 1
d388 1
a388 1
    return len;
d401 4
a404 4
    struct	hostent	*hs;
    
    bzero((char *)sin, sizeof *sin);
    
d414 5
a418 2
		sprintf(PQerrormsg,"%s: Not Internet\n",host);
		fprintf(stderr,PQerrormsg);
d421 1
a421 1
	    bcopy(hs->h_addr, (char *)&sin->sin_addr, hs->h_length);
a423 1
    
a425 1
    
d435 2
a436 2
    struct	sockaddr_in *sin;
    char	*host, *serv;
d438 2
a439 2
    struct	servent	*ss;
    
d441 1
a441 3
	return
	    pq_getinaddr(sin, host, atoi(serv));
    
d443 5
a447 3
	fputs(serv, stderr);
	fputs(": Unknown service\n", stderr);
	sprintf(PQerrormsg,"%s: Unknown service\n",serv);
d450 1
a450 3
    
    return
	pq_getinaddr(sin, host, ntohs(ss->s_port));
d472 84
a555 81
char	*dbname;
char	*user;
char	*args;
char	*hostName;
char	*debugTty;
char	*execFile;
short	portName;
{
/*
 * This data structure is used for the seq-packet protocol.  It
 * describes the frontend-backend connection.
 */
  Connection		*MyConn = NULL;
  Port			*SendPort = NULL; /* This is a TCP or UDP socket */
  StartupPacket		startup;
  int			status;
  MsgType		msgtype;

  /*
   * Initialize the startup packet.  Packet fields defined in comm.h
   */
  strncpy(startup.database,dbname,sizeof(startup.database));
  strncpy(startup.user,user,sizeof(startup.user));
  strncpy(startup.options,args,sizeof(startup.options));
  strncpy(startup.tty,debugTty,sizeof(startup.tty));
  if (execFile != NULL)
  {
    strncpy(startup.execFile, execFile, sizeof(startup.execFile));
  }
  else
  {
    strncpy(startup.execFile, "", sizeof(startup.execFile));
  }

  /* If no port  was suggested grab the default or PGPORT value */
  if (!portName)
    portName = pq_getport();
  /*
   * initialize connection structure.  This is really needed
   * only for the sequenced packet protocol, but these initializations
   * are important to the packet.c library.
   */
  MyConn = (Connection *) malloc(sizeof(Connection));
  bzero(MyConn, sizeof(Connection));
  MyConn->id = INVALID_ID;
  MyConn->seqno = INITIAL_SEQNO;

  /*
   * Open a connection to postmaster/backend.
   */
  SendPort = (Port *) malloc(sizeof(Port));
  bzero((char *) SendPort, sizeof(Port));
  status = StreamOpen(hostName, portName, SendPort);
  if (status != STATUS_OK)
    return(STATUS_ERROR);

  /* initialize */
  msgtype = fe_getauthsvc();
  status = PacketSend(SendPort, MyConn, &startup, msgtype,
		      sizeof(startup), BLOCKING);

  /* authenticate as required */
  if (fe_sendauth(msgtype, SendPort, hostName) != STATUS_OK) {
	  strcpy(PQerrormsg, "pq_connect: authentication failed\n");
	  fprintf(stderr, PQerrormsg);
	  return(STATUS_ERROR);
  }

  /* set up streams over which communic. will flow */
  Pfout = fdopen(SendPort->sock, "w");
  Pfin = fdopen(dup(SendPort->sock), "r");
  if (!Pfout && !Pfin)
  {
      strcpy(PQerrormsg, "Couldn't fdopen the socket descriptor\n");
    fprintf(stderr,PQerrormsg);
    return(STATUS_ERROR);
  }
  
  PQAsyncNotifyWaiting = 0;
  PQnotifies_init();
  pq_regoob(pq_async_notify);
d557 3
a559 2
  if (status != STATUS_OK)
    return(STATUS_ERROR);
d561 1
a561 1
  return(STATUS_OK);
a564 28
/* --------------------------------
 *	pq_accept - accept remote input / output connection
 * --------------------------------
 */
int
pq_accept()
{
    struct sockaddr_in	sin;
    int			fd, nfd, i;
    
    if (!(fd = socket(AF_INET, SOCK_STREAM, 0)))
	return(-2);
    
    pq_getinaddr(&sin, 0, pq_getport());
    if (bind(fd, (struct sockaddr *)&sin, sizeof sin))
	return(-3);
    
    listen(fd, SOMAXCONN);
    if ((nfd = accept(fd, NULL, NULL)) < 0)
	return(-1);
    
    close(fd);
    Pfout = fdopen(nfd, "w");
    Pfin = fdopen(dup(nfd), "r");
    
    return(0);
}

d571 1
a571 1
     void (*fptr)();
d584 2
a585 1
void pq_async_notify() {
d588 1
d593 1
a593 1
/*	PQappendNotify(msg+1);*/
d620 35
a654 37
char	*hostName;
short	portName;
int	*fdP;
{
  struct sockaddr_in	sin;
  int			fd;
  struct hostent	*hp;

  if (! hostName)
    hostName = "localhost";

  bzero((char *)&sin, sizeof sin);

  if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
      strcpy(PQerrormsg,"StreamServerPort: cannot make socket descriptor for port\n");
    fprintf(stderr,PQerrormsg);
    return(STATUS_ERROR);
  }

  sin.sin_family = AF_INET;
  sin.sin_port = htons(portName);

  if (bind(fd, (struct sockaddr *)&sin, sizeof sin) < 0) {
    strcpy(PQerrormsg,"StreamServerPort: cannot bind to port\n");
    fprintf(stderr,PQerrormsg);
    return(STATUS_ERROR);
  }

  listen(fd, SOMAXCONN);

  /* MS: I took this code from Dillon's version.  It makes the 
   * listening port non-blocking.  That is not necessary (and
   * may tickle kernel bugs).

   (void) fcntl(fd, F_SETFD, 1);
   (void) fcntl(fd, F_SETFL, FNDELAY);
   */
d656 12
a667 2
  *fdP = fd;
  return(STATUS_OK);
d679 2
a680 2
	int	server_fd;
	Port	*port;
d682 24
a705 1
	int	addrlen;
d707 1
a707 24
	/* accept connection (and fill in the client (remote) address) */
	addrlen = sizeof(struct sockaddr_in);
	if ((port->sock = accept(server_fd,
				 (struct sockaddr *) &port->raddr,
				 &addrlen)) < 0) {
		elog(WARN, "postmaster: StreamConnection: accept: %m");
		return(STATUS_ERROR);
	}
	
	/* fill in the server (local) address */
	addrlen = sizeof(struct sockaddr_in);
	if (getsockname(port->sock, (struct sockaddr *) &port->laddr,
			&addrlen) < 0) {
		elog(WARN, "postmaster: StreamConnection: getsockname: %m");
		return(STATUS_ERROR);
	}
	
	port->sock = port->sock;
	port->mask = 1 << port->sock;
	
	/* reset to non-blocking */
	fcntl(port->sock, F_SETFL, 1);	
	
	return(STATUS_OK);
d714 1
a714 1
	int	sock;
d716 1
a716 1
	close(sock); 
d731 55
a785 7
	char	*hostName;
	short	portName;
	Port	*port;
{
	struct hostent	*hp;
	int		laddrlen = sizeof(struct sockaddr_in);
	extern int errno;
d787 1
a787 41
	if (!hostName)
		hostName = "localhost";
	
	/* set up the server (remote) address */
	if (!(hp = gethostbyname(hostName)) || hp->h_addrtype != AF_INET) {
		sprintf(PQerrormsg, "StreamOpen: unknown hostname '%s'\n",
			hostName);
		fprintf(stderr,PQerrormsg);
		return(STATUS_ERROR);
	}
	bzero((char *) &port->raddr, sizeof(port->raddr));
	bcopy((char *) hp->h_addr, (char *) &(port->raddr.sin_addr),
	      hp->h_length);
	port->raddr.sin_family = AF_INET;
	port->raddr.sin_port = htons(portName);
	
	/* connect to the server */
	if ((port->sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		sprintf(PQerrormsg, "StreamOpen: socket: errno=%d\n",
			errno);
		fprintf(stderr, PQerrormsg);
		return(STATUS_ERROR);
	}
	if (connect(port->sock, (struct sockaddr *)&port->raddr,
	    sizeof(port->raddr)) < 0) {
		sprintf(PQerrormsg, "StreamOpen: connect: errno=%d\n",
			errno);
		fprintf(stderr, PQerrormsg);
		return(STATUS_ERROR);
	}

	/* fill in the client address */
	if (getsockname(port->sock, (struct sockaddr *) &port->laddr,
			&laddrlen) < 0) {
		sprintf(PQerrormsg, "StreamOpen: getsockname: errno=%d\n",
			errno);
		fprintf(stderr,PQerrormsg);
		return(STATUS_ERROR);
	}
	
	return(STATUS_OK);
@


1.20
log
@missing & - also casts
@
text
@d30 1
a30 1
 *	$Header: /a/staff/marc/src/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.19 92/12/29 01:37:09 aoki Exp Locker: marc $
d39 1
d47 1
a47 1
RcsId ("$Header: /a/staff/marc/src/postgres/src/backend/libpq/RCS/pqcomm.c,v 1.19 92/12/29 01:37:09 aoki Exp Locker: marc $");
d459 1
d540 1
a540 1
  if (pg_sendauth(msgtype, SendPort, hostName) != STATUS_OK) {
d565 1
@


1.19
log
@minor bug fix involving packet size
@
text
@d30 1
a30 1
 *	$Header: /usr/local/dev/postgres/mastertree/newconf/RCS/pqcomm.c,v 1.18 1992/04/21 13:13:53 clarsen Exp $
a38 1
#include <netinet/in.h>
d46 1
a46 1
RcsId ("$Header: /usr/local/dev/postgres/mastertree/newconf/RCS/pqcomm.c,v 1.18 1992/04/21 13:13:53 clarsen Exp $");
d578 1
a578 1
    if (bind(fd, &sin, sizeof sin))
d667 1
a667 1
  if (bind(fd, (char *)&sin, sizeof sin) < 0) {
d704 1
a704 1
				 (struct sockaddr *) port->raddr,
d754 1
d779 2
a780 1
	if (connect(port->sock, &port->raddr, sizeof(port->raddr)) < 0) {
@


1.18
log
@Put error messages in PQerrormsg
@
text
@d30 1
a30 1
 *	$Header: RCS/pqcomm.c,v 1.17 92/04/13 19:08:45 mer Exp Locker: clarsen $
d42 2
a44 1
#include "tmp/c.h"
d47 1
a47 1
RcsId ("$Header: RCS/pqcomm.c,v 1.17 92/04/13 19:08:45 mer Exp Locker: clarsen $");
a491 2
  int			sock;
  Addr			addr;
d493 1
d527 3
a529 1
  status = StreamOpen(hostName,portName,&sock);
a532 7
  /*
   * Save communication port state.
   */
  SendPort = (Port *) malloc(sizeof(Port));
  bzero(SendPort, sizeof(Port));
  SendPort->sock =  sock;

d534 10
a543 2
  status = PacketSend(SendPort, MyConn, 
		      &startup, STARTUP_MSG, sizeof(startup), BLOCKING);
d546 2
a547 2
  Pfout = fdopen(sock, "w");
  Pfin = fdopen(dup(sock), "r");
a658 11
#ifdef NOTDEF
  if ((hp = gethostbyname(hostName)) && hp->h_addrtype == AF_INET)
    bcopy(hp->h_addr, (char *)&(sin.sin_addr), hp->h_length);
  else {
    fprintf(stderr, 
        "StreamServerPort: cannot find hostname '%s' for stream port\n", 
        hostName);
    return(STATUS_ERROR);
  }
#endif

d692 1
a692 5
 * This one should be non-blocking.  The client could send us
 * part of a message.  Would not do at all to have the server
 * block waiting for the message to complete.  Not neccesary
 * to return the address, but it could conceivably be used
 * for protection checking.
d696 30
a725 16
StreamConnection(server_fd,new_fdP,addrP)
int 			server_fd;
int			*new_fdP;
struct sockaddr_in	*addrP;
{
  long 			len = sizeof (struct sockaddr_in);

  if ((*new_fdP = accept(server_fd, (char *)addrP, &len)) < 0) {
    strcpy(PQerrormsg,"StreamConnection: accept failed\n");
    fprintf(stderr,PQerrormsg);
    return(STATUS_ERROR);
  }
  /* reset to non-blocking */
  fcntl(*new_fdP, F_SETFL, 1);	

  return(STATUS_OK);
d732 1
a732 1
int	sock;
d734 1
a734 1
  close(sock); 
a745 3
 *
 * ASSUME that the client doesn't need the net address of the
 *	server after this routine exits.
d748 37
a784 8
StreamOpen(hostName,portName,sockP)
char	*hostName;
short	portName;
int	*sockP;
{
  struct sockaddr_in	addr;
  struct hostent	*hp;
  int			sock;
d786 10
a795 29
  if (! hostName)
    hostName = "localhost";

  bzero((char *)&addr, sizeof addr);

  if ((hp = gethostbyname(hostName)) && hp->h_addrtype == AF_INET)
    bcopy(hp->h_addr, (char *)&(addr.sin_addr), hp->h_length);
  else {
    sprintf(PQerrormsg,
	"StreamPort: cannot find hostname '%s' for stream port\n",
	hostName);
    fprintf(stderr,PQerrormsg);
    return(STATUS_ERROR);
  }

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
      strcpy(PQerrormsg,"StreamPort: cannot make socket descriptor for port\n");
    fprintf(stderr,PQerrormsg);
    return(STATUS_ERROR);
  }

  addr.sin_family = AF_INET;
  addr.sin_port = htons(portName);

  *sockP = sock;
  if (! connect(sock, &addr, sizeof(addr)))
    return(STATUS_OK);
  else
    return(STATUS_ERROR);
@


1.17
log
@add debug and error messages for socket manipulations and writes to socket
@
text
@d30 1
a30 1
 *	$Header: /users/mer/pg/src/lib/libpq/RCS/pqcomm.c,v 1.16 1992/02/25 15:29:53 clarsen Exp mer $
d46 1
a46 1
RcsId ("$Header: /users/mer/pg/src/lib/libpq/RCS/pqcomm.c,v 1.16 1992/02/25 15:29:53 clarsen Exp mer $");
d58 1
d305 2
a306 1
	    fprintf(stderr, "pq_putstr: write to backend failed\n");
d311 2
a312 1
	    fprintf(stderr, "pq_putstr: write to backend failed\n");
d334 2
a335 1
		fprintf(stderr, "pq_putnchar: write to backend failed\n");
d360 2
a361 1
		fprintf(stderr, "pq_putint: write to backend failed\n");
d418 2
a419 2
		fputs(host, stderr);
		fputs(": Not Internet\n", stderr);
d450 1
d547 2
a548 1
    fprintf(stderr, "Couldn't fdopen the socket descriptor\n");
d668 2
a669 2
    fprintf(stderr,
	"StreamServerPort: cannot make socket descriptor for port\n");
d677 2
a678 1
    fprintf(stderr,"StreamServerPort: cannot bind to port\n");
d716 2
a717 1
    fprintf(stderr,"StreamConnection: accept failed\n");
d766 1
a766 1
    fprintf(stderr,
d769 1
d774 2
a775 1
    fprintf(stderr,"StreamPort: cannot make socket descriptor for port\n");
@


1.16
log
@async portals.
@
text
@d30 1
a30 1
 *	$Header: RCS/pqcomm.c,v 1.15 91/11/11 23:19:20 hong Exp Locker: clarsen $
d46 1
a46 1
RcsId ("$Header: RCS/pqcomm.c,v 1.15 91/11/11 23:19:20 hong Exp Locker: clarsen $");
d77 2
d157 2
d160 1
d244 2
d247 1
d258 1
d260 1
d276 2
d279 1
d298 2
d301 10
a310 2
	fputs(s, Pfout);
	fputc('\0', Pfout);
d323 2
d327 7
a333 1
	    fputc(*s++, Pfout);
d345 2
d352 1
a352 1
	    fputc(i & 0xff, Pfout);
d354 4
d539 5
@


1.15
log
@for prototyping
@
text
@d23 1
d30 1
a30 1
 *	$Header: RCS/pqcomm.c,v 1.14 91/08/12 21:55:41 mao Exp $
d40 1
d46 1
a46 1
RcsId ("$Header: RCS/pqcomm.c,v 1.14 91/08/12 21:55:41 mao Exp $");
d57 1
d61 6
d77 1
d127 3
d325 28
d424 1
d502 4
d541 32
@


1.14
log
@check value of Pfout before writing to it.
@
text
@d29 1
a29 1
 *	$Header: /local/mao/postgres/src/lib/libpq/RCS/pqcomm.c,v 1.13 1991/08/12 21:40:31 mao Exp mao $
d44 1
a44 1
RcsId ("$Header: /local/mao/postgres/src/lib/libpq/RCS/pqcomm.c,v 1.13 1991/08/12 21:40:31 mao Exp mao $");
d285 1
@


1.13
log
@fix comm protocol to shut down channel cleanly on exit of monitor
@
text
@d29 1
a29 1
 *	$Header: /local/mao/postgres/src/lib/libpq/RCS/pqcomm.c,v 1.12 1991/03/09 16:45:19 kemnitz Exp mao $
d44 1
a44 1
RcsId ("$Header: /local/mao/postgres/src/lib/libpq/RCS/pqcomm.c,v 1.12 1991/03/09 16:45:19 kemnitz Exp mao $");
d208 1
d211 1
d272 4
a275 2
    fputs(s, Pfout);
    fputc('\0', Pfout);
d286 4
a289 2
    while (n--)
	fputc(*s++, Pfout);
d303 5
a307 3
    while (b--) {
	fputc(i & 0xff, Pfout);
	i >>= 8;
@


1.12
log
@It now works across the network (before it only worked with localhost).
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.11 91/03/08 19:55:56 kemnitz Exp Locker: kemnitz $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.11 91/03/08 19:55:56 kemnitz Exp Locker: kemnitz $");
d141 3
d173 5
a177 1
	int c;
d223 3
d250 3
@


1.11
log
@added stuff to deal with copy command protocols, including an interface
allowing users to simply read/write strings for the backend to deal
with.
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.10 91/03/08 00:36:54 kemnitz Exp Locker: kemnitz $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.10 91/03/08 00:36:54 kemnitz Exp Locker: kemnitz $");
d507 1
d516 1
@


1.10
log
@put htons back.
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.9 91/03/07 23:21:32 kemnitz Exp Locker: kemnitz $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.9 91/03/07 23:21:32 kemnitz Exp Locker: kemnitz $");
d153 50
@


1.9
log
@Fixed initialization problem - changed htons to htonl
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.8 91/03/07 02:03:58 kemnitz Exp Locker: kemnitz $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.8 91/03/07 02:03:58 kemnitz Exp Locker: kemnitz $");
d272 1
a272 1
    sin->sin_port = htonl(port);
d299 1
a299 1
	pq_getinaddr(sin, host, ntohl(ss->s_port));
d473 1
a473 1
  sin.sin_port = htonl(portName);
d575 1
a575 1
  addr.sin_port = htonl(portName);
@


1.8
log
@Fixed coredump in trying to strncpy null ptr.
@
text
@d29 1
a29 1
 *	$Header: src/lib/libpq/RCS/pqcomm.c,v 1.7 91/03/05 13:00:02 mao Exp $
d44 1
a44 1
RcsId ("$Header: src/lib/libpq/RCS/pqcomm.c,v 1.7 91/03/05 13:00:02 mao Exp $");
d272 1
a272 1
    sin->sin_port = htons(port);
d299 1
a299 1
	pq_getinaddr(sin, host, ntohs(ss->s_port));
d349 4
d363 1
d378 1
d473 1
a473 1
  sin.sin_port = htons(portName);
d575 1
a575 1
  addr.sin_port = htons(portName);
@


1.7
log
@get vacuumd daemon and vcontrol working
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.6 91/02/28 17:01:59 mer Exp Locker: mao $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.6 91/02/28 17:01:59 mer Exp Locker: mao $");
d345 4
a348 1
  strncpy(startup.execFile, execFile, sizeof(startup.execFile));
@


1.6
log
@pq_getnchars & pq_getstr return EOF when EOF is read
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.5 91/02/28 10:45:09 mer Exp Locker: mer $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.5 91/02/28 10:45:09 mer Exp Locker: mer $");
d318 1
a318 1
pq_connect(dbname,user,args,hostName,debugTty,portName)
d324 1
d345 1
a345 2

  startup.execFile[0] = NULL;	/* Don't allow front end to choose backends */
@


1.5
log
@added functionality to support backend debug output redirection
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.4 91/02/22 17:07:40 mer Exp Locker: mer $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.4 91/02/22 17:07:40 mer Exp Locker: mer $");
d134 1
a134 1
void
d144 9
d159 1
a159 1
void
d169 9
@


1.4
log
@revamped for new postmaster interface
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.3 91/02/20 00:39:13 cimarron Exp Locker: mer $
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.3 91/02/20 00:39:13 cimarron Exp Locker: mer $");
d300 1
a300 1
pq_connect(dbname,user,args,hostName,portName)
d305 1
d325 1
@


1.3
log
@removed temporary defn of pqtest
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.2 91/02/19 14:00:56 cimarron Exp Locker: cimarron $
d40 1
d44 1
a44 1
RcsId ("$Header: RCS/pqcomm.c,v 1.2 91/02/19 14:00:56 cimarron Exp Locker: cimarron $");
d284 14
a297 3
/* --------------------------------
 *	pq_connect - create remote input / output connection
 * --------------------------------
d300 6
a305 2
pq_connect(host, port)
    char	*host, *port;
d307 57
a363 25
    struct sockaddr_in	sin;
    int			fd, port_no;
    
    port_no = atoi(port);
    
    /* pq_getport() returns the environment variable PGPORT, default is 4321 */
    if (!port_no) 
	port_no = pq_getport();
    
    if (pq_getinaddr(&sin, host, port_no))
	return(-1);
    
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd == -1) {
	return(-1);
    }
    
    if (connect(fd, &sin, sizeof sin) == -1)
	return(-1);
    
    fcntl(fd,F_SETFL,0);
    Pfout = fdopen(fd, "w");
    Pfin = fdopen(dup(fd), "r");
    
    return(0);
d392 161
@


1.2
log
@added a dummy test function
@
text
@d29 1
a29 1
 *	$Header: RCS/pqcomm.c,v 1.1 91/02/09 20:43:56 cimarron Exp Locker: cimarron $
d43 1
a43 1
RcsId ("$Header: RCS/pqcomm.c,v 1.1 91/02/09 20:43:56 cimarron Exp Locker: cimarron $");
a344 6

/* ----------------
 *	pqtest
 * ----------------
 */
int pqtest() { return 1; }
@


1.1
log
@Initial revision
@
text
@d29 1
a29 1
 *	$Header$
d43 1
a43 1
RcsId ("$Header$");
d345 6
@
