File: PtProcess.cxx

package info (click to toggle)
fldiff 1.1%2B0-4
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 456 kB
  • ctags: 242
  • sloc: cpp: 2,977; makefile: 134; sh: 27
file content (135 lines) | stat: -rw-r--r-- 3,499 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//========================================================================
// PtProcess.cxx
//========================================================================
// Portable Process with  pipes Handling
// Features easy File and Pipe/Process opening and reading uniformization 
// support of read "r" or write "w" popen modes
// Copyright F. Costantini 2006
// Version 1.0
//========================================================================
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License v2 as published
// by the Free Software Foundation.
//========================================================================

#if defined(WIN32) 
#include <windows.h>
#include <io.h>
#include <FCNTL.H>
#endif
#include <stdio.h>

#include "PtProcess.h"

#ifdef WIN32
void CPtProcess::clean_close(HANDLE& h) {
  if (h!= INVALID_HANDLE_VALUE) CloseHandle(h);
  h = INVALID_HANDLE_VALUE;
}

bool CPtProcess::createPipe(HANDLE * h, BOOL bInheritHnd) {
  SECURITY_ATTRIBUTES sa;

  sa.nLength = sizeof(sa);
  sa.lpSecurityDescriptor = NULL;
  sa.bInheritHandle = bInheritHnd; 

  return CreatePipe (&h[0],&h[1],&sa,0) ? true : false;
}


FILE * CPtProcess::freeHandles() {
	clean_close(pin[0]);    clean_close(pin[1]);
	clean_close(pout[0]);   clean_close(pout[1]);
	clean_close(perr[0]);   clean_close(perr[1]);
	
	return NULL; // convenient for error management
}
#endif 


CPtProcess::CPtProcess() {
	_fpt= NULL;
}

CPtProcess::~CPtProcess() {
	if (_fpt) {
		close();
	}
}

// file open :
FILE * CPtProcess::fopen(const char *cmd, const char *mode) {
#ifdef WIN32
	pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE;
#endif
	if (_fpt) close(); // close first before reuse
	_fpt = ::fopen(cmd,mode);
	return _fpt;
}

// pipe open :
FILE * CPtProcess::popen(const char *cmd, const char *mode) {
#if defined(WIN32) 

  // PRECONDITIONS
  if (!mode || !*mode || (*mode!='r' && *mode!='w') ) return NULL;
  if (_fpt) close(); // close first before reuse
  
  ptmode = *mode;
  
  pin[0] = pin[1] = pout[0] = pout[1] = perr[0] = perr[1] = INVALID_HANDLE_VALUE;
  // stderr to stdout wanted ?
  int fusion = (strstr(cmd,"2>&1") !=NULL);


  // Create windows pipes
  if (!createPipe(pin) || !createPipe(pout) || (!fusion && !createPipe(perr) ) )
	return freeHandles(); // error

  // Initialize Startup Info
  ZeroMemory(&si, sizeof(STARTUPINFO));
  si.cb           = sizeof(STARTUPINFO);
  si.dwFlags    = STARTF_USESTDHANDLES;
  si.hStdInput    = pin[0];
  si.hStdOutput   = pout[1];
  si.hStdError  = fusion ? pout[1] : perr [1];


  if ( CreateProcess(NULL, (LPTSTR) cmd,NULL,NULL,TRUE,
	  DETACHED_PROCESS,NULL,NULL, &si, &pi)) {
	  // don't need theses handles inherited by child process:
	  clean_close(pin[0]); clean_close(pout[1]); clean_close(perr[1]); 
	  HANDLE & h = *mode == 'r' ? pout[0] : pin[1];
	  _fpt = _fdopen(_open_osfhandle((long) h,_O_BINARY),mode);
	  h= INVALID_HANDLE_VALUE;  // reset the handle pointer that is shared 
								// with _fpt so we don't free it twice
  }

  if (!_fpt)  freeHandles();
  return _fpt;
#else  
  _fpt=::popen(cmd,mode);
  return _fpt;
#endif 
}

// close: 
int CPtProcess::close() {
#if defined(WIN32)
  if (_fpt) {
    fclose(_fpt);
    clean_close(perr[0]);
    fclose(_fpt);
	clean_close(pin[1]);
	clean_close(pout[0]);
	_fpt = NULL;
    return 0;
  }
  return -1;
#else  
  int ret = ::pclose(_fpt);
  _fpt=NULL;
  return ret;
#endif 
}