2016-08-28 19:17:53 +02:00
|
|
|
#! /usr/bin/env python3
|
2015-01-25 18:36:02 +01:00
|
|
|
|
2016-12-27 13:30:44 +01:00
|
|
|
from __future__ import print_function
|
|
|
|
|
2016-08-28 19:17:53 +02:00
|
|
|
import os, re, string, sys, getopt, signal
|
|
|
|
|
2015-01-25 18:36:02 +01:00
|
|
|
|
|
|
|
def version():
|
2018-04-29 15:39:28 +02:00
|
|
|
print ("Generic Colouriser 1.11.3")
|
2015-01-25 18:36:02 +01:00
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
def help():
|
2018-04-29 15:39:28 +02:00
|
|
|
print("""Generic Colouriser 1.11.3
|
2015-01-25 18:36:02 +01:00
|
|
|
grc [options] command [args]
|
2017-02-09 14:33:16 +01:00
|
|
|
Options:
|
2015-01-25 18:36:02 +01:00
|
|
|
-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
|
2016-08-28 19:20:46 +02:00
|
|
|
--pty run command in pseudoterminal (experimental)
|
2015-01-25 18:36:02 +01:00
|
|
|
""")
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
|
|
|
|
def catch_signal(signum, frame):
|
|
|
|
"catch signal sent to grc and forward it to the original application"
|
|
|
|
global pidp
|
2016-10-17 20:47:57 +02:00
|
|
|
# print('signal')
|
2015-01-25 18:36:02 +01:00
|
|
|
try:
|
|
|
|
os.kill(pidp, signum)
|
|
|
|
except OSError: # if the subprocess already died
|
|
|
|
pass
|
|
|
|
|
|
|
|
try:
|
2016-08-28 19:20:46 +02:00
|
|
|
optlist, args = getopt.getopt(sys.argv[1:], "sec:", ["stdout", "stderr", "config=", "colour=", "pty"] )
|
2015-01-25 18:36:02 +01:00
|
|
|
except:
|
|
|
|
help()
|
|
|
|
|
|
|
|
if not args:
|
|
|
|
help()
|
|
|
|
|
|
|
|
stdoutf = 0
|
|
|
|
stderrf = 0
|
|
|
|
|
|
|
|
# configure file for grcat
|
|
|
|
cfile = ""
|
|
|
|
|
2018-04-29 10:05:34 +02:00
|
|
|
colour = sys.stdout.isatty()
|
2016-08-28 19:20:46 +02:00
|
|
|
use_pty = 0
|
2015-01-25 18:36:02 +01:00
|
|
|
|
|
|
|
for i in optlist:
|
|
|
|
if i[0] in ["--stderr", "-e"]:
|
2016-07-31 15:34:41 +02:00
|
|
|
# redirect stderr
|
2015-01-25 18:36:02 +01:00
|
|
|
stderrf = 1
|
|
|
|
elif i[0] in ["--stdout", "-s"]:
|
2016-07-31 15:34:41 +02:00
|
|
|
# redirect stdout
|
2015-01-25 18:36:02 +01:00
|
|
|
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()
|
2016-08-28 19:20:46 +02:00
|
|
|
elif i[0] == '--pty':
|
|
|
|
use_pty = 1
|
2015-01-25 18:36:02 +01:00
|
|
|
|
|
|
|
stdoutff = 1
|
|
|
|
stderrff = 0
|
|
|
|
if stderrf == 1:
|
|
|
|
stdoutff = 0
|
|
|
|
stderrff = 1
|
|
|
|
if stdoutf == 1:
|
|
|
|
stdoutff = 1
|
|
|
|
|
2016-08-28 19:20:46 +02:00
|
|
|
if use_pty:
|
|
|
|
import pty
|
|
|
|
|
2015-01-25 18:36:02 +01:00
|
|
|
if cfile == "":
|
2016-09-24 16:15:36 +02:00
|
|
|
home = os.environ.get('HOME')
|
|
|
|
xdg = os.environ.get('XDG_CONFIG_HOME')
|
|
|
|
if not xdg and home:
|
|
|
|
xdg = home + '/.config'
|
|
|
|
|
2020-05-30 03:06:13 +02:00
|
|
|
conffilenames = ['/etc/grc.conf', '/usr/local/etc/grc.conf']
|
2016-09-24 16:15:36 +02:00
|
|
|
if xdg:
|
|
|
|
conffilenames += [xdg + '/grc/grc.conf']
|
|
|
|
if home:
|
|
|
|
conffilenames += [home + '/.grc/grc.conf']
|
2020-05-30 03:06:13 +02:00
|
|
|
|
|
|
|
for conffile in conffilenames:
|
2016-12-14 14:53:36 +01:00
|
|
|
# test if conffile exists, it can be also a pipe
|
2020-05-30 03:06:13 +02:00
|
|
|
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
|
|
|
|
|
2015-01-25 18:36:02 +01:00
|
|
|
|
|
|
|
signal.signal(signal.SIGINT, catch_signal)
|
|
|
|
|
|
|
|
|
|
|
|
if cfile != "" and colour:
|
|
|
|
if stdoutff:
|
|
|
|
choo, chio = os.pipe()
|
|
|
|
if stderrff:
|
|
|
|
choe, chie = os.pipe()
|
2016-08-28 19:17:53 +02:00
|
|
|
if use_pty:
|
|
|
|
pidp, pty_fd = pty.fork()
|
|
|
|
else:
|
|
|
|
pidp = os.fork()
|
2016-08-28 20:51:20 +02:00
|
|
|
if pidp == 0: # child, command to run
|
2015-01-25 18:36:02 +01:00
|
|
|
if stdoutff:
|
2016-07-31 15:34:41 +02:00
|
|
|
# connect child (this) stdout to pipe write end
|
2016-08-28 19:17:53 +02:00
|
|
|
if not use_pty:
|
|
|
|
os.dup2(chio, 1)
|
|
|
|
os.close(choo)
|
|
|
|
os.close(chio)
|
2015-01-25 18:36:02 +01:00
|
|
|
if stderrff:
|
2016-08-28 19:17:53 +02:00
|
|
|
os.dup2(chie, 2)
|
|
|
|
os.close(choe)
|
|
|
|
os.close(chie)
|
2017-05-21 16:00:34 +02:00
|
|
|
try:
|
|
|
|
os.execvp(args[0], args)
|
|
|
|
except OSError as e:
|
|
|
|
sys.stderr.write('grc: %s: %s\n' % (args[0], e.strerror))
|
|
|
|
sys.exit(1)
|
2016-08-28 19:17:53 +02:00
|
|
|
|
2015-01-25 18:36:02 +01:00
|
|
|
|
|
|
|
if stdoutff:
|
|
|
|
pido = os.fork()
|
2016-08-28 20:51:20 +02:00
|
|
|
if pido == 0: # child, grcat
|
|
|
|
# connect grcat's stdin to pipe read end, or pty master
|
2016-08-28 19:17:53 +02:00
|
|
|
if use_pty:
|
|
|
|
os.dup2(pty_fd, 0)
|
|
|
|
else:
|
|
|
|
os.dup2(choo, 0)
|
2015-01-25 18:36:02 +01:00
|
|
|
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
|
2016-10-17 20:47:57 +02:00
|
|
|
# except KeyboardInterrupt: # catching SIGINT does not work when using pty...
|
|
|
|
# status = None
|
|
|
|
# os.kill(pidp, signal.SIGINT)
|
|
|
|
# pass
|
2015-01-25 18:36:02 +01:00
|
|
|
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:
|
2016-07-31 15:34:41 +02:00
|
|
|
pidp = os.fork()
|
2015-01-25 18:36:02 +01:00
|
|
|
if pidp == 0:
|
2017-02-06 19:37:45 +01:00
|
|
|
try:
|
|
|
|
os.execvp(args[0], args)
|
2017-04-23 13:35:18 +02:00
|
|
|
except OSError as e:
|
|
|
|
sys.stderr.write('grc: %s: %s\n' % (args[0], e.strerror))
|
2017-02-06 20:52:28 +01:00
|
|
|
sys.exit(1)
|
2015-01-25 18:36:02 +01:00
|
|
|
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))
|
|
|
|
|