master xplshn/aruu / cmd / pseudo / mktemp.c
  1/* See LICENSE file for copyright and license details. */
  2
  3#include <libgen.h>
  4#include <stdio.h>
  5#include <stdlib.h>
  6#include <string.h>
  7#include <unistd.h>
  8
  9#include "util.h"
 10
 11static void
 12usage(void)
 13{
 14  eprintf("usage: %s [-dqtu] [-p directory] [template]\n", argv0);
 15}
 16
 17// ?man mktemp: create temporary file
 18// ?man arguments: template
 19// ?man create a temporary file or directory safely
 20int
 21main(int argc, char *argv[])
 22{
 23  int dflag = 0, pflag = 0, qflag = 0, tflag = 0, uflag = 0, fd;
 24  char *template = "tmp.XXXXXXXXXX", *tmpdir = "", *pdir, *p, path[PATH_MAX], tmp[PATH_MAX];
 25  size_t len;
 26
 27  ARGBEGIN
 28  {
 29    // ?man -d: specify directory
 30    case 'd':
 31      dflag = 1;
 32      break;
 33    // ?man -p:dir: preserve file attributes
 34    case 'p':
 35      pflag = 1;
 36      pdir  = EARGF(usage());
 37      break;
 38    // ?man -q: quiet mode; suppress output
 39    case 'q':
 40      qflag = 1;
 41      break;
 42    // ?man -t: sort or specify timestamp
 43    case 't':
 44      tflag = 1;
 45      break;
 46    // ?man -u: unbuffered output
 47    case 'u':
 48      uflag = 1;
 49      break;
 50    default:
 51      usage();
 52  }
 53  ARGEND
 54
 55  if (argc > 1)
 56    usage();
 57  else if (argc == 1)
 58    template = argv[0];
 59
 60  if (!argc || pflag || tflag) {
 61    if ((p = getenv("TMPDIR")))
 62      tmpdir = p;
 63    else if (pflag)
 64      tmpdir = pdir;
 65    else
 66      tmpdir = "/tmp";
 67  }
 68
 69  len = estrlcpy(path, tmpdir, sizeof(path));
 70  if (path[0] && path[len - 1] != '/')
 71    estrlcat(path, "/", sizeof(path));
 72
 73  estrlcpy(tmp, template, sizeof(tmp));
 74  p = dirname(tmp);
 75  if (!(p[0] == '.' && p[1] == '\0')) {
 76    if (tflag && !pflag)
 77      eprintf(
 78          "template must not contain directory "
 79          "separators in -t mode\n"
 80      );
 81  }
 82  estrlcat(path, template, sizeof(path));
 83
 84  if (dflag) {
 85    if (!mkdtemp(path)) {
 86      if (!qflag)
 87        eprintf("mkdtemp %s:", path);
 88      return 1;
 89    }
 90  } else {
 91    if ((fd = mkstemp(path)) < 0) {
 92      if (!qflag)
 93        eprintf("mkstemp %s:", path);
 94      return 1;
 95    }
 96    if (close(fd))
 97      eprintf("close %s:", path);
 98  }
 99  if (uflag)
100    unlink(path);
101  puts(path);
102
103  efshut(stdout, "<stdout>");
104  return 0;
105}