Re-organized sub-directory by category
[staging/basesystem.git] / service / system / interface_unified / library / src / ss_system_process.cpp
1 /*
2  * @copyright Copyright (c) 2016-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 ///////////////////////////////////////////////////////////////////////////////
18 /// \ingroup  tag_SystemManagerIf
19 /// \brief    This file provides support for the System Manager client interface.
20 ///
21 ///////////////////////////////////////////////////////////////////////////////
22
23 #include "system_service/ss_system_process.h"
24 #include <errno.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <pwd.h>
29 #include <grp.h>
30 #include <elfio/elfio_dump.hpp>
31
32 #include <string.h>
33 #include <signal.h>
34 #include <sys/wait.h>
35 #include <assert.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include <libgen.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <vector>
42 #include "ss_system_if_interfaceunifiedlog.h"
43
44 const char* iProcess_DEFAULT_PROCESS_USER_NAME = "default_user";
45 uid_t iProcess_DEFAULT_PROCESS_USER = 4999;
46 gid_t iPrpocess_DEFAULT_PROCESS_GROUP = 4999;
47
48 /**
49  * Process: Called when the class is instantiated.
50  *
51  * @return 
52  */
53 Process::Process(int cpu_assign) :
54   m_lValidationTag(lProcess_VALIDATION_VALUE),
55   m_cpu_assign(cpu_assign),
56   m_tProcessId(-1),
57   m_eProcessLoadMode(NOWAIT),
58   m_strFile(""),
59   m_strProcessName(""),
60   m_iErrorCode(0),
61   m_fAutoKill(TRUE),
62   m_iReturnCode(0) {
63 }
64
65
66 /**
67  * ~Process: Called when the object is destroyed.
68  *
69  * @return 
70  */
71 Process::~Process() {
72   // ASSERT_VALID (this);
73
74   //
75   // Set the validation tag to NOT valid
76   m_lValidationTag = 0;
77
78   //
79   // Cleanup after ourselves...
80   //
81   if ((m_fAutoKill) && (m_tProcessId != -1) && (m_tProcessId != getpid())) {
82     KillProcess();        // Then remove the process from PosixBasedOS001
83   }
84 }
85
86 /**
87  * Process: Used to create an object and copy another
88  * object to the new object.
89  *
90  * @param p_rhs_i Reference to the class being copied from. 
91  * @return Process( const
92  */
93 Process::Process(const Process& p_rhs_i) {
94   // Copy data from the specified object to this object.
95   Copy(p_rhs_i);
96 }
97
98
99 /**
100  * operator=: Called when one object is assigned 
101  * to another object.
102  *
103  * @param p_rhs_i Reference to the class being copied from. 
104  * @return Process&
105  */
106 Process& Process::operator= (const Process& p_rhs_i) {
107   // Don't do anything if we're being copied on to ourselves.
108   if (this == &p_rhs_i) return (*this);
109
110   // Copy data from the specified object to this object.
111   Copy(p_rhs_i);
112
113   return (*this);
114 }
115
116
117 /**
118  * Copy: Copies data members from the specified object to this object.
119  * No attempt is made to free dynamically allocated objects within
120  * this object (you must do that before calling this function).
121  *
122  * @param p_rhs_i 
123  * @return void
124  */
125 void Process::Copy(const Process& p_rhs_i) {
126   // Copy data from the specified object to this object.
127   m_lValidationTag = p_rhs_i.m_lValidationTag;
128
129   m_tProcessId = p_rhs_i.m_tProcessId;
130   m_eProcessLoadMode = p_rhs_i.m_eProcessLoadMode;
131   m_strFile = p_rhs_i.m_strFile;
132   m_strlstArgv = p_rhs_i.m_strlstArgv;
133   m_strProcessName = p_rhs_i.m_strProcessName;
134   m_iErrorCode = p_rhs_i.m_iErrorCode;
135   m_fAutoKill = p_rhs_i.m_fAutoKill;
136   m_iReturnCode = p_rhs_i.m_iReturnCode;
137 }
138
139 /**
140  * GetProcessReturnCode: This function will return the processes
141  * exit/return code. This is not the value of ERRNO as returned by 
142  * GetLastPosixBasedOS001ErrorCode().
143  *
144  * @return code from the process
145  */
146 int Process::GetProcessReturnCode() {
147   int iProcessReturn = 0;
148   if (waitpid(m_tProcessId, &iProcessReturn, WNOHANG) > 0) {
149     m_iReturnCode = WEXITSTATUS(iProcessReturn);
150   }
151
152   return m_iReturnCode;
153 }
154
155 static int getIdsFromUserName(const char* user_name, uid_t *uid, gid_t *gid) {
156   int ret = -1;
157
158   try {
159     if (NULL == user_name) {
160       *uid = geteuid();
161       *gid = getegid();
162     } else {
163       static __thread size_t  bufSize = 0;
164       static __thread char   *buf = NULL;
165       struct passwd  pwd;
166       struct passwd *result;
167
168       if (0 == bufSize) {
169         struct stat statInfo;
170
171         bufSize = -1;
172
173         if (0 != stat("/etc/passwd", &statInfo) || 0 >= statInfo.st_size) {
174           throw "/etc/passwd is not exist";
175         }
176
177         bufSize = statInfo.st_size * 2;
178
179         // Since SystemManager is a resident service,
180         // the area secured here is not explicity released by free()
181         // in anticipation of release at the end of the process
182         buf = reinterpret_cast<char *>(malloc(sizeof(char) * bufSize));
183         if (NULL == buf) {
184           throw "malloc()";
185         }
186       }
187
188       if (NULL == buf) {
189         throw "buf = NULL";
190       }
191
192       ret = getpwnam_r(user_name, &pwd, buf, bufSize, &result);
193       if (ret == 0 && result != NULL) {
194         *uid = pwd.pw_uid;
195         *gid = pwd.pw_gid;
196       } else {
197         throw "getpwnam_r()";
198       }
199     }
200
201     ret = 0;
202   }
203
204   catch (const char *e) {
205     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "ERROR:%s", e);
206   }
207
208   return ret;
209 }
210
211 /**
212  * CreateProcess: This method will create a PosixBasedOS001 process with the executable provided and mode as a calling parameter. 
213  * The caller can also provide a list of arguments that will be provided to the executable at startup. 
214  * The calling p_strProcessName parameter is a textual name that will be
215  * associated with the newly created process by the OS. The process state information 
216  * will be maintained by this object.
217  *
218  * Upon successful creation of the process, the scheduling policy and priority
219  * of the process will be set to the provided values. The user can change these
220  * values through the SetSchedulingPolicy() and SetPriority() method calls.
221  *
222  * @param p_strFile_i Path and Filename of executable to create process for
223  * @param p_strlstArgv_i List of ARGV values for new process
224  * @param p_eMode_i Mode to create and load new process
225  *          WAIT     -  The invoked program is loaded into available memory, is executed,
226  *                      and then the original program resumes execution.
227  *          NOWAIT   -  Causes the current program to execute concurrently with the new child process.
228  * @param p_strProcessName_i This is the name that will be registered to the OS for this process
229  * @param p_eSchedulingPolicy_i Scheduling Policy for this process
230  *          FIFO          - A fixed priority scheduler in which the highest ready process runs until it
231  *                          blocks or is preempted by a higher priority process.
232  *          ROUND_ROBIN   - The same as FIFO, except processes at the same priority level time-slice.
233  *          OTHER         - A general time sharing scheduler in which a process decays in priority if it
234  *                          consumes too much processor before blocking. It reverts to its default priority
235  *                          when it blocks. Should it fail to run over a 2 second period and it has decayed
236  *                          then it's boosted one priority level up to a maximum of its default priority.
237  * @param p_iPriority_i Priority for this process
238  * @param p_lSpawnFlags_i Spawning flags. These are PosixBasedOS001 specific....
239  * @return void
240  */
241 void Process::CreateProcess(
242             const SS_String& p_strFile_i,      // Path and Filename of executable to create process for
243             const StringList& p_strlstArgv_i,    // List of ARGV values for new process
244             const eProcessLoadMode p_eMode_i,    // Mode to create and load new process
245             const SS_String& p_strProcessName_i,  // This is the name that will be registered to the OS for this process
246             const eProcessSchedulingPolicy p_eSchedulingPolicy_i,  // Scheduling Policy for this process
247             const int p_iPriority_i,        // Priority for this process
248                       const char* unix_user_name,
249             const long p_lSpawnFlags_i        // Posix Spawning flags. These are PosixBasedOS001 specific....  // NOLINT (runtime/int)
250 ) {
251   //========================================================================================
252   // Perform some idiot checking of the parameters that are passed in.
253   // Check the priority level that is being set to make sure it is in bounds.
254   // Then save off the calling parameters into the objects member variables.
255   // Also check the number of valid calling (argv[]) parameters passed in
256   //========================================================================================
257   m_iErrorCode = 0;   // Initialize to NO ERROR
258   m_iReturnCode = 0;  // Initialize value (0 usually means good in unix/PosixBasedOS001)
259
260   //
261   // Process filename os provided
262   //
263   if (p_strFile_i.empty()) {
264     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
265   }
266
267   //
268   // Save off process calling arguments
269   //
270   m_eProcessLoadMode = p_eMode_i;
271
272   m_strFile = p_strFile_i;
273
274   if (!p_strProcessName_i.empty())
275     m_strProcessName = p_strProcessName_i;
276
277   //
278   // Copy Argument List...
279   //
280   SetCallingArgumentList(p_strlstArgv_i);
281
282   //
283   // Valid number of calling arguments
284   //
285   int iNumberElements = m_strlstArgv.size();
286   if (iNumberElements > (iProcess_MAXIMUM_NUMBER_OF_PROCESS_ARGUMENTS - 3)) {
287     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
288   }
289
290
291   //========================================================================================
292   // Initialize to the beginning of the provided argument list.
293   // Allocate an array of buffer pointers that will be used for the ARGV calling parameters
294   // for the specified process.
295   // Set the ARGV[0] equal to the process name being created
296   // Set the ARGV[1] equal to the process name to be registered with the OS.
297   // If p_strProcessName_is NULL, do not set the cArgv[1] parameter
298   // Populate the array that will hold the argument list for the new process we are creating.
299   //========================================================================================
300   //
301
302   int iLoop = 1;
303   char * cArgv[iProcess_MAXIMUM_NUMBER_OF_PROCESS_ARGUMENTS];
304
305   cArgv[0] = basename(const_cast<char *>(p_strFile_i.c_str()));    // Set the executable filename
306
307   // Go through the list of provided argv calling parameters to the CreateProcess
308   // function, and copy the arguments to the ARGV[] calling argument which will be passed
309   // into the process being created.
310   StringListIter at = m_strlstArgv.begin();
311   for (; at !=  m_strlstArgv.end(); at++, iLoop++) {
312     cArgv[iLoop] = const_cast<char *>(at->c_str());
313   }
314
315   cArgv[iLoop] = NULL;
316
317   try {
318     CL_ProcessAttr_t        clAttr;
319     CL_ProcessSchedPolicy_t clPolicy = CL_PROCESS_SCHED_POLICY_OTHER;
320     int                     clPriority = 0;
321
322     if (0 != CL_ProcessCreateAttrInit(&clAttr)) {
323       throw "CL_ProcessCreateAttrInit()";
324     }
325
326
327     // In order to collect even the child processes of the service, all are group leaders.
328     if (0 != CL_ProcessCreateAttrSetGroup(&clAttr, 1)) {
329       throw "CL_ProcessCreateAttrInit()";
330     }
331
332     if (0 != CL_ProcessCreateAttrSetCpuAssign(&clAttr, m_cpu_assign)) {
333       throw "CL_ProcessCreateAttrSetCpuAssign()";
334     }
335
336     switch (p_eSchedulingPolicy_i) {
337       case FIFO:
338         clPolicy =  CL_PROCESS_SCHED_POLICY_FIFO;
339         break;
340       case ROUND_ROBIN:
341         clPolicy =  CL_PROCESS_SCHED_POLICY_RR;
342         break;
343       case OTHER:
344         clPolicy =  CL_PROCESS_SCHED_POLICY_OTHER;
345         break;
346       default:
347         FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "p_eSchedulingPolicy_i = %d", p_eSchedulingPolicy_i);
348         break;
349     }
350
351     switch (p_eSchedulingPolicy_i) {
352       case FIFO:
353       case ROUND_ROBIN:
354         if ((1 > p_iPriority_i) || (p_iPriority_i > 99)) {
355           FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "p_eSchedulingPolicy_i = %d", p_eSchedulingPolicy_i);
356         } else {
357           clPriority = p_iPriority_i;
358         }
359         break;
360       case OTHER:
361       default:
362         if ((-20 > p_iPriority_i) || (p_iPriority_i > 19)) {
363           FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "p_eSchedulingPolicy_i = %d", p_eSchedulingPolicy_i);
364         } else {
365           clPriority = p_iPriority_i;
366         }
367         break;
368     }
369
370     if (0 != CL_ProcessCreateAttrSetSchedule(&clAttr, clPolicy, clPriority)) {
371       throw "CL_ProcessCreateAttrSetSchedule()";
372     }
373
374     uid_t uid = 0;
375     gid_t gid = 0;
376
377     if (0 != getIdsFromUserName(unix_user_name, &uid, &gid)) {
378       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "unexpected unix_user_name [%s]", unix_user_name);
379       uid = geteuid();
380       gid = getegid();
381     }
382     if (uid == 0) {
383       FRAMEWORKUNIFIEDLOG(ZONE_ERR, __FUNCTION__, "!! uid=root %s", m_strFile.c_str());
384       uid = UINT_MAX;
385     }
386     if (0 != CL_ProcessCreateAttrSetUid(&clAttr, uid)) {
387       throw "CL_ProcessCreateAttrSetUid()";
388     }
389
390     if (0 != CL_ProcessCreateAttrSetGid(&clAttr, gid)) {
391       throw "CL_ProcessCreateAttrSetGid()";
392     }
393
394     if (0 != CL_ProcessCreateAttrSetDisableCloseFds(&clAttr)) {
395       throw "CL_ProcessCreateAttrSetDisableCloseFds()";
396     }
397     char environment_string[2048] = {0};  // Size is provisional
398     fprintf(stderr, "[%s](%d)Process Create Target : %s \n", __func__, __LINE__, m_strFile.c_str());
399
400     CheckLdPreLoad(&m_strFile, environment_string);
401
402     CreateProcess(&m_strFile, const_cast<char* const*>(cArgv), environment_string, &clAttr);
403   }
404
405   catch(const char *e) {
406     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "%s", e);
407   }
408 }
409
410 /**
411  * CreateProcess: This method will create a process with the executable provided and mode as a calling parameter.
412  * The caller can also provide a list of arguments that will be provided to the executable at startup.
413  * The calling p_strProcessName parameter is a textual name that will be
414  * associated with the newly created process by the OS. The process state information
415  * will be maintained by this object.
416  *
417  * @param p_str_file Path and Filename of executable to create process for
418  * @param c_argv use process arguments
419  * @param environment_string Set LD_PRELOAD string
420  * @param cl_attr CL_ProcessAttr_t
421  * @return void
422  */
423 void Process::CreateProcess(const SS_String *p_str_file, char* const*c_argv, char* environment_string,
424                             const CL_ProcessAttr_t *cl_attr) {
425   try {
426     if ((p_str_file == NULL) || (c_argv == NULL) || (cl_attr == NULL)) {
427       throw "CreateProcess() Invaild Param";
428     }
429
430     int process_id = -1;
431     if (environment_string[0] == '\0') {
432       // If there is no LD_PRELOAD setting, set envp to NULL
433       process_id = CL_ProcessCreate(p_str_file->c_str(), c_argv, NULL, cl_attr);
434     } else {
435       // vector holding preferences
436       std::vector<SS_String> *vec_environ = GetEnvironVector();
437
438       // Set LD_PRELOAD string as the last element
439       SS_String ld_preload_string = SS_String(environment_string);
440       vec_environ->push_back(environment_string);
441
442       // Number of acquired environment variables + 1(For terminal) memory allocation
443       size_t env_num = sizeof(char*) * (vec_environ->size() + 1);
444       char **p_environment = static_cast<char **>(malloc(env_num));
445       memset(p_environment, 0x00, env_num);
446
447       // Create environment variable list
448       int i = 0;
449       char **p_environment_tmp = p_environment;
450       for (std::vector<SS_String>::iterator itr = vec_environ->begin(); itr != vec_environ->end(); itr++, i++) {
451         p_environment_tmp[i] = static_cast<char *>(malloc(sizeof(char) * (itr->length() + 1)));
452
453         snprintf(p_environment_tmp[i], itr->length() + 1, "%s", itr->c_str());
454       }
455
456       // Set envp for environment variable
457       process_id = CL_ProcessCreate(p_str_file->c_str(), c_argv, p_environment, cl_attr);
458
459       // Free memory
460       i = 0;
461       p_environment_tmp = p_environment;
462       for (std::vector<SS_String>::iterator itr = vec_environ->begin(); itr != vec_environ->end(); itr++, i++) {
463         free(p_environment_tmp[i]);
464       }
465
466       free(p_environment);
467       delete(vec_environ);
468     }
469
470     if (process_id == -1) {
471       throw "CL_ProcessCreate()";
472     }
473
474     m_tProcessId = process_id;
475   }
476   catch (const char *e) {
477     FRAMEWORKUNIFIEDLOG(ZONE_ERR, __PRETTY_FUNCTION__, "%s", e);
478   }
479 }
480 /**
481  * CreateProcess: This method will create a PosixBasedOS001 process with the executable provided and mode as a calling parameter. 
482  * The caller can also provide a list of arguments that will be provided to the executable at startup. 
483  * The calling p_strProcessName parameter is a textual name that will be
484  * associated with the newly created process by the OS. The process state information 
485  * will be maintained by this object.
486  *
487  * @param p_strFile_i Path and Filename of executable to create process for
488  * @param p_strProcessName This is the name that will be registered to the OS for this process 
489  * @return void
490  */
491 void Process::CreateProcess(const SS_String& p_strFile_i, const SS_String& p_strProcessName,
492                             const char* unix_user_name, const long p_lSpawnFlags_i) {  // NOLINT (runtime/int)
493   StringList strlstArgv;
494
495   try {
496     CreateProcess(p_strFile_i,
497             strlstArgv,
498             NOWAIT,
499             p_strProcessName,
500             FIFO,
501             iProcess_DEFAULT_PROCESS_PRIORITY,
502                         unix_user_name,
503             p_lSpawnFlags_i);
504   }
505   catch (...) {
506     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
507   }
508 }
509
510
511 /**
512  * CreateProcess: This method will create a process with the executable provided and mode as a calling parameter.
513  * The caller can also provide a list of arguments that will be provided to the executable at startup. 
514  * The calling p_strProcessName parameter is a textual name that will be
515  * associated with the newly created process by the OS. The process state information 
516  * will be maintained by this object.
517  *
518  *
519  * @param p_strFile_i Path and Filename of executable to create process for
520  * @param p_strProcessName This is the name that will be registered to the OS for this process
521  * @param p_iPriority_i  Priority of process
522  * @return void
523  */
524 void Process::CreateProcess(const SS_String& p_strFile_i, const SS_String& p_strProcessName, const int p_iPriority_i,
525                             const char* unix_user_name, const long p_lSpawnFlags_i) {  // NOLINT (runtime/int)
526   StringList strlstArgv;
527
528   try {
529     eProcessSchedulingPolicy policy;
530
531     if (0 < p_iPriority_i) {
532        policy = FIFO;
533     } else {
534        policy = OTHER;
535     }
536
537     CreateProcess(p_strFile_i,
538             strlstArgv,
539             NOWAIT,
540             p_strProcessName,
541             policy,
542             p_iPriority_i,
543                         unix_user_name,
544             p_lSpawnFlags_i);
545   }
546   catch (...) {
547     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
548   }
549 }
550
551 /**
552  * CreateProcess: This method will create a process with the executable provided and mode as a calling parameter.
553  * The caller can also provide a list of arguments that will be provided to the executable at startup. 
554  * The calling p_strProcessName parameter is a textual name that will be
555  * associated with the newly created process by the OS. The process state information 
556  * will be maintained by this object.
557  *
558  * @param p_strFile_i Path and Filename of executable to create process for
559  * @param p_lSpawnFlags_i Spawning flags. These are PosixBasedOS001 specific.
560  * @return void
561  */
562 void  Process::CreateProcess(const SS_String& p_strFile_i, const char* unix_user_name, const long p_lSpawnFlags_i) {  // NOLINT (runtime/int)
563   StringList strlstArgv;
564
565   try {
566     CreateProcess(p_strFile_i,
567             strlstArgv,
568             NOWAIT,
569             basename(const_cast<char *>(p_strFile_i.c_str())),
570             FIFO,
571             iProcess_DEFAULT_PROCESS_PRIORITY,
572                         unix_user_name,
573             p_lSpawnFlags_i);
574   }
575   catch (...) {
576     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
577   }
578 }
579
580
581
582 /**
583  * CreateProcess: This method will create a  process with the executable provided and mode as a calling parameter.
584  * The caller can also provide a list of arguments that will be provided to the executable at startup. 
585  * The calling p_strProcessName parameter is a textual name that will be
586  * associated with the newly created process by the OS. The process state information 
587  * will be maintained by this object.
588  *
589  * @param p_strFile_i Path and Filename of executable to create process for
590  * @param p_strProcessName This is the name that will be registered to the OS for this process
591  * @param p_strlstArgv_i  List of ARGV values for new process
592  * @param p_lSpawnFlags_i Spawning flags. These are PosixBasedOS001 specific.
593  * @return void
594  */
595 void Process::CreateProcess(const SS_String& p_strFile_i, const SS_String& p_strProcessName_i,
596                             const StringList& p_strlstArgv_i, const char* unix_user_name, const long p_lSpawnFlags_i) {  // NOLINT (runtime/int)
597   try {
598     CreateProcess(p_strFile_i,
599             p_strlstArgv_i,
600             NOWAIT,
601             p_strProcessName_i,
602             FIFO,
603             iProcess_DEFAULT_PROCESS_PRIORITY,
604                         unix_user_name,
605             p_lSpawnFlags_i);
606   }
607   catch (...) {
608     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
609   }
610 }
611
612
613 void Process::CreateProcess(const SS_String& p_strFile_i, const SS_String& p_strProcessName_i, const int p_iPriority_i,
614                             const StringList& p_strlstArgv_i, const char* unix_user_name, const long p_lSpawnFlags_i) {  // NOLINT (runtime/int)
615   try {
616     eProcessSchedulingPolicy policy;
617
618     if (0 < p_iPriority_i) {
619        policy = FIFO;
620     } else {
621        policy = OTHER;
622     }
623
624     CreateProcess(p_strFile_i,
625             p_strlstArgv_i,
626             NOWAIT,
627             p_strProcessName_i,
628             policy,
629             p_iPriority_i,
630                         unix_user_name,
631             p_lSpawnFlags_i);
632   }
633   catch (...) {
634     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
635   }
636 }
637
638
639 /**
640  * CreateProcessWait: This method will create a process with the executable provided.
641  * The process state information will be maintained by this object.
642  *
643  * @param p_strFile_i Path and Filename of executable to create process for 
644  * @return void
645  */
646 void Process::CreateProcessWait(const SS_String& p_strFile_i) {
647   StringList strlstArgv;
648
649   try {
650     CreateProcess(p_strFile_i,
651             strlstArgv,
652             WAIT,
653             basename(const_cast<char *>(p_strFile_i.c_str())),
654             FIFO,
655             iProcess_DEFAULT_PROCESS_PRIORITY,
656             iProcess_DEFAULT_PROCESS_USER_NAME,
657             iProcess_DEFAULT_PROCESS_FLAGS);
658   }
659   catch (...) {
660     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
661   }
662 }
663
664 /**
665  * CreateProcessWait: This method will create a PosixBasedOS001 process with the executable provided.
666  * The process state information will be maintained by this object.
667  *
668  *
669  * @param p_strFile_i Path and Filename of executable to create process for 
670  * @param p_strlstArguments_i List of process calling arguments
671  * @return void
672  */
673 void Process::CreateProcessWait(const SS_String& p_strFile_i, const StringList& p_strlstArguments_i) {
674   try {
675     CreateProcess(p_strFile_i,
676             p_strlstArguments_i,
677             WAIT,
678             basename(const_cast<char *>(p_strFile_i.c_str())),
679             FIFO,
680             iProcess_DEFAULT_PROCESS_PRIORITY,
681             iProcess_DEFAULT_PROCESS_USER_NAME,
682             iProcess_DEFAULT_PROCESS_FLAGS);
683   }
684   catch (...) {
685     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
686   }
687 }
688
689
690
691 /**
692  * KillProcess: This method will delete the process represented by this object. All variables associated
693  * with this object will be initialized to a know value.
694  *
695  * @param  
696  * @return void
697  */
698 void Process::KillProcess(int signal) {
699   //=====================================================================================
700   // Intialize the objects m_iErrorCode member variable to 0 (no error).
701   // Then try to delete the process that this object represents.
702   m_iErrorCode = 0;
703
704   if (DoesProcessExist()) {
705     if (-1 == killpg(m_tProcessId, signal)) {
706       return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
707     }
708   }
709
710   //
711   // If no errors, clear out any process specific member variables for this object
712   //
713   m_tProcessId = -1;
714   m_strProcessName = "";
715 }
716
717 /**
718  * SetSchedulingPolicy: This method will change the scheduling policy for the process this
719  * object represents. 
720  *
721  * @param p_eSchedulingPolicy_i Scheduling policy 
722  * @return void
723  */
724 void Process::SetSchedulingPolicy(
725           const eProcessSchedulingPolicy p_eSchedulingPolicy_i  // Scheduling policy
726 ) {
727   //=======================================================================================
728   // Attempt to change the scheduling policy for the process that this object
729   // represents. If the change fails, restore the previous settings.
730   //
731   m_iErrorCode = 0;
732   struct sched_param cur_sch_params;
733   sched_getparam(m_tProcessId, &cur_sch_params);
734   if (0 != sched_setscheduler(m_tProcessId, ConvertToPosixBasedOS001SchedularPolicy(p_eSchedulingPolicy_i),
735                               &cur_sch_params)) {
736     m_iErrorCode = errno;
737     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
738   }
739 }
740
741 /**
742  * SetPriority: This method will change the priority for the process this
743  * object represents. 
744  *
745  * @param p_iPriority_i Scheduling Policy for this process
746  * @return void
747  */
748 void Process::SetPriority(const int p_iPriority_i) {
749   //=======================================================================================
750   // Attempt to change the priority for the process that this object
751   // represents. If the change fails, restore the previous settings.
752   //
753   m_iErrorCode = 0;
754   struct sched_param cur_sch_params;
755   sched_getparam(m_tProcessId, &cur_sch_params);
756   cur_sch_params.sched_priority = p_iPriority_i;
757
758   if (-1 == sched_setparam(m_tProcessId, &cur_sch_params)) {
759     m_iErrorCode = errno;
760     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
761   }
762 }
763
764
765 /**
766  * IncreasePriorityByOne: This method will increase the priority for the process this
767  * object represents by one.
768  *
769  * @param  
770  * @return void
771  */
772 void Process::IncreasePriorityByOne(void) {
773   //================================================================================
774   // Retrieve the current priority of the process. Check to see if already at max.
775   // If so just return. Otherwise increase by one and set the priority...
776   //
777   try {
778     int iCurrentPriority = GetPriority();
779     if (iCurrentPriority < iProcess_MAXIMUM_PROCESS_PRIORITY) {
780       SetPriority(iCurrentPriority + 1);
781     }
782   }
783   catch (...) {
784     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
785   }
786 }
787
788
789 /**
790  * DecreasePriorityByOne: This method will decrease the priority for the process this
791  * object represents by one.
792  *
793  *
794  * @return void
795  */
796 void Process::DecreasePriorityByOne(void) {
797   //================================================================================
798   // Retrieve the current priority of the process. Check to see if already at minimum.
799   // If so just return. Otherwise decrease by one and set the priority...
800   //
801   try {
802     int iCurrentPriority = GetPriority();
803     if (iCurrentPriority > 1) {
804       SetPriority(iCurrentPriority - 1);
805     }
806   }
807   catch (...) {
808     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
809   }
810 }
811
812
813
814
815
816 ////////////////////////////////////////////////////////////////////////////////////////////////////
817 // ConvertToPosixBasedOS001SchedularPolicy
818 //
819 // This method will return to the caller the equivalent PosixBasedOS001 schedular policy for the process
820 // that this object represents
821 //
822 //
823 // Calling Arguments:
824 //      NONE
825 //
826 // Return Argument:
827 //  FIFO,      // A fixed priority scheduler in which the highest ready process runs until it
828 //          // blocks or is preempted by a higher priority process.
829 //  ROUND_ROBIN,  // The same as FIFO, except processes at the same priority level time-slice.
830 //  OTHER      // A general time sharing scheduler in which a process decays in priority if it
831 //          // consumes too much processor before blocking. It reverts to its default priority
832 //          // when it blocks. Should it fail to run over a 2 second period and it has decayed
833 //          // then it's boosted one priority level up to a maximum of its default priority.
834 //
835 int const Process::ConvertToPosixBasedOS001SchedularPolicy(const eProcessSchedulingPolicy p_eSchedulingPolicy_i) {
836   int iReturnValue = SCHED_RR;  // Default is RR
837   switch (p_eSchedulingPolicy_i) {
838     case FIFO:
839     {
840       iReturnValue = SCHED_FIFO;
841       break;
842     }
843
844     case ROUND_ROBIN:
845     {
846       iReturnValue = SCHED_RR;
847       break;
848     }
849
850     case OTHER:
851     {
852       iReturnValue = SCHED_OTHER;
853       break;
854     }
855   }
856
857   return iReturnValue;
858 }
859
860 ////////////////////////////////////////////////////////////////////////////////////////////////////
861 // ConvertFromPosixBasedOS001SchedularPolicy
862 //
863 // This method will return to the caller the eProcessSchedulingPolicy based on the PosixBasedOS001 schedular
864 // policy for the process that this object represents
865 //
866 //
867 // Calling Arguments:
868 //      PosixBasedOS001 Scheduling Policy
869 //
870 // Return Argument:
871 //  FIFO,      // A fixed priority scheduler in which the highest ready process runs until it
872 //          // blocks or is preempted by a higher priority process.
873 //  ROUND_ROBIN,  // The same as FIFO, except processes at the same priority level time-slice.
874 //  OTHER      // A general time sharing scheduler in which a process decays in priority if it
875 //          // consumes too much processor before blocking. It reverts to its default priority
876 //          // when it blocks. Should it fail to run over a 2 second period and it has decayed
877 //          // then it's boosted one priority level up to a maximum of its default priority.
878 //
879 Process::eProcessSchedulingPolicy const Process::ConvertFromPosixBasedOS001SchedularPolicy
880                                                  (const int p_iPosixBasedOS001chedulingPolicy_i) {
881   eProcessSchedulingPolicy ePolicy = ROUND_ROBIN;  // Default is RR
882   switch (p_iPosixBasedOS001chedulingPolicy_i) {
883     case SCHED_FIFO:
884     {
885       ePolicy = FIFO;
886       break;
887     }
888
889     case SCHED_RR:
890     {
891       ePolicy = ROUND_ROBIN;
892       break;
893     }
894     case SCHED_OTHER:
895     {
896       ePolicy = OTHER;
897       break;
898     }
899   }  // Switch
900
901   return ePolicy;
902 }
903
904
905 /**
906  * DoesProcessExist: This method will return a BOOLean indicating whether this 
907  * process exists.
908  *
909  * @return BOOL TRUE  - Process Exists, FALSE - Process does not exist
910  */
911 BOOL Process::DoesProcessExist(void) {
912   struct sched_param cur_sch_params;
913   if (-1 >=  sched_getparam(m_tProcessId, &cur_sch_params)) {  // or the segment data
914     return FALSE;
915   }
916
917   return TRUE;
918 }
919
920
921
922 /**
923  * SetProcessName: This method will set this objects process name member variable to the 
924  * provided string value.
925  *
926  * @param p_strProcessName_i Process Name to set the m_strProcessName member variable to
927  * @return void
928  */
929 void Process::SetProcessName(const SS_String& p_strProcessName_i) {
930   //
931   // Idiot checking
932   //
933   assert(!p_strProcessName_i.empty());
934
935   m_strProcessName = p_strProcessName_i;
936 }
937
938 /**
939  * GetSchedulingPolicy: This method will return to the caller the 
940  * currently configured process scheduling policy.
941  *
942  * @return Process::eProcessSchedulingPolicy const
943  */
944 Process::eProcessSchedulingPolicy const Process::GetSchedulingPolicy(void) {
945   int policy = 0;
946   if (-1 == (policy = sched_getscheduler(m_tProcessId))) {
947     m_iErrorCode = errno;
948     return ROUND_ROBIN;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
949   }
950
951   return (ConvertFromPosixBasedOS001SchedularPolicy (policy));
952 }
953
954
955
956 /**
957  * GetPriority: This method will return to the caller the currently configured
958  * process priority.
959  *
960  * @return int const
961  */
962 int const Process::GetPriority(void) {
963   struct sched_param cur_sch_params;
964   if (-1 >=  sched_getparam(m_tProcessId, &cur_sch_params)) {
965     m_iErrorCode = errno;
966     return -1;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
967   }
968
969   return (cur_sch_params.sched_priority);
970 }
971
972
973
974 /**
975  * SetCallingArgumentList: This method will set the calling argument list 
976  * that this object represents.
977  *
978  * @param p_pcArgv_i Pointer to NULL terminated argument list.
979  * @param p_iArgc_i Number of parameters
980  * @return void
981  */
982 void Process::SetCallingArgumentList(const char *p_pcArgv_i[], const int p_iArgc_i) {
983   ////////////////////////////////////////////////////////////////////////
984   // Set the executable filename first. This is always the 1st argument
985   // in the argument list. Then set the argument list for the process
986   // which is held in m_strlstArgv.
987   //
988   if (p_iArgc_i > (iProcess_MAXIMUM_NUMBER_OF_PROCESS_ARGUMENTS - 3)) {
989     return;  // PAD THIS IS BAD!!! TODO: Change this to something meaningful
990   }
991
992   //
993   // First make sure that the argument list is empty.
994   //
995   if (!m_strlstArgv.empty()) {
996     m_strlstArgv.clear();      // Remove all elements from the current list
997   }  // Process Argument list is NOT empty
998
999   //
1000   // Once empty, put the new arguments into the list
1001   //
1002   StringListIter at = m_strlstArgv.begin();
1003   int iLoop;
1004   for (iLoop = 0; iLoop < p_iArgc_i; iLoop ++) {
1005     at = m_strlstArgv.insert(at, p_pcArgv_i[iLoop]);
1006   }
1007 }
1008
1009
1010 /**
1011  * SetCallingArgumentList: This method will set the calling argument 
1012  * list that this object represents.
1013  *
1014  * @param p_strlstParameters_i List of parameters 
1015  * @return void
1016  */
1017 void Process::SetCallingArgumentList(const StringList& p_strlstParameters_i) {
1018   if (p_strlstParameters_i.size()) {
1019     m_strlstArgv.clear();  // Empty the current list.
1020     m_strlstArgv = p_strlstParameters_i;
1021   }
1022 }
1023
1024 /**
1025  * Search if libTestFwCommon.so is dynamically linked.
1026  *
1027  * @param process_path Search target binary path
1028  * @return bool
1029  */
1030 static bool CheckLinkedTestfwLibrary(SS_String *process_path) {
1031   if (NULL == process_path) {
1032     fprintf(stderr, "[%s](%d)Invaild Param.\n", __func__, __LINE__);
1033     return false;
1034   }
1035
1036   ELFIO::elfio reader;
1037   if (!reader.load(process_path->c_str())) {
1038     fprintf(stderr, "[%s](%d)%s is not ELF!\n", __func__, __LINE__, process_path->c_str());
1039     return false;
1040   }
1041
1042   ELFIO::Elf_Half n = reader.sections.size();
1043   for ( ELFIO::Elf_Half i = 0; i < n; ++i ) {
1044     ELFIO::section* sec = reader.sections[i];
1045     if ( SHT_DYNAMIC == sec->get_type() ) {
1046       ELFIO::dynamic_section_accessor dynamic(reader, sec);
1047
1048       ELFIO::Elf_Xword dynamic_num = dynamic.get_entries_num();
1049       if ( dynamic_num > 0 ) {
1050         for ( ELFIO::Elf_Xword i = 0; i < dynamic_num; ++i ) {
1051           ELFIO::Elf_Xword   dynamic_tag   = 0;
1052           ELFIO::Elf_Xword   dynamic_value = 0;
1053           SS_String dynamic_str;
1054           dynamic.get_entry(i, dynamic_tag, dynamic_value, dynamic_str);
1055
1056           // Search if the acquired dynamic section string contains libTestFwCommon.so
1057           if (SS_String::npos != dynamic_str.find("libTestFwCommon.so")) {
1058             fprintf(stderr, "[%s](%d)libTestFwCommon is linked.\n", __func__, __LINE__);
1059             return true;
1060           }
1061
1062           // Check for continuation of dynamic section element
1063           if ( DT_NULL == dynamic_tag ) {
1064             break;
1065           }
1066         }
1067       } else {
1068         // If dynamic section is not found
1069         fprintf(stderr, "[%s](%d)dynamic symbol is not find.\n", __func__, __LINE__);
1070       }
1071     }
1072   }
1073
1074   fprintf(stderr, "[%s](%d)libTestFwCommon is not find. \n", __func__, __LINE__);
1075   return false;
1076 }
1077
1078 /**
1079  * This method is a private method to be called from CreateProcess func.
1080  * Check environment variable MOCK_LIBRARY where Mock Library Name to set in LD_PRELOAD is set
1081  * and output character string to set in LD_PRELOAD if there is setting.
1082  *
1083  * @param process_path,environment_string
1084  * @return void
1085  */
1086 void Process::CheckLdPreLoad(SS_String *process_path, char *environment_string) {
1087   if ((process_path == NULL || environment_string == NULL)) {
1088     fprintf(stderr, "[%s](%d)Invaild Param.\n", __func__, __LINE__);
1089     return;
1090   }
1091
1092   // Check if environment variable MOCK_LIBRARY for LD_PRELOAD setting is set
1093   char *value_mock_library = getenv("MOCK_LIBRARY");
1094
1095   if (value_mock_library != NULL) {
1096     // When MOCK_LIBRARY is set
1097     fprintf(stderr, "[%s](%d)MOCK_LIBRARY = %s \n", __func__, __LINE__, value_mock_library);
1098
1099     // Check whether the process to be started is a core unit or TestFW, and execute LD_PRELOAD if libTestFwCommon.so is linked
1100     if (CheckLinkedTestfwLibrary(process_path)) {
1101       SS_String key_value;
1102       SS_String key_ld_preload = "LD_PRELOAD=";
1103
1104       // Create LD_PRELOAD setting string
1105       // LD_PRELOAD is enabled when the string is an envp argument in the form "LD_PRELOAD=hoge_mock.so hoge_mock.so ..."
1106       key_value = key_ld_preload + value_mock_library;
1107       strncpy(environment_string, key_value.c_str(), key_value.length());
1108       fprintf(stderr, "[%s](%d)Set envp: %s \n", __func__, __LINE__, environment_string);
1109       return;
1110     } else {
1111       // If the unit does not require LD_PRELOAD setting, set envairoment_string to NULL.
1112       fprintf(stderr, "[%s](%d)Core Unit is not setting LD_PRELOAD\n", __func__, __LINE__);
1113       return;
1114     }
1115   } else {
1116     // If it is not set to MOCK_LIBRARY, it is not necessary to set LD_PRELOAD, so set envairoment_string to NULL.
1117     fprintf(stderr, "[%s](%d)The MOCK_LIBRARY variable was unestablished.\n", __func__, __LINE__);
1118     return;
1119   }
1120 }
1121
1122 /**
1123  * Acquire the character string of the environment variable and set it in String Vector
1124  * and return in a pointer of Vector.
1125  *
1126  * @param process_path,environment_string
1127  * @return vector<SS_String> pointer
1128  */
1129 extern char ** environ;
1130 std::vector<SS_String> *Process::GetEnvironVector(void) {
1131   // If LD_PRELOAD is set, copy existing environment settings and set to environment_pointer
1132
1133   std::vector<SS_String>* vector_environ = new std::vector<SS_String>;
1134
1135   char **environ_tmp = environ;
1136
1137   // Insert environ_string into the vector table
1138   int i = 0;
1139   while (environ_tmp[i] != NULL) {
1140     SS_String str_env(environ_tmp[i]);
1141     vector_environ->push_back(str_env);
1142     i++;
1143   }
1144
1145   return vector_environ;
1146 }
1147 // ----------------------------------------