#!/usr/bin/python3

import os
import pwd
import sys
import errno
import subprocess

def usage(retval):
    sys.stderr.write("Usage: %s --command command --string string\n" % sys.argv[0])
    sys.exit(retval)

def start_command(verbose, command, filename):
    if verbose:
        print('trying to start command')
    pid = os.fork()
    if pid == 0:
        try:
            exit_code = subprocess.call(command, shell=True)
            if exit_code != 0:
                sys.exit(exit_code)
        finally:
            os.unlink(filename)
    else:
        with open(filename, 'w') as file_:
            file_.write('%s\n' % pid)
        if verbose:
            print('waiting...')
        dummy, exit_code = os.wait()
        if verbose:
            print('returning...')
        return exit_code

def pid_exists(verbose, pid):
    if subprocess.call('ps -p %d > /dev/null 2>&1' % pid, shell=True) == 0:
        if verbose:
            print('pid does exist')
        return True
    else:
        if verbose:
            print('pid does not exist')
        return False

def get_just_one_dir():
    #just_one_dir = os.path.join(os.environ['HOME'], '.just-one')
    uid = os.geteuid()
    pwent = pwd.getpwuid(uid)
    home_dir = pwent.pw_dir
    just_one_dir = os.path.join(home_dir, '.just-one')

    try:
        os.mkdir(just_one_dir, 7 * 64 + 5 * 8 + 5)
    except (OSError, IOError):
        dummy, mkdir_extra, dummy = sys.exc_info()
        if mkdir_extra.errno == errno.EEXIST:
            pass
        else:
            raise

    return just_one_dir

def main():
    command = None
    string = None
    pid = None
    verbose = False

    while sys.argv[1:]:
        if sys.argv[1] == '--command':
            command = sys.argv[2]
            del sys.argv[1]
        elif sys.argv[1] == '--string':
            string = sys.argv[2]
            del sys.argv[1]
        elif sys.argv[1] == '--verbose':
            verbose = True
        elif sys.argv[1] in [ '--help', '-h' ]:
            usage(0)
        else:
            sys.stderr.write("%s: Unrecognized option: %s\n" % (sys.argv[0], sys.argv[1]))
            usage(1)
        del sys.argv[1]

    if not command:
        sys.stderr.write("%s: --command command is a required option\n" % sys.argv[0])
        usage(1)

    if not string:
        sys.stderr.write("%s: --string string is a required option\n" % sys.argv[0])
        usage(1)

    if verbose:
        print('about to mkdir')

    just_one_dir = get_just_one_dir()

    if verbose:
        print('about to get pid')

    filename = os.path.join(just_one_dir, string)

    try:
        file_ = open(filename, 'r')
    except (OSError, IOError):
        dummy, open_extra, dummy = sys.exc_info()
        if open_extra.errno == errno.ENOENT:
            pass
        else:
            raise
    else:
        pid = int(file_.readline())
        file_.close()
        
        
    if pid:
        if verbose:
            print('got pid %d' % pid)
        if pid_exists(verbose, pid):
            sys.stderr.write("%s: %s is locked\n" % (sys.argv[0], string))
            sys.exit(1)
        else:
            exit_code = start_command(verbose, command, filename)
    else:
        exit_code = start_command(verbose, command, filename)

    sys.exit(exit_code)

main()