| # builtin.py - builtins and utilities definitions for pysh. |
| # |
| # Copyright 2007 Patrick Mezard |
| # |
| # This software may be used and distributed according to the terms |
| # of the GNU General Public License, incorporated herein by reference. |
| |
| """Builtin and internal utilities implementations. |
| |
| - Beware not to use python interpreter environment as if it were the shell |
| environment. For instance, commands working directory must be explicitely handled |
| through env['PWD'] instead of relying on python working directory. |
| """ |
| import errno |
| import optparse |
| import os |
| import re |
| import subprocess |
| import sys |
| import time |
| |
| def has_subprocess_bug(): |
| return getattr(subprocess, 'list2cmdline') and \ |
| ( subprocess.list2cmdline(['']) == '' or \ |
| subprocess.list2cmdline(['foo|bar']) == 'foo|bar') |
| |
| # Detect python bug 1634343: "subprocess swallows empty arguments under win32" |
| # <http://sourceforge.net/tracker/index.php?func=detail&aid=1634343&group_id=5470&atid=105470> |
| # Also detect: "[ 1710802 ] subprocess must escape redirection characters under win32" |
| # <http://sourceforge.net/tracker/index.php?func=detail&aid=1710802&group_id=5470&atid=105470> |
| if has_subprocess_bug(): |
| import subprocess_fix |
| subprocess.list2cmdline = subprocess_fix.list2cmdline |
| |
| from sherrors import * |
| |
| class NonExitingParser(optparse.OptionParser): |
| """OptionParser default behaviour upon error is to print the error message and |
| exit. Raise a utility error instead. |
| """ |
| def error(self, msg): |
| raise UtilityError(msg) |
| |
| #------------------------------------------------------------------------------- |
| # set special builtin |
| #------------------------------------------------------------------------------- |
| OPT_SET = NonExitingParser(usage="set - set or unset options and positional parameters") |
| OPT_SET.add_option( '-f', action='store_true', dest='has_f', default=False, |
| help='The shell shall disable pathname expansion.') |
| OPT_SET.add_option('-e', action='store_true', dest='has_e', default=False, |
| help="""When this option is on, if a simple command fails for any of the \ |
| reasons listed in Consequences of Shell Errors or returns an exit status \ |
| value >0, and is not part of the compound list following a while, until, \ |
| or if keyword, and is not a part of an AND or OR list, and is not a \ |
| pipeline preceded by the ! reserved word, then the shell shall immediately \ |
| exit.""") |
| OPT_SET.add_option('-x', action='store_true', dest='has_x', default=False, |
| help="""The shell shall write to standard error a trace for each command \ |
| after it expands the command and before it executes it. It is unspecified \ |
| whether the command that turns tracing off is traced.""") |
| |
| def builtin_set(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| option, args = OPT_SET.parse_args(args) |
| env = interp.get_env() |
| |
| if option.has_f: |
| env.set_opt('-f') |
| if option.has_e: |
| env.set_opt('-e') |
| if option.has_x: |
| env.set_opt('-x') |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # shift special builtin |
| #------------------------------------------------------------------------------- |
| def builtin_shift(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| params = interp.get_env().get_positional_args() |
| if args: |
| try: |
| n = int(args[0]) |
| if n > len(params): |
| raise ValueError() |
| except ValueError: |
| return 1 |
| else: |
| n = 1 |
| |
| params[:n] = [] |
| interp.get_env().set_positional_args(params) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # export special builtin |
| #------------------------------------------------------------------------------- |
| OPT_EXPORT = NonExitingParser(usage="set - set or unset options and positional parameters") |
| OPT_EXPORT.add_option('-p', action='store_true', dest='has_p', default=False) |
| |
| def builtin_export(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| option, args = OPT_EXPORT.parse_args(args) |
| if option.has_p: |
| raise NotImplementedError() |
| |
| for arg in args: |
| try: |
| name, value = arg.split('=', 1) |
| except ValueError: |
| name, value = arg, None |
| env = interp.get_env().export(name, value) |
| |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # return special builtin |
| #------------------------------------------------------------------------------- |
| def builtin_return(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| res = 0 |
| if args: |
| try: |
| res = int(args[0]) |
| except ValueError: |
| res = 0 |
| if not 0<=res<=255: |
| res = 0 |
| |
| # BUG: should be last executed command exit code |
| raise ReturnSignal(res) |
| |
| #------------------------------------------------------------------------------- |
| # trap special builtin |
| #------------------------------------------------------------------------------- |
| def builtin_trap(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| if len(args) < 2: |
| stderr.write('trap: usage: trap [[arg] signal_spec ...]\n') |
| return 2 |
| |
| action = args[0] |
| for sig in args[1:]: |
| try: |
| env.traps[sig] = action |
| except Exception as e: |
| stderr.write('trap: %s\n' % str(e)) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # unset special builtin |
| #------------------------------------------------------------------------------- |
| OPT_UNSET = NonExitingParser("unset - unset values and attributes of variables and functions") |
| OPT_UNSET.add_option( '-f', action='store_true', dest='has_f', default=False) |
| OPT_UNSET.add_option( '-v', action='store_true', dest='has_v', default=False) |
| |
| def builtin_unset(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| option, args = OPT_UNSET.parse_args(args) |
| |
| status = 0 |
| env = interp.get_env() |
| for arg in args: |
| try: |
| if option.has_f: |
| env.remove_function(arg) |
| else: |
| del env[arg] |
| except KeyError: |
| pass |
| except VarAssignmentError: |
| status = 1 |
| |
| return status |
| |
| #------------------------------------------------------------------------------- |
| # wait special builtin |
| #------------------------------------------------------------------------------- |
| def builtin_wait(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| return interp.wait([int(arg) for arg in args]) |
| |
| #------------------------------------------------------------------------------- |
| # cat utility |
| #------------------------------------------------------------------------------- |
| def utility_cat(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| if not args: |
| args = ['-'] |
| |
| status = 0 |
| for arg in args: |
| if arg == '-': |
| data = stdin.read() |
| else: |
| path = os.path.join(env['PWD'], arg) |
| try: |
| f = file(path, 'rb') |
| try: |
| data = f.read() |
| finally: |
| f.close() |
| except IOError as e: |
| if e.errno != errno.ENOENT: |
| raise |
| status = 1 |
| continue |
| stdout.write(data) |
| stdout.flush() |
| return status |
| |
| #------------------------------------------------------------------------------- |
| # cd utility |
| #------------------------------------------------------------------------------- |
| OPT_CD = NonExitingParser("cd - change the working directory") |
| |
| def utility_cd(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| option, args = OPT_CD.parse_args(args) |
| env = interp.get_env() |
| |
| directory = None |
| printdir = False |
| if not args: |
| home = env.get('HOME') |
| if home: |
| # Unspecified, do nothing |
| return 0 |
| else: |
| directory = home |
| elif len(args)==1: |
| directory = args[0] |
| if directory=='-': |
| if 'OLDPWD' not in env: |
| raise UtilityError("OLDPWD not set") |
| printdir = True |
| directory = env['OLDPWD'] |
| else: |
| raise UtilityError("too many arguments") |
| |
| curpath = None |
| # Absolute directories will be handled correctly by the os.path.join call. |
| if not directory.startswith('.') and not directory.startswith('..'): |
| cdpaths = env.get('CDPATH', '.').split(';') |
| for cdpath in cdpaths: |
| p = os.path.join(cdpath, directory) |
| if os.path.isdir(p): |
| curpath = p |
| break |
| |
| if curpath is None: |
| curpath = directory |
| curpath = os.path.join(env['PWD'], directory) |
| |
| env['OLDPWD'] = env['PWD'] |
| env['PWD'] = curpath |
| if printdir: |
| stdout.write('%s\n' % curpath) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # colon utility |
| #------------------------------------------------------------------------------- |
| def utility_colon(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # echo utility |
| #------------------------------------------------------------------------------- |
| def utility_echo(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| # Echo only takes arguments, no options. Use printf if you need fancy stuff. |
| output = ' '.join(args) + '\n' |
| stdout.write(output) |
| stdout.flush() |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # egrep utility |
| #------------------------------------------------------------------------------- |
| # egrep is usually a shell script. |
| # Unfortunately, pysh does not support shell scripts *with arguments* right now, |
| # so the redirection is implemented here, assuming grep is available. |
| def utility_egrep(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| return run_command('grep', ['-E'] + args, interp, env, stdin, stdout, |
| stderr, debugflags) |
| |
| #------------------------------------------------------------------------------- |
| # env utility |
| #------------------------------------------------------------------------------- |
| def utility_env(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| if args and args[0]=='-i': |
| raise NotImplementedError('env: -i option is not implemented') |
| |
| i = 0 |
| for arg in args: |
| if '=' not in arg: |
| break |
| # Update the current environment |
| name, value = arg.split('=', 1) |
| env[name] = value |
| i += 1 |
| |
| if args[i:]: |
| # Find then execute the specified interpreter |
| utility = env.find_in_path(args[i]) |
| if not utility: |
| return 127 |
| args[i:i+1] = utility |
| name = args[i] |
| args = args[i+1:] |
| try: |
| return run_command(name, args, interp, env, stdin, stdout, stderr, |
| debugflags) |
| except UtilityError: |
| stderr.write('env: failed to execute %s' % ' '.join([name]+args)) |
| return 126 |
| else: |
| for pair in env.get_variables().iteritems(): |
| stdout.write('%s=%s\n' % pair) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # exit utility |
| #------------------------------------------------------------------------------- |
| def utility_exit(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| res = None |
| if args: |
| try: |
| res = int(args[0]) |
| except ValueError: |
| res = None |
| if not 0<=res<=255: |
| res = None |
| |
| if res is None: |
| # BUG: should be last executed command exit code |
| res = 0 |
| |
| raise ExitSignal(res) |
| |
| #------------------------------------------------------------------------------- |
| # fgrep utility |
| #------------------------------------------------------------------------------- |
| # see egrep |
| def utility_fgrep(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| return run_command('grep', ['-F'] + args, interp, env, stdin, stdout, |
| stderr, debugflags) |
| |
| #------------------------------------------------------------------------------- |
| # gunzip utility |
| #------------------------------------------------------------------------------- |
| # see egrep |
| def utility_gunzip(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| return run_command('gzip', ['-d'] + args, interp, env, stdin, stdout, |
| stderr, debugflags) |
| |
| #------------------------------------------------------------------------------- |
| # kill utility |
| #------------------------------------------------------------------------------- |
| def utility_kill(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| for arg in args: |
| pid = int(arg) |
| status = subprocess.call(['pskill', '/T', str(pid)], |
| shell=True, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.PIPE) |
| # pskill is asynchronous, hence the stupid polling loop |
| while 1: |
| p = subprocess.Popen(['pslist', str(pid)], |
| shell=True, |
| stdout=subprocess.PIPE, |
| stderr=subprocess.STDOUT) |
| output = p.communicate()[0] |
| if ('process %d was not' % pid) in output: |
| break |
| time.sleep(1) |
| return status |
| |
| #------------------------------------------------------------------------------- |
| # mkdir utility |
| #------------------------------------------------------------------------------- |
| OPT_MKDIR = NonExitingParser("mkdir - make directories.") |
| OPT_MKDIR.add_option('-p', action='store_true', dest='has_p', default=False) |
| |
| def utility_mkdir(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| # TODO: implement umask |
| # TODO: implement proper utility error report |
| option, args = OPT_MKDIR.parse_args(args) |
| for arg in args: |
| path = os.path.join(env['PWD'], arg) |
| if option.has_p: |
| try: |
| os.makedirs(path) |
| except IOError as e: |
| if e.errno != errno.EEXIST: |
| raise |
| else: |
| os.mkdir(path) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # netstat utility |
| #------------------------------------------------------------------------------- |
| def utility_netstat(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| # Do you really expect me to implement netstat ? |
| # This empty form is enough for Mercurial tests since it's |
| # supposed to generate nothing upon success. Faking this test |
| # is not a big deal either. |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # pwd utility |
| #------------------------------------------------------------------------------- |
| OPT_PWD = NonExitingParser("pwd - return working directory name") |
| OPT_PWD.add_option('-L', action='store_true', dest='has_L', default=True, |
| help="""If the PWD environment variable contains an absolute pathname of \ |
| the current directory that does not contain the filenames dot or dot-dot, \ |
| pwd shall write this pathname to standard output. Otherwise, the -L option \ |
| shall behave as the -P option.""") |
| OPT_PWD.add_option('-P', action='store_true', dest='has_L', default=False, |
| help="""The absolute pathname written shall not contain filenames that, in \ |
| the context of the pathname, refer to files of type symbolic link.""") |
| |
| def utility_pwd(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| option, args = OPT_PWD.parse_args(args) |
| stdout.write('%s\n' % env['PWD']) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # printf utility |
| #------------------------------------------------------------------------------- |
| RE_UNESCAPE = re.compile(r'(\\x[a-zA-Z0-9]{2}|\\[0-7]{1,3}|\\.)') |
| |
| def utility_printf(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| def replace(m): |
| assert m.group() |
| g = m.group()[1:] |
| if g.startswith('x'): |
| return chr(int(g[1:], 16)) |
| if len(g) <= 3 and len([c for c in g if c in '01234567']) == len(g): |
| # Yay, an octal number |
| return chr(int(g, 8)) |
| return { |
| 'a': '\a', |
| 'b': '\b', |
| 'f': '\f', |
| 'n': '\n', |
| 'r': '\r', |
| 't': '\t', |
| 'v': '\v', |
| '\\': '\\', |
| }.get(g) |
| |
| # Convert escape sequences |
| format = re.sub(RE_UNESCAPE, replace, args[0]) |
| stdout.write(format % tuple(args[1:])) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # true utility |
| #------------------------------------------------------------------------------- |
| def utility_true(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # sed utility |
| #------------------------------------------------------------------------------- |
| RE_SED = re.compile(r'^s(.).*\1[a-zA-Z]*$') |
| |
| # cygwin sed fails with some expressions when they do not end with a single space. |
| # see unit tests for details. Interestingly, the same expressions works perfectly |
| # in cygwin shell. |
| def utility_sed(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| # Scan pattern arguments and append a space if necessary |
| for i in xrange(len(args)): |
| if not RE_SED.search(args[i]): |
| continue |
| args[i] = args[i] + ' ' |
| |
| return run_command(name, args, interp, env, stdin, stdout, |
| stderr, debugflags) |
| |
| #------------------------------------------------------------------------------- |
| # sleep utility |
| #------------------------------------------------------------------------------- |
| def utility_sleep(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| time.sleep(int(args[0])) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # sort utility |
| #------------------------------------------------------------------------------- |
| OPT_SORT = NonExitingParser("sort - sort, merge, or sequence check text files") |
| |
| def utility_sort(name, args, interp, env, stdin, stdout, stderr, debugflags): |
| |
| def sort(path): |
| if path == '-': |
| lines = stdin.readlines() |
| else: |
| try: |
| f = file(path) |
| try: |
| lines = f.readlines() |
| finally: |
| f.close() |
| except IOError as e: |
| stderr.write(str(e) + '\n') |
| return 1 |
| |
| if lines and lines[-1][-1]!='\n': |
| lines[-1] = lines[-1] + '\n' |
| return lines |
| |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| option, args = OPT_SORT.parse_args(args) |
| alllines = [] |
| |
| if len(args)<=0: |
| args += ['-'] |
| |
| # Load all files lines |
| curdir = os.getcwd() |
| try: |
| os.chdir(env['PWD']) |
| for path in args: |
| alllines += sort(path) |
| finally: |
| os.chdir(curdir) |
| |
| alllines.sort() |
| for line in alllines: |
| stdout.write(line) |
| return 0 |
| |
| #------------------------------------------------------------------------------- |
| # hg utility |
| #------------------------------------------------------------------------------- |
| |
| hgcommands = [ |
| 'add', |
| 'addremove', |
| 'commit', 'ci', |
| 'debugrename', |
| 'debugwalk', |
| 'falabala', # Dummy command used in a mercurial test |
| 'incoming', |
| 'locate', |
| 'pull', |
| 'push', |
| 'qinit', |
| 'remove', 'rm', |
| 'rename', 'mv', |
| 'revert', |
| 'showconfig', |
| 'status', 'st', |
| 'strip', |
| ] |
| |
| def rewriteslashes(name, args): |
| # Several hg commands output file paths, rewrite the separators |
| if len(args) > 1 and name.lower().endswith('python') \ |
| and args[0].endswith('hg'): |
| for cmd in hgcommands: |
| if cmd in args[1:]: |
| return True |
| |
| # svn output contains many paths with OS specific separators. |
| # Normalize these to unix paths. |
| base = os.path.basename(name) |
| if base.startswith('svn'): |
| return True |
| |
| return False |
| |
| def rewritehg(output): |
| if not output: |
| return output |
| # Rewrite os specific messages |
| output = output.replace(': The system cannot find the file specified', |
| ': No such file or directory') |
| output = re.sub(': Access is denied.*$', ': Permission denied', output) |
| output = output.replace(': No connection could be made because the target machine actively refused it', |
| ': Connection refused') |
| return output |
| |
| |
| def run_command(name, args, interp, env, stdin, stdout, |
| stderr, debugflags): |
| # Execute the command |
| if 'debug-utility' in debugflags: |
| print interp.log(' '.join([name, str(args), interp['PWD']]) + '\n') |
| |
| hgbin = interp.options().hgbinary |
| ishg = hgbin and ('hg' in name or args and 'hg' in args[0]) |
| unixoutput = 'cygwin' in name or ishg |
| |
| exec_env = env.get_variables() |
| try: |
| # BUG: comparing file descriptor is clearly not a reliable way to tell |
| # whether they point on the same underlying object. But in pysh limited |
| # scope this is usually right, we do not expect complicated redirections |
| # besides usual 2>&1. |
| # Still there is one case we have but cannot deal with is when stdout |
| # and stderr are redirected *by pysh caller*. This the reason for the |
| # --redirect pysh() option. |
| # Now, we want to know they are the same because we sometimes need to |
| # transform the command output, mostly remove CR-LF to ensure that |
| # command output is unix-like. Cygwin utilies are a special case because |
| # they explicitely set their output streams to binary mode, so we have |
| # nothing to do. For all others commands, we have to guess whether they |
| # are sending text data, in which case the transformation must be done. |
| # Again, the NUL character test is unreliable but should be enough for |
| # hg tests. |
| redirected = stdout.fileno()==stderr.fileno() |
| if not redirected: |
| p = subprocess.Popen([name] + args, cwd=env['PWD'], env=exec_env, |
| stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| else: |
| p = subprocess.Popen([name] + args, cwd=env['PWD'], env=exec_env, |
| stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) |
| out, err = p.communicate() |
| except WindowsError as e: |
| raise UtilityError(str(e)) |
| |
| if not unixoutput: |
| def encode(s): |
| if '\0' in s: |
| return s |
| return s.replace('\r\n', '\n') |
| else: |
| encode = lambda s: s |
| |
| if rewriteslashes(name, args): |
| encode1_ = encode |
| def encode(s): |
| s = encode1_(s) |
| s = s.replace('\\\\', '\\') |
| s = s.replace('\\', '/') |
| return s |
| |
| if ishg: |
| encode2_ = encode |
| def encode(s): |
| return rewritehg(encode2_(s)) |
| |
| stdout.write(encode(out)) |
| if not redirected: |
| stderr.write(encode(err)) |
| return p.returncode |
| |