zuluCrypt  5.7.1
About: zuluCrypt is a simple but feature rich solution for hard drives encryption. It can manage PLAIN dm-crypt, LUKS, TrueCrypt and VeraCrypt encrypted volumes.
  Fossies Dox: zuluCrypt-5.7.1.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

process.c
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2012-2015
4  * name : Francis Banyikwa
5  * email: mhogomchungu@gmail.com
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef _GNU_SOURCE
21 #define _GNU_SOURCE
22 #endif
23 
24 #include "process.h"
25 
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <sys/wait.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <pthread.h>
32 #include <signal.h>
33 #include <stdarg.h>
34 #include <sys/types.h>
35 #include <sys/time.h>
36 #include <sys/resource.h>
37 #include <grp.h>
38 
39 #define _ignore_result( x ) if( x ){;}
40 
42  pid_t pid ;
43  int fd_0[ 2 ] ; /* this variable is used to write to child process */
44  int fd_1[ 2 ] ; /* this variable is used to read from child's std out */
45  int fd_2[ 2 ] ; /* this variable is used to read from child's std error */
47  int std_io ;
48  char * exe ;
49  char ** args ;
50  int signal ;
52  pthread_t * thread ;
54 };
55 
56 static void _f( void )
57 {
58 }
59 
60 static void ( *_memory_error )( void ) = _f ;
61 
62 void ProcessExitOnMemoryExaustion( void ( *f )( void ) )
63 {
64  _memory_error = f ;
65 }
66 
67 static void * _ProcessError( void )
68 {
69  _memory_error() ;
70  return NULL ;
71 }
72 
74 {
75  if( p == ProcessVoid ){
76  return NULL ;
77  }else{
78  return &p->str ;
79  }
80 }
81 
82 void ProcessSetEnvironmentalVariable( process_t p,char * const * env )
83 {
84  if( p != ProcessVoid ){
85  p->str.env = env ;
86  }
87 }
88 
89 static process_t _process( const char * path )
90 {
91  process_t p ;
92 
93  size_t len ;
94 
95  if( path == NULL ){
96  len = 0 ;
97  }else{
98  len = strlen( path ) ;
99  }
100 
101  p = malloc( sizeof( struct ProcessType_t ) ) ;
102 
103  if( p == NULL ){
104  return _ProcessError() ;
105  }
106 
107  if( len == 0 ){
108  p->exe = malloc( sizeof( char ) ) ;
109  if( p->exe == NULL ){
110  free( p ) ;
111  return _ProcessError() ;
112  }
113  p->exe[ 0 ] = '\0' ;
114  }else{
115  p->exe = malloc( sizeof( char ) * ( len + 1 ) ) ;
116  if( p->exe == NULL ){
117  free( p ) ;
118  return _ProcessError() ;
119  }
120  memcpy( p->exe,path,len + 1 ) ;
121  }
122 
123  p->std_io = 0 ;
124  p->wait_status = -1 ;
125  p->thread = NULL ;
126  p->fd_0[ 0 ] = -1 ;
127  p->args = NULL ;
128  p->str.args = NULL ;
129  p->str.timeout = -1 ;
130  p->str.env = NULL ;
131  p->str.user_id = -1 ;
132  p->str.priority = 0 ;
133  p->str.signal = SIGTERM ;
135  return p ;
136 }
137 
139 {
140  char * entry ;
141  char ** args ;
142  char ** e ;
143  size_t size = sizeof( char * ) ;
144  int index = 1 ;
145  va_list list ;
146 
147  if( p == ProcessVoid ){
148  return ;
149  }
150 
151  args = p->args ;
152 
153  va_start( list,p ) ;
154 
155  while( 1 ){
156 
157  entry = va_arg( list,char * ) ;
158  e = realloc( args,( 1 + index ) * size ) ;
159 
160  if( e == NULL ){
161  free( args ) ;
162  va_end( list ) ;
163  _ProcessError() ;
164  return ;
165  }else{
166  args = e ;
167  }
168 
169  if( entry == NULL ){
170  *( args + index ) = NULL ;
171  break ;
172  }else{
173  *( args + index ) = entry ;
174  index++ ;
175  }
176  }
177 
178  va_end( list ) ;
179 
180  p->args = args ;
181  p->args[ 0 ] = p->exe ;
182  p->str.args = args ;
183 }
184 
185 process_t Process( const char * path,... )
186 {
187  char * entry ;
188  char ** args ;
189  char ** e ;
190  size_t size = sizeof( char * ) ;
191  int index = 1 ;
192  va_list list ;
193  process_t p ;
194 
195  if( path == NULL ){
196  return _process( NULL ) ;
197  }
198 
199  p = _process( path ) ;
200 
201  if( p == ProcessVoid ){
202  return ProcessVoid ;
203  }
204 
205  args = p->args ;
206 
207  va_start( list,path ) ;
208 
209  while( 1 ){
210 
211  entry = va_arg( list,char * ) ;
212  e = realloc( args,( 1 + index ) * size ) ;
213 
214  if( e == NULL ){
215  ProcessCleanUp( &p ) ;
216  free( args ) ;
217  va_end( list ) ;
218  _ProcessError() ;
219  return ProcessVoid ;
220  }else{
221  args = e ;
222  }
223 
224  if( entry == NULL ){
225  *( args + index ) = NULL ;
226  break ;
227  }else{
228  *( args + index ) = entry ;
229  index++ ;
230  }
231  }
232 
233  va_end( list ) ;
234 
235  p->args = args ;
236  p->args[ 0 ] = p->exe ;
237  p->str.args = args ;
238 
239  return p ;
240 }
241 
242 int ProcessExecute( const char * exe,... )
243 {
244  char * entry ;
245  char ** args ;
246  char ** e ;
247  size_t size = sizeof( char * ) ;
248  int index = 1 ;
249  va_list list ;
250  process_t p ;
251 
252  if( exe == NULL ){
253  return -1 ;
254  }
255 
256  p = _process( exe ) ;
257 
258  if( p == ProcessVoid ){
259  return -1 ;
260  }
261 
262  args = p->args ;
263 
264  va_start( list,exe ) ;
265 
266  while( 1 ){
267 
268  entry = va_arg( list,char * ) ;
269  e = realloc( args,( 1 + index ) * size ) ;
270 
271  if( e == NULL ){
272  ProcessCleanUp( &p ) ;
273  free( args ) ;
274  va_end( list ) ;
275  _ProcessError() ;
276  return -1 ;
277  }else{
278  args = e ;
279  }
280 
281  if( entry == NULL ){
282  *( args + index ) = NULL ;
283  break ;
284  }else{
285  *( args + index ) = entry ;
286  index++ ;
287  }
288  }
289 
290  va_end( list ) ;
291 
292  p->args = args ;
293  p->args[ 0 ] = p->exe ;
294  p->str.args = args ;
295 
296  ProcessStart( p ) ;
297 
298  return ProcessWaitUntilFinished( &p ) ;
299 }
300 
301 static void * __timer( void * x )
302 {
303  process_t p = x ;
304 
305  sleep( p->str.timeout ) ;
306 
307  kill( p->pid,p->str.signal ) ;
308 
309  p->state = ProcessCancelled ;
310 
311  return NULL ;
312 }
313 
315 {
316  p->thread = malloc( sizeof( pthread_t ) ) ;
317 
318  if( p->thread == NULL ){
319  _ProcessError() ;
320  }else{
321  pthread_create( p->thread,NULL,__timer,p ) ;
322  }
323 }
324 
325 void ProcessSetOptionPriority( process_t p,int priority )
326 {
327  if( p != ProcessVoid ){
328  p->str.priority = priority ;
329  }
330 }
331 
332 static void _execve( process_t p,char * const * env )
333 {
334  execve( p->str.args[ 0 ],p->str.args,env ) ;
335 }
336 
338 {
339  char * const env[] = { "PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",NULL } ;
340 
341  if( pipe( p->fd_0 ) == -1 ){
342  return -1 ;
343  }
344  if( pipe( p->fd_1 ) == -1 ){
345  return -1 ;
346  }
347  if( pipe( p->fd_2 ) == -1 ){
348  return -1 ;
349  }
350 
351  p->pid = fork() ;
352 
353  if( p->pid == -1 ){
354  return -1 ;
355  }
356  if( p->pid == 0 ){
357  if( p->str.user_id != ( uid_t )-1 ){
358  /*
359  * drop privileges permanently
360  */
361  _ignore_result( seteuid( 0 ) ) ;
362  _ignore_result( setgid( p->str.user_id ) ) ;
363  _ignore_result( setgroups( 1,&p->str.user_id ) ) ;
364  _ignore_result( setegid( p->str.user_id ) ) ;
365  _ignore_result( setuid( p->str.user_id ) ) ;
366  }
367 
368  dup2( p->fd_0[ 1 ],0 ) ;
369  dup2( p->fd_1[ 1 ],1 ) ;
370  dup2( p->fd_2[ 1 ],2 ) ;
371 
372  close( p->fd_1[ 0 ] ) ;
373  close( p->fd_0[ 0 ] ) ;
374  close( p->fd_2[ 0 ] ) ;
375 
376  if( p->str.priority != 0 ){
377  setpriority( PRIO_PROCESS,0,p->str.priority ) ;
378  }
379 
380  if( p->str.env == NULL || p->str.env[ 0 ] == NULL ){
381 
382  if( environ[ 0 ] == NULL ){
383 
384  _execve( p,env ) ;
385  }else{
386  _execve( p,environ ) ;
387  }
388 
389  }else{
390  _execve( p,p->str.env ) ;
391  }
392 
393  /*
394  * execv has failed :-(
395  */
396 
397  _Exit( 1 ) ;
398  /*
399  * child process block ends here
400  */
401  }
402 
403  /*
404  * parent process continues from here
405  */
406  close( p->fd_0[ 0 ] ) ;
407  close( p->fd_1[ 1 ] ) ;
408  close( p->fd_2[ 1 ] ) ;
409 
411 
412  if( p->str.timeout != -1 ){
413  __ProcessStartTimer( p ) ;
414  }
415 
416  return p->pid ;
417 }
418 
419 #define FACTOR 2
420 static inline char * __bufferExpandMemory( char * buffer,size_t new_size,size_t * buffer_size )
421 {
422  char * e ;
423  if( new_size >= *buffer_size ) {
424  *buffer_size = new_size * FACTOR ;
425  e = realloc( buffer,*buffer_size ) ;
426  if( e == NULL ){
427  free( buffer ) ;
428  _ProcessError() ;
429  return NULL ;
430  }else{
431  return e ;
432  }
433  }else{
434  return buffer ;
435  }
436 }
437 
438 size_t ProcessGetOutPut( process_t p,char ** data,ProcessIO std_io )
439 {
440  #define SIZE 64
441  #define BUFFER_SIZE 128
442  char * buffer ;
443  char * e ;
444  char buff[ SIZE ] ;
445  size_t size = 0 ;
446  size_t count ;
447  size_t buffer_size = BUFFER_SIZE ;
448 
449  int fd ;
450 
451  if( p == ProcessVoid ){
452  return 0 ;
453  }
454 
455  switch( std_io ){
456  case ProcessStdOut : fd = p->fd_1[ 0 ] ; break ;
457  case ProcessStdError : fd = p->fd_2[ 0 ] ; break ;
458  default : return 0 ;
459  }
460 
461  buffer = malloc( sizeof( char ) * BUFFER_SIZE ) ;
462 
463  if( buffer == NULL ){
464  _ProcessError() ;
465  return 0 ;
466  }
467 
468  while( 1 ) {
469  count = read( fd,buff,SIZE ) ;
470  buffer = __bufferExpandMemory( buffer,size + count,&buffer_size ) ;
471 
472  if( buffer == NULL ){
473  _ProcessError() ;
474  return 0 ;
475  }else{
476  memcpy( buffer + size,buff,count ) ;
477  }
478 
479  size += count ;
480 
481  if( count < SIZE ){
482  break ;
483  }
484  }
485 
486  if( size > 0 ){
487  e = realloc( buffer,size + 1 ) ;
488  if( e == NULL ){
489  free( buffer ) ;
490  _ProcessError() ;
491  return 0 ;
492  }else{
493  *( e + size ) = '\0' ;
494  *data = e ;
495  }
496  }
497 
498  return size ;
499 }
500 
502 {
503  if( p != ProcessVoid ){
504  return p->state ;
505  }else{
506  return ProcessStatusUndefined ;
507  }
508 }
509 
510 ssize_t ProcessGetOutPut_1( process_t p,char * buffer,int size,ProcessIO std_io )
511 {
512  if( p != ProcessVoid ){
513  switch( std_io ){
514  case ProcessStdOut : return read( p->fd_1[ 1 ],buffer,size ) ;
515  case ProcessStdError : return read( p->fd_2[ 1 ],buffer,size ) ;
516  default : return -1 ;
517  }
518  }else{
519  return -1 ;
520  }
521 }
522 
523 size_t ProcessWrite( process_t p,const char * data,size_t len )
524 {
525  if( p != ProcessVoid ){
526  return write( p->fd_0[ 1 ],data,len ) ;
527  }else{
528  return 0 ;
529  }
530 }
531 
533 {
534  close( p->fd_0[ 1 ] ) ;
535  p->fd_0[ 1 ] = -1 ;
536 }
537 
538 void ProcessSetOptionTimeout( process_t p,int timeout,int signal )
539 {
540  if( p != ProcessVoid ){
541  p->str.signal = signal ;
542  p->str.timeout = timeout ;
543  }
544 }
545 
546 static void _ProcessDelete( process_t px )
547 {
548  if( px->thread != NULL ){
549  pthread_cancel( *( px->thread ) ) ;
550  free( px->thread ) ;
551  }
552 
553  close( px->fd_2[ 1 ] ) ;
554  close( px->fd_1[ 1 ] ) ;
555 
556  if( px->fd_0[ 0 ] != -1 ){
557  close( px->fd_0[ 0 ] ) ;
558  }
559  if( px->wait_status == -1 ){
560  waitpid( px->pid,0,WNOHANG ) ;
561  }
562 
563  free( px->args ) ;
564 
565  free( px->exe ) ;
566 
567  free( px ) ;
568 }
569 
571 {
572  if( p != NULL && *p != ProcessVoid ){
573  _ProcessDelete( *p ) ;
574  *p = ProcessVoid ;
575  }
576 }
577 
579 {
580  int st ;
581 
582  if( p == ProcessVoid ){
583  return -1 ;
584  }else{
585  p->state = ProcessCancelled ;
586  st = kill( p->pid,SIGTERM ) ;
587  waitpid( p->pid,0,WNOHANG ) ;
588  p->wait_status = 1 ;
589  return st ;
590  }
591 }
592 
593 void ProcessSetOptionUser( process_t p,uid_t uid )
594 {
595  if( p != ProcessVoid ){
596  p->str.user_id = uid ;
597  }
598 }
599 
601 {
602  int st ;
603  if( p == ProcessVoid ){
604  return -1 ;
605  }else{
606  p->state = ProcessCancelled ;
607  st = kill( p->pid,SIGKILL ) ;
608  waitpid( p->pid,0,WNOHANG ) ;
609  p->wait_status = 1 ;
610  return st ;
611  }
612 }
613 
615 {
616  int s ;
617 
618  process_t p ;
619 
620  if( e == NULL || *e == ProcessVoid ){
621  return -1 ;
622  }else{
623  p = *e ;
624  *e = ProcessVoid ;
625 
626  s = ProcessExitStatus( p ) ;
627 
628  _ProcessDelete( p ) ;
629 
630  return s ;
631  }
632 }
633 
635 {
636  int s ;
637 
638  if( p == ProcessVoid ){
639  return -1 ;
640  }else{
641  waitpid( p->pid,&s,0 ) ;
642 
643  p->state = ProcessCompleted ;
644  p->wait_status = 1 ;
645 
646  if( WIFEXITED( s ) == 0 ){
647  return -1 ;
648  }else{
649  return WEXITSTATUS( s ) ;
650  }
651  }
652 }
653 
655 {
656  ProcessExitStatus( p ) ;
657 }
658 
659 void ProcessSetArguments( process_t p,char * const s[] )
660 {
661  if( p != ProcessVoid ){
662  p->str.args = s ;
663  }
664 }
ProcessType_t::fd_2
int fd_2[2]
Definition: process.c:45
ProcessStructure::timeout
int timeout
Definition: process.h:46
ProcessGetOutPut
size_t ProcessGetOutPut(process_t p, char **data, ProcessIO std_io)
Definition: process.c:438
ProcessType_t::args
char ** args
Definition: process.c:49
ProcessExitOnMemoryExaustion
void ProcessExitOnMemoryExaustion(void(*f)(void))
Definition: process.c:62
ProcessCloseStdWrite
void ProcessCloseStdWrite(process_t p)
Definition: process.c:532
buffer_size
#define buffer_size
ProcessStructure::signal
int signal
Definition: process.h:50
ProcessStructure::env
char *const * env
Definition: process.h:41
ProcessType_t::state
ProcessStatus state
Definition: process.c:46
ProcessTerminate
int ProcessTerminate(process_t p)
Definition: process.c:578
ProcessType_t::wait_status
int wait_status
Definition: process.c:51
BUFFER_SIZE
#define BUFFER_SIZE
ProcessSetOptionPriority
void ProcessSetOptionPriority(process_t p, int priority)
Definition: process.c:325
ProcessSetEnvironmentalVariable
void ProcessSetEnvironmentalVariable(process_t p, char *const *env)
Definition: process.c:82
_memory_error
static void(* _memory_error)(void)
Definition: process.c:60
FACTOR
#define FACTOR
Definition: process.c:419
ProcessType_t::pid
pid_t pid
Definition: process.c:42
ProcessType_t::fd_1
int fd_1[2]
Definition: process.c:44
ProcessType_t::exe
char * exe
Definition: process.c:48
ProcessArgumentStructure
ProcessStructure * ProcessArgumentStructure(process_t p)
Definition: process.c:73
ProcessVoid
#define ProcessVoid
Definition: process.h:59
ProcessExecute
int ProcessExecute(const char *exe,...)
Definition: process.c:242
ProcessStatusUndefined
@ ProcessStatusUndefined
Definition: process.h:153
ProcessStdError
@ ProcessStdError
Definition: process.h:200
ProcessType_t::fd_0
int fd_0[2]
Definition: process.c:43
__bufferExpandMemory
static char * __bufferExpandMemory(char *buffer, size_t new_size, size_t *buffer_size)
Definition: process.c:420
ProcessType_t::thread
pthread_t * thread
Definition: process.c:52
ProcessWait
void ProcessWait(process_t p)
Definition: process.c:654
ProcessIsStillRunning
@ ProcessIsStillRunning
Definition: process.h:150
ProcessStructure
Definition: process.h:29
ProcessType_t::std_io
int std_io
Definition: process.c:47
ProcessWaitUntilFinished
int ProcessWaitUntilFinished(process_t *e)
Definition: process.c:614
process.h
Process
process_t Process(const char *path,...)
Definition: process.c:185
ProcessSetArguments
void ProcessSetArguments(process_t p, char *const s[])
Definition: process.c:659
__ProcessStartTimer
static void __ProcessStartTimer(process_t p)
Definition: process.c:314
args
Definition: open_plain.c:25
ProcessType_t
Definition: process.c:41
ProcessCancelled
@ ProcessCancelled
Definition: process.h:152
ProcessStatus
ProcessStatus
Definition: process.h:148
ProcessSetArgumentList
void ProcessSetArgumentList(process_t p,...)
Definition: process.c:138
ProcessHasNotStarted
@ ProcessHasNotStarted
Definition: process.h:149
ProcessGetOutPut_1
ssize_t ProcessGetOutPut_1(process_t p, char *buffer, int size, ProcessIO std_io)
Definition: process.c:510
ProcessKill
int ProcessKill(process_t p)
Definition: process.c:600
ProcessStart
pid_t ProcessStart(process_t p)
Definition: process.c:337
_ignore_result
#define _ignore_result(x)
Definition: process.c:39
_ProcessError
static void * _ProcessError(void)
Definition: process.c:67
ProcessState
ProcessStatus ProcessState(process_t p)
Definition: process.c:501
_process
static process_t _process(const char *path)
Definition: process.c:89
ProcessType_t::signal
int signal
Definition: process.c:50
_ProcessDelete
static void _ProcessDelete(process_t px)
Definition: process.c:546
ProcessStructure::user_id
uid_t user_id
Definition: process.h:37
__timer
static void * __timer(void *x)
Definition: process.c:301
e
static QString e
Definition: about.cpp:31
ProcessIO
ProcessIO
Definition: process.h:197
ProcessWrite
size_t ProcessWrite(process_t p, const char *data, size_t len)
Definition: process.c:523
ProcessCompleted
@ ProcessCompleted
Definition: process.h:151
ProcessStructure::args
char *const * args
Definition: process.h:33
SIZE
#define SIZE
ProcessStructure::priority
int priority
Definition: process.h:54
ProcessStdOut
@ ProcessStdOut
Definition: process.h:199
ProcessExitStatus
int ProcessExitStatus(process_t p)
Definition: process.c:634
ProcessSetOptionTimeout
void ProcessSetOptionTimeout(process_t p, int timeout, int signal)
Definition: process.c:538
_execve
static void _execve(process_t p, char *const *env)
Definition: process.c:332
ProcessCleanUp
void ProcessCleanUp(process_t *p)
Definition: process.c:570
ProcessType_t::str
ProcessStructure str
Definition: process.c:53
_f
static void _f(void)
Definition: process.c:56
ProcessSetOptionUser
void ProcessSetOptionUser(process_t p, uid_t uid)
Definition: process.c:593