/*
 *----------------------------------------------------------------------
 *           "THE BEER-WARE LICENSE" (Revision 42):
 * <jeang3nie@HitchHiker-Linux.org> wrote this file. As long as you
 * retain this notice you can do whatever you want with this stuff. If
 * we meet some day, and you think this stuff is worth it, you can buy
 * me a beer in return.
 * ---------------------------------------------------------------------
 *            ______   _______  _          _________
 *           (  __  \ (  ___  )( (    /|( )\__   __/
 *           | (  \  )| (   ) ||  \  ( ||/    ) (
 *           | |   ) || |   | ||   \ | |      | |
 *           | |   | || |   | || (\ \) |      | |
 *           | |   ) || |   | || | \   |      | |
 *           | (__/  )| (___) || )  \  |      | |
 *           (______/ (_______)|/    )_)      )_(
 *
 *         _______  _______  _       _________ _______
 *        (  ____ )(  ___  )( \    /|\__   __/(  ____ \
 *        | (    )|| (   ) ||  \  ( |   ) (   | (    |/
 *        | (____)|| (___) ||   \ | |   | |   | |
 *        |  _____)|  ___  || (\ \) |   | |   | |
 *        | (      | (   ) || | \   |   | |   | |
 *        | )      | )   ( || )  \  |___) (___| (____|\
 *        |/       |/     \||/    \_)\_______/(_______/
 *
 */

#define _GNU_SOURCE     // asprintf

#include <ctype.h>      // isprint
#include <libgen.h>     // basename
#include <paths.h>      // _PATH_TMP
#include <stdio.h>      // asprintf,fprintf, printf
#include <stdlib.h>     // exit
#include <string.h>     // strdup
#include <unistd.h>     // close,getopt

static const char * __progname;

static void usage(void);

int main(int argc, char * argv[]) {
  unsigned int c;
  int dflag = 0;
  int qflag = 0;
  int uflag = 0;
  int fd;
  char * tmpdir = NULL;
  char * template = NULL;
  char * tmpfile = NULL;
  __progname = basename(argv[0]);

  while ((c = getopt(argc, argv, "dp:qt:u")) != -1)
    switch (c) {
    case 'h':
      usage();
      return 0;
      break;
    case 'd':
      dflag = 1;
      break;
    case 'p':
      tmpdir = strdup(optarg);
      break;
    case 'q':
      qflag = 1;
      break;
    case 't':
      (void)asprintf(&template, "%s.XXXXXX", optarg);
      break;
    case 'u':
      uflag = 1;
      break;
    case '?':
      if (optopt == 'p' || optopt == 't') {
        usage();
        exit(1);
      } else if (isprint(optopt)) {
        usage();
        exit(1);
      }
    default:
      usage();
    }

  if (argv[optind] != NULL) {   /* template given as arg1 */
    if (template) {             /* template also given with -t flag */
      fprintf(stderr, "%s: extra operand: %s\n",
                       __progname, argv[optind]);
      usage();
      exit(EXIT_FAILURE);
    } else {
      if (tmpdir)               /* move arg1 into string */
        (void)asprintf(&tmpfile, "%s/%s", tmpdir, argv[optind]);
      else
        (void)asprintf(&tmpfile, "%s", argv[optind]);
    }
  } else {                      /* no arg1 */
    if (!template)              /* use default template */
      (void)asprintf(&template, "%s.XXXXXX", __progname);
    if (tmpdir)                 /* -p flag */
      (void)asprintf(&tmpfile, "%s/%s", tmpdir, template);
    else                        /* default temp directory */
      (void)asprintf(&tmpfile, "%s%s", _PATH_TMP, template);
  }

  if (template)
    free(template);

  if (dflag) {                  /* Create temp directory */
    if (mkdtemp(tmpfile) == NULL) {
      if (!qflag)
        perror("mkdtemp");
      exit(EXIT_FAILURE);
    } else {
      if (uflag)
        (void)rmdir(tmpfile);
    }
  } else {                      /* Create temp file */
    fd = mkstemp(tmpfile);
    if (fd < 0) {
      if (!qflag)
        perror("mkstemp");
      exit(EXIT_FAILURE);
    } else {
      (void)close(fd);
      if (uflag)
        (void)unlink(tmpfile);
    }
  }
  printf("%s\n", tmpfile);
  free(tmpfile);
  return 0;
}

static void usage(void) {
  fprintf(stderr, "Usage: %s [-hdqu] [-p tmpdir] [-t template]\n",
                   __progname);
}
