Annotation of src/usr.bin/cvs/sock.c, Revision 1.2
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 */
1.2 ! jfb 52: int cvsd_sock = -1;
1.1 jfb 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: *
1.2 ! jfb 63: * Open the daemon's local socket. If the server socket is already opened,
! 64: * we close it before reopening it.
! 65: * Returns 0 on success, -1 on failure.
1.1 jfb 66: */
67:
68: int
69: cvsd_sock_open(void)
70: {
1.2 ! jfb 71: if (cvs_sock >= 0)
! 72: cvsd_sock_close();
! 73:
1.1 jfb 74: cvsd_sun.sun_family = AF_LOCAL;
75: strlcpy(cvsd_sun.sun_path, cvsd_sock_path, sizeof(cvsd_sun.sun_path));
76:
77: cvsd_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
78: if (cvsd_sock == -1) {
79: cvs_log(LP_ERRNO, "failed to open socket");
80: return (-1);
81: }
82:
83: if (bind(cvsd_sock, (struct sockaddr *)&cvsd_sun,
84: SUN_LEN(&cvsd_sun)) == -1) {
85: cvs_log(LP_ERRNO, "failed to bind local socket to `%s'",
86: cvsd_sock_path);
87: (void)close(cvsd_sock);
88: return (-1);
89: }
90:
91: listen(cvsd_sock, 10);
92:
93: if (chmod(cvsd_sock_path, CVSD_SOCK_PERMS) == -1) {
94: cvs_log(LP_ERRNO, "failed to change mode of `%s'",
95: cvsd_sock_path);
96: (void)close(cvsd_sock);
97: (void)unlink(cvsd_sock_path);
98: return (-1);
99: }
100:
101: cvs_log(LP_DEBUG, "opened local socket `%s'", cvsd_sock_path);
102:
103: return (0);
104: }
105:
106:
107: /*
108: * cvsd_sock_close()
109: *
110: * Close the local socket.
111: */
112:
113: void
114: cvsd_sock_close(void)
115: {
116: cvs_log(LP_DEBUG, "closing local socket `%s'", CVSD_SOCK_PATH);
117: if (close(cvsd_sock) == -1) {
118: cvs_log(LP_ERRNO, "failed to close local socket");
119: }
120: if (unlink(cvsd_sock_path) == -1)
121: cvs_log(LP_ERRNO, "failed to unlink local socket `%s'",
1.2 ! jfb 122: cvsd_sock_path);
1.1 jfb 123: }
124:
125:
126: /*
1.2 ! jfb 127: * cvsd_sock_accept()
1.1 jfb 128: *
1.2 ! jfb 129: * Handler for connections made on the server's local domain socket.
! 130: * It accepts connections and looks for a child process that is currently
! 131: * idle to which it can dispatch the connection's descriptor. If there are
! 132: * no available child processes, a new one will be created unless the number
! 133: * of children has attained the maximum.
1.1 jfb 134: */
135:
1.2 ! jfb 136: int
! 137: cvsd_sock_accept(int fd)
1.1 jfb 138: {
1.2 ! jfb 139: int cfd;
1.1 jfb 140: socklen_t slen;
141: struct sockaddr_un sun;
142:
1.2 ! jfb 143: slen = sizeof(sun);
! 144: cfd = accept(fd, (struct sockaddr *)&sun, &slen);
! 145: if (cfd == -1) {
! 146: cvs_log(LP_ERRNO, "failed to accept client connection");
1.1 jfb 147: return (-1);
148: }
149:
150: return (0);
151: }
152:
153:
154: /*
155: * cvs_sock_connect()
156: *
157: * Open a connection to the CVS server's local socket.
158: */
159:
160: int
161: cvs_sock_connect(const char *cvsroot)
162: {
163: cvs_sun.sun_family = AF_LOCAL;
164: snprintf(cvs_sun.sun_path, sizeof(cvs_sun.sun_path), "%s/%s",
165: cvsroot, CVSD_SOCK_PATH);
166:
167: cvs_log(LP_INFO, "connecting to CVS server socket `%s'",
168: cvs_sun.sun_path);
169:
170: cvs_sock = socket(AF_LOCAL, SOCK_STREAM, 0);
171: if (cvs_sock == -1) {
172: cvs_log(LP_ERRNO, "failed to open local socket");
173: return (-1);
174: }
175:
176: if (connect(cvs_sock, (struct sockaddr *)&cvs_sun,
177: SUN_LEN(&cvs_sun)) == -1) {
178: cvs_log(LP_ERRNO, "failed to connect to server socket `%s'",
179: cvs_sun.sun_path);
180: (void)close(cvs_sock);
181: return (-1);
182: }
183:
184: return (0);
185: }
186:
187:
188: /*
189: * cvs_sock_disconnect()
190: *
191: * Disconnect from the open socket to the CVS server.
192: */
193:
194: void
195: cvs_sock_disconnect(void)
196: {
197: if (close(cvs_sock) == -1)
198: cvs_log(LP_ERRNO, "failed to close local socket");
199: }