]>
Commit | Line | Data |
---|---|---|
7fafc032 KS |
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> | |
0be0c18d GKH |
26 | #include <sys/socket.h> |
27 | #include <sys/wait.h> | |
28 | #include <sys/un.h> | |
7fafc032 KS |
29 | #include <errno.h> |
30 | #include <stdio.h> | |
31 | #include <stdlib.h> | |
32 | #include <string.h> | |
33db4b8d KS |
33 | #include <unistd.h> |
34 | #include <time.h> | |
7fafc032 KS |
35 | |
36 | #include "udev.h" | |
35b7d88c | 37 | #include "udev_version.h" |
7fafc032 KS |
38 | #include "udevd.h" |
39 | #include "logging.h" | |
40 | ||
95a6f4c8 | 41 | unsigned char logname[42]; |
53921bfa | 42 | |
7fafc032 KS |
43 | static inline char *get_action(void) |
44 | { | |
45 | char *action; | |
46 | ||
47 | action = getenv("ACTION"); | |
48 | return action; | |
49 | } | |
50 | ||
51 | static inline char *get_devpath(void) | |
52 | { | |
53 | char *devpath; | |
54 | ||
55 | devpath = getenv("DEVPATH"); | |
56 | return devpath; | |
57 | } | |
58 | ||
59 | static inline char *get_seqnum(void) | |
60 | { | |
61 | char *seqnum; | |
62 | ||
63 | seqnum = getenv("SEQNUM"); | |
64 | return seqnum; | |
65 | } | |
66 | ||
71c077fb | 67 | static int build_hotplugmsg(struct hotplug_msg *msg, char *action, |
7fafc032 KS |
68 | char *devpath, char *subsystem, int seqnum) |
69 | { | |
35b7d88c | 70 | memset(msg, 0x00, sizeof(*msg)); |
53921bfa | 71 | strfieldcpy(msg->magic, UDEV_MAGIC); |
71c077fb GKH |
72 | msg->seqnum = seqnum; |
73 | strncpy(msg->action, action, 8); | |
74 | strncpy(msg->devpath, devpath, 128); | |
75 | strncpy(msg->subsystem, subsystem, 16); | |
7fafc032 KS |
76 | return sizeof(struct hotplug_msg); |
77 | } | |
78 | ||
33db4b8d KS |
79 | static int start_daemon(void) |
80 | { | |
81 | pid_t pid; | |
82 | pid_t child_pid; | |
83 | ||
84 | pid = fork(); | |
85 | switch (pid) { | |
86 | case 0: | |
87 | /* helper child */ | |
88 | child_pid = fork(); | |
89 | switch (child_pid) { | |
90 | case 0: | |
91 | /* daemon */ | |
a695feae | 92 | setsid(); |
2a25816f | 93 | chdir("/"); |
35b7d88c | 94 | execl(UDEVD_BIN, "udevd", NULL); |
33db4b8d KS |
95 | dbg("exec of daemon failed"); |
96 | exit(1); | |
97 | case -1: | |
98 | dbg("fork of daemon failed"); | |
99 | return -1; | |
100 | default: | |
101 | exit(0); | |
102 | } | |
103 | break; | |
104 | case -1: | |
105 | dbg("fork of helper failed"); | |
106 | return -1; | |
107 | default: | |
a695feae | 108 | wait(NULL); |
33db4b8d KS |
109 | } |
110 | return 0; | |
111 | } | |
112 | ||
7fafc032 KS |
113 | int main(int argc, char* argv[]) |
114 | { | |
71c077fb | 115 | struct hotplug_msg message; |
7fafc032 KS |
116 | char *action; |
117 | char *devpath; | |
118 | char *subsystem; | |
119 | char *seqnum; | |
120 | int seq; | |
121 | int retval = -EINVAL; | |
122 | int size; | |
33db4b8d KS |
123 | int loop; |
124 | struct timespec tspec; | |
53921bfa KS |
125 | int sock; |
126 | struct sockaddr_un saddr; | |
7fafc032 | 127 | |
e047ca9b | 128 | #ifdef DEBUG |
95a6f4c8 | 129 | init_logging("udevsend"); |
e047ca9b | 130 | #endif |
95a6f4c8 | 131 | |
7fafc032 KS |
132 | subsystem = argv[1]; |
133 | if (subsystem == NULL) { | |
134 | dbg("no subsystem"); | |
135 | goto exit; | |
136 | } | |
137 | ||
138 | devpath = get_devpath(); | |
139 | if (devpath == NULL) { | |
140 | dbg("no devpath"); | |
141 | goto exit; | |
142 | } | |
143 | ||
144 | action = get_action(); | |
145 | if (action == NULL) { | |
146 | dbg("no action"); | |
147 | goto exit; | |
148 | } | |
149 | ||
150 | seqnum = get_seqnum(); | |
151 | if (seqnum == NULL) { | |
152 | dbg("no seqnum"); | |
153 | goto exit; | |
154 | } | |
7fafc032 | 155 | seq = atoi(seqnum); |
7b15897b | 156 | |
53921bfa KS |
157 | sock = socket(AF_LOCAL, SOCK_STREAM, 0); |
158 | if (sock == -1) { | |
159 | dbg("error getting socket"); | |
7fafc032 KS |
160 | goto exit; |
161 | } | |
162 | ||
53921bfa KS |
163 | memset(&saddr, 0x00, sizeof(saddr)); |
164 | saddr.sun_family = AF_LOCAL; | |
8e2229c4 | 165 | strcpy(saddr.sun_path, UDEVD_SOCK); |
53921bfa KS |
166 | |
167 | /* try to connect, if it fails start daemon */ | |
d5c6d80f | 168 | retval = connect(sock, (struct sockaddr *) &saddr, sizeof(saddr)); |
53921bfa KS |
169 | if (retval != -1) { |
170 | goto send; | |
171 | } else { | |
172 | dbg("connect failed, try starting daemon..."); | |
173 | retval = start_daemon(); | |
174 | if (retval == 0) { | |
175 | dbg("daemon started"); | |
176 | } else { | |
177 | dbg("error starting daemon"); | |
178 | goto exit; | |
179 | } | |
7fafc032 | 180 | } |
7fafc032 | 181 | |
53921bfa | 182 | /* try to connect while daemon to starts */ |
33db4b8d | 183 | tspec.tv_sec = 0; |
53921bfa KS |
184 | tspec.tv_nsec = 100000000; /* 100 millisec */ |
185 | loop = UDEVSEND_CONNECT_RETRY; | |
33db4b8d | 186 | while (loop--) { |
d5c6d80f | 187 | retval = connect(sock, (struct sockaddr *) &saddr, sizeof(saddr)); |
53921bfa KS |
188 | if (retval != -1) |
189 | goto send; | |
190 | else | |
191 | dbg("retry to connect %d", | |
192 | UDEVSEND_CONNECT_RETRY - loop); | |
33db4b8d KS |
193 | nanosleep(&tspec, NULL); |
194 | } | |
53921bfa KS |
195 | dbg("error connecting to daemon, start daemon failed"); |
196 | goto exit; | |
7fafc032 | 197 | |
53921bfa KS |
198 | send: |
199 | size = build_hotplugmsg(&message, action, devpath, subsystem, seq); | |
200 | retval = send(sock, &message, size, 0); | |
201 | if (retval == -1) { | |
202 | dbg("error sending message"); | |
203 | close (sock); | |
204 | goto exit; | |
205 | } | |
206 | close (sock); | |
207 | return 0; | |
33db4b8d KS |
208 | |
209 | exit: | |
53921bfa | 210 | return 1; |
7fafc032 | 211 | } |