freeprocess.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. // freeprocess.c
  2. #include <brl.mod/blitz.mod/blitz.h>
  3. #include <stdio.h>
  4. #define HIDECONSOLE 1
  5. #if __APPLE__ || __linux
  6. #include <sys/ioctl.h>
  7. #include <unistd.h>
  8. #include <sys/wait.h>
  9. int fdClose(int fd) {return close(fd);}
  10. int fdRead(int fd,char *buffer,int count) {return read(fd,buffer,count);}
  11. int fdWrite(int fd,char *buffer,int count) {return write(fd,buffer,count);}
  12. int fdAvail(int fd) {int avail;if (ioctl(fd,FIONREAD,&avail)) avail=avail;return avail;}
  13. int fdFlush(int fd) {}//flush(fd);}
  14. ///return 1 for running, 0 for finished
  15. //
  16. int fdProcessStatus( int pid ){
  17. int status=0;
  18. return !waitpid( pid,&status,WNOHANG );
  19. }
  20. //returns 0 for success, -1 for error
  21. //
  22. int fdTerminateProcess(int pid){
  23. if( !killpg( pid,SIGTERM ) ){
  24. int status=0;
  25. waitpid( pid,&status,0 );
  26. return 0;
  27. }
  28. return -1;
  29. }
  30. static char **makeargv( const char *cmd ){
  31. int n,c;
  32. char *p;
  33. static char *args,**argv;
  34. if( args ) free( args );
  35. if( argv ) free( argv );
  36. args=(char*)malloc( strlen(cmd)+1 );
  37. strcpy( args,cmd );
  38. n=0;
  39. p=args;
  40. while( c=*p++ ){
  41. if( c==' ' ){
  42. continue;
  43. }else if( c=='\"' ){
  44. while( *p && *p!='\"' ) ++p;
  45. }else{
  46. while( *p && *p!=' ' ) ++p;
  47. }
  48. if( *p ) ++p;
  49. ++n;
  50. }
  51. argv=(char**)malloc( (n+1)*sizeof(char*) );
  52. n=0;
  53. p=args;
  54. while( c=*p++ ){
  55. if( c==' ' ){
  56. continue;
  57. }else if( c=='\"' ){
  58. argv[n]=p;
  59. while( *p && *p!='\"' ) ++p;
  60. }else{
  61. argv[n]=p-1;
  62. while( *p && *p!=' ' ) ++p;
  63. }
  64. if( *p ) *p++=0;
  65. ++n;
  66. }
  67. argv[n]=0;
  68. return argv;
  69. }
  70. #define PIPEREAD 0
  71. #define PIPEWRITE 1
  72. static int in[2],out[2],errfd[2];
  73. int fdProcess( BBString *bbcmd,int *procin,int *procout,int *procerr,int flags)
  74. {
  75. char *const*argv;
  76. int procid;
  77. const char *cmd=bbTmpUTF8String(bbcmd);
  78. //Set-up interprocess communication
  79. if (pipe(in)) return 0;
  80. if (pipe(out)) return 0;
  81. if (pipe(errfd)) return 0;
  82. //Fork process (returned value used to distinguish between child and parent process)
  83. procid=vfork(); //vfork() avoids memory overhead of fork()
  84. //Child process
  85. if (procid==0)
  86. {
  87. #if __linux
  88. setsid(); //Linux doesn't mind setsid()
  89. #else
  90. setpgid(0,0); //but OS X doesn't like it, therefore resort to using setpgid().
  91. #endif
  92. dup2(out[PIPEREAD],STDIN_FILENO);
  93. close(out[PIPEWRITE]);
  94. dup2(in[PIPEWRITE],STDOUT_FILENO);
  95. close(in[PIPEREAD]);
  96. dup2(errfd[PIPEWRITE],STDERR_FILENO);
  97. close(errfd[PIPEREAD]);
  98. argv=makeargv(cmd);
  99. execvp(argv[0],argv);
  100. _exit( -1 );
  101. return 0; //Supposedly, we need this for some compilers.
  102. }
  103. //Parent process
  104. if(procid==-1) return 0; //Return if child process couldn't be started.
  105. close(out[PIPEREAD]); //Close the end of the pipes in that the child
  106. close(in[PIPEWRITE]); //process is using.
  107. close(errfd[PIPEWRITE]);
  108. *procin=in[PIPEREAD]; //And return the end of the pipes that we should
  109. *procout=out[PIPEWRITE]; //be using.
  110. *procerr=errfd[PIPEREAD];
  111. return procid;
  112. }
  113. #endif
  114. #ifdef _WIN32
  115. extern int _bbusew;
  116. #define WIN32_LEAN_AND_MEAN
  117. #include <windows.h>
  118. #include <tlhelp32.h>
  119. int TerminateProcessGroup(HANDLE prochandle,int procid)
  120. {
  121. HANDLE snapshot,child;
  122. PROCESSENTRY32 procinfo;
  123. int gotinfo,res;
  124. snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
  125. if (snapshot!=INVALID_HANDLE_VALUE)
  126. {
  127. procinfo.dwSize=sizeof(procinfo);
  128. gotinfo=Process32First(snapshot,&procinfo);
  129. while (gotinfo)
  130. {
  131. if (procinfo.th32ParentProcessID==procid)
  132. {
  133. // printf("process=%x parent=%x module=%x path=%s\n",procinfo.th32ProcessID,procinfo.th32ParentProcessID,procinfo.th32ModuleID,procinfo.szExeFile);
  134. child=OpenProcess(PROCESS_ALL_ACCESS,0,procinfo.th32ProcessID);
  135. if (child)
  136. {
  137. res=TerminateProcess(child,-1);
  138. CloseHandle(child);
  139. }
  140. }
  141. gotinfo=Process32Next(snapshot,&procinfo);
  142. }
  143. CloseHandle(snapshot);
  144. }
  145. res=TerminateProcess(prochandle,-1);
  146. return res;
  147. }
  148. int fdClose(int fd)
  149. {
  150. return CloseHandle((HANDLE)fd);
  151. }
  152. int fdRead(int fd,char *buffer,int bytes)
  153. {
  154. int res;
  155. long count;
  156. res=ReadFile((HANDLE)fd,buffer,bytes,&count,0);
  157. if (res) return count;
  158. return 0;
  159. }
  160. int fdWrite(int fd,char *buffer,int bytes)
  161. {
  162. int res;
  163. long count;
  164. res=WriteFile((HANDLE)fd,buffer,bytes,&count,0);
  165. if (res) return count;
  166. return 0;
  167. }
  168. int fdFlush(int fd)
  169. {
  170. int res;
  171. res=FlushFileBuffers((HANDLE)fd);
  172. return res;
  173. }
  174. int fdAvail(int fd)
  175. {
  176. int res;
  177. long avail;
  178. res=PeekNamedPipe((HANDLE)fd,0,0,0,&avail,0);
  179. if (res) return avail;
  180. return 0;
  181. }
  182. //returns 1 for running, 0 for finished
  183. int fdProcessStatus( int pid ){
  184. PROCESS_INFORMATION *pi=(PROCESS_INFORMATION *)pid;
  185. long exitcode;
  186. if( GetExitCodeProcess( pi->hProcess,&exitcode ) ){
  187. if( exitcode==STILL_ACTIVE ) return 1;
  188. CloseHandle( pi->hProcess );
  189. free( pi );
  190. }
  191. return 0;
  192. }
  193. //returns 0 for success
  194. int fdTerminateProcess( int pid ){
  195. PROCESS_INFORMATION *pi=(PROCESS_INFORMATION *)pid;
  196. int res=TerminateProcessGroup( pi->hProcess,pi->dwProcessId );
  197. CloseHandle( pi->hProcess );
  198. free( pi );
  199. return res;
  200. }
  201. int fdProcess( BBString *cmd,int *procin,int *procout,int *procerr,int flags)
  202. {
  203. int res;
  204. int pflags=CREATE_NEW_PROCESS_GROUP;
  205. PROCESS_INFORMATION *pi;
  206. SECURITY_ATTRIBUTES sa={sizeof(sa),0,1};
  207. HANDLE istr,p_ostr; //our in-stream, process out-stream
  208. HANDLE ostr,p_istr; //our out-stream, process in-stream
  209. HANDLE estr,p_estr; //our errin-stream, process errout-stream
  210. if( !CreatePipe( &istr,&p_ostr,&sa,0 ) ){
  211. //unable to create pipe
  212. return 0;
  213. }
  214. if( !CreatePipe( &p_istr,&ostr,&sa,0 ) ){
  215. CloseHandle( istr );
  216. CloseHandle( p_ostr );
  217. //ditto
  218. return 0;
  219. }
  220. if (!CreatePipe(&estr,&p_estr,&sa,0)) {
  221. CloseHandle( istr );
  222. CloseHandle( p_ostr );
  223. CloseHandle( ostr );
  224. CloseHandle( p_istr );
  225. //unable to create pipe
  226. return 0;
  227. }
  228. pi=(PROCESS_INFORMATION*)calloc(1,sizeof(PROCESS_INFORMATION));
  229. if( _bbusew ){
  230. STARTUPINFOW si={sizeof(si)};
  231. si.dwFlags=STARTF_USESTDHANDLES;
  232. si.wShowWindow=SW_HIDE;
  233. si.hStdInput=p_istr;
  234. si.hStdOutput=p_ostr;
  235. si.hStdError=p_estr;
  236. if (flags&HIDECONSOLE) {
  237. si.dwFlags|=STARTF_USESHOWWINDOW;
  238. si.wShowWindow=SW_HIDE;
  239. }
  240. else {
  241. pflags|=DETACHED_PROCESS;
  242. }
  243. res=CreateProcessW( 0,bbTmpWString(cmd),0,0,-1,pflags,0,0,&si,pi );
  244. }else{
  245. STARTUPINFO si={sizeof(si)};
  246. si.dwFlags=STARTF_USESTDHANDLES;
  247. si.wShowWindow=SW_HIDE;
  248. si.hStdInput=p_istr;
  249. si.hStdOutput=p_ostr;
  250. si.hStdError=p_estr;
  251. if (flags&HIDECONSOLE) {
  252. si.dwFlags|=STARTF_USESHOWWINDOW;
  253. si.wShowWindow=SW_HIDE;
  254. }
  255. else {
  256. pflags|=DETACHED_PROCESS;
  257. }
  258. res=CreateProcess( 0,bbTmpCString(cmd),0,0,-1,pflags,0,0,&si,pi );
  259. }
  260. if( !res ){
  261. CloseHandle( istr );
  262. CloseHandle( ostr );
  263. CloseHandle( estr );
  264. CloseHandle( p_istr );
  265. CloseHandle( p_ostr );
  266. CloseHandle( p_estr );
  267. return 0;
  268. }
  269. CloseHandle( pi->hThread );
  270. *procin=(int)istr;
  271. *procout=(int)ostr;
  272. *procerr=(int)estr;
  273. CloseHandle( p_istr );
  274. CloseHandle( p_ostr );
  275. CloseHandle( p_estr );
  276. return (int)pi;
  277. }
  278. #endif