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: }