#!/usr/bin/env python
# $FreeBSD: ports/Tools/portbuild/scripts/buildproxy,v 1.4 2010/06/25 23:02:09 linimon Exp $
#
# Allow access to privileged build commands to ports-* users for
# managing their own build spaces.

import sys, socket, os, commands

from freebsd import *
from freebsd_config import *

CONFIG_DIR="/var/portbuild"
CONFIG_SUBDIR="conf"
CONFIG_FILENAME="server.conf"

valid_cmds = ['create', 'clone', 'portsupdate', 'srcupdate', 'destroy']

def validate(uid, arch):
    if uid == 0:
        return True

    if getuidbyname("ports-%s" % arch) == uid:
        return True

    return False

def process(cmd, sockfile):

    if len(cmd) < 5:
        return (254, "Wrong number of arguments")

    if cmd[0] != "build":
        return (254, "Invalid command")

    try:
        if not validate(uid, cmd[2]):
            return (254, "Permission denied")
    except:
        return (254, "Internal error")

    if cmd[1] not in valid_cmds:
        return (254, "Permission denied")

    for i in cmd:
        for j in i:
            if not j.isalnum() and not j in "-_.":
                return (254, "Illegal characters in input")
    
    (status, out) = commands.getstatusoutput("/var/portbuild/scripts/build %s" % " ".join(cmd[1:]))

    return (status, out)

config = getConfig( CONFIG_DIR, CONFIG_SUBDIR, CONFIG_FILENAME )
BUILDPROXY_SOCKET_FILE = config.get( 'BUILDPROXY_SOCKET_FILE' )

if os.path.exists(BUILDPROXY_SOCKET_FILE):
    os.unlink(BUILDPROXY_SOCKET_FILE)
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.bind(BUILDPROXY_SOCKET_FILE)
os.chmod(BUILDPROXY_SOCKET_FILE, 0660)
os.chown(BUILDPROXY_SOCKET_FILE, -1, getgidbyname('portmgr'))

s.listen(10)

while True:
    try:
        (conn, addr) = s.accept()

        (uid, gids) = getpeerid(conn)

        sockfile = conn.makefile()
        cmd = sockfile.readline().rstrip().split()
        print cmd
        try:
            (status, out) = process(cmd, sockfile)
        except:
            (status, out) = (254, "Internal error")

        sockfile.write("%d\n" % status)
        sockfile.write(out)
        sockfile.flush()

        sockfile.close()
        conn.close()
    except Exception, e:
        print "buildproxy: exception: " + str( e )
        pass

