diff --git a/mktemp.1 b/mktemp.1 index 1d9da15..d8fa5b4 100644 --- a/mktemp.1 +++ b/mktemp.1 @@ -1,4 +1,4 @@ -.Dd January 31, 2015 +.Dd May 8, 2015 .Dt MKTEMP 1 .Os sbase .Sh NAME @@ -6,7 +6,8 @@ .Nd create temporary file or directory .Sh SYNOPSIS .Nm -.Op Fl dq +.Op Fl dqtu +.Op Fl p Ar directory .Op Ar template .Sh DESCRIPTION .Nm @@ -20,8 +21,25 @@ tmpdir set to '/tmp' or, if set, the TMPDIR environment variable. .Bl -tag -width Ds .It Fl d Create a temporary directory instead of a file. +.It Fl p Ar directory +Use the specified +.Ar directory +as a prefix when generating the temporary filename. The directory will be +overridden by the user's +.Ev TMPDIR +environment variable if it is set. This option implies the +.Fl t +flag (see below). .It Fl q Fail silently if an error occurs. +.It Fl t +Generate a path rooted in a temporary directory. +.It Fl u +Unlink file before +.Nm +exits. This is slightly better than +.Xr mktemp 3 +but still introduces a race condition. Use of this option is not encouraged. .El .Sh SEE ALSO .Xr mkdtemp 3 , diff --git a/mktemp.c b/mktemp.c index e25ef43..68c2591 100644 --- a/mktemp.c +++ b/mktemp.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "util.h" @@ -9,24 +10,34 @@ static void usage(void) { - eprintf("usage: %s [-dq] [template]\n", argv0); + eprintf("usage: %s [-dqtu] [-p directory] [template]\n", argv0); } int main(int argc, char *argv[]) { - int dflag = 0, qflag = 0, fd; - char *template = "tmp.XXXXXXXXXX", - *tmpdir = "/tmp", *p, - path[PATH_MAX], tmp[PATH_MAX]; + int dflag = 0, pflag = 0, qflag = 0, tflag = 0, uflag = 0, fd; + char *template = "tmp.XXXXXXXXXX", *tmpdir = "", *pdir, + *p, path[PATH_MAX], tmp[PATH_MAX]; + size_t len; ARGBEGIN { case 'd': dflag = 1; break; + case 'p': + pflag = 1; + pdir = EARGF(usage()); + break; case 'q': qflag = 1; break; + case 't': + tflag = 1; + break; + case 'u': + uflag = 1; + break; default: usage(); } ARGEND; @@ -36,18 +47,26 @@ main(int argc, char *argv[]) else if (argc == 1) template = argv[0]; - if ((p = getenv("TMPDIR"))) - tmpdir = p; + if (!argc || pflag || tflag) { + if ((p = getenv("TMPDIR"))) + tmpdir = p; + else if (pflag) + tmpdir = pdir; + else + tmpdir = "/tmp"; + } + + len = estrlcpy(path, tmpdir, sizeof(path)); + if (path[0] && path[len - 1] != '/') + estrlcat(path, "/", sizeof(path)); estrlcpy(tmp, template, sizeof(tmp)); p = dirname(tmp); - if (p[0] != '.') { - estrlcpy(path, template, sizeof(path)); - } else { - estrlcpy(path, tmpdir, sizeof(path)); - estrlcat(path, "/", sizeof(path)); - estrlcat(path, template, sizeof(path)); + if (!(p[0] == '.' && p[1] == '\0')) { + if (tflag && !pflag) + eprintf("template must not contain directory separators in -t mode\n"); } + estrlcat(path, template, sizeof(path)); if (dflag) { if (!mkdtemp(path)) { @@ -64,6 +83,8 @@ main(int argc, char *argv[]) if (close(fd)) eprintf("close %s:", path); } + if (uflag) + unlink(path); puts(path); efshut(stdout, "");