[BACK]Return to sock.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

File: [local] / src / usr.bin / cvs / Attic / sock.c (download)

Revision 1.3, Mon Aug 2 17:30:10 2004 UTC (19 years, 10 months ago) by jfb
Branch: MAIN
Changes since 1.2: +6 -4 lines

* add the appropriate preprocessor wrappers to compile only the code
  required for each program
* make cvs_sock_connect() take a full path to the socket

/*	$OpenBSD: sock.c,v 1.3 2004/08/02 17:30:10 jfb Exp $	*/
/*
 * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
 * All rights reserved. 
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met: 
 *
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer. 
 * 2. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <poll.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

#include "log.h"
#include "sock.h"
#include "cvsd.h"
#include "event.h"


volatile sig_atomic_t  cvs_sock_doloop;


char     *cvsd_sock_path = CVSD_SOCK_PATH;



/* daemon API */
int cvsd_sock = -1;
static struct sockaddr_un cvsd_sun;

/* for client API */
static int cvs_sock = -1;
static struct sockaddr_un cvs_sun;


#ifdef CVSD
/*
 * cvsd_sock_open()
 *
 * Open the daemon's local socket.  If the server socket is already opened,
 * we close it before reopening it.
 * Returns 0 on success, -1 on failure.
 */

int
cvsd_sock_open(void)
{
	if (cvs_sock >= 0)
		cvsd_sock_close();

	cvsd_sun.sun_family = AF_LOCAL;
	strlcpy(cvsd_sun.sun_path, cvsd_sock_path, sizeof(cvsd_sun.sun_path));

	cvsd_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
	if (cvsd_sock == -1) {
		cvs_log(LP_ERRNO, "failed to open socket"); 
		return (-1);
	}

	if (bind(cvsd_sock, (struct sockaddr *)&cvsd_sun,
	    SUN_LEN(&cvsd_sun)) == -1) {
		cvs_log(LP_ERRNO, "failed to bind local socket to `%s'",
		    cvsd_sock_path);
		(void)close(cvsd_sock);
		return (-1);
	}

	listen(cvsd_sock, 10);

	if (chmod(cvsd_sock_path, CVSD_SOCK_PERMS) == -1) {
		cvs_log(LP_ERRNO, "failed to change mode of `%s'",
		    cvsd_sock_path);
		(void)close(cvsd_sock);
		(void)unlink(cvsd_sock_path);
		return (-1);
	}

	cvs_log(LP_DEBUG, "opened local socket `%s'", cvsd_sock_path);

	return (0);
}


/*
 * cvsd_sock_close()
 *
 * Close the local socket.
 */

void
cvsd_sock_close(void)
{
	cvs_log(LP_DEBUG, "closing local socket `%s'", CVSD_SOCK_PATH);
	if (close(cvsd_sock) == -1) {
		cvs_log(LP_ERRNO, "failed to close local socket");
	}
	if (unlink(cvsd_sock_path) == -1)
		cvs_log(LP_ERRNO, "failed to unlink local socket `%s'",
		    cvsd_sock_path);
}


/*
 * cvsd_sock_accept()
 *
 * Handler for connections made on the server's local domain socket.
 * It accepts connections and looks for a child process that is currently
 * idle to which it can dispatch the connection's descriptor.  If there are
 * no available child processes, a new one will be created unless the number
 * of children has attained the maximum.
 */

int
cvsd_sock_accept(int fd)
{
	int cfd;
	socklen_t slen;
	struct sockaddr_un sun;

	slen = sizeof(sun);
	cfd = accept(fd, (struct sockaddr *)&sun, &slen);
	if (cfd == -1) {
		cvs_log(LP_ERRNO, "failed to accept client connection");
		return (-1);
	}

	return (0);
}
#endif

#ifdef CVS
/*
 * cvs_sock_connect()
 *
 * Open a connection to the CVS server's local socket.
 */

int
cvs_sock_connect(const char *path)
{
	cvs_sun.sun_family = AF_LOCAL;
	strlcpy(cvs_sun.sun_path, path, sizeof(cvs_sun.sun_path));

	cvs_log(LP_INFO, "connecting to CVS server socket `%s'",
	    cvs_sun.sun_path);

	cvs_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
	if (cvs_sock == -1) {
		cvs_log(LP_ERRNO, "failed to open local socket");
		return (-1);
	}

	if (connect(cvs_sock, (struct sockaddr *)&cvs_sun,
	    SUN_LEN(&cvs_sun)) == -1) {
		cvs_log(LP_ERRNO, "failed to connect to server socket `%s'",
		    cvs_sun.sun_path);
		(void)close(cvs_sock);
		return (-1);
	}

	return (0);
}


/*
 * cvs_sock_disconnect()
 *
 * Disconnect from the open socket to the CVS server.
 */

void
cvs_sock_disconnect(void)
{
	if (close(cvs_sock) == -1)
		cvs_log(LP_ERRNO, "failed to close local socket");
}
#endif