bash-color-grc/grc

202 lines
5.1 KiB
Python
Executable File

#! /usr/bin/env python3
from __future__ import print_function
import os, re, string, sys, getopt, signal
def version():
print ("Generic Colouriser 1.13")
sys.exit()
def help():
print("""Generic Colouriser 1.13
grc [options] command [args]
Options:
-e --stderr redirect stderr. If this option is selected,
do not automatically redirect stdout
-s --stdout redirect stdout, even if -e is selected
-c name --config=name use name as configuration file for grcat
--colour=word word is one of: on, off, auto
--pty run command in pseudoterminal (experimental)
""")
sys.exit()
def catch_signal(signum, frame):
"catch signal sent to grc and forward it to the original application"
global pidp
try:
os.kill(pidp, signum)
except OSError: # if the subprocess already died
pass
try:
optlist, args = getopt.getopt(sys.argv[1:], "sec:", ["stdout", "stderr", "config=", "colour=", "pty"] )
except:
help()
if not args:
help()
stdoutf = 0
stderrf = 0
# configure file for grcat
cfile = ""
colour = sys.stdout.isatty()
use_pty = 0
for i in optlist:
if i[0] in ["--stderr", "-e"]:
# redirect stderr
stderrf = 1
elif i[0] in ["--stdout", "-s"]:
# redirect stdout
stdoutf = 1
elif i[0] in ["--config", "-c"]:
cfile = i[1]
elif i[0] == "--colour":
if i[1] == "on":
colour = 1
elif i[1] == "off":
colour = 0
elif i[1] == "auto":
colour = sys.stdout.isatty()
else:
help()
elif i[0] == '--pty':
use_pty = 1
stdoutff = 1
stderrff = 0
if stderrf == 1:
stdoutff = 0
stderrff = 1
if stdoutf == 1:
stdoutff = 1
if use_pty:
import pty
if cfile == "":
home = os.environ.get('HOME')
xdg = os.environ.get('XDG_CONFIG_HOME')
if not xdg and home:
xdg = home + '/.config'
conffilenames = ['/etc/grc.conf', '/usr/local/etc/grc.conf']
if xdg:
conffilenames += [xdg + '/grc/grc.conf']
if home:
conffilenames += [home + '/.grc/grc.conf']
for conffile in conffilenames:
# test if conffile exists, it can be also a pipe
if os.path.exists(conffile) and not os.path.isdir(conffile):
f = open(conffile, "r")
while 1:
l = f.readline()
if l == "":
break
if l[0] == "#" or l[0] == '\012':
continue
regexp = l.strip()
if re.search(regexp, ' '.join(args)):
cfile = f.readline().strip()
break
signal.signal(signal.SIGINT, catch_signal)
if cfile != "" and colour:
if stdoutff:
choo, chio = os.pipe()
if stderrff:
choe, chie = os.pipe()
if use_pty:
pidp, pty_fd = pty.fork()
else:
pidp = os.fork()
if pidp == 0: # child, command to run
if stdoutff:
# connect child (this) stdout to pipe write end
if not use_pty:
os.dup2(chio, 1)
os.close(choo)
os.close(chio)
if stderrff:
os.dup2(chie, 2)
os.close(choe)
os.close(chie)
try:
os.execvp(args[0], args)
except OSError as e:
sys.stderr.write('grc: %s: %s\n' % (args[0], e.strerror))
sys.exit(1)
if stdoutff:
pido = os.fork()
if pido == 0: # child, grcat
# connect grcat's stdin to pipe read end, or pty master
if use_pty:
os.dup2(pty_fd, 0)
else:
os.dup2(choo, 0)
os.close(choo)
os.close(chio)
if stderrff:
os.close(choe)
os.close(chie)
os.execvp("grcat", ["grcat", cfile])
if stderrff:
pide = os.fork()
if pide == 0: # child
os.dup2(choe, 0)
os.dup2(2, 1)
os.close(choe)
os.close(chie)
if stdoutff:
os.close(choo)
os.close(chio)
os.execvp("grcat", ["grcat", cfile])
try:
status = os.waitpid(pidp, 0)[1]
except OSError: # interrupted system call
status = None
pass # this is probably not correct
# except KeyboardInterrupt: # catching SIGINT does not work when using pty...
# status = None
# os.kill(pidp, signal.SIGINT)
# pass
if stderrff:
os.close(chie)
os.waitpid(pide, 0)
os.close(choe)
if stdoutff:
os.close(chio)
os.waitpid(pido, 0)
os.close(choo)
sys.exit(status and os.WEXITSTATUS(status))
else:
pidp = os.fork()
if pidp == 0:
try:
os.execvp(args[0], args)
except OSError as e:
sys.stderr.write('grc: %s: %s\n' % (args[0], e.strerror))
sys.exit(1)
try:
status = os.wait()[1]
except OSError: # interrupted system call
status = None
pass # this is probably not correct
sys.exit(status and os.WEXITSTATUS(status))