sysd/src/main.c

Go to the documentation of this file.
00001 /*
00002  * File Name: main.c
00003  */
00004 
00005 /*
00006  * This file is part of sysd.
00007  *
00008  * sysd is free software: you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation, either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * sysd is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00020  */
00021 
00022 /**
00023  * Copyright (C) 2008 iRex Technologies B.V.
00024  * All rights reserved.
00025  */
00026 
00027 //----------------------------------------------------------------------------
00028 // Include Files
00029 //----------------------------------------------------------------------------
00030 
00031 #include "config.h"
00032 
00033 // system include files, between < >
00034 #include <glib.h>
00035 #include <gtk/gtk.h>
00036 #include <signal.h>
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041 #include <sys/time.h>
00042 #ifndef _XOPEN_SOURCE 
00043 #define _XOPEN_SOURCE // glibc2 needs this
00044 #endif 
00045 #include <time.h>
00046 
00047 // ereader include files, between < >
00048 #include <liberipc/eripc.h>
00049 #include <liberutils/display_utils.h>
00050 
00051 // local include files, between " "
00052 #include "log.h"
00053 #include "busy.h"
00054 #include "conf.h"
00055 #include "display.h"
00056 #include "connections.h"
00057 #include "hal.h"
00058 #include "ipc.h"
00059 #include "process.h"
00060 #include "system.h"
00061 #include "tasks.h"
00062 #include "xwindow.h"
00063 
00064 
00065 //----------------------------------------------------------------------------
00066 // Type Declarations
00067 //----------------------------------------------------------------------------
00068 
00069 
00070 //----------------------------------------------------------------------------
00071 // Global Constants
00072 //----------------------------------------------------------------------------
00073 
00074 
00075 //----------------------------------------------------------------------------
00076 // Static Variables
00077 //----------------------------------------------------------------------------
00078 
00079 static gboolean do_detach = FALSE;
00080 
00081 
00082 //============================================================================
00083 // Local Function Definitions
00084 //============================================================================
00085 
00086 
00087 //============================================================================
00088 // Functions Implementation
00089 //============================================================================
00090 
00091 // print usage text and quit
00092 static void usage(const char *argv_0)
00093 {
00094     static const char *usage_text = 
00095                         "\n"
00096                         "usage: %s [options]\n"
00097                         "\n"
00098                         "options:\n"
00099                         "    --help\n"
00100                         "        Print help text and quit\n"
00101                         "    --detach\n"
00102                         "        Detach from console to run as daemon\n";
00103     printf(usage_text, argv_0);
00104 
00105     exit(1);
00106 }
00107 
00108 // get command-line options
00109 static void parse_arguments(int argc, char **argv)
00110 {
00111     int  i;
00112 
00113     // parse contentLister options
00114     for (i = 1 ; i < argc ; i++)
00115     {
00116         if (strcmp(argv[i], "--help") == 0)
00117         {
00118             usage(argv[0]);
00119         }
00120         if (strcmp(argv[i], "--detach") == 0)
00121         {
00122             do_detach = TRUE;
00123         }
00124     }
00125 }
00126 
00127 
00128 static void on_sigterm(int signo)
00129 {
00130     WARNPRINTF("    -- entry " PACKAGE_NAME ", my pid [%d]", getpid());
00131 
00132     // stop main process, prepare to quit application
00133     gtk_main_quit();
00134 
00135     WARNPRINTF("    -- leave " PACKAGE_NAME);
00136 }
00137 
00138 
00139 static long int read_timestamp (const char* path)
00140 {
00141     FILE* thefile = NULL; 
00142     size_t result;
00143     char tbuffer[20];
00144     char buf[20];
00145     const char* timeformat = "%m%d%H%M%Y" ; // current timestamp format
00146     struct tm mytime;
00147 
00148     long int ts = -1 ; // 0 = epoch 
00149 
00150     thefile = fopen(path, "r");
00151     if (NULL == thefile)
00152     {
00153         // only allow positive time, 0 = 1970-01-01 00:00
00154         goto error_fopen; 
00155     }
00156     bzero(tbuffer, sizeof(tbuffer));
00157     bzero(buf, sizeof(buf));
00158     bzero(&mytime, sizeof(struct tm));
00159     result = fread((void*) tbuffer,  sizeof(char), 20, thefile);
00160     if ( result > 0 && result <= sizeof(tbuffer) )
00161     {
00162         // transform to epoch time
00163         LOGPRINTF("Read timestamp from file: [%s]", tbuffer);
00164         
00165         // timestamp string to time struct
00166         strptime(tbuffer, timeformat, &mytime);
00167         
00168         // time is seconds since epoch
00169         result = strftime(buf, sizeof(buf), "%s", &mytime);  
00170         
00171         if ( result > 0 && result < sizeof(buf) )
00172         {
00173             LOGPRINTF("Old time stamp: [%s], New timestamp (secs since epoch) [%s]", tbuffer, buf);
00174         }
00175 
00176         // buf now holds a time stamp, compare to
00177         // translate to int
00178         ts = strtol(buf, NULL, 10);
00179         goto exit;
00180     }
00181     else 
00182     {
00183         goto error;
00184     }
00185         
00186 error: 
00187     ts = -1;
00188 exit:
00189     if (NULL != thefile)
00190     {
00191         fclose(thefile);
00192     }
00193     return ts;
00194 
00195 error_fopen:
00196     return -1;
00197 }
00198 
00199 
00200 static gboolean check_set_datetime(void)
00201 {
00202     gboolean need_set = FALSE; 
00203     struct timeval tod; 
00204     long int ts = 0;
00205 
00206     ts = read_timestamp("/etc/timestamp");  
00207 
00208     // now get the current time
00209     gettimeofday(&tod, NULL); 
00210     LOGPRINTF("timeofday = %ld", tod.tv_sec);
00211 
00212     if (ts < tod.tv_sec) 
00213     {
00214         LOGPRINTF("timestamp < timeofday"); 
00215         // do nothing
00216     }
00217     else  
00218     {
00219         need_set = TRUE;
00220     }
00221 
00222     return need_set;
00223 }
00224 
00225 
00226 static void on_phase_3_complete(void)
00227 {
00228     LOGPRINTF("entry");
00229 
00230     // all apps started, stop busy and allow display updates again
00231     busy_remove_foreground(0);
00232     display_return_control();
00233     
00234     sys_starting_finished();
00235 }
00236 
00237 
00238 static void start_phase_3(void)
00239 {
00240     LOGPRINTF("entry");
00241 
00242     // detect hardware, mount volumes
00243     hal_add_devices();
00244      
00245     process_add("/usr/bin/ctb", NULL, G_CALLBACK(on_phase_3_complete), NULL, PS_WAIT_STARTED | PS_RESPAWN);
00246 }
00247 
00248 
00249 static void on_phase_2_complete(void)
00250 {
00251     LOGPRINTF("entry");
00252 
00253     busy_add_foreground(0, BUSY_DIALOG_NONE, NULL);
00254     display_gain_control();
00255     sys_request_popup("localunblock");
00256     
00257     sys_set_device_state(STATE_DEVICE_STARTED);
00258     
00259     start_phase_3();
00260 }
00261 
00262 
00263 static void start_phase_2(void)
00264 {
00265     LOGPRINTF("entry");
00266 
00267     // complex solution to make sure the menu is blocked before the 
00268     // first app starts and unblocked after the last app exists
00269     gboolean run_firstboot = FALSE;
00270     gboolean run_gtktscal  = FALSE;
00271     gboolean run_datetime  = FALSE;
00272     
00273     if (conf_get_first_boot())
00274     {
00275         if (conf_is_multi_language())
00276         {
00277             run_firstboot = TRUE;
00278         }
00279         
00280         if (sys_has_stylus() && !sys_is_emulator())
00281         {
00282             run_gtktscal = TRUE;
00283         }
00284     }
00285 
00286     if (check_set_datetime())
00287     {
00288         run_datetime = TRUE;
00289     }
00290 
00291     if (run_firstboot || run_gtktscal || run_datetime)
00292     {
00293         sys_request_popup("localblock");
00294         busy_remove_foreground(0);
00295         display_return_control();
00296 
00297         if (run_firstboot)
00298         {
00299             process_add("/usr/bin/settings --firstboot", NULL, NULL, run_gtktscal || run_datetime ? NULL : G_CALLBACK(on_phase_2_complete), PS_WAIT_EXIT);
00300         }
00301         
00302         if (run_gtktscal)
00303         {
00304             process_add("/usr/bin/gtktscal -firstboot", NULL, NULL, run_datetime ? NULL : G_CALLBACK(on_phase_2_complete), PS_WAIT_EXIT);
00305         }
00306         
00307         if (run_datetime)
00308         {
00309             // set busy to make sure the system does not suspend
00310             busy_add_background(0);
00311             sys_spawn_sync("date `cat /etc/timestamp` && /sbin/hwclock --systohc --utc");
00312             busy_remove_background(0);
00313             
00314             // show time/date settings dialog
00315             process_add("/usr/bin/settings --fdatetime", NULL, NULL, G_CALLBACK(on_phase_2_complete), PS_WAIT_EXIT);
00316         }
00317     }
00318     else
00319     {
00320         start_phase_3();
00321     }
00322 }
00323 
00324 
00325 static void on_phase_1_complete(void)
00326 {
00327     LOGPRINTF("entry");
00328 
00329 #if MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW    
00330     conf_disabled_sensor_lock();
00331 #endif
00332     conn_update_statusbar();
00333     
00334     if (!sys_is_emulator())
00335     {
00336         ipc_send_volume_mounted(MOUNTPOINT_CARD);
00337     }
00338 
00339     start_phase_2();
00340 }
00341 
00342 
00343 int main(int argc, char *argv[])
00344 {
00345     struct sigaction on_term;
00346     
00347     // parse command-line arguments
00348     parse_arguments(argc, argv);
00349 
00350     // catch the SIGTERM signal
00351     memset(&on_term, 0x00, sizeof(on_term));
00352     on_term.sa_handler = on_sigterm;
00353     sigaction(SIGTERM, &on_term, NULL);
00354 
00355     if (do_detach)
00356     {
00357         if (daemon(0, 0) !=0)
00358         {
00359             LOGPRINTF("Daemonize error: %s", strerror(errno));
00360             exit (1);
00361         }
00362     }
00363 
00364     // init gdk (for windowing)
00365     g_type_init();
00366     gtk_init(&argc, &argv);
00367     
00368     // prepare IPC, system (micro) and display
00369     ipc_set_services();
00370     window_set_services(); 
00371     sys_set_services();     /* relies on ipc */
00372     display_set_services(); /* relies on system/micro and window*/
00373     busy_add_foreground(0, BUSY_DIALOG_NONE, NULL);
00374     
00375     // prepare GConf
00376     conf_set_services();
00377 
00378     // prepare HAL and mountpoints
00379     hal_set_services();
00380     display_gain_control();
00381 
00382     // spawn applications 
00383     process_add("/usr/bin/popupmenu", NULL, NULL, NULL, PS_WAIT_STARTED | PS_RESPAWN);
00384     process_add("/usr/bin/uds",       NULL, G_CALLBACK(on_phase_1_complete), NULL, PS_WAIT_STARTED | PS_RESPAWN);
00385     
00386     // run the main loop
00387     LOGPRINTF("before gtk_main");
00388     gtk_main();
00389     LOGPRINTF("after gtk_main");
00390 
00391     return 0;
00392 }
Generated by  doxygen 1.6.2-20100208