#!/usr/bin/perl -w
##
## Perl-version mktemp(1) command
## Copyright (c) 2007 SATOH Fumiyasu @ OSS Technology, Co., Japan
##                    <http://www.osstech.co.jp/>
##
## License: GNU General Public License version 3
## Date: 2007-07-11, since 2007-07-11
##

use strict;
#use warnings;
use Getopt::Long;
use POSIX;
use IO::File;

umask(0077);

my @seed = ('0'..'9', 'a'..'z', 'A'..'Z');

my $flag_dir = undef;
my $flag_quiet = undef;
my $flag_unsafe = undef;
my $flag_generate_path = undef;
my $prefix_dir = undef;
my $template = 'tmp.XXXXXXXXXX';

my $cmd_name = $0;
$cmd_name =~ s#^.*/##;
my $cmd_usage = "Usage: $cmd_name [-dptu] [-p DIRECTORY] [TEMPLATE]\n";

Getopt::Long::Configure('bundling');
Getopt::Long::Configure('no_ignore_case');
Getopt::Long::Configure('no_auto_abbrev');
GetOptions(
  'd' =>	\$flag_dir,
  'q' =>	\$flag_quiet,
  't' =>	\$flag_generate_path,
  'u' =>	\$flag_unsafe,
  'p=s' =>	sub {
    $prefix_dir = $_[1];
    $flag_generate_path = 1;
  }
) || die "$cmd_usage";

if ($flag_quiet) {
  $SIG{'__DIE__'} = sub {
    exit(1);
  }
}

if ($flag_unsafe) {
  die "$cmd_name: -u option is not supported yet\n";
}

if (@ARGV == 1) {
  $template = $ARGV[0];
}
elsif (@ARGV > 1) {
  die "$cmd_name: too many argument\n";
}

if ($flag_generate_path) {
  if ($template =~ m#/#) {
    die "$cmd_name: template must not contain directory separators in -t mode\n";
  }

  if (defined($ENV{'TMPDIR'})) {
    $template = "$ENV{'TMPDIR'}/$template";
  }
  elsif (defined($prefix_dir)) {
    $template = "$prefix_dir/$template";
  }
  else {
    $template = "/tmp/$template";
  }
}
$template =~ s#//+#/#g;

$template =~ s/(X+)$//;
my $seed_n = defined($1) ? length($1) : 0;
my $try_max = $seed_n * 10;

for (my $try = 0; $try <= $try_max; $try++) {
  my $temp = $template;
  for (my $n = 0; $n < $seed_n; $n++) {
    $temp .= $seed[int(rand(@seed))];
  }

  if ($flag_dir) {
    if (mkdir($temp, 0700)) {
      print "$temp\n";
      exit(0);
    }
    elsif ($! != POSIX::EEXIST || $try == $try_max) {
      die "$cmd_name: cannot create temporary directory $temp: $!\n";
    }
  }
  else {
    my $fh = IO::File->new($temp, O_RDWR|O_CREAT|O_EXCL, 0600);
    if (defined($fh)) {
      print "$temp\n";
      exit(0);
    }
    elsif ($! != POSIX::EEXIST || $try == $try_max) {
      die "$cmd_name: cannot create temporary file $temp: $!\n";
    }
  }
}

## Not reached
exit(1);

