libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmExec.c 2.1KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmGlobal.h"
  4. #include "cmRpt.h"
  5. #include "cmErr.h"
  6. #include "cmExec.h"
  7. #include <sys/wait.h>
  8. cmExRC_t cmExecV( cmErr_t* err, int* returnValRef, const cmChar_t* pgmFn, va_list vl0 )
  9. {
  10. cmExRC_t rc = kOkExRC;
  11. int n = 0;
  12. int i = 0;
  13. pid_t pid;
  14. va_list vl1;
  15. if( pgmFn == NULL )
  16. return cmErrMsg(err,kInvalidPgmFnExRC,"No executable program file name given in call to %s.",__FUNCTION__);
  17. // get the count of arguments
  18. va_copy(vl1,vl0);
  19. while( va_arg(vl1,cmChar_t*)!=NULL )
  20. ++n;
  21. va_end(vl1);
  22. // load argv with ptrs to the args
  23. cmChar_t* argv[n+2];
  24. argv[0] = (cmChar_t*)pgmFn;
  25. for(i=0; i<n+1; ++i)
  26. argv[i+1] = va_arg(vl0,cmChar_t*);
  27. argv[n+1] = NULL;
  28. errno = 0;
  29. switch( pid = fork())
  30. {
  31. case -1:
  32. rc = cmErrSysMsg(err,kForkFailExRC,errno,"Fork failed.");
  33. break;
  34. case 0:
  35. // we are in the child process - never to return
  36. execvp(pgmFn,argv);
  37. // under normal conditions execlp() does not return so we should never get here.
  38. rc = cmErrSysMsg(err,kExecFailExRC,errno,"Fork to '%s' failed. Is '%s' installed and on the execution path?",pgmFn,pgmFn);
  39. break;
  40. default:
  41. {
  42. int rv;
  43. int wrc;
  44. // we are in the parent process - wait for the child to return
  45. if((wrc = waitpid(pid,&rv,0))==-1)
  46. {
  47. rc = cmErrSysMsg(err,kWaitFailExRC,errno,"Wait failed on call to '%s'.",pgmFn);
  48. goto errLabel;
  49. }
  50. if( returnValRef != NULL )
  51. *returnValRef = rv;
  52. if( WEXITSTATUS(rv) != 0 )
  53. rc = cmErrMsg(err,kPgmFailExRC,"'%s' failed.",pgmFn);
  54. }
  55. break;
  56. }
  57. errLabel:
  58. return rc;
  59. }
  60. cmExRC_t cmExec( cmErr_t* err, int* returnValRef, const cmChar_t* pgmFn, ... )
  61. {
  62. va_list vl;
  63. va_start(vl,pgmFn);
  64. cmExRC_t rc = cmExecV(err,returnValRef,pgmFn,vl);
  65. va_end(vl);
  66. return rc;
  67. }