viewvc-4intranet/lib/popen.py

191 lines
5.4 KiB
Python
Raw Permalink Normal View History

# -*-python-*-
#
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
Work on issue 168, s/ViewCVS/ViewVC. This patch changes references to ViewCVS in comments, strings, and documentation. References to ViewCVS in filenames and urls still need to be fixed. Also, logo.png (the blimp) needs to be updated or replaced. This patch is by Gerard Gerritsen (sigcafe), the only change I've made is to restore a reference to ViewCVS in a comment about backwards compatibility. * windows/README * viewcvs-install * README * templates/include/footer.ezt * templates/include/header.ezt * templates/error.ezt * templates/query.ezt * templates/docroot/help.css * templates/docroot/help_query.html * templates/docroot/help_dirview.html * templates/docroot/help_rootview.html * templates/docroot/styles.css * templates/docroot/help_log.html * templates/diff.ezt * tools/make-release * lib/sapi.py * lib/dbi.py * lib/accept.py * lib/cvsdb.py * lib/config.py * lib/query.py * lib/vclib/bincvs/__init__.py * lib/vclib/svn/__init__.py * lib/vclib/__init__.py * lib/vclib/svn_ra/__init__.py * lib/vclib/ccvs/rcsparse/common.py * lib/vclib/ccvs/rcsparse/__init__.py * lib/vclib/ccvs/rcsparse/default.py * lib/vclib/ccvs/rcsparse/texttools.py * lib/vclib/ccvs/rcsparse/debug.py * lib/vclib/ccvs/__init__.py * lib/vclib/ccvs/blame.py * lib/blame.py * lib/popen.py * lib/compat.py * lib/viewcvs.py * lib/debug.py * INSTALL * bin/standalone.py * bin/make-database * bin/mod_python/query.py * bin/mod_python/viewcvs.py * bin/cgi/query.cgi * bin/cgi/viewcvs.cgi * bin/asp/query.asp * bin/asp/viewcvs.asp * bin/svndbadmin * bin/loginfo-handler * bin/cvsdbadmin * viewcvs.conf.dist git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1200 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-12-17 20:19:28 +03:00
# the LICENSE.html file which can be found at the top level of the ViewVC
# distribution or at http://viewvc.org/license-1.html.
#
# For more information, visit http://viewvc.org/
#
# -----------------------------------------------------------------------
#
# popen.py: a replacement for os.popen()
#
# This implementation of popen() provides a cmd + args calling sequence,
# rather than a system() type of convention. The shell facilities are not
# available, but that implies we can avoid worrying about shell hacks in
# the arguments.
#
# -----------------------------------------------------------------------
import os
import sys
import sapi
import threading
if sys.platform == "win32":
import win32popen
import win32event
import win32process
import debug
import StringIO
def popen(cmd, args, mode, capture_err=1):
if sys.platform == "win32":
command = win32popen.CommandLine(cmd, args)
Wow. Drop a "general code cleanup" kind of bomb on the codebase. All of this is aimed at not paying the maintenance price of supporting Python versions prior to 2.4 any longer, plus a little bit of just getting dead code out of the way. * lib/compat.py Remove as unused. * bin/cvsdbadmin, * bin/loginfo-handler, * bin/make-database, * bin/svndbadmin, * lib/accept.py, * lib/blame.py, * lib/cvsdb.py, * lib/popen.py, * lib/query.py, * lib/sapi.py, * lib/vcauth/forbidden/__init__.py * lib/vcauth/forbiddenre/__init__.py, * lib/vcauth/svnauthz/__init__.py, * lib/vclib/__init__.py, * lib/vclib/ccvs/blame.py, * lib/win32popen.py, * tests/timelog.py Replace explicit import and use of the 'string' module with newer constructs. * bin/standalone.py, * lib/viewvc.py No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. * lib/dbi.py Use calender.timegm() instead of compat.timegm(). * lib/vcauth/__init__.py Lose unused module imports. * lib/config.py, Replace explicit import and use of the 'string' module with newer constructs where possible. Lose old ConfigParser patch-up code for Python 1.5.1. * lib/vclib/ccvs/ccvs.py Replace explicit import and use of the 'string' module with newer constructs where possible. Import _path_join() from bincvs, and use it instead of a bunch of copy-and-pasted string join() statements throughout. * lib/vclib/ccvs/__init__.py (cvs_strptime): Moved here from the 'compat' module. * lib/vclib/ccvs/bincvs.py (): No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. (_path_join): New, used now instead of a bunch of copy-and-pasted string join() statements throughout. * viewvc-install Don't use the 'compat' module any more. Also, so some rearranging of non-critical bits. * misc/: New directory. * misc/py2html.py: Moved from 'lib/py2html.py'. * misc/PyFontify.py: Moved from 'lib/PyFontify.py'. * misc/elemx/: Moved from 'elemx/'. * misc/tparse/: Moved from 'tparse/'. * tools/make-release Omit 'misc' directory from releases, too. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2437 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-03 20:49:52 +04:00
if mode.find('r') >= 0:
hStdIn = None
if debug.SHOW_CHILD_PROCESSES:
dbgIn, dbgOut = None, StringIO.StringIO()
handle, hStdOut = win32popen.MakeSpyPipe(0, 1, (dbgOut,))
if capture_err:
hStdErr = hStdOut
dbgErr = dbgOut
else:
dbgErr = StringIO.StringIO()
x, hStdErr = win32popen.MakeSpyPipe(None, 1, (dbgErr,))
else:
handle, hStdOut = win32popen.CreatePipe(0, 1)
if capture_err:
hStdErr = hStdOut
else:
hStdErr = win32popen.NullFile(1)
else:
if debug.SHOW_CHILD_PROCESSES:
dbgIn, dbgOut, dbgErr = StringIO.StringIO(), StringIO.StringIO(), StringIO.StringIO()
hStdIn, handle = win32popen.MakeSpyPipe(1, 0, (dbgIn,))
x, hStdOut = win32popen.MakeSpyPipe(None, 1, (dbgOut,))
x, hStdErr = win32popen.MakeSpyPipe(None, 1, (dbgErr,))
else:
hStdIn, handle = win32popen.CreatePipe(0, 1)
hStdOut = None
hStdErr = None
phandle, pid, thandle, tid = win32popen.CreateProcess(command, hStdIn, hStdOut, hStdErr)
if debug.SHOW_CHILD_PROCESSES:
debug.Process(command, dbgIn, dbgOut, dbgErr)
return _pipe(win32popen.File2FileObject(handle, mode), phandle)
# flush the stdio buffers since we are about to change the FD under them
sys.stdout.flush()
sys.stderr.flush()
r, w = os.pipe()
pid = os.fork()
if pid:
# in the parent
# close the descriptor that we don't need and return the other one.
Wow. Drop a "general code cleanup" kind of bomb on the codebase. All of this is aimed at not paying the maintenance price of supporting Python versions prior to 2.4 any longer, plus a little bit of just getting dead code out of the way. * lib/compat.py Remove as unused. * bin/cvsdbadmin, * bin/loginfo-handler, * bin/make-database, * bin/svndbadmin, * lib/accept.py, * lib/blame.py, * lib/cvsdb.py, * lib/popen.py, * lib/query.py, * lib/sapi.py, * lib/vcauth/forbidden/__init__.py * lib/vcauth/forbiddenre/__init__.py, * lib/vcauth/svnauthz/__init__.py, * lib/vclib/__init__.py, * lib/vclib/ccvs/blame.py, * lib/win32popen.py, * tests/timelog.py Replace explicit import and use of the 'string' module with newer constructs. * bin/standalone.py, * lib/viewvc.py No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. * lib/dbi.py Use calender.timegm() instead of compat.timegm(). * lib/vcauth/__init__.py Lose unused module imports. * lib/config.py, Replace explicit import and use of the 'string' module with newer constructs where possible. Lose old ConfigParser patch-up code for Python 1.5.1. * lib/vclib/ccvs/ccvs.py Replace explicit import and use of the 'string' module with newer constructs where possible. Import _path_join() from bincvs, and use it instead of a bunch of copy-and-pasted string join() statements throughout. * lib/vclib/ccvs/__init__.py (cvs_strptime): Moved here from the 'compat' module. * lib/vclib/ccvs/bincvs.py (): No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. (_path_join): New, used now instead of a bunch of copy-and-pasted string join() statements throughout. * viewvc-install Don't use the 'compat' module any more. Also, so some rearranging of non-critical bits. * misc/: New directory. * misc/py2html.py: Moved from 'lib/py2html.py'. * misc/PyFontify.py: Moved from 'lib/PyFontify.py'. * misc/elemx/: Moved from 'elemx/'. * misc/tparse/: Moved from 'tparse/'. * tools/make-release Omit 'misc' directory from releases, too. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2437 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-03 20:49:52 +04:00
if mode.find('r') >= 0:
os.close(w)
return _pipe(os.fdopen(r, mode), pid)
os.close(r)
return _pipe(os.fdopen(w, mode), pid)
# in the child
# we'll need /dev/null for the discarded I/O
null = os.open('/dev/null', os.O_RDWR)
Wow. Drop a "general code cleanup" kind of bomb on the codebase. All of this is aimed at not paying the maintenance price of supporting Python versions prior to 2.4 any longer, plus a little bit of just getting dead code out of the way. * lib/compat.py Remove as unused. * bin/cvsdbadmin, * bin/loginfo-handler, * bin/make-database, * bin/svndbadmin, * lib/accept.py, * lib/blame.py, * lib/cvsdb.py, * lib/popen.py, * lib/query.py, * lib/sapi.py, * lib/vcauth/forbidden/__init__.py * lib/vcauth/forbiddenre/__init__.py, * lib/vcauth/svnauthz/__init__.py, * lib/vclib/__init__.py, * lib/vclib/ccvs/blame.py, * lib/win32popen.py, * tests/timelog.py Replace explicit import and use of the 'string' module with newer constructs. * bin/standalone.py, * lib/viewvc.py No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. * lib/dbi.py Use calender.timegm() instead of compat.timegm(). * lib/vcauth/__init__.py Lose unused module imports. * lib/config.py, Replace explicit import and use of the 'string' module with newer constructs where possible. Lose old ConfigParser patch-up code for Python 1.5.1. * lib/vclib/ccvs/ccvs.py Replace explicit import and use of the 'string' module with newer constructs where possible. Import _path_join() from bincvs, and use it instead of a bunch of copy-and-pasted string join() statements throughout. * lib/vclib/ccvs/__init__.py (cvs_strptime): Moved here from the 'compat' module. * lib/vclib/ccvs/bincvs.py (): No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. (_path_join): New, used now instead of a bunch of copy-and-pasted string join() statements throughout. * viewvc-install Don't use the 'compat' module any more. Also, so some rearranging of non-critical bits. * misc/: New directory. * misc/py2html.py: Moved from 'lib/py2html.py'. * misc/PyFontify.py: Moved from 'lib/PyFontify.py'. * misc/elemx/: Moved from 'elemx/'. * misc/tparse/: Moved from 'tparse/'. * tools/make-release Omit 'misc' directory from releases, too. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2437 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-03 20:49:52 +04:00
if mode.find('r') >= 0:
# hook stdout/stderr to the "write" channel
os.dup2(w, 1)
# "close" stdin; the child shouldn't use it
### this isn't quite right... we may want the child to read from stdin
os.dup2(null, 0)
# what to do with errors?
if capture_err:
os.dup2(w, 2)
else:
os.dup2(null, 2)
else:
# hook stdin to the "read" channel
os.dup2(r, 0)
# "close" stdout/stderr; the child shouldn't use them
### this isn't quite right... we may want the child to write to these
os.dup2(null, 1)
os.dup2(null, 2)
# don't need these FDs any more
os.close(null)
os.close(r)
os.close(w)
# the stdin/stdout/stderr are all set up. exec the target
try:
os.execvp(cmd, (cmd,) + tuple(args))
except:
# aid debugging, if the os.execvp above fails for some reason:
Wow. Drop a "general code cleanup" kind of bomb on the codebase. All of this is aimed at not paying the maintenance price of supporting Python versions prior to 2.4 any longer, plus a little bit of just getting dead code out of the way. * lib/compat.py Remove as unused. * bin/cvsdbadmin, * bin/loginfo-handler, * bin/make-database, * bin/svndbadmin, * lib/accept.py, * lib/blame.py, * lib/cvsdb.py, * lib/popen.py, * lib/query.py, * lib/sapi.py, * lib/vcauth/forbidden/__init__.py * lib/vcauth/forbiddenre/__init__.py, * lib/vcauth/svnauthz/__init__.py, * lib/vclib/__init__.py, * lib/vclib/ccvs/blame.py, * lib/win32popen.py, * tests/timelog.py Replace explicit import and use of the 'string' module with newer constructs. * bin/standalone.py, * lib/viewvc.py No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. * lib/dbi.py Use calender.timegm() instead of compat.timegm(). * lib/vcauth/__init__.py Lose unused module imports. * lib/config.py, Replace explicit import and use of the 'string' module with newer constructs where possible. Lose old ConfigParser patch-up code for Python 1.5.1. * lib/vclib/ccvs/ccvs.py Replace explicit import and use of the 'string' module with newer constructs where possible. Import _path_join() from bincvs, and use it instead of a bunch of copy-and-pasted string join() statements throughout. * lib/vclib/ccvs/__init__.py (cvs_strptime): Moved here from the 'compat' module. * lib/vclib/ccvs/bincvs.py (): No longer use 'compat' module. Replace explicit import and use of the 'string' module with newer constructs. (_path_join): New, used now instead of a bunch of copy-and-pasted string join() statements throughout. * viewvc-install Don't use the 'compat' module any more. Also, so some rearranging of non-critical bits. * misc/: New directory. * misc/py2html.py: Moved from 'lib/py2html.py'. * misc/PyFontify.py: Moved from 'lib/PyFontify.py'. * misc/elemx/: Moved from 'elemx/'. * misc/tparse/: Moved from 'tparse/'. * tools/make-release Omit 'misc' directory from releases, too. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2437 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-03 20:49:52 +04:00
print "<h2>exec failed:</h2><pre>", cmd, ' '.join(args), "</pre>"
raise
# crap. shouldn't be here.
sys.exit(127)
class _pipe:
"Wrapper for a file which can wait() on a child process at close time."
def __init__(self, file, child_pid, done_event = None, thread = None):
self.file = file
self.child_pid = child_pid
if sys.platform == "win32":
if done_event:
self.wait_for = (child_pid, done_event)
else:
self.wait_for = (child_pid,)
else:
self.thread = thread
def eof(self):
### should be calling file.eof() here instead of file.close(), there
### may be data in the pipe or buffer after the process exits
if sys.platform == "win32":
r = win32event.WaitForMultipleObjects(self.wait_for, 1, 0)
if r == win32event.WAIT_OBJECT_0:
self.file.close()
self.file = None
return win32process.GetExitCodeProcess(self.child_pid)
return None
if self.thread and self.thread.isAlive():
return None
pid, status = os.waitpid(self.child_pid, os.WNOHANG)
if pid:
self.file.close()
self.file = None
return status
return None
def close(self):
if self.file:
self.file.close()
self.file = None
if sys.platform == "win32":
win32event.WaitForMultipleObjects(self.wait_for, 1, win32event.INFINITE)
return win32process.GetExitCodeProcess(self.child_pid)
else:
if self.thread:
self.thread.join()
if type(self.child_pid) == type([]):
for pid in self.child_pid:
exit = os.waitpid(pid, 0)[1]
return exit
else:
return os.waitpid(self.child_pid, 0)[1]
return None
def __getattr__(self, name):
return getattr(self.file, name)
def __del__(self):
self.close()