summaryrefslogtreecommitdiff
path: root/core
authorsandman <sandman>2002-07-01 22:28:22 (UTC)
committer sandman <sandman>2002-07-01 22:28:22 (UTC)
commitb34df43c4d141b6845a6251e8f52f7daf3d1a867 (patch) (unidiff)
treed829feab33887adcf47ac56f6625ea2fb6414281 /core
parentcce43bef3e68b007f027f52328972b6b86af1098 (diff)
downloadopie-b34df43c4d141b6845a6251e8f52f7daf3d1a867.zip
opie-b34df43c4d141b6845a6251e8f52f7daf3d1a867.tar.gz
opie-b34df43c4d141b6845a6251e8f52f7daf3d1a867.tar.bz2
This is the release version with all debug stuff thrown out -- in return
I have heavily commented the code, so maybe someone else besides me culd get the hang of this programm.
Diffstat (limited to 'core') (more/less context) (show whitespace changes)
-rw-r--r--core/opiealarm/opiealarm.c202
1 files changed, 95 insertions, 107 deletions
diff --git a/core/opiealarm/opiealarm.c b/core/opiealarm/opiealarm.c
index d96ffaf..70e5415 100644
--- a/core/opiealarm/opiealarm.c
+++ b/core/opiealarm/opiealarm.c
@@ -1,10 +1,10 @@
1/* opiealarm.c 1/*
2 * opiealarm.c
3 *
2* This program is for extracting the event time/date out 4* This program is for extracting the event time/date out
3* of /etc/resumeat and setting the RTC alarm to that time/date. 5* of /etc/resumeat and setting the RTC alarm to that time/date.
4* It is designed to run via a script just before the iPaq 6 * It is designed to run via a script just before the iPAQ
5* is suspended. 7 * is suspended and right after the iPAQ resumes operation.
6*
7* Roughly based on ipaqalarm from Benjamin Long
8* 8*
9* written by Robert Griebl <sandman@handhelds.org> 9 * written and copyrighted by Robert Griebl <sandman@handhelds.org>
10*/ 10*/
@@ -30,4 +30,2 @@
30 30
31FILE *log; // debug only
32
33int resume ( int resuspend ); 31int resume ( int resuspend );
@@ -39,4 +37,4 @@ void remove_pidfile ( void );
39void usage ( void ); 37void usage ( void );
40void sig_handler ( int sig ); 38void sig_handler_child ( int sig );
41void error_msg_and_die ( int perr, const char *msg ); 39void sig_handler_parent ( int sig );
42int onac ( void ); 40int onac ( void );
@@ -44,34 +42,10 @@ int onac ( void );
44static int opiealarm_was_running; 42static int opiealarm_was_running;
43static pid_t parent_pid = 0;
45 44
46static pid_t startpid = 0;
47 45
48 46
49void log_msg ( const char *msg ) 47void sig_handler_child ( int sig )
50{
51 if ( log ) {
52 fprintf ( log, msg );
53 fflush ( log );
54 }
55}
56
57void error_msg_and_die ( int perr, const char *msg )
58{ 48{
59 if ( perr ) 49 // child got SIGUSR2 -> cleanup pidfile and exit
60 log_msg ( strerror ( errno ));
61 log_msg ( msg );
62
63 if ( getpid ( ) != startpid )
64 kill ( startpid, SIGUSR1 );
65
66 while ( 1 ) // pretend we are waiting on RTC, so opiealarm -r can kill us
67 sleep ( 1 );
68}
69
70 50
71void sig_handler ( int sig )
72{
73 if ( log ) {
74 log_msg ( "GOT SIGNAL -> EXITING\n" );
75 fclose ( log );
76 }
77 remove_pidfile ( ); 51 remove_pidfile ( );
@@ -82,2 +56,5 @@ void sig_handler_parent ( int sig )
82{ 56{
57 // parent got SIGUSR1 -> safe to exit now
58
59 parent_pid = 0;
83 exit ( 0 ); 60 exit ( 0 );
@@ -103,2 +80,7 @@ int fork_with_pidfile ( void )
103 if ( pid > 0 ) { 80 if ( pid > 0 ) {
81 // We can not just exit now, because the kernel could suspend
82 // the iPAQ just before the child process sets the RTC.
83 // Solution: just wait for SIGUSR1 - the child process will
84 // signal this when it thinks it is safe to exit.
85
104 signal ( SIGUSR1, sig_handler_parent ); 86 signal ( SIGUSR1, sig_handler_parent );
@@ -113,4 +95,6 @@ int fork_with_pidfile ( void )
113 95
114 signal ( SIGTERM, sig_handler ); 96 // child process needs to react to SIGUSR2. This is sent when
115 signal ( SIGINT, sig_handler ); 97 // a new opiealarm process is started.
98
99 signal ( SIGUSR2, sig_handler_child );
116 100
@@ -140,2 +124,6 @@ int kill_with_pidfile ( void )
140 pid_t pid; 124 pid_t pid;
125 int res = 0;
126
127 // terminate a running opiealarm child process
128 // return 1 if we really killed one
141 129
@@ -143,6 +131,6 @@ int kill_with_pidfile ( void )
143 if ( fscanf ( fp, "%d", &pid ) == 1 ) 131 if ( fscanf ( fp, "%d", &pid ) == 1 )
144 return ( kill ( pid, SIGTERM ) == 0 ) ? 1 : 0; 132 res = ( kill ( pid, SIGUSR2 ) == 0 ) ? 1 : 0;
145 fclose ( fp ); 133 fclose ( fp );
146 } 134 }
147 return 0; 135 return res;
148} 136}
@@ -151,6 +139,6 @@ void remove_pidfile ( void )
151{ 139{
152 unlink ( PIDFILE ); 140 // child is about to exit - cleanup
153 141
154 signal ( SIGTERM, SIG_DFL ); 142 unlink ( PIDFILE );
155 signal ( SIGINT, SIG_DFL ); 143 signal ( SIGUSR2, SIG_DFL );
156} 144}
@@ -197,4 +185,6 @@ int main ( int argc, char **argv )
197 185
186
187 parent_pid = getpid ( );
188
198 // kill running opiealarm 189 // kill running opiealarm
199 startpid = getpid ( );
200 opiealarm_was_running = kill_with_pidfile ( ); 190 opiealarm_was_running = kill_with_pidfile ( );
@@ -203,9 +193,12 @@ int main ( int argc, char **argv )
203 switch ( mode ) { 193 switch ( mode ) {
204 case 'r': return resume ( ac_resusp ); 194 case 'r': opt = resume ( ac_resusp );
195 break;
205 case 's': 196 case 's':
206 default : return suspend ( fix_rtc ); 197 default : opt = suspend ( fix_rtc );
207 } 198 break;
208 return 0;
209 } 199 }
210 200
201 parent_pid = 0;
202 return opt;
203 }
211 204
@@ -225,11 +218,14 @@ int suspend ( int fix_rtc )
225 218
226 log = fopen ( "/tmp/opiealarm.log", "w" ); 219 // we are the child process from here on ...
227 log_msg ( "STARTING\n" ); 220
221 tzset ( ); // not sure if it is really needed -- it probably doesn't hurt ...
228 222
223 do { // try/catch simulation
229 224
225 // read the wakeup time from /etc/resumeat
230 if (!( fp = fopen ( "/etc/resumeat", "r" ))) 226 if (!( fp = fopen ( "/etc/resumeat", "r" )))
231 error_msg_and_die ( 1, "/etc/resumeat" ); 227 break; // ( 1, "/etc/resumeat" );
232 228
233 if ( !fgets ( buf, sizeof( buf ) - 1, fp )) 229 if ( !fgets ( buf, sizeof( buf ) - 1, fp ))
234 error_msg_and_die ( 1, "/etc/resumeat" ); 230 break; // ( 1, "/etc/resumeat" );
235 231
@@ -237,71 +233,48 @@ int suspend ( int fix_rtc )
237 233
238 alrt = atoi ( buf ); 234 alrt = atoi ( buf ); // get the alarm time
239
240 if ( alrt == 0 ) 235 if ( alrt == 0 )
241 error_msg_and_die ( 0, "/etc/resumeat contains an invalid time description" ); 236 break; // ( 0, "/etc/resumeat contains an invalid time description" );
242
243 alrt -= 5; // wake up 5 sec before the specified time 237 alrt -= 5; // wake up 5 sec before the specified time
244
245
246 if ( log )
247 fprintf ( log, "Setting RTC alarm to %d\n", alrt );
248
249 tzset ( );
250
251 alr = *gmtime ( &alrt ); 238 alr = *gmtime ( &alrt );
252 239
253 // get system time 240 time ( &syst );// get the UNIX system time
254 time ( &syst );
255 sys = *localtime ( &syst ); 241 sys = *localtime ( &syst );
256 242
257 // Write alarm time to RTC 243 if (( fd = open ( "/dev/misc/rtc", O_RDWR )) < 0 ) // open the RTC device
258 if (( fd = open ( "/dev/misc/rtc", O_RDWR )) < 0 ) 244 break; // ( 1, "/dev/misc/rtc" );
259 error_msg_and_die ( 1, "/dev/misc/rtc" );
260 245
261 // get RTC time 246 memset ( &rtc, 0, sizeof ( struct tm )); // get the RTC time
262 memset ( &rtc, 0, sizeof ( struct tm ));
263 if ( ioctl ( fd, RTC_RD_TIME, &rtc ) < 0 ) 247 if ( ioctl ( fd, RTC_RD_TIME, &rtc ) < 0 )
264 error_msg_and_die ( 1, "ioctl RTC_RD_TIME" ); 248 break; // ( 1, "ioctl RTC_RD_TIME" );
265 rtct = mktime ( &rtc ); 249 rtct = mktime ( &rtc );
266 250
267 fprintf ( log, "System time: %02d.%02d.%04d %02d:%02d:%02d DST: %d (TZ: %s, offset: %d)\n", sys. tm_mday, sys. tm_mon + 1, sys. tm_year + 1900, sys. tm_hour, sys. tm_min, sys. tm_sec, sys. tm_isdst, sys. tm_zone, sys. tm_gmtoff ); 251 rtc_sys_diff = ( syst - rtct ) - sys. tm_gmtoff; // calculate the difference between system and hardware time
268 fprintf ( log, "RTC time: %02d.%02d.%04d %02d:%02d:%02d DST: %d (TZ: %s, offset: %d)\n", rtc. tm_mday, rtc. tm_mon + 1, rtc. tm_year + 1900, rtc. tm_hour, rtc. tm_min, rtc. tm_sec, rtc. tm_isdst, rtc. tm_zone, rtc. tm_gmtoff );
269 fprintf ( log, "Wakeup time: %02d.%02d.%04d %02d:%02d:%02d DST: %d (TZ: %s, offset: %d)\n", alr. tm_mday, alr. tm_mon + 1, alr. tm_year + 1900, alr. tm_hour, alr. tm_min, alr. tm_sec, alr. tm_isdst, alr. tm_zone, alr. tm_gmtoff );
270
271 fprintf ( log, "System/RTC diff: %d seconds\n", ( syst - rtct ) - sys. tm_gmtoff );
272 252
273 253 if ( fix_rtc && (( rtc_sys_diff < -3 ) || ( rtc_sys_diff > 3 ))) {
274 rtc_sys_diff = ( syst - rtct ) - sys. tm_gmtoff;
275
276 if ( fix_rtc && (( rtc_sys_diff < -4 ) || ( rtc_sys_diff > 4 ))) {
277 struct tm set; 254 struct tm set;
278
279 set = *gmtime ( &syst ); 255 set = *gmtime ( &syst );
280 256
281 fprintf ( log, "Correcting RTC: %d seconds\n", rtc_sys_diff ); 257 // if the difference between system and hardware time is more than 3 seconds,
258 // we have to set the RTC (hwclock --systohc), or alarms won't work reliably.
282 259
283 if ( ioctl ( fd, RTC_SET_TIME, &set ) < 0 ) 260 if ( ioctl ( fd, RTC_SET_TIME, &set ) < 0 )
284 error_msg_and_die ( 1, "ioctl RTC_SET_TIME" ); 261 break; // ( 1, "ioctl RTC_SET_TIME" );
285 } 262 }
286 263
287 // set alarm time 264 if ( ioctl ( fd, RTC_ALM_SET, &alr ) < 0 ) // set RTC alarm time
288 if ( ioctl ( fd, RTC_ALM_SET, &alr ) < 0 ) 265 break; // ( 1, "ioctl RTC_ALM_SET" );
289 error_msg_and_die ( 1, "ioctl RTC_ALM_SET" );
290 // enable alarm irq
291 if ( ioctl ( fd, RTC_AIE_ON, 0 ) < 0 ) 266 if ( ioctl ( fd, RTC_AIE_ON, 0 ) < 0 )
292 error_msg_and_die ( 1, "ioctl RTC_AIE_ON" ); 267 break; // ( 1, "ioctl RTC_AIE_ON" ); // enable RTC alarm irq
293 268
294 if ( log ) 269 // tell the parent it is safe to exit now .. we have set the RTC alarm
295 fprintf( log, "SIGUSR: pid %d - SLEEPING: pid %d\n", startpid, getpid ( )); 270 kill ( parent_pid, SIGUSR1 );
296 kill ( startpid, SIGUSR1 );
297 271
298 // wait for alarm irq 272 if ( read ( fd, buf, sizeof( unsigned long )) < 0 ) // wait for the RTC alarm irq
299 if ( read ( fd, buf, sizeof( unsigned long )) < 0 ) 273 break; // ( 1, "read rtc alarm" );
300 error_msg_and_die ( 1, "read rtc alarm" );
301 274
302 log_msg ( "WAKEUP\n" ); 275 // iPAQ woke up via RTC irq -- otherwise we would have received a SIGUSR2
276 // from the "resume instance" of opiealarm.
303 277
304 // disable alarm irq 278 if ( ioctl ( fd, RTC_AIE_OFF, 0 ) < 0 ) // disable RTC alarm irq
305 if ( ioctl ( fd, RTC_AIE_OFF, 0 ) < 0 ) 279 break; // ( 1, "ioctl RTC_AIE_OFF" );
306 error_msg_and_die ( 1, "ioctl RTC_AIE_OFF" );
307 280
@@ -309,7 +282,11 @@ int suspend ( int fix_rtc )
309 282
310 log_msg ( "EXITING\n" ); 283 remove_pidfile ( ); // normal exit
284 return 0;
311 285
312 fclose ( log ); 286 } while ( 0 );
313 remove_pidfile ( ); 287
288 kill ( parent_pid, SIGUSR1 ); // parent is still running - it can exit now
314 289
290 while ( 1 ) // pretend that we are waiting on RTC, so opiealarm -r can kill us
291 sleep ( 1000 ); // if we don't do this, the "resuspend on AC" would be triggerd
315 return 0; 292 return 0;
@@ -323,2 +300,4 @@ int onac ( void )
323 300
301 // check the apm proc interface for AC status
302
324 if (( fp = fopen ( APMFILE, "r" ))) { 303 if (( fp = fopen ( APMFILE, "r" ))) {
@@ -340,3 +319,6 @@ int resume ( int resuspend )
340 319
341 if ( !opiealarm_was_running ) { // opiealarm -s got it's RTC signal -> wake up by RTC 320 if ( !opiealarm_was_running ) {
321 // if opiealarm -s didn't wake up via RTC, the old process gets killed
322 // by kill_by_pidfile(), which is recorded in opiealarm_was_running
323
342 if ( resuspend && onac ( )) { 324 if ( resuspend && onac ( )) {
@@ -347,5 +329,9 @@ int resume ( int resuspend )
347 return 4; 329 return 4;
348 kill ( startpid, SIGUSR1 );
349 330
350 // sleep <resuspend> sec (not less!) 331 // we can't wait for the resuspend timeout in the parent process.
332 // so we fork and tell the parent it can exit immediatly
333
334 kill ( parent_pid, SIGUSR1 );
335
336 // sleep <resuspend> seconds - this method is much more precise than sleep() !
351 time ( &start ); 337 time ( &start );
@@ -356,4 +342,3 @@ int resume ( int resuspend )
356 342
357 if ( onac ( )) { // still on ac 343 if ( onac ( )) { // still on ac ?
358 // system() without fork
359 argv[0] = "qcop"; 344 argv[0] = "qcop";
@@ -364,2 +349,4 @@ int resume ( int resuspend )
364 // hard coded for now ...but needed 349 // hard coded for now ...but needed
350 // another way would be to simulate a power-button press
351
365 setenv ( "LOGNAME", "root", 1 ); 352 setenv ( "LOGNAME", "root", 1 );
@@ -371,2 +358,3 @@ int resume ( int resuspend )
371 358
359 // no need for system() since this process is no longer usefull anyway
372 execv ( "/opt/QtPalmtop/bin/qcop", argv ); 360 execv ( "/opt/QtPalmtop/bin/qcop", argv );