#!/usr/bin/python3 '''Create a series of temporary files for the benefit of code that can't read from stdin''' import os import sys import subprocess def usage(): '''Usage message''' sys.stderr.write('Usage: %s -c chunkhandlerprog -n nameprefix [-t tmpdir] [-b blocksize]\n' % sys.argv[0]) sys.stderr.write('-c specifies the chunk handling program to handle each chunk, and is required\n') sys.stderr.write('-n specifies the nameprefix to use on all files created, and is required\n') sys.stderr.write('-t specifies the temporary directory to write files to, and is optional. Defaults to $TMPDIR or /tmp\n') sys.stderr.write('-b specifies the length of files to create, and is optional. Defaults to 1 gigabyte\n') sys.stderr.write('-d specifies the number of digits to use in filenames. Defaults to 5\n') sys.exit(1) def pad(number, digits): ''' Pad a number with leading zeros, converting it from an integer to a string. Slow on some Pythons. ''' string = str(number) while len(string) < digits: string = '0' + string return string def process(options): '''Process stdin''' blockno = 0 while True: if options.verbose: sys.stderr.write('Reading block %d\n' % blockno) block = sys.stdin.read(options.blocksize) if not block: break if options.verbose: sys.stderr.write('Read block of length %d\n' % len(block)) filename = "%s/%s.%s" % (options.tmpdir, options.nameprefix, pad(blockno, options.digits)) if options.verbose: sys.stderr.write('Writing file %s\n' % filename) with open(filename, 'w') as file_: file_.write(block) command = "%s %s" % (options.prog, filename) if options.verbose: sys.stderr.write('Performing command %s\n' % command) # retval is likely the shell return value * 256, but 0 is still 0, and # nonzero is still nonzero #retval = os.system(command) retval = subprocess.call(command, shell=True) if retval == 0: if options.verbose: sys.stderr.write('Command executed successfully\n') else: sys.stderr.write('Error executing %s\n' % command) sys.stderr.write('Return value from command was %s\n' % str(retval)) sys.stderr.write('Abnormal termination\n') sys.exit(1) if options.verbose: sys.stderr.write('Deleting %s\n' % filename) os.unlink(filename) blockno += 1 class Options(object): '''Handle command line options''' def __init__(self): '''Set defaults''' self.prog = '' self.nameprefix = '' if 'TMPDIR' in os.environ: self.tmpdir = os.environ['TMPDIR'] else: self.tmpdir = '/tmp' self.blocksize = 2**(3*10) self.digits = 5 self.verbose = False def handle_argv(self): '''Arrange argv into options variables''' while sys.argv[1:]: if sys.argv[1] == '-c' and sys.argv[2:]: self.prog = sys.argv[2] del sys.argv[1] del sys.argv[1] elif sys.argv[1] == '-n' and sys.argv[2:]: self.nameprefix = sys.argv[2] del sys.argv[1] del sys.argv[1] elif sys.argv[1] == '-t' and sys.argv[2:]: self.tmpdir = sys.argv[2] del sys.argv[1] del sys.argv[1] elif sys.argv[1] == '-b' and sys.argv[2:]: self.blocksize = int(sys.argv[2]) del sys.argv[1] del sys.argv[1] elif sys.argv[1] == '-b' and sys.argv[2:]: self.digits = int(sys.argv[2]) del sys.argv[1] del sys.argv[1] elif sys.argv[1] == '-v': self.verbose = True del sys.argv[1] else: usage() def check(self): '''verify options''' if self.nameprefix == '' or self.prog == '': sys.stderr.write('-n and -c are both required options\n') usage() def main(): '''Main function''' options = Options() options.handle_argv() options.check() process(options) if options.verbose: sys.stderr.write('Normal termination\n') sys.exit(0) main()