# portage.py -- core Portage functionality
# Copyright 1998-2004 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Id: /var/cvsroot/gentoo-src/portage/pym/portage_exec.py,v 1.13.2.4 2005/04/17 09:01:56 jstubbs Exp $


import os,types,atexit,string,stat
import signal
import portage_data
import portage_util

try:
	import resource
	max_fd_limit=resource.getrlimit(RLIMIT_NOFILE)
except SystemExit, e:
	raise
except:
	# hokay, no resource module.
	max_fd_limit=256

spawned_pids = []
def cleanup():
	global spawned_pids
	while spawned_pids:
		pid = spawned_pids.pop()
		try:
			os.kill(pid,SIGKILL)
		except SystemExit, e:
			raise
		except:
			pass
atexit.register(cleanup)

from portage_const import BASH_BINARY,SANDBOX_BINARY,SANDBOX_PIDS_FILE

sandbox_capable = (os.path.exists(SANDBOX_BINARY) and os.access(SANDBOX_BINARY, os.X_OK))

def spawn_bash(mycommand,env={},debug=False,opt_name=None,**keywords):
	args=[BASH_BINARY]
	if not opt_name:
		opt_name=mycommand.split()[0]
	if not env.has_key("BASH_ENV"):
		env["BASH_ENV"] = "/etc/spork/is/not/valid/profile.env"
	if debug:
		args.append("-x")
	args.append("-c")
	args.append(mycommand)
	return spawn(args,env=env,opt_name=opt_name,**keywords)

def spawn_sandbox(mycommand,uid=None,opt_name=None,**keywords):
	if not sandbox_capable:
		return spawn_bash(mycommand,opt_name=opt_name,**keywords)
	args=[SANDBOX_BINARY]
	if not opt_name:
		opt_name=mycommand.split()[0]
	args.append(mycommand)
	if not uid:
		uid=os.getuid()
	try:
		os.chown(SANDBOX_PIDS_FILE,uid,portage_data.portage_gid)
		os.chmod(SANDBOX_PIDS_FILE,0664)
	except SystemExit, e:
		raise
	except:
		pass
	return spawn(args,uid=uid,opt_name=opt_name,**keywords)

# base spawn function
def spawn(mycommand,env={},opt_name=None,fd_pipes=None,returnpid=False,uid=None,gid=None,groups=None,umask=None,logfile=None,path_lookup=True):
	if type(mycommand)==types.StringType:
		mycommand=mycommand.split()
	myc = mycommand[0]
	if not os.path.isabs(myc) or not os.access(myc, os.X_OK):
		if not path_lookup:
			return None
		myc = find_binary(myc)
		if myc == None:
			return None
		
	mypid=[]
	if logfile:
		pr,pw=os.pipe()
		mypid.extend(spawn(('tee','-i','-a',logfile),returnpid=True,fd_pipes={0:pr,1:1,2:2}))
		retval=os.waitpid(mypid[-1],os.WNOHANG)[1]
		if retval != 0:
			# he's dead jim.
			if (retval & 0xff)==0:
				return (retval >> 8) # exit code
			else:
				return ((retval & 0xff) << 8) # signal
		if not fd_pipes:
			fd_pipes={}
			fd_pipes[0] = 0
		fd_pipes[1]=pw
		fd_pipes[2]=pw
		
	if not opt_name:
		opt_name = mycommand[0]
	myargs=[opt_name]
	myargs.extend(mycommand[1:])
	mypid.append(os.fork())
	if mypid[-1] == 0:
		# this may look ugly, but basically it moves file descriptors around to ensure no
		# handles that are needed are accidentally closed during the final dup2 calls.
		trg_fd=[]
		if type(fd_pipes)==types.DictType:
			src_fd=[]
			k=fd_pipes.keys()
			k.sort()
			for x in k:
				trg_fd.append(x)
				src_fd.append(fd_pipes[x])
			for x in range(0,len(trg_fd)):
				if trg_fd[x] == src_fd[x]:
					continue
				if trg_fd[x] in src_fd[x+1:]:
					new=os.dup2(trg_fd[x],max(src_fd) + 1)
					os.close(trg_fd[x])
					try:
						while True: 
							src_fd[s.index(trg_fd[x])]=new
					except SystemExit, e:
						raise
					except:
						pass
			for x in range(0,len(trg_fd)):
				if trg_fd[x] != src_fd[x]:
					os.dup2(src_fd[x], trg_fd[x])
		else:
			trg_fd=[0,1,2]
		for x in range(0,max_fd_limit):
			if x not in trg_fd:
				try: 
					os.close(x)
				except SystemExit, e:
					raise
				except:
					pass
		# note this order must be preserved- can't change gid/groups if you change uid first.
		if gid:
			os.setgid(gid)
		if groups:
			os.setgroups(groups)
		if uid:
			os.setuid(uid)
		if umask:
			os.umask(umask)
		try:
			# XXX: We would do this to stop ebuild.sh from getting any
			# XXX: output, and consequently, we'd get to handle the sigINT.
			#os.close(sys.stdin.fileno())
			pass
		except SystemExit, e:
			raise
		except:
			pass

		try:
			#print "execing", myc, myargs
			os.execve(myc,myargs,env)
		except SystemExit, e:
			raise
		except Exception, e:
			raise str(e)+":\n   "+myc+" "+string.join(myargs)
		# If the execve fails, we need to report it, and exit
		# *carefully* --- report error here
		os._exit(1)
		sys.exit(1)
		return # should never get reached

	if logfile:
		os.close(pr)
		os.close(pw)
	
	if returnpid:
		global spawned_pids
		spawned_pids.append(mypid[-1])
		return mypid
	while len(mypid):
		retval=os.waitpid(mypid[-1],0)[1]
		if retval != 0:
			for x in mypid[0:-1]:
				try:
					os.kill(x,signal.SIGTERM)
					if os.waitpid(x,os.WNOHANG)[1] == 0:
						# feisty bugger, still alive.
						os.kill(x,signal.SIGKILL)
					os.waitpid(x,0)
				except OSError, oe:
					if oe.errno not in (10,3):
						raise oe
			
			# at this point we've killed all other kid pids generated via this call.
			# return now.
			
			if (retval & 0xff)==0:
				return (retval >> 8) # return exit code
			else:
				return ((retval & 0xff) << 8) # interrupted by signal
		else:
			mypid.pop(-1)
	return 0

def find_binary(myc):
	p=os.getenv("PATH")
	if p == None:
		return None
	for x in p.split(":"):
		# if it exists, and is executable
		if os.access("%s/%s" % (x,myc), os.X_OK):
			return "%s/%s" % (x,myc)

	return None


