#!/usr/local/bin/python2.3
# Written by Ross Cohen
# See LICENSE.txt for license information.
try:
import psyco
assert psyco.__version__ >= 0x010300f0
psyco.full()
except:
pass
try:
import Codeville.db
except ImportError:
import sys, os.path
from os.path import dirname, abspath, join
pypath = "lib/python%d.%d/site-packages" % \
(sys.version_info[0], sys.version_info[1])
base = dirname(dirname(abspath(sys.argv[0])))
sys.path[0:0] = [ join(base, pypath) ] # first place to look
from Codeville.agent import Agent
from getopt import getopt, GetoptError
import os
from os import path
from resource import setrlimit, RLIMIT_CORE
from signal import alarm, signal
from signal import SIGALRM, SIGHUP, SIGPIPE, SIGINT, SIGTERM, SIG_IGN
import socket
import sys
from tempfile import mkdtemp
ppid = None
agent = None
def cleanup_handler(signum, foo):
agent.cleanup()
sys.exit(2)
return
def check_parent_exists(signum, foo):
if ppid is not None:
try:
os.kill(ppid, 0)
except OSError:
cleanup_handler(signum, foo)
alarm(10)
return
def usage():
stderr = sys.stderr
print >> stderr, "Usage: %s [options] [command [args ...]]" % sys.argv[0]
print >> stderr, "Options:"
print >> stderr, " -c Generate C-shell commands on stdout."
print >> stderr, " -s Generate Bourne shell commands on stdout"
print >> stderr, " -k Kill the current agent."
print >> stderr, " -d Debug mode."
print >> stderr, " -a socket Bind agent socket to given name."
print >> stderr, " -t life Default identity lifetime (seconds) (ignored)."
sys.exit(1)
def fork_stuff(agent, sock, args, c_flag):
pid = os.fork()
if pid != 0:
sock.close()
if len(args) == 0:
if c_flag:
print 'setenv %s %s' % ('CDV_AGENT_PID', pid)
print 'setenv %s %s' % ('CDV_AUTH_SOCK', agent.auth_file)
else:
print '%s=%s; export %s;' % ('CDV_AGENT_PID', pid,
'CDV_AGENT_PID')
print '%s=%s; export %s;' % ('CDV_AUTH_SOCK', agent.auth_file,
'CDV_AUTH_SOCK')
print "echo Agent pid %d;" % (pid)
sys.exit(0)
os.environ['CDV_AGENT_PID'] = str(pid)
os.environ['CDV_AUTH_SOCK'] = agent.auth_file
try:
os.execvp(args[0], args)
except OSError, msg:
print msg
sys.exit(1)
os.setsid()
os.chdir('/')
fd = open('/dev/null', 'r+')
os.dup2(fd.fileno(), sys.stdin.fileno())
os.dup2(fd.fileno(), sys.stdout.fileno())
os.dup2(fd.fileno(), sys.stderr.fileno())
# set rlimit to prevent core dumping
setrlimit(RLIMIT_CORE, (0, 0))
return
def run(args):
global ppid
global agent
auth_path = None
auth_file = None
os.setegid(os.getgid())
os.setgid(os.getgid())
try:
optlist, args = getopt(args, 'a:cdkst:')
except GetoptError:
usage()
c_flag, d_flag, k_flag, s_flag = 0, 0, 0, 0
for (opt, arg) in optlist:
if opt == '-a':
auth_file = arg
elif opt == '-c':
if s_flag:
usage()
c_flag += 1
elif opt == '-d':
if d_flag:
usage()
d_flag += 1
elif opt == '-k':
k_flag += 1
elif opt == '-s':
if c_flag:
usage()
s_flag += 1
elif opt == '-t':
# XXX: for compatibility
pass
if len(args) and (c_flag or k_flag or s_flag or d_flag):
usage()
if len(args) and not c_flag and not s_flag:
try:
shell = os.environ['SHELL']
except KeyError:
pass
else:
if shell.endswith('csh'):
c_flag = 1
if k_flag:
try:
kpid = int(os.environ['CDV_AGENT_PID'])
except KeyError:
'CDV_AGENT_PID is not set, cannot kill agent'
sys.exit(1)
if kpid < 1:
print 'CDV_AGENT_PID=%d, which is not a good PID' % (kpid)
sys.exit(1)
try:
os.kill(kpid, SIGTERM)
except OSError, msg:
print msg
sys.exit(1)
if c_flag:
print 'unsetenv %s;' % ('CDV_AUTH_SOCK')
print 'unsetenv %s;' % ('CDV_AGENT_PID')
else:
print 'unset %s;' % ('CDV_AUTH_SOCK')
print 'unset %s;' % ('CDV_AGENT_PID')
print 'echo Agent pid %d killed;' % (kpid)
sys.exit(0)
agent = Agent()
ppid = os.getpid()
if auth_file is None:
auth_path = mkdtemp('', 'cdv-')
auth_file = path.join(auth_path, 'agent.' + str(ppid))
try:
sock = agent.listen_sock(auth_path, auth_file)
if sock is None:
sys.exit(1)
except socket.error, reason:
print reason[1]
sys.exit(1)
if d_flag:
if c_flag:
print 'setenv %s %s' % ('CDV_AUTH_SOCK', agent.auth_file)
else:
print '%s=%s; export %s;' % ('CDV_AUTH_SOCK', agent.auth_file,
'CDV_AUTH_SOCK')
print "echo Agent pid %d;" % (ppid)
else:
fork_stuff(agent, sock, args, c_flag)
# periodically check that parent exists
if len(args):
signal(SIGALRM, check_parent_exists)
alarm(10)
if not d_flag:
signal(SIGINT, SIG_IGN)
signal(SIGPIPE, SIG_IGN)
signal(SIGHUP, cleanup_handler)
signal(SIGTERM, cleanup_handler)
agent.listen()
return
if __name__ == '__main__':
sys.exit(run(sys.argv[1:]))
syntax highlighted by Code2HTML, v. 0.9.1