Mercurial > pt1.oyama
comparison src/pt1_lnbd.c @ 124:9c7bc6c0327e
Add DLNA server function test. (from uShare project)
author | naoyan@johnstown.minaminoshima.org |
---|---|
date | Wed, 29 Sep 2010 23:18:55 +0900 |
parents | recpt1/pt1_lnbd.c@215a51fa3df3 |
children |
comparison
equal
deleted
inserted
replaced
123:215a51fa3df3 | 124:9c7bc6c0327e |
---|---|
1 #include <fcntl.h> | |
2 #include <limits.h> | |
3 #include <pwd.h> | |
4 #include <sys/ioctl.h> | |
5 #include <sys/stat.h> | |
6 #include <sys/types.h> | |
7 #include <signal.h> | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <string.h> | |
11 #include <unistd.h> | |
12 #include "pt1_ioctl.h" | |
13 | |
14 #ifdef O_NOFOLLOW | |
15 #define OPEN_FLAGS O_NOFOLLOW | O_NONBLOCK | |
16 #else | |
17 #define OPEN_FLAGS O_NONBLOCK | |
18 #endif | |
19 | |
20 /* ヘッダに移動すること */ | |
21 #define C_RET_OK 0 | |
22 #define C_RET_NG -1 | |
23 #define MYNAME "pt1_lnb_enabler" | |
24 #define PID_DIR "/var/run/" | |
25 #define PIDFILENAME PID_DIR MYNAME ".pid" | |
26 #define NUMBER "0123456789" | |
27 #define device "/dev/pt1video0" | |
28 #define ROOT "root" | |
29 /* ヘッダに移動すること */ | |
30 | |
31 mode_t umask_val = 0133; | |
32 | |
33 void fin_action(int); | |
34 | |
35 int main() { | |
36 struct sigaction ign_sigaction; | |
37 struct sigaction fin_sigaction; | |
38 FILE *fp; | |
39 int i; | |
40 int i_ret; | |
41 int fd; | |
42 int pt1_fd; | |
43 int string_length; | |
44 int number_length; | |
45 int i_pid; | |
46 struct stat orig_st; | |
47 struct stat open_st; | |
48 int flags; | |
49 char file_name[] = PIDFILENAME; | |
50 char buf[1024] = ""; | |
51 pid_t mypid; | |
52 char *p; | |
53 struct passwd *p_st_passwd; | |
54 uid_t uid_root; | |
55 | |
56 /* 初期処理 */ | |
57 /* root権限で動作していなければ終了 */ | |
58 p_st_passwd = getpwnam(ROOT); | |
59 if (p_st_passwd == NULL) { | |
60 printf("faile to get pwent. id=[%s].\n", ROOT); | |
61 exit(C_RET_NG); | |
62 } | |
63 uid_root = p_st_passwd->pw_uid; | |
64 if( uid_root != getuid() ) { | |
65 /* root 意外の実行権限なのでエラー */ | |
66 printf("This process must be run by root. uid=[%d].\n", getuid()); | |
67 exit(C_RET_NG); | |
68 } | |
69 /* fork して親は即自殺してターミナルを離す */ | |
70 mypid = fork(); | |
71 if( mypid == -1 ) { | |
72 /* fork エラー */ | |
73 printf("fork error.\n"); | |
74 exit(C_RET_NG); | |
75 } else if ( mypid != 0 ) { | |
76 /* 親プロセスは即終了(プロンプトに戻す) */ | |
77 return(C_RET_OK); | |
78 } | |
79 umask(umask_val); | |
80 ign_sigaction.sa_handler = SIG_IGN; | |
81 fin_sigaction.sa_handler = fin_action; | |
82 if (sigaction(SIGHUP, &ign_sigaction, NULL) != 0) { | |
83 printf("failed to set signal handler. SIGHUP\n"); | |
84 exit(C_RET_NG); | |
85 } | |
86 if (sigaction(SIGTERM, &fin_sigaction, NULL) != 0) { | |
87 printf("failed to set signal handler. SIGTERM\n"); | |
88 exit(C_RET_NG); | |
89 } | |
90 if (sigaction(SIGPIPE, &fin_sigaction, NULL) != 0) { | |
91 printf("failed to set signal handler. SIGPIPE\n"); | |
92 exit(C_RET_NG); | |
93 } | |
94 if (sigaction(SIGINT, &fin_sigaction, NULL) != 0) { | |
95 printf("failed to set signal handler. SIGINT\n"); | |
96 exit(C_RET_NG); | |
97 } | |
98 if (sigaction(SIGQUIT, &fin_sigaction, NULL) != 0) { | |
99 printf("failed to set signal handler. SIGQUIT\n"); | |
100 exit(C_RET_NG); | |
101 } | |
102 if (sigaction(SIGILL, &fin_sigaction, NULL) != 0) { | |
103 printf("failed to set signal handler. SIGILL\n"); | |
104 exit(C_RET_NG); | |
105 } | |
106 if (sigaction(SIGABRT, &fin_sigaction, NULL) != 0) { | |
107 printf("failed to set signal handler. SIGABRT\n"); | |
108 exit(C_RET_NG); | |
109 } | |
110 if (sigaction(SIGFPE, &fin_sigaction, NULL) != 0) { | |
111 printf("failed to set signal handler. SIGFPE\n"); | |
112 exit(C_RET_NG); | |
113 } | |
114 if (sigaction(SIGSEGV, &fin_sigaction, NULL) != 0) { | |
115 printf("failed to set signal handler. SIGSEGV\n"); | |
116 exit(C_RET_NG); | |
117 } | |
118 /* sleep を使うので SIGALRM は放置 | |
119 * if (sigaction(SIGALRM, &ign_sigaction, NULL) != 0) { | |
120 * printf("failed to set signal handler. SIGALRM\n"); | |
121 * exit(C_RET_NG); | |
122 * } | |
123 */ | |
124 if (sigaction(SIGUSR1, &ign_sigaction, NULL) != 0) { | |
125 printf("failed to set signal handler. SIGUSR1\n"); | |
126 exit(C_RET_NG); | |
127 } | |
128 if (sigaction(SIGUSR2, &ign_sigaction, NULL) != 0) { | |
129 printf("failed to set signal handler. SIGUSR2\n"); | |
130 exit(C_RET_NG); | |
131 } | |
132 if (sigaction(SIGCHLD, &ign_sigaction, NULL) != 0) { | |
133 printf("failed to set signal handler. SIGCHLD\n"); | |
134 exit(C_RET_NG); | |
135 } | |
136 if (sigaction(SIGCONT, &ign_sigaction, NULL) != 0) { | |
137 printf("failed to set signal handler. SIGCONT\n"); | |
138 exit(C_RET_NG); | |
139 } | |
140 if (sigaction(SIGTSTP, &ign_sigaction, NULL) != 0) { | |
141 printf("failed to set signal handler. SIGTSTP\n"); | |
142 exit(C_RET_NG); | |
143 } | |
144 if (sigaction(SIGTTIN, &ign_sigaction, NULL) != 0) { | |
145 printf("failed to set signal handler. SIGTTIN\n"); | |
146 exit(C_RET_NG); | |
147 } | |
148 if (sigaction(SIGTTOU, &ign_sigaction, NULL) != 0) { | |
149 printf("failed to set signal handler. SIGTTOU\n"); | |
150 exit(C_RET_NG); | |
151 } | |
152 if (sigaction(SIGPOLL, &ign_sigaction, NULL) != 0) { | |
153 printf("failed to set signal handler. SIGPOLL\n"); | |
154 exit(C_RET_NG); | |
155 } | |
156 if (sigaction(SIGIO, &ign_sigaction, NULL) != 0) { | |
157 printf("failed to set signal handler. SIGIO\n"); | |
158 exit(C_RET_NG); | |
159 } | |
160 if (sigaction(SIGPROF, &ign_sigaction, NULL) != 0) { | |
161 printf("failed to set signal handler. SIGPROF\n"); | |
162 exit(C_RET_NG); | |
163 } | |
164 if (sigaction(SIGSYS, &ign_sigaction, NULL) != 0) { | |
165 printf("failed to set signal handler. SIGSYS\n"); | |
166 exit(C_RET_NG); | |
167 } | |
168 if (sigaction(SIGTRAP, &ign_sigaction, NULL) != 0) { | |
169 printf("failed to set signal handler. SIGTRAP\n"); | |
170 exit(C_RET_NG); | |
171 } | |
172 if (sigaction(SIGURG, &ign_sigaction, NULL) != 0) { | |
173 printf("failed to set signal handler. SIGURG\n"); | |
174 exit(C_RET_NG); | |
175 } | |
176 if (sigaction(SIGVTALRM, &ign_sigaction, NULL) != 0) { | |
177 printf("failed to set signal handler. SIGVTALRM\n"); | |
178 exit(C_RET_NG); | |
179 } | |
180 if (sigaction(SIGXCPU, &ign_sigaction, NULL) != 0) { | |
181 printf("failed to set signal handler. SIGXCPU\n"); | |
182 exit(C_RET_NG); | |
183 } | |
184 if (sigaction(SIGXFSZ, &ign_sigaction, NULL) != 0) { | |
185 printf("failed to set signal handler. SIGXFSZ\n"); | |
186 exit(C_RET_NG); | |
187 } | |
188 /* ないって | |
189 * if (sigaction(SIGEMT, &ign_sigaction, NULL) != 0) { | |
190 * printf("failed to set signal handler. SIGEMT\n"); | |
191 * exit(C_RET_NG); | |
192 * } | |
193 */ | |
194 if (sigaction(SIGSTKFLT, &ign_sigaction, NULL) != 0) { | |
195 printf("failed to set signal handler. SIGSTKFLT\n"); | |
196 exit(C_RET_NG); | |
197 } | |
198 if (sigaction(SIGIO, &ign_sigaction, NULL) != 0) { | |
199 printf("failed to set signal handler. SIGIO\n"); | |
200 exit(C_RET_NG); | |
201 } | |
202 if (sigaction(SIGCLD, &ign_sigaction, NULL) != 0) { | |
203 printf("failed to set signal handler. SIGCLD\n"); | |
204 exit(C_RET_NG); | |
205 } | |
206 if (sigaction(SIGPWR, &ign_sigaction, NULL) != 0) { | |
207 printf("failed to set signal handler. SIGPWR\n"); | |
208 exit(C_RET_NG); | |
209 } | |
210 /* ないって | |
211 * if (sigaction(SIGINFO, &ign_sigaction, NULL) != 0) { | |
212 * printf("failed to set signal handler. SIGINFO\n"); | |
213 * exit(C_RET_NG); | |
214 * } | |
215 */ | |
216 /* ないって | |
217 * if (sigaction(SIGLOST, &ign_sigaction, NULL) != 0) { | |
218 * printf("failed to set signal handler. SIGLOST\n"); | |
219 * exit(C_RET_NG); | |
220 * } | |
221 */ | |
222 if (sigaction(SIGWINCH, &ign_sigaction, NULL) != 0) { | |
223 printf("failed to set signal handler. SIGWINCH\n"); | |
224 exit(C_RET_NG); | |
225 } | |
226 if (sigaction(SIGUNUSED, &ign_sigaction, NULL) != 0) { | |
227 printf("failed to set signal handler. SIGUNUSED\n"); | |
228 exit(C_RET_NG); | |
229 } | |
230 | |
231 /* ファイルチェック処理 */ | |
232 if ((lstat(file_name, &orig_st) != 0) || | |
233 (!S_ISREG(orig_st.st_mode))) | |
234 { | |
235 /* ファイル無しの場合は前回正常終了 */ | |
236 i_ret = C_RET_OK; | |
237 } else { | |
238 /* PIDファイルが存在する場合には、現在の状態を確認する。 | |
239 * ・二重起動状態(pidファイルのpid値を持つプロセスが存在する) | |
240 * ・前回pidファイルを消さずに死んでしまった */ | |
241 i_ret = C_RET_NG; | |
242 } | |
243 /* ここに TOCTOU 競合状態の問題があるが、 | |
244 * /var/run はセキュアなディレクトリなので問題は無い */ | |
245 if (i_ret != C_RET_OK) { | |
246 fd = open(file_name, (OPEN_FLAGS | O_RDWR)); | |
247 if (fd == -1) { | |
248 /* エラー処理 */ | |
249 printf("open error. file:[%s].\n", file_name); | |
250 exit(C_RET_NG); | |
251 } | |
252 | |
253 if (fstat(fd, &open_st) != 0) { | |
254 /* エラー処理 */ | |
255 printf("stat error. file:[%s].\n", file_name); | |
256 exit(C_RET_NG); | |
257 } | |
258 | |
259 if ((orig_st.st_mode != open_st.st_mode) || | |
260 (orig_st.st_ino != open_st.st_ino) || | |
261 (orig_st.st_dev != open_st.st_dev)) { | |
262 /* ファイルはすでにすり替えられている */ | |
263 printf("file switch has occurred. file:[%s].\n", file_name); | |
264 close(fd); | |
265 exit(C_RET_NG); | |
266 } | |
267 | |
268 /* 問題ないファイルであることが確認できたので O_NONBLOCK | |
269 * を無効にする (省略可能) */ | |
270 if ((flags = fcntl(fd, F_GETFL)) == -1) { | |
271 /* エラー処理 */ | |
272 printf("fcntl error. file:[%s].\n", file_name); | |
273 close(fd); | |
274 exit(C_RET_NG); | |
275 } | |
276 | |
277 if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) != 0) { | |
278 /* エラー処理 */ | |
279 printf("fcntl error. file:[%s].\n", file_name); | |
280 close(fd); | |
281 exit(C_RET_NG); | |
282 } | |
283 /* ファイルサイズが0以外である場合にはPID値のチェック */ | |
284 if(open_st.st_size != 0) { | |
285 /* ファイルを読みPID値を取得する */ | |
286 if((fp = fdopen(fd, "w+")) == NULL) { | |
287 /* fdopen()失敗 */ | |
288 printf("fdopen error. fd:[%d].\n", fd); | |
289 close(fd); | |
290 exit(C_RET_NG); | |
291 } | |
292 if ( fgets(buf, sizeof(buf), fp) == NULL ) { | |
293 /* fgetsエラー */ | |
294 printf("fgets error. fd:[%d].\n", fd); | |
295 fclose(fp); | |
296 exit(C_RET_NG); | |
297 } | |
298 buf[sizeof(buf)-1] = '\0'; | |
299 p = strchr(buf, (int)'\n'); | |
300 if(p != NULL) { | |
301 *p = '\0'; | |
302 } | |
303 string_length = strlen(buf); | |
304 number_length = strspn(buf, NUMBER); | |
305 if ( string_length != number_length ) { | |
306 /* PIDファイル異常 */ | |
307 printf("invalid pid file[%s] buf[%s].\n", file_name, buf); | |
308 fclose(fp); | |
309 exit(C_RET_NG); | |
310 } | |
311 i_pid = atoi(buf); | |
312 | |
313 /* PIDファイルのPIDと同じPIDを持つプロセスが存在するか? */ | |
314 i_ret = kill(i_pid, 0); | |
315 if ( i_ret == 0 ) { | |
316 /* 存在する場合には二重起動とみなして処理終了 */ | |
317 printf("process already exists. pid[%d]\n", i_pid); | |
318 exit(C_RET_NG); | |
319 } else { | |
320 /* 存在しない場合は前回異常終了なのでfpを先頭に戻して処理続行 */ | |
321 rewind(fp); | |
322 } | |
323 } | |
324 } | |
325 if ( i_ret == C_RET_OK ) { | |
326 /* PIDファイルが存在しない場合はPIDファイルの新規作成を行う */ | |
327 fd = open(file_name, O_CREAT|O_EXCL|O_RDWR, 00644); | |
328 if ( fd == -1 ){ | |
329 /* open 失敗 */ | |
330 printf("file open error. file_name[%s].\n", file_name); | |
331 exit(C_RET_NG); | |
332 } | |
333 if((fp = fdopen(fd, "w+")) == NULL) { | |
334 /* fdopen()失敗 */ | |
335 printf("fdopen error. fd:[%d].\n", fd); | |
336 close(fd); | |
337 exit(C_RET_NG); | |
338 } | |
339 } | |
340 /* fpのPIDファイルが書き込める状態なので、PIDを書き込む */ | |
341 mypid = getpid(); | |
342 snprintf(buf, sizeof(buf), "%d\n", mypid); | |
343 i_ret = fputs(buf, fp); | |
344 if(i_ret == EOF) { | |
345 /* fputs エラー */ | |
346 printf("fputs error. file_name[%s].\n", file_name); | |
347 fclose(fp); | |
348 exit(C_RET_NG); | |
349 } | |
350 fclose(fp); | |
351 /* PID関係処理終了*/ | |
352 /* fd に pt1 デバイスを open */ | |
353 pt1_fd = open(device, O_RDONLY); | |
354 if(pt1_fd == -1) { | |
355 /* open エラー */ | |
356 printf("open error. file_name[%s].\n", device); | |
357 exit(C_RET_NG); | |
358 } | |
359 /* fcntl で LNB 電源を有効化する */ | |
360 if(ioctl(pt1_fd, LNB_ENABLE, 0) < 0) { | |
361 printf("Power on LNB failed. device:[%s].\n", device); | |
362 exit(C_RET_NG); | |
363 } | |
364 close(pt1_fd); | |
365 /* 無限待ち(終了は終了するsignalを受けたらとする) */ | |
366 while(1){ | |
367 sleep(UINT_MAX); | |
368 } | |
369 return C_RET_OK; | |
370 } | |
371 | |
372 /* 終了処理実行関数 */ | |
373 /* プロセスを終了させるべきsignalを受けたときに動作する */ | |
374 void fin_action(int sig) { | |
375 int pt1_fd; | |
376 char file_name[] = PIDFILENAME; | |
377 /* fd に pt1 デバイスをopen */ | |
378 pt1_fd = open(device, O_RDONLY); | |
379 if(pt1_fd == -1) { | |
380 /* open エラー */ | |
381 printf("open error. file_name[%s].\n", device); | |
382 exit(C_RET_NG); | |
383 } | |
384 /* fcntl で LNB 電源断する */ | |
385 if(ioctl(pt1_fd, LNB_DISABLE, 0) < 0) { | |
386 printf("Power on LNB failed. device:[%s].\n", device); | |
387 close(pt1_fd); | |
388 exit(C_RET_NG); | |
389 } | |
390 /* fd close */ | |
391 close(pt1_fd); | |
392 /* pidファイルを削除する */ | |
393 if ( unlink(file_name) != 0 ) { | |
394 /* pid file unlink エラー */ | |
395 printf("unlink error. file_name[%s].\n", device); | |
396 exit(C_RET_NG); | |
397 } | |
398 /* おしまい */ | |
399 exit(C_RET_OK); | |
400 } |