Annotation of src/usr.bin/cvs/sock.c, Revision 1.1
1.1 ! jfb 1: /* $OpenBSD$ */
! 2: /*
! 3: * Copyright (c) 2004 Jean-Francois Brousseau <jfb@openbsd.org>
! 4: * All rights reserved.
! 5: *
! 6: * Redistribution and use in source and binary forms, with or without
! 7: * modification, are permitted provided that the following conditions
! 8: * are met:
! 9: *
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. The name of the author may not be used to endorse or promote products
! 13: * derived from this software without specific prior written permission.
! 14: *
! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
! 16: * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
! 17: * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
! 18: * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
! 19: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
! 20: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
! 21: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
! 23: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
! 24: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27: #include <sys/types.h>
! 28: #include <sys/socket.h>
! 29: #include <sys/un.h>
! 30:
! 31: #include <poll.h>
! 32: #include <stdlib.h>
! 33: #include <stdio.h>
! 34: #include <unistd.h>
! 35: #include <errno.h>
! 36: #include <string.h>
! 37:
! 38: #include "log.h"
! 39: #include "sock.h"
! 40: #include "cvsd.h"
! 41: #include "event.h"
! 42:
! 43:
! 44: volatile sig_atomic_t cvs_sock_doloop;
! 45:
! 46:
! 47: char *cvsd_sock_path = CVSD_SOCK_PATH;
! 48:
! 49:
! 50:
! 51: /* daemon API */
! 52: static int cvsd_sock = -1;
! 53: static struct sockaddr_un cvsd_sun;
! 54:
! 55: /* for client API */
! 56: static int cvs_sock = -1;
! 57: static struct sockaddr_un cvs_sun;
! 58:
! 59:
! 60: /*
! 61: * cvsd_sock_open()
! 62: *
! 63: * Open the daemon's local socket.
! 64: */
! 65:
! 66: int
! 67: cvsd_sock_open(void)
! 68: {
! 69: cvsd_sun.sun_family = AF_LOCAL;
! 70: strlcpy(cvsd_sun.sun_path, cvsd_sock_path, sizeof(cvsd_sun.sun_path));
! 71:
! 72: cvsd_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
! 73: if (cvsd_sock == -1) {
! 74: cvs_log(LP_ERRNO, "failed to open socket");
! 75: return (-1);
! 76: }
! 77:
! 78: if (bind(cvsd_sock, (struct sockaddr *)&cvsd_sun,
! 79: SUN_LEN(&cvsd_sun)) == -1) {
! 80: cvs_log(LP_ERRNO, "failed to bind local socket to `%s'",
! 81: cvsd_sock_path);
! 82: (void)close(cvsd_sock);
! 83: return (-1);
! 84: }
! 85:
! 86: listen(cvsd_sock, 10);
! 87:
! 88: if (chmod(cvsd_sock_path, CVSD_SOCK_PERMS) == -1) {
! 89: cvs_log(LP_ERRNO, "failed to change mode of `%s'",
! 90: cvsd_sock_path);
! 91: (void)close(cvsd_sock);
! 92: (void)unlink(cvsd_sock_path);
! 93: return (-1);
! 94: }
! 95:
! 96: cvs_log(LP_DEBUG, "opened local socket `%s'", cvsd_sock_path);
! 97:
! 98: return (0);
! 99: }
! 100:
! 101:
! 102: /*
! 103: * cvsd_sock_close()
! 104: *
! 105: * Close the local socket.
! 106: */
! 107:
! 108: void
! 109: cvsd_sock_close(void)
! 110: {
! 111: cvs_log(LP_DEBUG, "closing local socket `%s'", CVSD_SOCK_PATH);
! 112: if (close(cvsd_sock) == -1) {
! 113: cvs_log(LP_ERRNO, "failed to close local socket");
! 114: }
! 115: if (unlink(cvsd_sock_path) == -1)
! 116: cvs_log(LP_ERRNO, "failed to unlink local socket `%s'",
! 117: CVSD_SOCK_PATH);
! 118: }
! 119:
! 120:
! 121: /*
! 122: * cvsd_sock_loop()
! 123: *
! 124: */
! 125:
! 126: void
! 127: cvsd_sock_loop(void)
! 128: {
! 129: int nfds, sock;
! 130: socklen_t slen;
! 131: struct sockaddr_un sun;
! 132: struct pollfd pfd[1];
! 133:
! 134: cvs_sock_doloop = 1;
! 135:
! 136: while (cvs_sock_doloop) {
! 137: pfd[0].fd = cvsd_sock;
! 138: pfd[0].events = POLLIN;
! 139:
! 140: nfds = poll(pfd, 1, INFTIM);
! 141: if (nfds == -1) {
! 142: if (errno == EINTR)
! 143: continue;
! 144: cvs_log(LP_ERR, "failed to poll local socket");
! 145: }
! 146:
! 147: if ((nfds == 0) || !(pfd[0].revents & POLLIN))
! 148: continue;
! 149:
! 150: sock = accept(pfd[0].fd, (struct sockaddr *)&sun, &slen);
! 151: if (sock == -1) {
! 152: cvs_log(LP_ERRNO, "failed to accept connection");
! 153: }
! 154: cvs_log(LP_DEBUG, "accepted connection");
! 155:
! 156: cvsd_sock_hdl(sock);
! 157: }
! 158:
! 159:
! 160: }
! 161:
! 162:
! 163: /*
! 164: * cvsd_sock_hdl()
! 165: *
! 166: * Handle the events for a single connection.
! 167: */
! 168:
! 169: int
! 170: cvsd_sock_hdl(int fd)
! 171: {
! 172: uid_t uid;
! 173: gid_t gid;
! 174: struct cvs_event ev;
! 175:
! 176: /* don't trust what the other end put in */
! 177: if (getpeereid(fd, &uid, &gid) == -1) {
! 178: cvs_log(LP_ERR, "failed to get peer credentials");
! 179: (void)close(fd);
! 180: return (-1);
! 181: }
! 182:
! 183: if (read(fd, &ev, sizeof(ev)) == -1) {
! 184: cvs_log(LP_ERR, "failed to read cvs event");
! 185: return (-1);
! 186: }
! 187:
! 188: return (0);
! 189: }
! 190:
! 191:
! 192: /*
! 193: * cvs_sock_connect()
! 194: *
! 195: * Open a connection to the CVS server's local socket.
! 196: */
! 197:
! 198: int
! 199: cvs_sock_connect(const char *cvsroot)
! 200: {
! 201: cvs_sun.sun_family = AF_LOCAL;
! 202: snprintf(cvs_sun.sun_path, sizeof(cvs_sun.sun_path), "%s/%s",
! 203: cvsroot, CVSD_SOCK_PATH);
! 204:
! 205: cvs_log(LP_INFO, "connecting to CVS server socket `%s'",
! 206: cvs_sun.sun_path);
! 207:
! 208: cvs_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
! 209: if (cvs_sock == -1) {
! 210: cvs_log(LP_ERRNO, "failed to open local socket");
! 211: return (-1);
! 212: }
! 213:
! 214: if (connect(cvs_sock, (struct sockaddr *)&cvs_sun,
! 215: SUN_LEN(&cvs_sun)) == -1) {
! 216: cvs_log(LP_ERRNO, "failed to connect to server socket `%s'",
! 217: cvs_sun.sun_path);
! 218: (void)close(cvs_sock);
! 219: return (-1);
! 220: }
! 221:
! 222: return (0);
! 223: }
! 224:
! 225:
! 226: /*
! 227: * cvs_sock_disconnect()
! 228: *
! 229: * Disconnect from the open socket to the CVS server.
! 230: */
! 231:
! 232: void
! 233: cvs_sock_disconnect(void)
! 234: {
! 235: if (close(cvs_sock) == -1)
! 236: cvs_log(LP_ERRNO, "failed to close local socket");
! 237: }