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