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}