- Timestamp:
- Jul 7, 2009, 1:49:11 AM (16 years ago)
- Location:
- trunk/src/corelib/io
- Files:
-
- 3 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/corelib/io/qprocess.cpp
r2 r71 231 231 \snippet doc/src/snippets/process/process.cpp 0 232 232 233 \section1 Notes for Windows Users 233 \section1 Notes for Windows Users 234 234 235 235 Some Windows commands (for example, \c dir) are not provided by … … 413 413 processError = QProcess::UnknownError; 414 414 processState = QProcess::NotRunning; 415 #ifdef Q_OS_OS2 416 pid = PID_NULL; 417 #else 415 418 pid = 0; 419 #endif 416 420 sequenceNumber = 0; 417 421 exitCode = 0; … … 454 458 { 455 459 q_func()->setProcessState(QProcess::NotRunning); 460 #if !defined(Q_OS_OS2) 456 461 #ifdef Q_OS_WIN 457 462 if (pid) { … … 469 474 #endif 470 475 pid = 0; 476 #else 477 pid = PID_NULL; 478 #endif 471 479 sequenceNumber = 0; 472 480 dying = false; 473 481 482 #if !defined(Q_OS_OS2) 474 483 if (stdoutChannel.notifier) { 475 484 stdoutChannel.notifier->setEnabled(false); … … 504 513 destroyPipe(stderrChannel.pipe); 505 514 destroyPipe(stdinChannel.pipe); 515 #else 516 destroyPipe(stdoutChannel); 517 destroyPipe(stderrChannel); 518 destroyPipe(stdinChannel); 519 #endif 520 #if !defined(Q_OS_OS2) 506 521 destroyPipe(childStartedPipe); 507 522 destroyPipe(deathPipe); 523 #endif 508 524 #ifdef Q_OS_UNIX 509 525 serial = 0; … … 518 534 qint64 available = bytesAvailableFromStdout(); 519 535 if (available == 0) { 536 #if !defined(Q_OS_OS2) 520 537 if (stdoutChannel.notifier) 521 538 stdoutChannel.notifier->setEnabled(false); 522 539 destroyPipe(stdoutChannel.pipe); 540 #else 541 destroyPipe(stdoutChannel); 542 #endif 523 543 #if defined QPROCESS_DEBUG 524 544 qDebug("QProcessPrivate::canReadStandardOutput(), 0 bytes available"); … … 573 593 qint64 available = bytesAvailableFromStderr(); 574 594 if (available == 0) { 595 #if !defined(Q_OS_OS2) 575 596 if (stderrChannel.notifier) 576 597 stderrChannel.notifier->setEnabled(false); 577 598 destroyPipe(stderrChannel.pipe); 599 #else 600 destroyPipe(stderrChannel); 601 #endif 578 602 return false; 579 603 } … … 628 652 writeBuffer.nextDataBlockSize()); 629 653 if (written < 0) { 654 #if !defined(Q_OS_OS2) 630 655 destroyPipe(stdinChannel.pipe); 656 #else 657 destroyPipe(stdinChannel); 658 #endif 631 659 processError = QProcess::WriteError; 632 660 q->setErrorString(QProcess::tr("Error writing to process")); … … 766 794 qDeleteInEventHandler(stdinChannel.notifier); 767 795 stdinChannel.notifier = 0; 768 } 796 } 769 797 } 770 798 #ifdef Q_OS_WIN … … 773 801 flushPipeWriter(); 774 802 #endif 803 #if !defined(Q_OS_OS2) 775 804 destroyPipe(stdinChannel.pipe); 805 #else 806 destroyPipe(stdinChannel); 807 #endif 776 808 } 777 809 … … 1075 1107 /*! 1076 1108 Returns the native process identifier for the running process, if 1077 available. If no process is currently running, 0 is returned. 1109 available. If no process is currently running, 0 is returned on all 1110 platforms except OS/2 which returns PID_NULL in this case. 1078 1111 */ 1079 1112 Q_PID QProcess::pid() const -
trunk/src/corelib/io/qprocess.h
r2 r71 56 56 #if (!defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)) || defined(qdoc) 57 57 typedef qint64 Q_PID; 58 #elif defined(Q_OS_OS2) 59 typedef PID Q_PID; 60 #define PID_NULL PID(~0) 58 61 #else 59 62 QT_END_NAMESPACE -
trunk/src/corelib/io/qprocess_os2.cpp
r63 r71 3 3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 4 4 ** Contact: Qt Software Information (qt-info@nokia.com) 5 ** 6 ** Copyright (C) 2009 netlabs.org. OS/2 parts. 5 7 ** 6 8 ** This file is part of the QtCore module of the Qt Toolkit. … … 42 44 #include "qprocess.h" 43 45 #include "qprocess_p.h" 44 #include "qwindowspipewriter_p.h" 45 46 #include <qdatetime.h> 47 #include <qdir.h> 48 #include <qfileinfo.h> 49 #include <qtimer.h> 50 #include <qthread.h> 51 #include <qmutex.h> 52 #include <qwaitcondition.h> 53 #include <private/qwineventnotifier_p.h> 54 #include <private/qthread_p.h> 55 #include <qdebug.h> 56 57 #include "private/qfsfileengine_p.h" // for longFileName and win95FileName 46 // @todo need? 47 //#include "qwindowspipewriter_p.h" 48 49 // @todo need what? 50 //#include <qdatetime.h> 51 //#include <qdir.h> 52 //#include <qfileinfo.h> 53 //#include <qtimer.h> 54 //#include <qthread.h> 55 //#include <qmutex.h> 56 //#include <qwaitcondition.h> 57 //#include <private/qthread_p.h> 58 //#include <qdebug.h> 58 59 59 60 … … 64 65 //#define QPROCESS_DEBUG 65 66 66 #define NOTIFYTIMEOUT 100 67 68 static void qt_create_pipe(Q_PIPE *pipe, bool in) 69 { 70 // Open the pipes. Make non-inheritable copies of input write and output 71 // read handles to avoid non-closable handles (this is done by the 72 // DuplicateHandle() call). 73 74 #if !defined(Q_OS_WINCE) 75 SECURITY_ATTRIBUTES secAtt = { sizeof( SECURITY_ATTRIBUTES ), NULL, TRUE }; 76 77 HANDLE tmpHandle; 78 if (in) { // stdin 79 if (!CreatePipe(&pipe[0], &tmpHandle, &secAtt, 1024 * 1024)) 80 return; 81 if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, GetCurrentProcess(), 82 &pipe[1], 0, FALSE, DUPLICATE_SAME_ACCESS)) 83 return; 84 } else { // stdout or stderr 85 if (!CreatePipe(&tmpHandle, &pipe[1], &secAtt, 1024 * 1024)) 86 return; 87 if (!DuplicateHandle(GetCurrentProcess(), tmpHandle, GetCurrentProcess(), 88 &pipe[0], 0, FALSE, DUPLICATE_SAME_ACCESS)) 89 return; 90 } 91 92 CloseHandle(tmpHandle); 93 #else 94 Q_UNUSED(pipe); 95 Q_UNUSED(in); 96 #endif 97 } 67 // @todo need? 68 //#define NOTIFYTIMEOUT 100 69 70 enum 71 { 72 PIPE_SIZE_STDIN = 65520, // max 73 PIPE_SIZE_STDOUT = 65520, // max 74 PIPE_SIZE_STDERR = 4096, 75 76 // @todo need? 77 // POLL_TIMER = 100, 78 // 79 // // new pipe data notification 80 // WM_U_PIPE_RDATA = WM_USER + 0, 81 // WM_U_PIPE_CLOSE = WM_USER + 1, 82 }; 98 83 99 84 /* … … 107 92 108 93 if (&channel == &stderrChannel && processChannelMode == QProcess::MergedChannels) { 109 return DuplicateHandle(GetCurrentProcess(), stdoutChannel.pipe[1], GetCurrentProcess(), 110 &stderrChannel.pipe[1], 0, TRUE, DUPLICATE_SAME_ACCESS); 111 } 94 // we will make a stdout to stderr redirection upon process startup 95 channel.pipe = HP_NULL; 96 channel.file = HF_NULL; 97 return true; 98 } 99 100 // we need the process identifier to guarantee pipe name unicity 101 PPIB ppib = NULL; 102 DosGetInfoBlocks(NULL, &ppib); 103 104 APIRET rc = 0; 105 char pathBuf[CCHMAXPATH]; 112 106 113 107 if (channel.type == Channel::Normal) { 114 // we're piping this channel to our own process 115 qt_create_pipe(channel.pipe, &channel == &stdinChannel); 108 const char *name; 109 ULONG pipeMode; 110 ULONG outBufSize; 111 ULONG inBufSize; 112 ULONG fileMode; 113 if (&channel == &stdinChannel) { 114 name = "Stdin"; 115 pipeMode = NP_ACCESS_OUTBOUND; 116 outBufSize = PIPE_SIZE_STDIN; 117 inBufSize = 0; 118 fileMode = OPEN_ACCESS_READONLY; 119 } else if (&channel == &stdoutChannel) { 120 name = "Stdout"; 121 pipeMode = NP_ACCESS_INBOUND; 122 outBufSize = 0; 123 inBufSize = PIPE_SIZE_STDOUT; 124 fileMode = OPEN_ACCESS_WRITEONLY; 125 } else if (&channel == &stderrChannel) { 126 name = "Stderr"; 127 pipeMode = NP_ACCESS_INBOUND; 128 outBufSize = 0; 129 inBufSize = PIPE_SIZE_STDERR; 130 fileMode = OPEN_ACCESS_WRITEONLY; 131 } else { 132 Q_ASSERT(false); 133 return false; 134 } 135 136 sprintf(pathBuf, "\\pipe\\Qt\\%08lX\\QProcess\\%p\\%s", 137 ppib->pib_ulpid, name, this); 138 rc = DosCreateNPipe(pathBuf, &channel.pipe, 139 pipeMode | NP_NOINHERIT, NP_NOWAIT | NP_TYPE_BYTE | 1, 140 outBufSize, inBufSize, 0); 141 if (rc != NO_ERROR) { 142 qWarning("QProcessPrivate::createChannel: DosCreateNPipe(%s) " 143 "returned %lu", pathBuf, rc); 144 return false; 145 } 146 DosConnectNPipe(channel.pipe); 147 148 // open the client end of the pipe 149 ULONG action = 0; 150 rc = DosOpen(pathBuf, &channel.file, &action, 0, FILE_NORMAL, FILE_OPEN, 151 fileMode | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_NOINHERIT, 152 (PEAOP2) NULL); 153 if (rc != NO_ERROR) { 154 qWarning("QProcessPrivate::createChannel: DosOpen(%s) " 155 "returned %lu", pathBuf, rc); 156 return false; 157 } 116 158 117 159 return true; 118 160 } else if (channel.type == Channel::Redirect) { 119 161 // we're redirecting the channel to/from a file 120 SECURITY_ATTRIBUTES secAtt = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; 162 channel.pipe = HP_NULL; 163 QByteArray fname = QFile::encodeName(channel.file); 164 ULONG action = 0; 121 165 122 166 if (&channel == &stdinChannel) { 123 // try to open in read-only mode 124 channel.pipe[1] = INVALID_Q_PIPE; 125 QT_WA({ 126 channel.pipe[0] = 127 CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), 128 GENERIC_READ, 129 FILE_SHARE_READ | FILE_SHARE_WRITE, 130 &secAtt, 131 OPEN_EXISTING, 132 FILE_ATTRIBUTE_NORMAL, 133 NULL); 134 }, { 135 channel.pipe[0] = 136 CreateFileA(QFSFileEnginePrivate::win95Name(channel.file), 137 GENERIC_READ, 138 FILE_SHARE_READ | FILE_SHARE_WRITE, 139 &secAtt, 140 OPEN_EXISTING, 141 FILE_ATTRIBUTE_NORMAL, 142 NULL); 143 }); 144 if (channel.pipe[0] != INVALID_Q_PIPE) 167 // open in read-only mode 168 rc = DosOpen(fname, &channel.file, &action, 0, FILE_NORMAL, FILE_OPEN, 169 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT, 170 (PEAOP2) NULL); 171 if (rc == NO_ERROR) 145 172 return true; 146 173 … … 148 175 } else { 149 176 // open in write mode 150 channel.pipe[0] = INVALID_Q_PIPE; 151 DWORD creation; 152 if (channel.append) 153 creation = OPEN_ALWAYS; 154 else 155 creation = CREATE_ALWAYS; 156 157 QT_WA({ 158 channel.pipe[1] = 159 CreateFileW((TCHAR*)QFSFileEnginePrivate::longFileName(channel.file).utf16(), 160 GENERIC_WRITE, 161 FILE_SHARE_READ | FILE_SHARE_WRITE, 162 &secAtt, 163 creation, 164 FILE_ATTRIBUTE_NORMAL, 165 NULL); 166 }, { 167 channel.pipe[1] = 168 CreateFileA(QFSFileEnginePrivate::win95Name(channel.file), 169 GENERIC_WRITE, 170 FILE_SHARE_READ | FILE_SHARE_WRITE, 171 &secAtt, 172 creation, 173 FILE_ATTRIBUTE_NORMAL, 174 NULL); 175 }); 176 if (channel.pipe[1] != INVALID_Q_PIPE) { 177 ULONG flags = channel.append ? FILE_OPEN : FILE_CREATE; 178 rc = DosOpen(fname, &channel.file, &action, 0, FILE_NORMAL, 179 channel.append ? FILE_OPEN : FILE_CREATE, 180 OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_NOINHERIT, 181 (PEAOP2) NULL); 182 if (rc == NO_ERROR) { 177 183 if (channel.append) { 178 SetFilePointer(channel.pipe[1], 0, NULL, FILE_END); 184 ULONG actual; 185 DosSetFilePtr(channel.file, 0, &actual); 179 186 } 180 187 return true; … … 200 207 sink = &channel.process->stdinChannel; 201 208 202 if (source->pipe[1] != INVALID_Q_PIPE) {203 // already constructed by the sink204 // make it inheritable205 HANDLE tmpHandle = source->pipe[1];206 if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,207 GetCurrentProcess(), &source->pipe[1],208 0, TRUE, DUPLICATE_SAME_ACCESS))209 return false;210 211 CloseHandle(tmpHandle);212 return true;213 }214 215 209 Q_ASSERT(source == &stdoutChannel); 216 210 Q_ASSERT(sink->process == this && sink->type == Channel::PipeSink); 217 218 qt_create_pipe(source->pipe, /* in = */ false); // source is stdout219 sink->pipe[0] = source->pipe[0];220 source->pipe[0] = INVALID_Q_PIPE;221 222 return true;223 211 } else { 224 212 // we are the sink; … … 226 214 sink = &channel; 227 215 228 if (sink->pipe[0] != INVALID_Q_PIPE) {229 // already constructed by the source230 // make it inheritable231 HANDLE tmpHandle = sink->pipe[0];232 if (!DuplicateHandle(GetCurrentProcess(), tmpHandle,233 GetCurrentProcess(), &sink->pipe[0],234 0, TRUE, DUPLICATE_SAME_ACCESS))235 return false;236 237 CloseHandle(tmpHandle);238 return true;239 }240 216 Q_ASSERT(sink == &stdinChannel); 241 217 Q_ASSERT(source->process == this && source->type == Channel::PipeSource); 242 243 qt_create_pipe(sink->pipe, /* in = */ true); // sink is stdin 244 source->pipe[1] = sink->pipe[1];245 sink->pipe[1] = INVALID_Q_PIPE;246 218 } 219 220 if (source->pipe != HP_NULL && sink->file != HF_NULL) { 221 // already created, do nothing 222 Q_ASSERT(sink->pipe == HP_NULL && source->file == HF_NULL); 247 223 return true; 248 } 249 } 250 } 251 252 void QProcessPrivate::destroyPipe(Q_PIPE pipe[2]) 253 { 254 if (pipe[0] == stdinChannel.pipe[0] && pipe[1] == stdinChannel.pipe[1] && pipeWriter) { 255 delete pipeWriter; 256 pipeWriter = 0; 257 } 258 259 if (pipe[0] != INVALID_Q_PIPE) { 260 CloseHandle(pipe[0]); 261 pipe[0] = INVALID_Q_PIPE; 262 } 263 if (pipe[1] != INVALID_Q_PIPE) { 264 CloseHandle(pipe[1]); 265 pipe[1] = INVALID_Q_PIPE; 266 } 267 } 268 269 270 static QString qt_create_commandline(const QString &program, const QStringList &arguments) 271 { 272 QString args; 273 if (!program.isEmpty()) { 274 QString programName = program; 275 if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1String(" "))) 276 programName = QLatin1String("\"") + programName + QLatin1String("\""); 277 programName.replace(QLatin1String("/"), QLatin1String("\\")); 278 279 // add the prgram as the first arg ... it works better 280 args = programName + QLatin1String(" "); 281 } 282 283 for (int i=0; i<arguments.size(); ++i) { 284 QString tmp = arguments.at(i); 285 // in the case of \" already being in the string the \ must also be escaped 286 tmp.replace( QLatin1String("\\\""), QLatin1String("\\\\\"") ); 287 // escape a single " because the arguments will be parsed 288 tmp.replace( QLatin1String("\""), QLatin1String("\\\"") ); 289 if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) { 290 // The argument must not end with a \ since this would be interpreted 291 // as escaping the quote -- rather put the \ behind the quote: e.g. 292 // rather use "foo"\ than "foo\" 293 QString endQuote(QLatin1String("\"")); 294 int i = tmp.length(); 295 while (i>0 && tmp.at(i-1) == QLatin1Char('\\')) { 296 --i; 297 endQuote += QLatin1String("\\"); 224 } else { 225 // create a single pipe for both processes (source will get its handle) 226 Q_ASSERT(source->pipe == HP_NULL && source->file == HF_NULL); 227 Q_ASSERT(sink->pipe == HP_NULL && sink->file == HF_NULL); 228 229 sprintf(pathBuf, "\\pipe\\Qt\\%08lX\\QProcess\\%p\\SinkTo\\%p", 230 ppib->pib_ulpid, sink->process, source->process); 231 rc = DosCreateNPipe(pathBuf, &source->pipe, 232 NP_ACCESS_OUTBOUND | NP_NOINHERIT, NP_NOWAIT | NP_TYPE_BYTE | 1, 233 PIPE_SIZE_STDOUT, 0, 0); 234 if (rc != NO_ERROR) { 235 qWarning("QProcessPrivate::createChannel: DosCreateNPipe(%s) " 236 "returned %lu", pathBuf, rc); 237 return false; 298 238 } 299 args += QLatin1String(" \"") + tmp.left(i) + endQuote; 300 } else { 301 args += QLatin1Char(' ') + tmp; 302 } 303 } 304 return args; 305 } 306 307 static QByteArray qt_create_environment(const QStringList &environment) 308 { 309 QByteArray envlist; 310 if (!environment.isEmpty()) { 311 QStringList envStrings = environment; 312 int pos = 0; 313 // add PATH if necessary (for DLL loading) 314 if (envStrings.filter(QRegExp(QLatin1String("^PATH="),Qt::CaseInsensitive)).isEmpty()) { 315 QByteArray path = qgetenv("PATH"); 316 if (!path.isEmpty()) 317 envStrings.prepend(QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path))); 318 } 319 // add systemroot if needed 320 if (envStrings.filter(QRegExp(QLatin1String("^SystemRoot="),Qt::CaseInsensitive)).isEmpty()) { 321 QByteArray systemRoot = qgetenv("SystemRoot"); 322 if (!systemRoot.isEmpty()) 323 envStrings.prepend(QString(QLatin1String("SystemRoot=%1")).arg(QString::fromLocal8Bit(systemRoot))); 324 } 325 #ifdef UNICODE 326 if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { 327 for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); ++it) { 328 QString tmp = *it; 329 uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); 330 envlist.resize(envlist.size() + tmpSize); 331 memcpy(envlist.data()+pos, tmp.utf16(), tmpSize); 332 pos += tmpSize; 333 } 334 // add the 2 terminating 0 (actually 4, just to be on the safe side) 335 envlist.resize( envlist.size()+4 ); 336 envlist[pos++] = 0; 337 envlist[pos++] = 0; 338 envlist[pos++] = 0; 339 envlist[pos++] = 0; 340 } else 341 #endif // UNICODE 342 { 343 for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); it++) { 344 QByteArray tmp = (*it).toLocal8Bit(); 345 uint tmpSize = tmp.length() + 1; 346 envlist.resize(envlist.size() + tmpSize); 347 memcpy(envlist.data()+pos, tmp.data(), tmpSize); 348 pos += tmpSize; 239 DosConnectNPipe(source->pipe); 240 241 // open the client end of the pipe that sink will get 242 ULONG action = 0; 243 rc = DosOpen(pathBuf, &sink->file, &action, 0, FILE_NORMAL, FILE_OPEN, 244 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYREADWRITE | OPEN_FLAGS_NOINHERIT, 245 (PEAOP2) NULL); 246 if (rc != NO_ERROR) { 247 qWarning("QProcessPrivate::createChannel: DosOpen(%s) " 248 "returned %lu", pathBuf, rc); 249 return false; 349 250 } 350 // add the terminating 0 (actually 2, just to be on the safe side) 351 envlist.resize(envlist.size()+2); 352 envlist[pos++] = 0; 353 envlist[pos++] = 0; 354 } 355 } 356 return envlist; 357 } 251 252 source->file = HF_NULL; 253 sink->pipe = HP_NULL; 254 return true; 255 } 256 } 257 } 258 259 void QProcessPrivate::destroyPipe(QProcessPrivate::Channel &channel) 260 { 261 if (channel.file != HF_NULL) { 262 DosClose(channel.file); 263 channel.file = HP_NULL; 264 } 265 266 if (channel.pipe != HP_NULL) { 267 DosDisConnectPipe(channel.pipe); 268 DosClose(channel.pipe); 269 channel.pipe = HP_NULL; 270 } 271 } 272 273 // @todo need? 274 //static QString qt_create_commandline(const QString &program, const QStringList &arguments) 275 //{ 276 // QString args; 277 // if (!program.isEmpty()) { 278 // QString programName = program; 279 // if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1String(" "))) 280 // programName = QLatin1String("\"") + programName + QLatin1String("\""); 281 // programName.replace(QLatin1String("/"), QLatin1String("\\")); 282 // 283 // // add the prgram as the first arg ... it works better 284 // args = programName + QLatin1String(" "); 285 // } 286 // 287 // for (int i=0; i<arguments.size(); ++i) { 288 // QString tmp = arguments.at(i); 289 // // in the case of \" already being in the string the \ must also be escaped 290 // tmp.replace( QLatin1String("\\\""), QLatin1String("\\\\\"") ); 291 // // escape a single " because the arguments will be parsed 292 // tmp.replace( QLatin1String("\""), QLatin1String("\\\"") ); 293 // if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) { 294 // // The argument must not end with a \ since this would be interpreted 295 // // as escaping the quote -- rather put the \ behind the quote: e.g. 296 // // rather use "foo"\ than "foo\" 297 // QString endQuote(QLatin1String("\"")); 298 // int i = tmp.length(); 299 // while (i>0 && tmp.at(i-1) == QLatin1Char('\\')) { 300 // --i; 301 // endQuote += QLatin1String("\\"); 302 // } 303 // args += QLatin1String(" \"") + tmp.left(i) + endQuote; 304 // } else { 305 // args += QLatin1Char(' ') + tmp; 306 // } 307 // } 308 // return args; 309 //} 310 // 311 //static QByteArray qt_create_environment(const QStringList &environment) 312 //{ 313 // QByteArray envlist; 314 // if (!environment.isEmpty()) { 315 // QStringList envStrings = environment; 316 // int pos = 0; 317 // // add PATH if necessary (for DLL loading) 318 // if (envStrings.filter(QRegExp(QLatin1String("^PATH="),Qt::CaseInsensitive)).isEmpty()) { 319 // QByteArray path = qgetenv("PATH"); 320 // if (!path.isEmpty()) 321 // envStrings.prepend(QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path))); 322 // } 323 // // add systemroot if needed 324 // if (envStrings.filter(QRegExp(QLatin1String("^SystemRoot="),Qt::CaseInsensitive)).isEmpty()) { 325 // QByteArray systemRoot = qgetenv("SystemRoot"); 326 // if (!systemRoot.isEmpty()) 327 // envStrings.prepend(QString(QLatin1String("SystemRoot=%1")).arg(QString::fromLocal8Bit(systemRoot))); 328 // } 329 //#ifdef UNICODE 330 // if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { 331 // for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); ++it) { 332 // QString tmp = *it; 333 // uint tmpSize = sizeof(TCHAR) * (tmp.length()+1); 334 // envlist.resize(envlist.size() + tmpSize); 335 // memcpy(envlist.data()+pos, tmp.utf16(), tmpSize); 336 // pos += tmpSize; 337 // } 338 // // add the 2 terminating 0 (actually 4, just to be on the safe side) 339 // envlist.resize( envlist.size()+4 ); 340 // envlist[pos++] = 0; 341 // envlist[pos++] = 0; 342 // envlist[pos++] = 0; 343 // envlist[pos++] = 0; 344 // } else 345 //#endif // UNICODE 346 // { 347 // for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); it++) { 348 // QByteArray tmp = (*it).toLocal8Bit(); 349 // uint tmpSize = tmp.length() + 1; 350 // envlist.resize(envlist.size() + tmpSize); 351 // memcpy(envlist.data()+pos, tmp.data(), tmpSize); 352 // pos += tmpSize; 353 // } 354 // // add the terminating 0 (actually 2, just to be on the safe side) 355 // envlist.resize(envlist.size()+2); 356 // envlist[pos++] = 0; 357 // envlist[pos++] = 0; 358 // } 359 // } 360 // return envlist; 361 //} 358 362 359 363 void QProcessPrivate::startProcess() … … 362 366 363 367 bool success = false; 364 365 if (pid) {366 CloseHandle(pid->hThread);367 CloseHandle(pid->hProcess);368 delete pid;369 pid = 0;370 }371 pid = new PROCESS_INFORMATION;372 memset(pid, 0, sizeof(PROCESS_INFORMATION));373 368 374 369 q->setProcessState(QProcess::Starting); … … 379 374 return; 380 375 381 #if defined(Q_OS_WINCE) 382 QString args = qt_create_commandline(QString(), arguments); 383 #else 384 QString args = qt_create_commandline(program, arguments); 385 QByteArray envlist = qt_create_environment(environment); 386 #endif 387 388 #if defined QPROCESS_DEBUG 389 qDebug("Creating process"); 390 qDebug(" program : [%s]", program.toLatin1().constData()); 391 qDebug(" args : %s", args.toLatin1().constData()); 392 qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes"); 393 #endif 394 395 DWORD dwCreationFlags = 0; 396 if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) 397 dwCreationFlags |= CREATE_NO_WINDOW; 398 399 #ifdef UNICODE 400 if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) { 401 #if defined(Q_OS_WINCE) 402 QString fullPathProgram = program; 403 if (!QDir::isAbsolutePath(fullPathProgram)) 404 fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath(); 405 fullPathProgram.replace(QLatin1String("/"), QLatin1String("\\")); 406 success = CreateProcessW((WCHAR*)fullPathProgram.utf16(), 407 (WCHAR*)args.utf16(), 408 0, 0, false, 0, 0, 0, 0, pid); 409 #else 410 dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; 411 STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0, 412 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 413 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 414 0, 0, 0, 415 STARTF_USESTDHANDLES, 416 0, 0, 0, 417 stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] 418 }; 419 success = CreateProcessW(0, (WCHAR*)args.utf16(), 420 0, 0, TRUE, dwCreationFlags, 421 environment.isEmpty() ? 0 : envlist.data(), 422 workingDirectory.isEmpty() ? 0 423 : (WCHAR*)QDir::toNativeSeparators(workingDirectory).utf16(), 424 &startupInfo, pid); 425 #endif 426 } else 427 #endif // UNICODE 428 { 429 #ifndef Q_OS_WINCE 430 STARTUPINFOA startupInfo = { sizeof( STARTUPINFOA ), 0, 0, 0, 431 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 432 (ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT, 433 0, 0, 0, 434 STARTF_USESTDHANDLES, 435 0, 0, 0, 436 stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1] 437 }; 438 439 success = CreateProcessA(0, args.toLocal8Bit().data(), 440 0, 0, TRUE, dwCreationFlags, environment.isEmpty() ? 0 : envlist.data(), 441 workingDirectory.isEmpty() ? 0 442 : QDir::toNativeSeparators(workingDirectory).toLocal8Bit().data(), 443 &startupInfo, pid); 444 #endif // Q_OS_WINCE 445 } 446 #ifndef Q_OS_WINCE 447 if (stdinChannel.pipe[0] != INVALID_Q_PIPE) { 448 CloseHandle(stdinChannel.pipe[0]); 449 stdinChannel.pipe[0] = INVALID_Q_PIPE; 450 } 451 if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) { 452 CloseHandle(stdoutChannel.pipe[1]); 453 stdoutChannel.pipe[1] = INVALID_Q_PIPE; 454 } 455 if (stderrChannel.pipe[1] != INVALID_Q_PIPE) { 456 CloseHandle(stderrChannel.pipe[1]); 457 stderrChannel.pipe[1] = INVALID_Q_PIPE; 458 } 459 #endif // Q_OS_WINCE 376 // @todo remove 377 //#if defined(Q_OS_WINCE) 378 // QString args = qt_create_commandline(QString(), arguments); 379 //#else 380 // QString args = qt_create_commandline(program, arguments); 381 // QByteArray envlist = qt_create_environment(environment); 382 //#endif 383 // 384 //#if defined QPROCESS_DEBUG 385 // qDebug("Creating process"); 386 // qDebug(" program : [%s]", program.toLatin1().constData()); 387 // qDebug(" args : %s", args.toLatin1().constData()); 388 // qDebug(" pass environment : %s", environment.isEmpty() ? "no" : "yes"); 389 //#endif 390 391 392 393 394 395 396 397 398 399 400 401 402 460 403 461 404 if (!success) { … … 470 413 q->setProcessState(QProcess::Running); 471 414 // User can call kill()/terminate() from the stateChanged() slot 472 // so check before proceeding 473 if ( !pid)415 // so check before proceeding 416 if (pid == PID_NULL) 474 417 return; 475 418 476 if (threadData->eventDispatcher) { 477 processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q); 478 QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied())); 479 processFinishedNotifier->setEnabled(true); 480 notifier = new QTimer(q); 481 QObject::connect(notifier, SIGNAL(timeout()), q, SLOT(_q_notified())); 482 notifier->start(NOTIFYTIMEOUT); 483 } 484 485 // give the process a chance to start ... 486 Sleep(SLEEPMIN*2); 419 // @todo check this 487 420 _q_startupNotification(); 488 421 } … … 875 808 }; 876 809 success = CreateProcessW(0, (WCHAR*)args.utf16(), 877 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, 810 0, 0, FALSE, CREATE_UNICODE_ENVIRONMENT | CREATE_NEW_CONSOLE, 0, 878 811 workingDir.isEmpty() ? (const WCHAR *)0 : (const WCHAR *)workingDir.utf16(), 879 812 &startupInfo, &pinfo); -
trunk/src/corelib/io/qprocess_p.h
r2 r71 59 59 #include "private/qiodevice_p.h" 60 60 61 #if def Q_OS_WIN61 #if defined(Q_OS_WIN) 62 62 #include "QtCore/qt_windows.h" 63 63 typedef HANDLE Q_PIPE; 64 64 #define INVALID_Q_PIPE INVALID_HANDLE_VALUE 65 #elif defined(Q_OS_OS2) 66 #include "QtCore/qt_os2.h" 67 #define HP_NULL HPIPE(~0) 68 #define HF_NULL HFILE(~0) 65 69 #else 66 70 typedef int Q_PIPE; … … 93 97 Channel() : process(0), notifier(0), type(Normal), closed(false), append(false) 94 98 { 99 #if !defined(Q_OS_OS2) 95 100 pipe[0] = INVALID_Q_PIPE; 96 101 pipe[1] = INVALID_Q_PIPE; 102 #else 103 pipe = HP_NULL; 104 file = HF_NULL; 105 #endif 97 106 } 98 107 … … 123 132 QString file; 124 133 QProcessPrivate *process; 134 #if !defined(Q_OS_OS2) 125 135 QSocketNotifier *notifier; 126 136 Q_PIPE pipe[2]; 137 #else 138 HPIPE pipe; 139 HFILE file; 140 #endif 127 141 128 142 unsigned type : 2; … … 168 182 QRingBuffer writeBuffer; 169 183 184 #if !defined(Q_OS_OS2) 170 185 Q_PIPE childStartedPipe[2]; 171 186 Q_PIPE deathPipe[2]; … … 179 194 QWindowsPipeWriter *pipeWriter; 180 195 QWinEventNotifier *processFinishedNotifier; 196 #else 197 void destroyPipe(Channel &channel); 198 #endif 181 199 182 200 void startProcess();
Note:
See TracChangeset
for help on using the changeset viewer.