0.9.21 release -- It changes so that the layer controlling function of GENIVI may...
[profile/ivi/ico-uxf-homescreen.git] / lib / system-controller / CicoSCUserManager.cpp
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 /*========================================================================*/
11 /**
12  *  @file   CicoSCUserManager.cpp
13  *
14  *  @brief  This file implementation of CicoSCUserManager class
15  */
16 /*========================================================================*/
17
18 #include <sys/stat.h>
19 #include <dirent.h>
20
21 #include <fstream>
22 #include <boost/property_tree/ptree.hpp>
23 #include <boost/property_tree/xml_parser.hpp>
24 #include <boost/foreach.hpp>
25 #include <cstdio>
26 using namespace boost;
27 using namespace boost::property_tree;
28
29 #include "ico_syc_error.h"
30 #include "ico_syc_msg_cmd_def.h"
31 #include "ico_syc_public.h"
32
33 #include "CicoLog.h"
34
35 #include "CicoSCCommand.h"
36 #include "CicoSCLastInfo.h"
37 #include "CicoAulItems.h"
38 #include "CicoSCLifeCycleController.h"
39 #include "CicoSCMessage.h"
40 #include "CicoSCServer.h"
41 #include "CicoSCUserManager.h"
42 #include "CicoSCUser.h"
43 #include "CicoConf.h"
44 #include "CicoSystemConfig.h"
45 #include "Cico_aul_listen_app.h"
46
47 using namespace std;
48
49 //==========================================================================
50 //
51 //  definition
52 //
53 //==========================================================================
54 #define ICO_SYC_DEFAULT_PATH    "/home/app/ico"
55 #define ICO_SYC_APP_INFO        "runningApp.info"
56 #define ICO_SYC_APP_INFO_DEF    "defaultApps.info"
57 #define ICO_SYC_LASTINFO_DIR    (char*)"/lastinfo/"
58 #define ICO_SYC_LASTUSER_FILE   (char*)"/home/app/ico/lastuser.txt"
59 #define ICO_SYC_CHGUSR_FLAG_DIR "/tmp/ico"
60 #define ICO_SYC_CHGUSR_FLAG_FIL "changeUser.flag"
61
62 void chkAndAddSlash(string& s);
63
64 /**
65  * @brief applications die. callback function
66  * @param pid
67  * @param data user data
68  * @return int
69  * @retval -1: parameter error
70  * @retval 0: handler execute
71  */
72 static int CSCUMapp_dead_handler(int pid, void *data)
73 {
74     CicoSCUserManager* x = (CicoSCUserManager*)data;
75     if ((NULL == x) || (0 == x)) {
76         return -1;
77     }
78     x->appDeadHandler(pid);
79     return 0;
80 }
81
82 //==========================================================================
83 //
84 //  private static variable
85 //
86 //==========================================================================
87 CicoSCUserManager* CicoSCUserManager::ms_myInstance = NULL;
88
89 //--------------------------------------------------------------------------
90 /**
91  *  @brief  default constructor
92  */
93 //--------------------------------------------------------------------------
94 CicoSCUserManager::CicoSCUserManager()
95     : m_login("")
96 {
97     ICO_TRA("start");
98     aul_listen_app_dead_signal_add(CSCUMapp_dead_handler, (void*)this);
99     m_vppa.clear();
100     m_waitName.clear();
101     m_waitHS.clear();
102     m_wait = false;
103     // login-user application information file
104     m_uConfig = CicoSystemConfig::getInstance()->getUserConf();
105     if ((NULL == m_uConfig) || (true == m_uConfig->m_parent_dir.empty())) {
106         m_parentDir = ICO_SYC_DEFAULT_PATH;
107     }
108     else {
109         m_parentDir = m_uConfig->m_parent_dir;
110     }
111     chkAndAddSlash(m_parentDir);
112
113     // flag file
114     m_flagPath = ICO_SYC_CHGUSR_FLAG_DIR;
115     struct stat st;
116     int ret = stat(m_flagPath.c_str(), &st);
117     if (0 != ret) {
118         mkdir(m_flagPath.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
119     }
120     chkAndAddSlash(m_flagPath);
121     m_flagPath += ICO_SYC_CHGUSR_FLAG_FIL;
122     ICO_TRA("end");
123
124     CicoSCUserManager::ms_myInstance = this;
125 }
126
127 //--------------------------------------------------------------------------
128 /**
129  *  @brief  destructor
130  */
131 //--------------------------------------------------------------------------
132 CicoSCUserManager::~CicoSCUserManager()
133 {
134     ICO_TRA("CicoSCUserManager::~CicoSCUserManager Enter");
135
136     // clear homescreen list
137     m_homescreenList.clear();
138
139     // clear userlist
140     vector<CicoSCUser*>::iterator itr;
141     itr = m_userList.begin();
142     for (; itr != m_userList.end(); ++itr) {
143         CicoSCUser *user = const_cast<CicoSCUser*>(*itr);
144         // clear list of last information
145         vector<CicoSCLastInfo*>::iterator info_itr;
146         info_itr = user->lastInfoList.begin();
147         for (; info_itr != user->lastInfoList.end(); ++info_itr) {
148             // free memory
149             delete *info_itr;
150         }
151         // free memory
152         delete *itr;
153     }
154     m_userList.clear();
155     m_vppa.clear();
156
157     CicoSCUserManager::ms_myInstance = NULL;
158
159     ICO_TRA("CicoSCUserManager::~CicoSCUserManager Leave");
160 }
161
162 //--------------------------------------------------------------------------
163 /**
164  *  @brief  Get instance of CicoSCUserManager
165  *
166  *  @return  pointer of CicoSCUserManager object
167  */
168 //--------------------------------------------------------------------------
169 CicoSCUserManager*
170 CicoSCUserManager::getInstance(void)
171 {
172     if (NULL == ms_myInstance) {
173         ms_myInstance = new CicoSCUserManager();
174     }
175     return ms_myInstance;
176 }
177
178 //--------------------------------------------------------------------------
179 /**
180  *  @brief  Handle command
181  *
182  *  @param  [in] cmd            control command
183  *  @return none
184  */
185 //--------------------------------------------------------------------------
186 void
187 CicoSCUserManager::handleCommand(const CicoSCCommand * cmd)
188 {
189     ICO_TRA("CicoSCUserManager::handleCommand Enter(%d)", cmd->cmdid);
190
191     CicoSCCmdUserMgrOpt *opt = static_cast<CicoSCCmdUserMgrOpt*>(cmd->opt);
192
193     switch (cmd->cmdid) {
194     case MSG_CMD_CHANGE_USER:
195         // change user
196         changeUser(opt->user, opt->pass);
197         break;
198     case MSG_CMD_GET_USERLIST:
199         // get userlist
200         userlistCB(cmd->appid);
201         break;
202     case MSG_CMD_GET_LASTINFO:
203         // get last information
204         lastinfoCB(cmd->appid);
205         break;
206     case MSG_CMD_SET_LASTINFO:
207         // set application's last information
208         setLastInfo(cmd->appid, opt->lastinfo);
209         break;
210     default:
211         ICO_WRN("Unknown Command(0x%08X)", cmd->cmdid);
212         break;
213     }
214
215     ICO_TRA("CicoSCUserManager::handleCommand Leave");
216 }
217
218 //--------------------------------------------------------------------------
219 /**
220  *  @brief  Load configuration file
221  *
222  *  @param  [in] confFile       configuration file path
223  *  @return 0 on success, other on error
224  */
225 //--------------------------------------------------------------------------
226 int
227 CicoSCUserManager::load(const string & confFile)
228 {
229     ICO_TRA("CicoSCUserManager::load Enter (%s)", confFile.c_str());
230
231     ptree root;
232     // read config file (xml)
233     read_xml(confFile, root);
234
235     // create lists
236     createUserList(root);
237     createHomeScreenList(root);
238     // set login user name
239     setLoginUser(root);
240
241     ICO_TRA("CicoSCUserManager::load Leave(EOK)");
242
243     // always success
244     return ICO_SYC_EOK;
245 }
246
247 //--------------------------------------------------------------------------
248 /**
249  *  @brief  Initialize CicoSCUserManager
250  *          This API must call after load() API
251  *
252  *  @return 0 on success, other on error
253  */
254 //--------------------------------------------------------------------------
255 int
256 CicoSCUserManager::initialize(void)
257 {
258     ICO_TRA("CicoSCUserManager::initialize Enter");
259
260     // get login user information
261     const CicoSCUser *user = findUserConfbyName(m_login);
262     if (NULL == user) {
263         ICO_ERR("user not found");
264         ICO_TRA("CicoSCUserManager::initialize Leave(ENXIO)");
265         return ICO_SYC_ENXIO;
266     }
267
268     // launch homescreen
269     if (true == user->autolaunch) {
270         launchHomescreenReq(user->name, user->homescreen);
271     }
272     else {
273         ICO_DBG("launch homescreen skip");
274     }
275
276     // load last information
277     loadLastInfo();
278
279     // make root directory
280     string root_dir = m_uConfig->m_parent_dir;
281     struct stat st;
282     int ret = stat(root_dir.c_str(), &st);
283     if (0 != ret) {
284         mkdir(root_dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
285     }
286     // make user's directory
287     string user_dir = m_parentDir + m_login;
288     chkAndAddSlash(user_dir);
289     ret = stat(user_dir.c_str(), &st);
290     if (0 != ret) {
291         mkdir(user_dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
292     }
293
294     // save last user
295     saveLastUser();
296
297     ICO_TRA("CicoSCUserManager::initialize Leave(EOK)");
298
299     return ICO_SYC_EOK;
300 }
301
302 //--------------------------------------------------------------------------
303 /**
304  *  @brief  Get login user information
305  *
306  *  @return pointer of CicoSCUser
307  */
308 //--------------------------------------------------------------------------
309 const CicoSCUser*
310 CicoSCUserManager::getLoginUser(void)
311 {
312     return findUserConfbyName(m_login);
313 }
314
315 //--------------------------------------------------------------------------
316 /**
317  *  @brief  Get userlist
318  *
319  *  @return pointer of userlist
320  */
321 //--------------------------------------------------------------------------
322 const vector<CicoSCUser*>&
323 CicoSCUserManager::getUserList(void)
324 {
325     return m_userList;
326 }
327
328 //--------------------------------------------------------------------------
329 /**
330  *  @brief  Get homescreen list
331  *
332  *  @return pointer of homescreen list
333  */
334 //--------------------------------------------------------------------------
335 const vector<string>&
336 CicoSCUserManager::getHomeScreenList(void)
337 {
338     return m_homescreenList;
339 }
340
341 //--------------------------------------------------------------------------
342 /**
343  *  @brief  Change login user
344  *
345  *  @param  [in] name           user name
346  *  @param  [in] passwd         password
347  *  @return none
348  */
349 //--------------------------------------------------------------------------
350 void
351 CicoSCUserManager::changeUser(const string & name, const string & passwd)
352 {
353     ICO_TRA("CicoSCUserManager::changeUser Enter"
354             "(user=%s pass=%s)", name.c_str(), passwd.c_str());
355
356     char tmpText[128];
357     sprintf(tmpText, "CHG USER[%s]->[%s]", m_login.c_str(), name.c_str());
358
359     string oldUsr = m_login; /* get before login user */
360     const CicoSCUser *conf = NULL;
361     // check all user logoff
362     if ((name.empty()) || (name[0] == ' ')) {
363         ICO_TRA("CicoSCUserManager::changeUser Leave(all user logoff)");
364         flagFileOn();
365         killingAppsAndHS(oldUsr);
366         return;
367     }
368
369     // if changed user name is same last user name
370     if (0 == name.compare(m_login)) {
371         ICO_TRA("CicoSCUserManager::changeUser Leave(request is same user)");
372         return;
373     }
374
375     // get user config
376     conf = findUserConfbyName(name);
377     if (NULL == conf) {
378         ICO_TRA("CicoSCUserManager::changeUser Leave(ENXIO)");
379         return;
380     }
381
382     // check password
383     if (passwd != conf->passwd) {
384         ICO_TRA("CicoSCUserManager::changeUser Leave(EINVAL)");
385         return;
386     }
387
388     flagFileOn();
389
390 #if 0
391     // Imprinting to file, that file is application's running information
392     string usr_dir_old;
393     getWorkingDir(oldUsr, usr_dir_old);
394     string outfilename = usr_dir_old + ICO_SYC_APP_INFO;
395     impritingLastApps(outfilename);
396 #endif
397
398     // killing running application and homeScreen
399     killingAppsAndHS(oldUsr);
400     CicoSCLifeCycleController* csclcc = CicoSCLifeCycleController::getInstance();
401     csclcc->startAppResource(name);
402
403     // check wheather directory exists
404     vector<string> mk_dir_info;
405     mk_dir_info.push_back(m_uConfig->m_parent_dir);
406     string usr_dir;
407     getWorkingDir(conf->name, usr_dir);
408     mk_dir_info.push_back(usr_dir);
409     vector<string>::iterator it = mk_dir_info.begin();
410     for (; it != mk_dir_info.end(); it++) {
411         const char* dir = (*it).c_str();
412         struct stat st;
413         if (0 == stat(dir, &st)) {
414             continue; // continue of for
415         }
416         mkdir(dir, S_IRWXU | S_IRWXG | S_IRWXO);
417     }
418     csclcc->createAppResourceFile(name);
419
420     if (0 != m_vppa.size()) {
421         // wait dead signal recieve
422         m_waitName = conf->name;
423         m_waitHS = conf->homescreen;
424         m_wait = true;
425         // run call launchHomescreenReq is appDeadHandler !
426         ICO_TRA("CicoSCUserManager::changeUser Leave(WAIT:%s)", m_waitName.c_str());
427         return;
428     }
429     // change homescreen application
430     sleep(2);                   // wait 2 sec for dead all applications
431     launchHomescreenReq(conf->name, conf->homescreen);
432     // change login user
433     m_login = conf->name;
434     saveLastUser();
435     ICO_DBG("login user changed (user=%s)", m_login.c_str());
436     ICO_INF("%s", tmpText);
437     flagFileOff();
438     m_waitName.clear();
439     m_waitHS.clear();
440     m_wait = false;
441     ICO_TRA("CicoSCUserManager::changeUser Leave(EOK)");
442 }
443
444 //--------------------------------------------------------------------------
445 /**
446  *  @brief  imprinting to file, that file is application's running information
447  *  @param  usrnam target user name
448  *  @return bool
449  *  @retval true success
450  *  @retval false fail
451  */
452 //--------------------------------------------------------------------------
453 bool CicoSCUserManager::impritingLastApps(const string& ofnm)
454 {
455     ICO_TRA("CicoSCUserManager::impritingLastApps Enter");
456     vector<string> vs;
457     CicoSCLifeCycleController* oCSCLCC;
458     oCSCLCC = CicoSCLifeCycleController::getInstance();
459     if ((NULL == oCSCLCC) || (0 == oCSCLCC)) {
460         ICO_ERR(" CicoSCLifeCycleController is null");
461         ICO_TRA("CicoSCUserManager::impritingLastApps Leave(false)");
462         return false;
463     }
464     const vector<CicoAulItems>& aulList = oCSCLCC->getAulList();
465     for (int i=aulList.size() ; i != 1; i--) {
466         const CicoAulItems* pO = aulList[i-1].p();
467         if ((NULL == pO) || (0 == pO)) {
468             continue;
469         }
470         if (pO->m_appid == "org.tizen.ico.login") {
471             continue;
472         }
473         if (pO->m_appid == "org.tizen.ico.statusbar") {
474             continue;
475         }
476         if (pO->m_appid == "org.tizen.ico.homescreen") {
477             continue;
478         }
479         vs.push_back(pO->m_appid);
480     }
481
482     if (0 == vs.size()) {
483         remove(ofnm.c_str());
484         ICO_TRA("CicoSCUserManager::impritingLastApps Leave(app none)");
485         return true;
486     }
487     ofstream ofs;
488     ofs.open(ofnm.c_str(), ios::trunc);
489     vector<string>::iterator it = vs.begin();
490     for (; it != vs.end(); it++) {
491         ofs << *it << endl;
492     }
493     ofs.close();
494     ICO_TRA("CicoSCUserManager::impritingLastApps app = %d", vs.size());
495     return false;
496 }
497
498 //--------------------------------------------------------------------------
499 /**
500  *  @brief  killing running applications and homeScreen
501  *  @param  usrnam target user name
502  *  @return bool
503  *  @retval true success
504  *  @retval false fail
505  */
506 //--------------------------------------------------------------------------
507 bool CicoSCUserManager::killingAppsAndHS(const string&)
508 {
509     ICO_TRA("CicoSCUserManager::killingAppsAndHS Enter");
510
511     m_vppa.clear();
512     CicoSCLifeCycleController* oCSCLCC;
513     oCSCLCC = CicoSCLifeCycleController::getInstance();
514     if ((NULL == oCSCLCC) || (0 == oCSCLCC)) {
515         ICO_TRA("CicoSCUserManager::killingAppsAndHS Leave(ENXIO)");
516         return false;
517     }
518     bool r = false;
519     const vector<CicoAulItems>& aulList = oCSCLCC->getAulList();
520     vector<int> pids;
521     for (int i=aulList.size() ; i != 0; i--) {
522         const CicoAulItems* pObj = aulList[i-1].p();
523         if ((NULL == pObj) || (0 == pObj)) {
524             continue;
525         }
526         ICO_DBG("CicoSCUserManager::killingAppsAndHS Tgt:%d(%s)", pObj->m_pid,
527                 pObj->m_appid.c_str());
528         pids.push_back(pObj->m_pid);
529         m_vppa.push_back(pairPidAppid(pObj->m_pid, pObj->m_appid));
530         r = true;
531     }
532     int sz = pids.size();
533     for (int j=0; j < sz; j++) {
534         oCSCLCC->terminate(pids[j]);
535     }
536     ICO_TRA("CicoSCUserManager::killingAppsAndHS Leave(ret=%s)",
537             r? "true": "false");
538     return r;
539 }
540
541 //--------------------------------------------------------------------------
542 /**
543  *  @brief  homescreen launch request
544  *  @param  usrnam target user name
545  *  @return bool
546  *  @retval true success
547  *  @retval false fail
548  */
549 //--------------------------------------------------------------------------
550 void CicoSCUserManager::getWorkingDir(const string& usr, string& dir)
551 {
552     dir = m_parentDir;
553     dir += usr;
554     chkAndAddSlash(dir);
555     return;
556 }
557 //--------------------------------------------------------------------------
558 /**
559  *  @brief  homescreen launch request
560  *  @param  usrnam target user name
561  *  @return bool
562  *  @retval true success
563  *  @retval false fail
564  */
565 //--------------------------------------------------------------------------
566 bool CicoSCUserManager::launchHomescreenReq(const string& usr,
567                                             const string& appid_hs)
568 {
569     string usr_dir;
570     getWorkingDir(usr, usr_dir);
571     // set login-user history file path
572     string a_prmfn = usr_dir + ICO_SYC_APP_INFO;
573     // set default history file path
574     string d_prmfn = m_parentDir + string(ICO_SYC_APP_INFO_DEF);
575
576     bundle *b;
577     b = bundle_create();
578     // bundle add login-user name
579     bundle_add(b, ICO_SYC_APP_BUNDLE_KEY1, usr.c_str());
580     // bundle add login-user history file path
581     bundle_add(b, ICO_SYC_APP_BUNDLE_KEY2, a_prmfn.c_str());
582     // bundle add default history file path
583     bundle_add(b, ICO_SYC_APP_BUNDLE_KEY3, d_prmfn.c_str());
584     // bundle add flag file path
585     bundle_add(b, ICO_SYC_APP_BUNDLE_KEY4, m_flagPath.c_str());
586
587     ICO_DBG("launch homescreen (user=%s, appid=%s, parm=%s, %s)",
588             usr.c_str(), appid_hs.c_str(), a_prmfn.c_str(), d_prmfn.c_str());
589
590     CicoSCLifeCycleController* oCSCLCC;
591     oCSCLCC = CicoSCLifeCycleController::getInstance();
592     int r = oCSCLCC->launch(appid_hs.c_str(), b);
593
594     bundle_free(b);
595
596     if (ICO_SYC_EOK != r) {
597         ICO_DBG("CicoSCUserManager::launchHomescreenReq false(%d)", r);
598         return false;
599     }
600     ICO_DBG("CicoSCUserManager::launchHomescreenReq true(ICO_SYC_EOK)");
601     return true;
602 }
603
604 //--------------------------------------------------------------------------
605 /**
606  *  @brief  dump log m_userList member variables
607  *
608  *  @return none
609  */
610 //--------------------------------------------------------------------------
611 void
612 CicoSCUserManager::dumpUserList(void)
613 {
614     vector<CicoSCUser*>::iterator itr;
615     itr = m_userList.begin();
616     for (; itr != m_userList.end(); ++itr) {
617         const CicoSCUser* conf = const_cast<CicoSCUser*>(*itr);
618         ICO_DBG("user name=%s, pass=%s, homescreen=%s",
619                 (conf->name).c_str(), (conf->passwd).c_str(),
620                 (conf->homescreen).c_str());
621     }
622 }
623
624 //--------------------------------------------------------------------------
625 /**
626  *  @brief  dump log m_homescreenList member variables
627  *
628  *  @return none
629  */
630 //--------------------------------------------------------------------------
631 void
632 CicoSCUserManager::dumpHomeScreenList(void)
633 {
634     vector<string>::iterator itr;
635     itr = m_homescreenList.begin();
636     for (; itr != m_homescreenList.end(); ++itr) {
637         ICO_DBG("homescreen=%s", (*itr).c_str());
638     }
639 }
640
641 //--------------------------------------------------------------------------
642 /**
643  *  @brief  Callback of "get userlist"
644  *
645  *  @param  [in] appid          application id to send message
646  *
647  *  @return none
648  */
649 //--------------------------------------------------------------------------
650 void
651 CicoSCUserManager::userlistCB(const string & appid)
652 {
653     ICO_TRA("CicoSCUserManager::userlistCB Enter (%s)", appid.c_str());
654
655     // send message
656     CicoSCMessage *message = new CicoSCMessage();
657     message->addRootObject("command", MSG_CMD_GET_USERLIST);
658     message->addRootObject("appid", appid);
659     // set number of user
660     message->addArgObject("user_num", m_userList.size());
661     // set user list
662     vector<CicoSCUser*>::iterator itr;
663     itr = m_userList.begin();
664     for (; itr != m_userList.end(); ++itr) {
665         const CicoSCUser* conf = const_cast<CicoSCUser*>(*itr);
666         message->addElmArray(conf->name);
667     }
668     message->addArgObject("user_list");
669
670     // set login user name
671     message->addArgObject("user_login", m_login);
672
673     CicoSCServer::getInstance()->sendMessage(appid, message);
674
675     ICO_TRA("CicoSCUserManager::userlistCB Leave");
676 }
677
678 //--------------------------------------------------------------------------
679 /**
680  *  @brief  Callback of "get application's last information"
681  *
682  *  @param  [in] appid          application id to send message
683  *
684  *  @return none
685  */
686 //--------------------------------------------------------------------------
687 void
688 CicoSCUserManager::lastinfoCB(const string & appid)
689 {
690     ICO_TRA("CicoSCUserManager::lastinfoCB Enter(%s)", appid.c_str());
691
692     // send message
693     CicoSCMessage *message = new CicoSCMessage();
694     message->addRootObject("command", MSG_CMD_GET_LASTINFO);
695     message->addRootObject("appid", appid);
696
697     CicoSCUser* user = const_cast<CicoSCUser*>(findUserConfbyName(m_login));
698     // search application's last information
699     vector<CicoSCLastInfo*>::iterator itr;
700     itr = user->lastInfoList.begin();
701     for (; itr != user->lastInfoList.end(); ++itr) {
702         const CicoSCLastInfo *info = const_cast<CicoSCLastInfo*>(*itr);
703         if (appid == info->appid) {
704             // set last information
705             message->addArgObject("lastinfo", info->lastinfo);
706             break;
707         }
708     }
709
710     CicoSCServer::getInstance()->sendMessage(appid, message);
711
712     ICO_TRA("CicoSCUserManager::lastinfoCB Leave");
713 }
714
715 //--------------------------------------------------------------------------
716 /**
717  *  @brief  Save last user name to last user file
718  *
719  *  @return none
720  */
721 //--------------------------------------------------------------------------
722 void
723 CicoSCUserManager::saveLastUser(void)
724 {
725     ICO_TRA("CicoSCUserManager::saveLastUser Enter(name=%s)", m_login.c_str());
726
727     // output last user name to file
728     std::ofstream stream;
729     string file = ICO_SYC_LASTUSER_FILE;
730     stream.open(file.c_str());
731     stream << m_login << std::endl;
732     stream.close();
733
734     ICO_TRA("CicoSCUserManager::saveLastUser Leave");
735 }
736
737 //--------------------------------------------------------------------------
738 /**
739  *  @brief  Load last user name from last user file
740  *
741  *  @return none
742  */
743 //--------------------------------------------------------------------------
744 void
745 CicoSCUserManager::loadLastUser(void)
746 {
747     ICO_TRA("CicoSCUserManager::loadLastUser Enter");
748
749     // check weather file exists
750     struct stat st;
751     int ret = stat(ICO_SYC_LASTUSER_FILE, &st);
752     if (0 != ret) {
753         // last user file does not exist
754         ICO_TRA("CicoSCUserManager::loadLastUser Leave");
755         return;
756     }
757
758     // load last user name
759     std::ifstream stream;
760     stream.open(ICO_SYC_LASTUSER_FILE);
761     stream >> m_login;
762     stream.close();
763
764     // check login name is valid
765     if (false == m_login.empty()) {
766         bool bValid = false;
767         vector<CicoSCUser*>::iterator it = m_userList.begin();
768         while (it != m_userList.end()) {
769             if (0 == (*it)->name.compare(m_login)) {
770                 bValid = true;
771                 break;
772             }
773             ++it;
774         }
775         if (false == bValid) {
776             ICO_WRN("last user NG!, user name \"%s\" clear", m_login.c_str());
777             m_login.clear();
778         }
779     }
780
781     ICO_TRA("CicoSCUserManager::loadLastUser Leave");
782 }
783
784 //--------------------------------------------------------------------------
785 /**
786  *  @brief  Load application's last information
787  *
788  *  @return none
789  */
790 //--------------------------------------------------------------------------
791 void
792 CicoSCUserManager::loadLastInfo()
793 {
794     ICO_TRA("CicoSCUserManager::loadLastInfo Enter(name=%s)", m_login.c_str());
795
796     if (m_login.empty()) {
797         ICO_ERR("m_login is empty");
798         ICO_TRA("CicoSCUserManager::loadLastInfo Leave(m_login is empty)");
799         return;
800     }
801
802     // get login user object
803     CicoSCUser* loginUser = NULL;
804     loginUser = const_cast<CicoSCUser*>(findUserConfbyName(m_login));
805     // check login user
806     if (NULL == loginUser) {
807         // login user does not exist in the user list
808         ICO_ERR("login user not found");
809         ICO_TRA("CicoSCUserManager::setLastInfo Leave(login user not found)");
810         return;
811     }
812
813     // check weather file exists
814     struct stat st;
815     string dir = m_parentDir + m_login + ICO_SYC_LASTINFO_DIR;
816     int ret = stat(dir.c_str(), &st);
817     if (0 != ret) {
818         // lastinfo directory does not exist
819         ICO_ERR("lastinfo directory dose not exist)");
820         ICO_TRA("CicoSCUserManager::loadLastInfo Leave(dir dose not exist)");
821         return;
822     }
823
824     // get file list
825     struct dirent **filelist;
826     int filenum = scandir(dir.c_str(), &filelist, NULL, NULL);
827     for (int i = 0; i < filenum; ++i) {
828         string filename = filelist[i]->d_name;
829         string::size_type index = filename.find(".txt");
830         if (string::npos != index) {
831             // load last information from file
832             string infofile = dir + filename;
833             string info;
834             std::ifstream stream;
835             stream.open(infofile.c_str());
836             std::getline(stream, info);
837             stream.close();
838
839             // get appid (erase ".txt" from filename)
840             filename.erase(index, filename.size());
841             // create new object
842             CicoSCLastInfo* lastInfo = new CicoSCLastInfo;
843             // set application's information
844             lastInfo->appid = filename;
845             lastInfo->lastinfo = info;
846             // add to list
847             loginUser->lastInfoList.push_back(lastInfo);
848         }
849         free(filelist[i]);
850     }
851     free(filelist);
852
853     ICO_TRA("CicoSCUserManager::loadLastInfo Leave");
854 }
855
856 //--------------------------------------------------------------------------
857 /**
858  *  @brief  Set login user information
859  *
860  *  @param  [in] root           pointer of ptree object
861  *  @return none
862  */
863 //--------------------------------------------------------------------------
864 void
865 CicoSCUserManager::setLoginUser(const ptree & root)
866 {
867     ICO_TRA("CicoSCUserManager::setLoginUser Enter");
868
869     // load last user name
870     loadLastUser();
871
872     if (m_login.empty()) {
873         // get user name from config file
874         ptree default_user = root.get_child("userconfig.default");
875
876         int check_flag = 0;
877         BOOST_FOREACH (const ptree::value_type& child, default_user) {
878             if (0 != strcmp(child.first.data(), "user")) {
879                 ICO_ERR("unknown element (%s)", child.first.data());
880             }
881
882             optional<string> name;
883             name = child.second.get_optional<string>("name");
884             if (false == name.is_initialized()) {
885                 ICO_ERR("user.name element not found");
886                 continue;
887             }
888             m_login = name.get();
889             check_flag++;
890         }
891
892         // default user name does not exist in the m_userList
893         if (check_flag == 0) {
894             vector<CicoSCUser*>::iterator itr;
895             itr = m_userList.begin();
896             const CicoSCUser* conf = const_cast<CicoSCUser*>(*itr);
897             m_login = conf->name;
898         }
899     }
900
901     // dump data
902     ICO_DBG("login user name: %s", m_login.c_str());
903
904     ICO_TRA("CicoSCUserManager::setLoginUser Leave");
905 }
906
907 //--------------------------------------------------------------------------
908 /**
909  *  @brief  Create userlist
910  *
911  *  @param  [in] root           pointer of ptree object
912  *  @return none
913  */
914 //--------------------------------------------------------------------------
915 void
916 CicoSCUserManager::createUserList(const ptree & root)
917 {
918     ICO_TRA("CicoSCUserManager::createUserList Enter");
919
920     ptree homescreens = root.get_child("userconfig.users");
921
922     BOOST_FOREACH (const ptree::value_type& child, homescreens) {
923         if (0 != strcmp(child.first.data(), "user")) {
924             ICO_ERR("unknown element (%s)", child.first.data());
925         }
926
927         // get value
928         optional<string> name;
929         optional<string> passwd;
930         optional<string> homescreen;
931         optional<string> autolaunch;
932
933         name = child.second.get_optional<string>("name");
934         if (false == name.is_initialized()) {
935             ICO_ERR("user.name element not found");
936             continue;
937         }
938         passwd = child.second.get_optional<string>("passwd");
939         if (false == passwd.is_initialized()) {
940             ICO_ERR("user.passwd element not found");
941             continue;
942         }
943         autolaunch = child.second.get_optional<string>("hs.<xmlattr>.autolaunch");
944         if (false == autolaunch.is_initialized()) {
945             autolaunch = optional<string>("true");
946         }
947         homescreen = child.second.get_optional<string>("hs");
948         if (false == homescreen.is_initialized()) {
949             ICO_ERR("user.hs element not found");
950             continue;
951         }
952
953         CicoSCUser* userConf = new CicoSCUser;
954         userConf->name       = name.get();
955         userConf->passwd     = passwd.get();
956         userConf->homescreen = homescreen.get();
957         userConf->autolaunch = (autolaunch.get().compare("false") == 0) ? false : true;
958         // dump data
959         userConf->dump();
960
961         // add object to the list
962         m_userList.push_back(userConf);
963     }
964
965     ICO_TRA("CicoSCUserManager::createUserList Leave");
966 }
967
968 //--------------------------------------------------------------------------
969 /**
970  *  @brief  Create homescreen list
971  *
972  *  @param  [in] root           pointer of ptree object
973  *  @return none
974  */
975 //--------------------------------------------------------------------------
976 void
977 CicoSCUserManager::createHomeScreenList(const ptree & root)
978 {
979     ICO_TRA("CicoSCUserManager::createHomeScreenList Enter");
980
981     ptree homescreens = root.get_child("userconfig.homescreens");
982
983     BOOST_FOREACH (const ptree::value_type& child, homescreens) {
984         if (0 != strcmp(child.first.data(), "homescreen")) {
985             ICO_ERR("unknown element (%s)", child.first.data());
986         }
987         // get value
988         optional<string> name;
989         name = child.second.get_optional<string>("<xmlattr>.name");
990         if (false == name.is_initialized()) {
991             ICO_ERR("homescreen.name attr not found");
992             continue;
993         }
994         // add value to the list
995         m_homescreenList.push_back(name.get());
996     }
997     // dump data
998     dumpHomeScreenList();
999
1000     ICO_TRA("CicoSCUserManager::createHomeScreenList Leave");
1001 }
1002
1003 //--------------------------------------------------------------------------
1004 /**
1005  *  @brief  Set last user information
1006  *
1007  *  @param  [in] appid          application id
1008  *  @param  [in] info           application's last information
1009  *  @return none
1010  */
1011 //--------------------------------------------------------------------------
1012 void
1013 CicoSCUserManager::setLastInfo(const string & appid, const string & info)
1014 {
1015     ICO_TRA("CicoSCUserManager::setLastInfo Enter(appid: %s, info: %s)",
1016             appid.c_str(), info.c_str());
1017
1018     CicoSCUser* loginUser = NULL;
1019     CicoSCLastInfo* lastInfo = NULL;
1020
1021     // get login user object
1022     loginUser = const_cast<CicoSCUser*>(findUserConfbyName(m_login));
1023     // check login user
1024     if (NULL == loginUser) {
1025         // login user does not exist in the user list
1026         ICO_ERR("login user does not exist in the user list");
1027         ICO_TRA("CicoSCUserManager::setLastInfo Leave");
1028         return;
1029     }
1030
1031     // check whether lastinfo object exists
1032     vector<CicoSCLastInfo*>::iterator info_itr;
1033     info_itr = loginUser->lastInfoList.begin();
1034     for (; info_itr != loginUser->lastInfoList.end(); ++info_itr) {
1035         CicoSCLastInfo *linfo = const_cast<CicoSCLastInfo*>(*info_itr);
1036         if (appid == linfo->appid) {
1037             lastInfo = linfo;
1038             break;
1039         }
1040     }
1041
1042     if (NULL == lastInfo) {
1043         // create new object
1044         lastInfo = new CicoSCLastInfo;
1045         // set application's information
1046         lastInfo->appid = appid;
1047         lastInfo->lastinfo = info;
1048         // add to list
1049         loginUser->lastInfoList.push_back(lastInfo);
1050     }
1051     else {
1052         // update application's last information
1053         lastInfo->lastinfo = info;
1054     }
1055
1056     // check wheather directory exists
1057     string info_dir =  m_parentDir + m_login + ICO_SYC_LASTINFO_DIR;
1058     struct stat st;
1059     int ret = stat(info_dir.c_str(), &st);
1060     if (0 != ret) {
1061         // make directory
1062         mkdir(info_dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
1063     }
1064
1065     // output application's last information to file
1066     std::ofstream stream;
1067     string file = info_dir + lastInfo->appid + ".txt";
1068     stream.open(file.c_str());
1069     stream << lastInfo->lastinfo << std::endl;
1070     stream.close();
1071
1072     // dump data
1073     ICO_DBG("login user=%s", (loginUser->name).c_str());
1074     lastInfo->dumpLastInfo();
1075
1076     ICO_TRA("CicoSCUserManager::setLastInfo Leave(EOK)");
1077 }
1078
1079 //--------------------------------------------------------------------------
1080 /**
1081  *  @brief  Find user configuration by user name
1082  *
1083  *  @param  [in] name           user name
1084  *  @return pointer of CicoSCUser data on success, NULL on error
1085  */
1086 //--------------------------------------------------------------------------
1087 const CicoSCUser*
1088 CicoSCUserManager::findUserConfbyName(const string & name)
1089 {
1090 //    ICO_TRA("CicoSCUserManager::findUserConfbyName Enter (%s)", name.c_str());
1091
1092     vector<CicoSCUser*>::iterator itr;
1093     itr = m_userList.begin();
1094     for (; itr != m_userList.end(); ++itr) {
1095         const CicoSCUser* conf = const_cast<CicoSCUser*>(*itr);
1096         if (name == conf->name) {
1097 //            ICO_TRA("CicoSCUserManager::findUserConfbyName Leave(%s)",
1098 //                    conf->name);
1099             return conf;
1100         }
1101     }
1102
1103 //    ICO_TRA("CicoSCUserManager::findUserConfbyName Leave(NULL)");
1104     return NULL;
1105 }
1106
1107 /**
1108  * @brief flag file on(create)
1109  */
1110 void CicoSCUserManager::flagFileOn(const char* text)
1111 {
1112     if (true == m_flagPath.empty()) {
1113         ICO_DBG("FLAG(FILE) empty");
1114         return;
1115     }
1116     const char* f = m_flagPath.c_str();
1117     ofstream oFlagFile;
1118     oFlagFile.open(f, ios::trunc);
1119     if ((NULL != text) && (0 != text) && (0 != strlen(text))) {
1120         oFlagFile << text << endl;
1121     }
1122     oFlagFile.close();
1123     ICO_DBG("FILE(%s) create(FLAG ON)", f);
1124 }
1125
1126 /**
1127  * @brief flag file off(remove)
1128  */
1129 void CicoSCUserManager::flagFileOff()
1130 {
1131     if (true == m_flagPath.empty()) {
1132         ICO_DBG("FLAG(FILE) empty");
1133         return;
1134     }
1135     const char* f = m_flagPath.c_str();
1136     struct stat st;
1137     int r = stat(f, &st);
1138     if (0 != r) {
1139         ICO_DBG("FILE(%s) is Nothing", f);
1140         return;
1141     }
1142     remove(f);
1143     ICO_DBG("FILE(%s) FLAG off(remove)", f);
1144     return;
1145 }
1146
1147 /**
1148  * @brief app dead Handler
1149  * @param pid dead pid
1150  * @return bool
1151  * @retval true pid is target
1152  * @retval false pid is no target
1153  */
1154 bool CicoSCUserManager::appDeadHandler(int pid)
1155 {
1156     ICO_TRA("start (%d)", pid);
1157     if (false == m_wait) {
1158         ICO_TRA("end");
1159         return false;
1160     }
1161     ICO_DBG("dead app(%d)", pid);
1162     bool bBINGO = false;
1163     string appid;
1164     vector<pairPidAppid>::iterator it = m_vppa.begin(); // iterator set begin
1165     while(it != m_vppa.end()) {  // loop to the last data
1166         if ((*it).first == pid) {
1167             appid = (*it).second;
1168             m_vppa.erase(it);
1169             bBINGO = true;
1170             break;  // break of while it
1171         }
1172         ++it;   // next data
1173     }
1174     if (false == bBINGO) {
1175         ICO_TRA("end FAIL pid(%d)", pid);
1176         return false;
1177     }
1178 #if 1
1179     int sz = m_vppa.size();
1180     if (0 != sz) {
1181         ICO_TRA("end contenue wait(%d)", sz);
1182         return true;
1183     }
1184 #else
1185     if (0 != appid.compare(m_waitHS)) {
1186         ICO_TRA("end contenue wait(%s)", appid.c_str());
1187         return true;
1188     }
1189 #endif
1190     char tmpText[128];
1191     sprintf(tmpText, "CHG USER[%s]->[%s]", m_login.c_str(), m_waitName.c_str());
1192
1193     // change homescreen application
1194     sleep(2);                   // wait 2 sec for dead all applications
1195     launchHomescreenReq(m_waitName, m_waitHS);
1196     // change login user
1197     m_login = m_waitName;
1198     saveLastUser();
1199     ICO_DBG("login user changed (user=%s)", m_login.c_str());
1200     ICO_INF("%s", tmpText);
1201     flagFileOff();
1202     m_waitName.clear();
1203     m_waitHS.clear();
1204     m_wait = false;
1205     ICO_TRA("end homescreen start req.(%s)", appid.c_str());
1206     return true;
1207 }
1208 // vim:set expandtab ts=4 sw=4: