]> git.ipfire.org Git - thirdparty/systemd.git/blob - udevsend.c
[PATCH] fix Makefile typo for USE_LSB install.
[thirdparty/systemd.git] / udevsend.c
1 /*
2 * udevsend.c
3 *
4 * Userspace devfs
5 *
6 * Copyright (C) 2004 Ling, Xiaofeng <xiaofeng.ling@intel.com>
7 * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation version 2 of the License.
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 675 Mass Ave, Cambridge, MA 02139, USA.
22 *
23 */
24
25 #include <sys/types.h>
26 #include <sys/ipc.h>
27 #include <sys/msg.h>
28 #include <errno.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <time.h>
34 #include <wait.h>
35
36 #include "udev.h"
37 #include "udevd.h"
38 #include "logging.h"
39
40 static inline char *get_action(void)
41 {
42 char *action;
43
44 action = getenv("ACTION");
45 return action;
46 }
47
48 static inline char *get_devpath(void)
49 {
50 char *devpath;
51
52 devpath = getenv("DEVPATH");
53 return devpath;
54 }
55
56 static inline char *get_seqnum(void)
57 {
58 char *seqnum;
59
60 seqnum = getenv("SEQNUM");
61 return seqnum;
62 }
63
64 static int build_hotplugmsg(struct hotplug_msg *msg, char *action,
65 char *devpath, char *subsystem, int seqnum)
66 {
67 memset(msg, 0x00, sizeof(msg));
68 msg->mtype = HOTPLUGMSGTYPE;
69 msg->seqnum = seqnum;
70 strncpy(msg->action, action, 8);
71 strncpy(msg->devpath, devpath, 128);
72 strncpy(msg->subsystem, subsystem, 16);
73 return sizeof(struct hotplug_msg);
74 }
75
76 static int start_daemon(void)
77 {
78 pid_t pid;
79 pid_t child_pid;
80
81 pid = fork();
82 switch (pid) {
83 case 0:
84 /* helper child */
85 child_pid = fork();
86 switch (child_pid) {
87 case 0:
88 /* daemon */
89 setsid();
90 chdir("/");
91 execl(UDEVD_EXEC, "udevd", NULL);
92 dbg("exec of daemon failed");
93 exit(1);
94 case -1:
95 dbg("fork of daemon failed");
96 return -1;
97 default:
98 exit(0);
99 }
100 break;
101 case -1:
102 dbg("fork of helper failed");
103 return -1;
104 default:
105 wait(NULL);
106 }
107 return 0;
108 }
109
110
111 int main(int argc, char* argv[])
112 {
113 int msgid;
114 key_t key;
115 struct msqid_ds msg_queue;
116 struct hotplug_msg message;
117 char *action;
118 char *devpath;
119 char *subsystem;
120 char *seqnum;
121 int seq;
122 int retval = -EINVAL;
123 int size;
124 int loop;
125 struct timespec tspec;
126
127 subsystem = argv[1];
128 if (subsystem == NULL) {
129 dbg("no subsystem");
130 goto exit;
131 }
132
133 devpath = get_devpath();
134 if (devpath == NULL) {
135 dbg("no devpath");
136 goto exit;
137 }
138
139 action = get_action();
140 if (action == NULL) {
141 dbg("no action");
142 goto exit;
143 }
144
145 seqnum = get_seqnum();
146 if (seqnum == NULL) {
147 dbg("no seqnum");
148 goto exit;
149 }
150 seq = atoi(seqnum);
151
152 /* create ipc message queue or get id of our existing one */
153 key = ftok(UDEVD_EXEC, IPC_KEY_ID);
154 size = build_hotplugmsg(&message, action, devpath, subsystem, seq);
155 msgid = msgget(key, IPC_CREAT);
156 if (msgid == -1) {
157 dbg("error open ipc queue");
158 goto exit;
159 }
160
161 /* send ipc message to the daemon */
162 retval = msgsnd(msgid, &message, size, 0);
163 if (retval == -1) {
164 dbg("error sending ipc message");
165 goto exit;
166 }
167
168 /* get state of ipc queue */
169 tspec.tv_sec = 0;
170 tspec.tv_nsec = 10000000; /* 10 millisec */
171 loop = 30;
172 while (loop--) {
173 retval = msgctl(msgid, IPC_STAT, &msg_queue);
174 if (retval == -1) {
175 dbg("error getting info on ipc queue");
176 goto exit;
177 }
178 if (msg_queue.msg_qnum == 0)
179 goto exit;
180 nanosleep(&tspec, NULL);
181 }
182
183 info("message is still in the ipc queue, starting daemon...");
184 retval = start_daemon();
185
186 exit:
187 return retval;
188 }