8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / libdscfg / common / cfg_lockdmsg.c
blob238c75967e61ad36287b587ad68e278a9bd03d42
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <signal.h>
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <netinet/tcp.h>
32 #include <netdb.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <errno.h>
39 #include "cfg_lockd.h"
41 static daemonaddr_t clientaddr;
42 static daemonaddr_t server;
44 static unsigned short server_port = CFG_SERVER_PORT;
45 static int lock_soc = 0;
46 static int pf_inet = AF_INET;
47 static int locked;
48 static int initdone;
49 static int initresult;
50 static pid_t socket_pid;
52 static void cfg_lockd_reinit();
54 static int last_cmd = -1;
55 static uint8_t seq = 0;
57 static void
58 send_cmd(int cmd)
60 struct lock_msg message_buf;
61 int rc;
63 if (last_cmd == cmd) {
64 message_buf.seq = seq;
65 } else {
66 message_buf.seq = ++seq;
67 last_cmd = cmd;
69 message_buf.message = cmd;
70 if ((message_buf.pid = getpid()) != socket_pid)
71 cfg_lockd_reinit();
73 do {
74 rc = sendto(lock_soc, &message_buf, sizeof (message_buf), 0,
75 (struct sockaddr *)&server, sizeof (server));
76 } while (rc == -1 && errno == EINTR);
77 #ifdef CFG_LOCKD_DEBUG
78 if (rc < 0) {
79 perror("send");
81 #endif
84 static void
85 read_msg(struct lock_msg *mp)
87 struct sockaddr from;
88 int rc, len;
90 /* wait for response */
91 do {
92 struct pollfd fds;
94 fds.fd = lock_soc;
95 fds.events = POLLIN;
96 fds.revents = 0;
98 rc = poll(&fds, 1, 500);
99 if (!rc) {
100 #ifdef CFG_LOCKD_DEBUG
101 fprintf(stderr, "LOCKD: resending last command (%d)\n",
102 last_cmd);
103 #endif
104 send_cmd(last_cmd);
106 } while (rc == 0 ||
107 (rc == -1 && errno == EINTR));
109 do {
110 len = sizeof (from);
111 rc = recvfrom(lock_soc, mp, sizeof (*mp), 0,
112 &from, &len);
113 } while (rc == -1 && errno == EINTR);
114 #ifdef CFG_LOCKD_DEBUG
115 if (rc < 0) {
116 perror("revcfrom");
118 #endif
121 static void
122 read_reply()
124 struct lock_msg message_buf;
126 do {
127 read_msg(&message_buf);
128 } while (message_buf.seq != seq || message_buf.message != LOCK_LOCKED);
131 static void
132 read_ack()
134 struct lock_msg message_buf;
136 do {
137 read_msg(&message_buf);
138 } while (message_buf.seq != seq || message_buf.message != LOCK_ACK);
141 void
142 cfg_lockd_rdlock()
144 #ifdef CFG_LOCKD_DEBUG
145 FILE *fp;
146 #endif
148 send_cmd(LOCK_READ);
149 locked = 1;
150 read_reply();
152 #ifdef CFG_LOCKD_DEBUG
153 fp = fopen("/tmp/locktag", "a");
154 if (fp) {
155 time_t t = time(0);
156 fprintf(fp, "%19.19s read lock acquired\n", ctime(&t));
157 fclose(fp);
159 sleep(3);
160 #endif
163 void
164 cfg_lockd_wrlock()
166 #ifdef CFG_LOCKD_DEBUG
167 FILE *fp;
168 #endif
170 send_cmd(LOCK_WRITE);
171 locked = 1;
172 read_reply();
174 #ifdef CFG_LOCKD_DEBUG
175 fp = fopen("/tmp/locktag", "a");
176 if (fp) {
177 time_t t = time(0);
178 fprintf(fp, "%19.19s write lock acquired\n", ctime(&t));
179 fclose(fp);
181 sleep(3);
182 #endif
185 void
186 cfg_lockd_unlock()
188 #ifdef CFG_LOCKD_DEBUG
189 FILE *fp;
190 #endif
192 send_cmd(LOCK_NOTLOCKED);
193 read_ack();
194 locked = 0;
196 #ifdef CFG_LOCKD_DEBUG
197 fp = fopen("/tmp/locktag", "a");
198 if (fp) {
199 time_t t = time(0);
200 fprintf(fp, "%19.19s ----- lock released\n", ctime(&t));
201 fclose(fp);
203 sleep(3);
204 #endif
207 void
208 cfg_lockd_stat()
210 send_cmd(LOCK_STAT);
213 cfglockd_t
214 cfg_lockedby(pid_t *pidp)
216 struct lock_msg message_buf;
217 send_cmd(LOCK_LOCKEDBY);
218 read_msg(&message_buf);
219 *pidp = message_buf.pid;
220 return ((cfglockd_t)message_buf.message);
223 static void
224 cfg_atexit()
226 if (locked)
227 cfg_lockd_unlock();
230 static int
231 cfg_lockd_socket()
233 if ((lock_soc = socket(pf_inet, SOCK_DGRAM, 0)) < 0) {
234 #ifdef CFG_LOCKD_DEBUG
235 fprintf(stderr, "libcfg: failed to create socket\n");
236 perror("socket");
237 #endif
238 return (-1);
240 clientaddr.sin_family = AF_INET;
241 clientaddr.sin_addr.s_addr = INADDR_ANY;
242 clientaddr.sin_port = htons(0);
243 if (bind(lock_soc, (struct sockaddr *)&clientaddr,
244 sizeof (clientaddr)) < 0) {
245 #ifdef CFG_LOCKD_DEBUG
246 perror("bind");
247 #endif
248 return (-1);
250 socket_pid = getpid();
251 return (0);
255 * Re-initialise after a fork has been detected.
257 * Needs to create a new socket for new process to receive messages
258 * from the lock daemon and enter pid into lock file so that the daemon
259 * can detect new processes exit if it doesn't call unlock first.
262 static void
263 cfg_lockd_reinit()
265 if (lock_soc)
266 close(lock_soc);
267 lock_soc = 0;
268 if (cfg_lockd_socket()) {
269 initresult = 0;
270 return;
272 cfg_enterpid();
273 initresult = 1;
277 cfg_lockd_init()
279 struct hostent *hp;
280 FILE *fp;
281 int pid = 0x12345678;
283 if (initdone) {
284 /* only perform reinit if init worked first time */
285 if (getpid() != socket_pid && initresult != 0)
286 cfg_lockd_reinit();
287 return (initresult);
290 initdone = 1;
291 initresult = 0;
293 /* check if there's a lock daemon out there */
294 if ((fp = fopen(CFG_PIDFILE, "r")) == NULL)
295 return (0);
296 if (fscanf(fp, "%d\n", &pid) != 1) {
297 fclose(fp);
298 return (0);
300 fclose(fp);
301 if (kill((pid_t)pid, 0) != 0)
302 return (0);
304 /* there is a lock daemon */
305 cfg_lfinit();
306 cfg_enterpid();
307 if (cfg_lockd_socket())
308 return (0);
310 if ((hp = gethostbyname("localhost")) == NULL) {
311 #ifdef CFG_LOCKD_DEBUG
312 fprintf(stderr, "Can't find hostent for %s\n", "localhost");
313 #endif
314 return (0);
316 (void) memcpy(&(server.sin_addr.s_addr), *(hp->h_addr_list),
317 sizeof (server.sin_addr));
318 server.sin_port = htons(server_port);
319 server.sin_family = hp->h_addrtype;
320 endhostent();
321 atexit(cfg_atexit);
322 initresult = 1;
323 return (1);