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

Annotation of src/usr.bin/cvs/sock.c, Revision 1.1.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: }