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}