mirror of
https://github.com/garabik/grc.git
synced 2024-11-15 14:48:26 +01:00
206 lines
5.1 KiB
Python
Executable file
206 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.10.1")
|
|
sys.exit()
|
|
|
|
def help():
|
|
print("""Generic Colouriser 1.10.1
|
|
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
|
|
# print('signal')
|
|
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 = 1
|
|
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
|
|
|
|
conffile = None
|
|
if cfile == "":
|
|
home = os.environ.get('HOME')
|
|
xdg = os.environ.get('XDG_CONFIG_HOME')
|
|
if not xdg and home:
|
|
xdg = home + '/.config'
|
|
|
|
conffilenames = []
|
|
if xdg:
|
|
conffilenames += [xdg + '/grc/grc.conf']
|
|
if home:
|
|
conffilenames += [home + '/.grc/grc.conf']
|
|
conffilenames += ['/usr/local/etc/grc.conf', '/etc/grc.conf']
|
|
for i in conffilenames:
|
|
# test if conffile exists, it can be also a pipe
|
|
if os.path.exists(i) and not os.path.isdir(i):
|
|
conffile = i
|
|
break
|
|
regexplist = []
|
|
|
|
if 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)
|
|
os.execvp(args[0], args)
|
|
|
|
|
|
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 FileNotFoundError:
|
|
sys.stderr.write('grc: %s: command not found\n' % args[0])
|
|
sys.exit(1)
|
|
except PermissionError:
|
|
sys.stderr.write('grc: %s: Permission error\n' % args[0])
|
|
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))
|
|
|