pikeyd165 – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /**** daemon.c *****************************/ |
2 | /* M. Moller 2013-01-16 */ |
||
3 | /* Univeral RPi GPIO keyboard daemon */ |
||
4 | /*******************************************/ |
||
5 | |||
6 | /* |
||
7 | Copyright (C) 2013 Michael Moller. |
||
8 | This file is part of the Universal Raspberry Pi GPIO keyboard daemon. |
||
9 | |||
10 | This is free software; you can redistribute it and/or |
||
11 | modify it under the terms of the GNU Lesser General Public |
||
12 | License as published by the Free Software Foundation; either |
||
13 | version 2.1 of the License, or (at your option) any later version. |
||
14 | |||
15 | The software is distributed in the hope that it will be useful, |
||
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
18 | Lesser General Public License for more details. |
||
19 | |||
20 | You should have received a copy of the GNU Lesser General Public |
||
21 | License along with the GNU C Library; if not, write to the Free |
||
22 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
||
23 | 02111-1307 USA. |
||
24 | */ |
||
25 | |||
26 | #include <stdio.h> |
||
27 | #include <signal.h> |
||
28 | #include <syslog.h> |
||
29 | #include <errno.h> |
||
30 | #include <stdlib.h> |
||
31 | #include <fcntl.h> |
||
32 | #include <string.h> |
||
33 | #include <unistd.h> |
||
34 | #include "daemon.h" |
||
35 | |||
36 | #define DAEMON_NAME "pikeyd" |
||
37 | |||
38 | void daemonShutdown(void); |
||
39 | void signal_handler(int sig); |
||
40 | void daemonize(char *rundir, char *pidfile); |
||
41 | |||
42 | int pid_fd; |
||
43 | char *pid_lock_file; |
||
44 | |||
45 | void daemonShutdown(void) |
||
46 | { |
||
47 | close(pid_fd); |
||
48 | unlink(pid_lock_file); |
||
49 | } |
||
50 | |||
51 | void signal_handler(int sig) |
||
52 | { |
||
53 | switch(sig){ |
||
54 | case SIGHUP: |
||
55 | syslog(LOG_WARNING, "Received SIGHUP."); |
||
56 | break; |
||
57 | case SIGINT: |
||
58 | case SIGTERM: |
||
59 | syslog(LOG_INFO, "Exiting."); |
||
60 | daemonShutdown(); |
||
61 | exit(0); |
||
62 | break; |
||
63 | default: |
||
64 | syslog(LOG_WARNING, "Unhandled signal %s", strsignal(sig)); |
||
65 | } |
||
66 | } |
||
67 | |||
68 | /* get the pid from the pid lock file and terminate the daemon */ |
||
69 | void daemonKill(char *pidfile) |
||
70 | { |
||
71 | int n; |
||
72 | pid_t pid; |
||
73 | char str[10]; |
||
74 | |||
75 | |||
76 | pid_fd = open(pidfile, O_RDONLY, 0600); |
||
77 | if(pid_fd < 0){ |
||
78 | perror(pidfile); |
||
79 | } |
||
80 | else{ |
||
81 | if( read(pid_fd, str, 10) > 0 ){ |
||
82 | pid = strtol(str, NULL, 0); |
||
83 | if(pid){ |
||
84 | printf("terminating %d\n", pid); |
||
85 | n = kill(pid, SIGTERM); |
||
86 | if(n<0){ |
||
87 | perror("kill"); |
||
88 | } |
||
89 | } |
||
90 | } |
||
91 | close(pid_fd); |
||
92 | } |
||
93 | } |
||
94 | |||
95 | void daemonize(char *rundir, char *pidfile) |
||
96 | { |
||
97 | int pid, sid, i, r; |
||
98 | char str[10]; |
||
99 | struct sigaction newSA; |
||
100 | sigset_t newSS; |
||
101 | |||
102 | if(getppid() == 1){ |
||
103 | /* don't need to do it twice */ |
||
104 | return; |
||
105 | } |
||
106 | |||
107 | setlogmask(LOG_UPTO(LOG_INFO)); |
||
108 | openlog(DAEMON_NAME, LOG_CONS | LOG_PERROR, LOG_USER); |
||
109 | syslog(LOG_INFO, "Daemon starting"); |
||
110 | |||
111 | sigemptyset(&newSS); |
||
112 | sigaddset(&newSS, SIGCHLD); |
||
113 | sigaddset(&newSS, SIGTSTP); |
||
114 | sigaddset(&newSS, SIGTTOU); |
||
115 | sigaddset(&newSS, SIGTTIN); |
||
116 | sigprocmask(SIG_BLOCK, &newSS, NULL); /* block these signals */ |
||
117 | |||
118 | newSA.sa_handler = signal_handler; |
||
119 | sigemptyset(&newSA.sa_mask); |
||
120 | newSA.sa_flags = 0; |
||
121 | sigaction(SIGHUP, &newSA, NULL); |
||
122 | sigaction(SIGTERM, &newSA, NULL); |
||
123 | sigaction(SIGINT, &newSA, NULL); |
||
124 | |||
125 | pid = fork(); |
||
126 | |||
127 | if(pid < 0){ |
||
128 | perror("fork"); |
||
129 | exit(EXIT_FAILURE); |
||
130 | } |
||
131 | |||
132 | if(pid > 0){ /* success. terminate the parent */ |
||
133 | exit(0); |
||
134 | } |
||
135 | |||
136 | /* child continues here. */ |
||
137 | |||
138 | umask(027); |
||
139 | sid = setsid(); |
||
140 | if(sid < 0){ |
||
141 | perror("set SID"); |
||
142 | exit(EXIT_FAILURE); |
||
143 | } |
||
144 | |||
145 | for(i = getdtablesize(); i>=0; --i){ |
||
146 | close(i); |
||
147 | } |
||
148 | |||
149 | close(STDIN_FILENO); |
||
150 | close(STDOUT_FILENO); |
||
151 | close(STDERR_FILENO); |
||
152 | |||
153 | if( chdir(rundir) < 0 ){ |
||
154 | perror(rundir); |
||
155 | } |
||
156 | |||
157 | /* only one at a time */ |
||
158 | pid_lock_file = pidfile; |
||
159 | pid_fd = open(pidfile, O_RDWR|O_CREAT, 0600); |
||
160 | if(pid_fd < 0){ |
||
161 | syslog(LOG_INFO, "Could not open lock file %s. Exiting.", pidfile); |
||
162 | exit(EXIT_FAILURE); |
||
163 | } |
||
164 | if(lockf(pid_fd, F_TLOCK, 0) < 0){ |
||
165 | syslog(LOG_INFO, "Could not lock lock file %s. Exiting.", pidfile); |
||
166 | unlink(pidfile); |
||
167 | exit(EXIT_FAILURE); |
||
168 | } |
||
169 | sprintf(str, "%d\n", getpid()); |
||
170 | if( write(pid_fd, str, strlen(str)) < 0 ){ |
||
171 | perror(pidfile); |
||
172 | } |
||
173 | |||
174 | syslog(LOG_INFO, "Daemon running."); |
||
175 | } |