-rw-r--r-- | core/opiealarm/opiealarm.c | 57 | ||||
-rwxr-xr-x | root/etc/suspend-scripts/S46opiealarm | 2 |
2 files changed, 44 insertions, 15 deletions
diff --git a/core/opiealarm/opiealarm.c b/core/opiealarm/opiealarm.c index ac98832..128929e 100644 --- a/core/opiealarm/opiealarm.c +++ b/core/opiealarm/opiealarm.c | |||
@@ -10,92 +10,93 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <stdio.h> | 12 | #include <stdio.h> |
13 | #include <linux/rtc.h> | 13 | #include <linux/rtc.h> |
14 | #include <sys/ioctl.h> | 14 | #include <sys/ioctl.h> |
15 | #include <sys/time.h> | 15 | #include <sys/time.h> |
16 | #include <sys/types.h> | 16 | #include <sys/types.h> |
17 | #include <fcntl.h> | 17 | #include <fcntl.h> |
18 | #include <unistd.h> | 18 | #include <unistd.h> |
19 | #include <errno.h> | 19 | #include <errno.h> |
20 | #include <time.h> | 20 | #include <time.h> |
21 | #include <stdlib.h> | 21 | #include <stdlib.h> |
22 | #include <syslog.h> | 22 | #include <syslog.h> |
23 | #include <signal.h> | 23 | #include <signal.h> |
24 | #include <errno.h> | 24 | #include <errno.h> |
25 | #include <string.h> | 25 | #include <string.h> |
26 | 26 | ||
27 | 27 | ||
28 | #define PIDFILE "/var/run/opiealarm.pid" | 28 | #define PIDFILE "/var/run/opiealarm.pid" |
29 | #define APMFILE "/proc/apm" | 29 | #define APMFILE "/proc/apm" |
30 | 30 | ||
31 | FILE *log; // debug only | 31 | FILE *log; // debug only |
32 | 32 | ||
33 | int resume ( int resuspend ); | 33 | int resume ( int resuspend ); |
34 | int suspend ( void ); | 34 | int suspend ( int fix_rtc ); |
35 | int main ( int argc, char **argv ); | 35 | int main ( int argc, char **argv ); |
36 | int fork_with_pidfile ( void ); | 36 | int fork_with_pidfile ( void ); |
37 | int kill_with_pidfile ( void ); | 37 | int kill_with_pidfile ( void ); |
38 | void remove_pidfile ( void ); | 38 | void remove_pidfile ( void ); |
39 | void usage ( void ); | 39 | void usage ( void ); |
40 | void sig_handler ( int sig ); | 40 | void sig_handler ( int sig ); |
41 | void error_msg_and_die ( int perr, const char *msg ); | 41 | void error_msg_and_die ( int perr, const char *msg ); |
42 | int onac ( void ); | 42 | int onac ( void ); |
43 | 43 | ||
44 | static int opiealarm_was_running; | 44 | static int opiealarm_was_running; |
45 | 45 | ||
46 | 46 | ||
47 | void log_msg ( const char *msg ) | 47 | void log_msg ( const char *msg ) |
48 | { | 48 | { |
49 | if ( log ) { | 49 | if ( log ) { |
50 | fprintf ( log, msg ); | 50 | fprintf ( log, msg ); |
51 | fflush ( log ); | 51 | fflush ( log ); |
52 | } | 52 | } |
53 | } | 53 | } |
54 | 54 | ||
55 | void error_msg_and_die ( int perr, const char *msg ) | 55 | void error_msg_and_die ( int perr, const char *msg ) |
56 | { | 56 | { |
57 | if ( perr ) | 57 | if ( perr ) |
58 | log_msg ( strerror ( errno )); | 58 | log_msg ( strerror ( errno )); |
59 | log_msg ( msg ); | 59 | log_msg ( msg ); |
60 | 60 | ||
61 | while ( 1 ) // pretend we are waiting on RTC, so opiealarm -r can kill us | 61 | while ( 1 ) // pretend we are waiting on RTC, so opiealarm -r can kill us |
62 | sleep ( 1 ); | 62 | sleep ( 1 ); |
63 | } | 63 | } |
64 | 64 | ||
65 | 65 | ||
66 | void sig_handler ( int sig ) | 66 | void sig_handler ( int sig ) |
67 | { | 67 | { |
68 | log_msg ( "GOT SIGNAL -> EXITING\n" ); | 68 | log_msg ( "GOT SIGNAL -> EXITING\n" ); |
69 | fclose ( log ); | 69 | fclose ( log ); |
70 | remove_pidfile ( ); | 70 | remove_pidfile ( ); |
71 | exit ( 0 ); | 71 | exit ( 0 ); |
72 | } | 72 | } |
73 | 73 | ||
74 | void usage ( void ) | 74 | void usage ( void ) |
75 | { | 75 | { |
76 | fprintf ( stderr, "Usage: opiealarm -r|-s [-a]\n\n" ); | 76 | fprintf ( stderr, "Usage: opiealarm -s [-f] | -r [-a]\n\n" ); |
77 | fprintf ( stderr, "\t-s\tSuspend mode: set RTC alarm\n" ); | 77 | fprintf ( stderr, "\t-s\tSuspend mode: set RTC alarm\n" ); |
78 | fprintf ( stderr, "\t-f \tFix RTC, if RTC and system have more than 5sec difference (suspend mode)\n" ); | ||
78 | fprintf ( stderr, "\t-r\tResume mode: kill running opiealarm\n" ); | 79 | fprintf ( stderr, "\t-r\tResume mode: kill running opiealarm\n" ); |
79 | fprintf ( stderr, "\t-a <x>\tResuspend in <x> seconds (resume mode)\n\n" ); | 80 | fprintf ( stderr, "\t-a <x>\tResuspend in <x> seconds (resume mode)\n\n" ); |
80 | exit ( 1 ); | 81 | exit ( 1 ); |
81 | } | 82 | } |
82 | 83 | ||
83 | int fork_with_pidfile ( void ) | 84 | int fork_with_pidfile ( void ) |
84 | { | 85 | { |
85 | FILE *fp; | 86 | FILE *fp; |
86 | pid_t pid; | 87 | pid_t pid; |
87 | 88 | ||
88 | pid = fork ( ); | 89 | pid = fork ( ); |
89 | 90 | ||
90 | if ( pid > 0 ) | 91 | if ( pid > 0 ) |
91 | exit ( 0 ); | 92 | exit ( 0 ); |
92 | else if ( pid < 0 ) { | 93 | else if ( pid < 0 ) { |
93 | perror ( "forking failed" ); | 94 | perror ( "forking failed" ); |
94 | return 0; | 95 | return 0; |
95 | } | 96 | } |
96 | 97 | ||
97 | signal ( SIGTERM, sig_handler ); | 98 | signal ( SIGTERM, sig_handler ); |
98 | signal ( SIGINT, sig_handler ); | 99 | signal ( SIGINT, sig_handler ); |
99 | 100 | ||
100 | // save pid | 101 | // save pid |
101 | if (( fp = fopen ( PIDFILE, "w" ))) { | 102 | if (( fp = fopen ( PIDFILE, "w" ))) { |
@@ -122,135 +123,163 @@ int kill_with_pidfile ( void ) | |||
122 | FILE *fp; | 123 | FILE *fp; |
123 | pid_t pid; | 124 | pid_t pid; |
124 | 125 | ||
125 | if (( fp = fopen ( PIDFILE, "r" ))) { | 126 | if (( fp = fopen ( PIDFILE, "r" ))) { |
126 | if ( fscanf ( fp, "%d", &pid ) == 1 ) | 127 | if ( fscanf ( fp, "%d", &pid ) == 1 ) |
127 | return ( kill ( pid, SIGTERM ) == 0 ) ? 1 : 0; | 128 | return ( kill ( pid, SIGTERM ) == 0 ) ? 1 : 0; |
128 | fclose ( fp ); | 129 | fclose ( fp ); |
129 | } | 130 | } |
130 | return 0; | 131 | return 0; |
131 | } | 132 | } |
132 | 133 | ||
133 | void remove_pidfile ( void ) | 134 | void remove_pidfile ( void ) |
134 | { | 135 | { |
135 | unlink ( PIDFILE ); | 136 | unlink ( PIDFILE ); |
136 | 137 | ||
137 | signal ( SIGTERM, SIG_DFL ); | 138 | signal ( SIGTERM, SIG_DFL ); |
138 | signal ( SIGINT, SIG_DFL ); | 139 | signal ( SIGINT, SIG_DFL ); |
139 | } | 140 | } |
140 | 141 | ||
141 | 142 | ||
142 | int main ( int argc, char **argv ) | 143 | int main ( int argc, char **argv ) |
143 | { | 144 | { |
144 | int mode = 0; | 145 | int mode = 0; |
145 | int ac_resusp = 0; | 146 | int ac_resusp = 0; |
147 | int fix_rtc = 0; | ||
146 | int opt; | 148 | int opt; |
147 | 149 | ||
148 | while (( opt = getopt ( argc, argv, "a:rs" )) != EOF ) { | 150 | while (( opt = getopt ( argc, argv, "a:frs" )) != EOF ) { |
149 | switch ( opt ) { | 151 | switch ( opt ) { |
150 | case 's': | 152 | case 's': |
151 | mode = 's'; | 153 | mode = 's'; |
152 | break; | 154 | break; |
153 | case 'r': | 155 | case 'r': |
154 | mode = 'r'; | 156 | mode = 'r'; |
155 | break; | 157 | break; |
156 | case 'a': | 158 | case 'a': |
157 | ac_resusp = atoi ( optarg ); | 159 | ac_resusp = atoi ( optarg ); |
158 | if ( ac_resusp < 30 ) { | 160 | if ( ac_resusp < 30 ) { |
159 | ac_resusp = 120; | 161 | ac_resusp = 120; |
160 | 162 | ||
161 | fprintf ( stderr, "Warning: resuspend timeout must be >= 30 sec. -- now set to 120 sec\n" ); | 163 | fprintf ( stderr, "Warning: resuspend timeout must be >= 30 sec. -- now set to 120 sec\n" ); |
162 | } | 164 | } |
163 | break; | 165 | break; |
166 | case 'f': | ||
167 | fix_rtc = 1; | ||
168 | break; | ||
164 | default: | 169 | default: |
165 | usage ( ); | 170 | usage ( ); |
166 | } | 171 | } |
167 | } | 172 | } |
168 | 173 | ||
169 | if ( geteuid ( ) != 0 ) { | 174 | if ( geteuid ( ) != 0 ) { |
170 | fprintf ( stderr, "You need root priviledges to run opiealarm." ); | 175 | fprintf ( stderr, "You need root priviledges to run opiealarm." ); |
171 | return 2; | 176 | return 2; |
172 | } | 177 | } |
173 | 178 | ||
174 | if ( !mode ) | 179 | if ( !mode ) |
175 | usage ( ); | 180 | usage ( ); |
176 | 181 | ||
177 | // kill running opiealarm | 182 | // kill running opiealarm |
178 | opiealarm_was_running = kill_with_pidfile ( ); | 183 | opiealarm_was_running = kill_with_pidfile ( ); |
179 | remove_pidfile ( ); | 184 | remove_pidfile ( ); |
180 | 185 | ||
181 | switch ( mode ) { | 186 | switch ( mode ) { |
182 | case 'r': return resume ( ac_resusp ); | 187 | case 'r': return resume ( ac_resusp ); |
183 | case 's': | 188 | case 's': |
184 | default : return suspend ( ); | 189 | default : return suspend ( fix_rtc ); |
185 | } | 190 | } |
186 | return 0; | 191 | return 0; |
187 | } | 192 | } |
188 | 193 | ||
189 | 194 | ||
190 | int suspend ( void ) | 195 | int suspend ( int fix_rtc ) |
191 | { | 196 | { |
192 | FILE *fp; | 197 | FILE *fp; |
193 | char buf [64]; | 198 | char buf [64]; |
194 | time_t t; | 199 | time_t alrt, syst, rtct; |
195 | struct tm *tm; | 200 | struct tm alr, sys, rtc; |
196 | int fd; | 201 | int fd; |
197 | 202 | int rtc_sys_diff; | |
203 | |||
198 | 204 | ||
199 | if ( !fork_with_pidfile ( )) | 205 | if ( !fork_with_pidfile ( )) |
200 | return 3; | 206 | return 3; |
201 | 207 | ||
202 | log = fopen ( "/tmp/opiealarm.log", "w" ); | 208 | log = fopen ( "/tmp/opiealarm.log", "w" ); |
203 | log_msg ( "STARTING\n" ); | 209 | log_msg ( "STARTING\n" ); |
204 | 210 | ||
205 | 211 | ||
206 | 212 | ||
207 | if (!( fp = fopen ( "/etc/resumeat", "r" ))) | 213 | if (!( fp = fopen ( "/etc/resumeat", "r" ))) |
208 | error_msg_and_die ( 1, "/etc/resumeat" ); | 214 | error_msg_and_die ( 1, "/etc/resumeat" ); |
209 | 215 | ||
210 | if ( !fgets ( buf, sizeof( buf ) - 1, fp )) | 216 | if ( !fgets ( buf, sizeof( buf ) - 1, fp )) |
211 | error_msg_and_die ( 1, "/etc/resumeat" ); | 217 | error_msg_and_die ( 1, "/etc/resumeat" ); |
212 | 218 | ||
213 | fclose ( fp ); | 219 | fclose ( fp ); |
214 | 220 | ||
215 | t = atoi ( buf ); | 221 | alrt = atoi ( buf ); |
216 | 222 | ||
217 | if ( t == 0 ) | 223 | if ( alrt == 0 ) |
218 | error_msg_and_die ( 0, "/etc/resumeat contains an invalid time description" ); | 224 | error_msg_and_die ( 0, "/etc/resumeat contains an invalid time description" ); |
219 | 225 | ||
220 | /* subtract 5 sec from event time... */ | 226 | /* subtract 5 sec from event time... */ |
221 | t -= 5; | 227 | alrt -= 5; |
222 | 228 | ||
223 | if ( log ) | 229 | if ( log ) |
224 | fprintf ( log, "Setting RTC alarm to %d\n", t ); | 230 | fprintf ( log, "Setting RTC alarm to %d\n", alrt ); |
225 | 231 | ||
226 | tm = gmtime ( &t ); | 232 | alr = *gmtime ( &alrt ); |
227 | 233 | ||
234 | // get system time | ||
235 | time ( &syst ); | ||
236 | sys = *localtime ( &syst ); | ||
237 | |||
228 | // Write alarm time to RTC | 238 | // Write alarm time to RTC |
229 | if (( fd = open ( "/dev/misc/rtc", O_RDWR )) < 0 ) | 239 | if (( fd = open ( "/dev/misc/rtc", O_RDWR )) < 0 ) |
230 | error_msg_and_die ( 1, "/dev/misc/rtc" ); | 240 | error_msg_and_die ( 1, "/dev/misc/rtc" ); |
241 | |||
242 | // get RTC time | ||
243 | if ( ioctl ( fd, RTC_ALM_SET, &rtc ) < 0 ) | ||
244 | error_msg_and_die ( 1, "ioctl RTC_RD_TIME" ); | ||
245 | rtct = mktime ( &rtc ); | ||
246 | |||
247 | rtc_sys_diff = ( syst - rtct ) - sys. tm_gmtoff; | ||
248 | |||
249 | if ( fix_rtc && (( rtc_sys_diff < -4 ) || ( rtc_sys_diff > 4 ))) { | ||
250 | struct tm set; | ||
251 | |||
252 | set = *gmtime ( &syst ); | ||
253 | |||
254 | fprintf ( log, "Correcting RTC: %d seconds\n", rtc_sys_diff ); | ||
255 | |||
256 | if ( ioctl ( fd, RTC_SET_TIME, &set ) < 0 ) | ||
257 | error_msg_and_die ( 1, "ioctl RTC_SET_TIME" ); | ||
258 | } | ||
259 | |||
231 | // set alarm time | 260 | // set alarm time |
232 | if ( ioctl ( fd, RTC_ALM_SET, tm ) < 0 ) | 261 | if ( ioctl ( fd, RTC_ALM_SET, &alr ) < 0 ) |
233 | error_msg_and_die ( 1, "ioctl RTC_ALM_SET" ); | 262 | error_msg_and_die ( 1, "ioctl RTC_ALM_SET" ); |
234 | // enable alarm irq | 263 | // enable alarm irq |
235 | if ( ioctl ( fd, RTC_AIE_ON, 0 ) < 0 ) | 264 | if ( ioctl ( fd, RTC_AIE_ON, 0 ) < 0 ) |
236 | error_msg_and_die ( 1, "ioctl RTC_AIE_ON" ); | 265 | error_msg_and_die ( 1, "ioctl RTC_AIE_ON" ); |
237 | 266 | ||
238 | log_msg ( "SLEEPING\n" ); | 267 | log_msg ( "SLEEPING\n" ); |
239 | 268 | ||
240 | // wait for alarm irq | 269 | // wait for alarm irq |
241 | if ( read ( fd, buf, sizeof( unsigned long )) < 0 ) | 270 | if ( read ( fd, buf, sizeof( unsigned long )) < 0 ) |
242 | error_msg_and_die ( 1, "read rtc alarm" ); | 271 | error_msg_and_die ( 1, "read rtc alarm" ); |
243 | 272 | ||
244 | log_msg ( "WAKEUP\n" ); | 273 | log_msg ( "WAKEUP\n" ); |
245 | 274 | ||
246 | // disable alarm irq | 275 | // disable alarm irq |
247 | if ( ioctl ( fd, RTC_AIE_OFF, 0 ) < 0 ) | 276 | if ( ioctl ( fd, RTC_AIE_OFF, 0 ) < 0 ) |
248 | error_msg_and_die ( 1, "ioctl RTC_AIE_OFF" ); | 277 | error_msg_and_die ( 1, "ioctl RTC_AIE_OFF" ); |
249 | 278 | ||
250 | close ( fd ); | 279 | close ( fd ); |
251 | 280 | ||
252 | log_msg ( "EXITING\n" ); | 281 | log_msg ( "EXITING\n" ); |
253 | 282 | ||
254 | fclose ( log ); | 283 | fclose ( log ); |
255 | remove_pidfile ( ); | 284 | remove_pidfile ( ); |
256 | 285 | ||
diff --git a/root/etc/suspend-scripts/S46opiealarm b/root/etc/suspend-scripts/S46opiealarm index 9b936e4..a41dae5 100755 --- a/root/etc/suspend-scripts/S46opiealarm +++ b/root/etc/suspend-scripts/S46opiealarm | |||
@@ -1,5 +1,5 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | # Starts opiealarm, which only runs while the iPaq sleeps | 2 | # Starts opiealarm, which only runs while the iPaq sleeps |
3 | # and wakes it up when the RTC alarm goes off. | 3 | # and wakes it up when the RTC alarm goes off. |
4 | 4 | ||
5 | /opt/QtPalmtop/bin/opiealarm -s | 5 | /opt/QtPalmtop/bin/opiealarm -s -f |