From 5eea59ad575105f50c5027c4b6e3765c6d44bb9d Mon Sep 17 00:00:00 2001 From: tg Date: Sat, 14 Apr 2012 16:07:48 +0000 Subject: [PATCH] rewrite maketemp() obsoleting tempnam(3) and mkstemp(3) external deps --- Build.sh | 12 ++------ Makefile | 4 +-- check.t | 4 +-- exec.c | 12 ++++---- histrap.c | 16 +++++------ main.c | 85 ++++++++++++++++++++++++++++++++++--------------------- sh.h | 26 ++++++++--------- 7 files changed, 86 insertions(+), 73 deletions(-) diff --git a/Build.sh b/Build.sh index 0158afa..e933657 100644 --- a/Build.sh +++ b/Build.sh @@ -1,5 +1,5 @@ #!/bin/sh -srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.548 2012/04/14 14:11:07 tg Exp $' +srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.549 2012/04/14 16:07:43 tg Exp $' #- # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 @@ -1402,7 +1402,7 @@ else #define EXTERN #define MKSH_INCLUDES_ONLY #include "sh.h" - __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.548 2012/04/14 14:11:07 tg Exp $"); + __RCSID("$MirOS: src/bin/mksh/Build.sh,v 1.549 2012/04/14 16:07:43 tg Exp $"); int main(void) { printf("Hello, World!\n"); return (0); } EOF case $cm in @@ -1508,12 +1508,6 @@ ac_test mknod '' 'if to use mknod(), makedev() and friends' <<-'EOF' } EOF -ac_test mkstemp <<-'EOF' - #include - #include - int main(void) { char tmpl[] = "X"; return (mkstemp(tmpl)); } -EOF - ac_test mmap lock_fcntl 0 'for mmap and munmap' <<-'EOF' #include #if HAVE_SYS_FILE_H @@ -2103,7 +2097,7 @@ MKSH_NO_EXTERNAL_CAT omit hack to skip cat builtin when flags passed MKSH_NO_LIMITS omit ulimit code MKSH_NO_SIGSETJMP define if sigsetjmp is broken or not available MKSH_SMALL omit some code, optimise hard for size (slower) -MKSH_S_NOVI disable Vi editing mode (default if MKSH_SMALL) +MKSH_S_NOVI=1 disable Vi editing mode (default if MKSH_SMALL) MKSH_TYPEDEF_SIG_ATOMIC_T define to e.g. 'int' if sig_atomic_t is missing MKSH_TYPEDEF_SSIZE_T define to e.g. 'long' if your OS has no ssize_t MKSH_UNEMPLOYED disable job control (but not jobs/co-processes) diff --git a/Makefile b/Makefile index 308ba6f..b9edb40 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/Makefile,v 1.97 2012/04/07 11:19:46 tg Exp $ +# $MirOS: src/bin/mksh/Makefile,v 1.98 2012/04/14 16:07:44 tg Exp $ #- # Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 @@ -42,7 +42,7 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 -DMKSH_DISABLE_DEPRECATED \ -DHAVE_SIG_T=1 -DHAVE_SYS_SIGNAME=1 -DHAVE_SYS_SIGLIST=1 \ -DHAVE_STRSIGNAL=0 -DHAVE_FLOCK=1 -DHAVE_LOCK_FCNTL=1 \ -DHAVE_GETRUSAGE=1 -DHAVE_KILLPG=1 -DHAVE_MKNOD=0 \ - -DHAVE_MKSTEMP=1 -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=1 \ + -DHAVE_MMAP=1 -DHAVE_NICE=1 -DHAVE_REVOKE=1 \ -DHAVE_SETLOCALE_CTYPE=0 -DHAVE_LANGINFO_CODESET=0 \ -DHAVE_SELECT=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 \ -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 -DHAVE_REVOKE_DECL=1 \ diff --git a/check.t b/check.t index e7e2413..d257067 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.531 2012/04/07 11:19:47 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.532 2012/04/14 16:07:44 tg Exp $ # $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $ # $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $ @@ -29,7 +29,7 @@ # http://www.freebsd.org/cgi/cvsweb.cgi/src/tools/regression/bin/test/regress.sh?rev=HEAD expected-stdout: - @(#)MIRBSD KSH R40 2012/04/07 + @(#)MIRBSD KSH R40 2012/04/14 description: Check version of shell. stdin: diff --git a/exec.c b/exec.c index 75c75a2..4267a91 100644 --- a/exec.c +++ b/exec.c @@ -1,7 +1,8 @@ /* $OpenBSD: exec.c,v 1.49 2009/01/29 23:27:26 jaredy Exp $ */ /*- - * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, + * 2011, 2012 * Thorsten Glaser * * Provided that these terms and disclaimer and all copyright notices @@ -22,7 +23,7 @@ #include "sh.h" -__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.97 2012/03/31 17:29:58 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.98 2012/04/14 16:07:46 tg Exp $"); #ifndef MKSH_DEFAULT_EXECSHELL #define MKSH_DEFAULT_EXECSHELL "/bin/sh" @@ -1467,10 +1468,10 @@ herein(const char *content, int sub, char **resbuf) * so temp doesn't get removed too soon). */ h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps); - if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) { + if (!(shf = h->shf) || (fd = open(h->tffn, O_RDONLY, 0)) < 0) { i = errno; warningf(true, "can't %s temporary file %s: %s", - !shf ? "create" : "open", h->name, strerror(i)); + !shf ? "create" : "open", h->tffn, strerror(i)); if (shf) shf_close(shf); /* special to iosetup(): don't print error */ @@ -1486,7 +1487,8 @@ herein(const char *content, int sub, char **resbuf) if (shf_close(shf) == EOF) { i = errno; close(fd); - warningf(true, "%s: %s: %s", "write", h->name, strerror(i)); + warningf(true, "can't %s temporary file %s: %s", + "write", h->tffn, strerror(i)); /* special to iosetup(): don't print error */ return (-2); } diff --git a/histrap.c b/histrap.c index 5299058..2cfdccc 100644 --- a/histrap.c +++ b/histrap.c @@ -27,7 +27,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.122 2012/04/06 13:29:00 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.123 2012/04/14 16:07:47 tg Exp $"); Trap sigtraps[NSIG + 1]; static struct sigaction Sigact_ign; @@ -297,7 +297,7 @@ c_fc(const char **wp) tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps); if (!(shf = tf->shf)) { bi_errorf("can't %s temporary file %s: %s", - "create", tf->name, strerror(errno)); + "create", tf->tffn, strerror(errno)); return (1); } for (hp = rflag ? hlast : hfirst; @@ -305,12 +305,12 @@ c_fc(const char **wp) shf_fprintf(shf, "%s\n", *hp); if (shf_close(shf) == EOF) { bi_errorf("can't %s temporary file %s: %s", - "write", tf->name, strerror(errno)); + "write", tf->tffn, strerror(errno)); return (1); } /* Ignore setstr errors here (arbitrary) */ - setstr(local("_", false), tf->name, KSH_RETURN_ERROR); + setstr(local("_", false), tf->tffn, KSH_RETURN_ERROR); /* XXX: source should not get trashed by this.. */ { @@ -329,13 +329,13 @@ c_fc(const char **wp) char *xp; ssize_t n; - if (!(shf = shf_open(tf->name, O_RDONLY, 0, 0))) { + if (!(shf = shf_open(tf->tffn, O_RDONLY, 0, 0))) { bi_errorf("can't %s temporary file %s: %s", - "open", tf->name, strerror(errno)); + "open", tf->tffn, strerror(errno)); return (1); } - if (stat(tf->name, &statb) < 0) + if (stat(tf->tffn, &statb) < 0) n = 128; else if ((off_t)statb.st_size > MKSH_MAXHISTFSIZE) { bi_errorf("%s %s too large: %lu", Thistory, @@ -351,7 +351,7 @@ c_fc(const char **wp) } if (n < 0) { bi_errorf("can't %s temporary file %s: %s", - "read", tf->name, strerror(shf_errno(shf))); + "read", tf->tffn, strerror(shf_errno(shf))); errout: shf_close(shf); return (1); diff --git a/main.c b/main.c index ba40613..b37ab86 100644 --- a/main.c +++ b/main.c @@ -34,7 +34,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.215 2012/04/06 12:59:26 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.216 2012/04/14 16:07:47 tg Exp $"); extern char **environ; @@ -1015,7 +1015,7 @@ remove_temps(struct temp *tp) { for (; tp != NULL; tp = tp->next) if (tp->pid == procpid) - unlink(tp->name); + unlink(tp->tffn); } /* @@ -1499,42 +1499,61 @@ coproc_cleanup(int reuse) struct temp * maketemp(Area *ap, Temp_type type, struct temp **tlist) { - struct temp *tp; + char *cp; size_t len; - int fd; - char *pathname; + int i; + struct temp *tp; const char *dir; + struct stat sb; dir = tmpdir ? tmpdir : MKSH_DEFAULT_TMPDIR; -#if HAVE_MKSTEMP - len = strlen(dir) + 6 + 10 + 1; -#else - pathname = tempnam(dir, "mksh."); - len = ((pathname == NULL) ? 0 : strlen(pathname)) + 1; -#endif - /* reasonably sure that this will not overflow */ - tp = alloc(sizeof(struct temp) + len, ap); - tp->name = (char *)&tp[1]; -#if !HAVE_MKSTEMP - if (pathname == NULL) - tp->name[0] = '\0'; - else { - memcpy(tp->name, pathname, len); - free_ostempnam(pathname); - } -#endif - pathname = tp->name; - tp->shf = NULL; - tp->type = type; -#if HAVE_MKSTEMP - shf_snprintf(pathname, len, "%s%s", dir, "/mksh.XXXXXXXXXX"); - if ((fd = mkstemp(pathname)) >= 0) -#else - if (tp->name[0] && (fd = open(tp->name, O_CREAT | O_RDWR, 0600)) >= 0) -#endif - tp->shf = shf_fdopen(fd, SHF_WR, NULL); - tp->pid = procpid; + /* add "/shXXXXXX.tmp" plus NUL */ + len = strlen(dir); + checkoktoadd(len, offsetof(struct temp, tffn[0]) + 14); + tp = alloc(offsetof(struct temp, tffn[0]) + 14 + len, ap); + tp->shf = NULL; + tp->pid = procpid; + tp->type = type; + + if (stat(dir, &sb) || !S_ISDIR(sb.st_mode)) { + tp->tffn[0] = '\0'; + goto maketemp_out; + } + + cp = (void *)tp; + cp += offsetof(struct temp, tffn[0]); + memcpy(cp, dir, len); + cp += len; + memcpy(cp, "/shXXXXXX.tmp", 14); + /* point to the first of six Xes */ + cp += 3; + /* generate random part of filename */ + len = -1; + do { + i = rndget() % 36; + cp[++len] = i < 26 ? 'a' + i : '0' + i - 26; + } while (len < 5); + + /* cyclically attempt to open a temporary file */ + while ((i = open(tp->tffn, O_CREAT | O_EXCL | O_RDWR, 0600)) == -1) { + if (errno != EEXIST) + goto maketemp_out; + /* count down from z to a then from 9 to 0 */ + while (cp[len] == '0') + if (!len--) + goto maketemp_out; + if (cp[len] == 'a') + cp[len] = '9'; + else + --cp[len]; + /* do another cycle */ + } + + /* shf_fdopen cannot fail, so no fd leak */ + tp->shf = shf_fdopen(i, SHF_WR, NULL); + + maketemp_out: tp->next = *tlist; *tlist = tp; return (tp); diff --git a/sh.h b/sh.h index bf65be9..a22bef1 100644 --- a/sh.h +++ b/sh.h @@ -152,9 +152,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.548 2012/04/14 14:35:12 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.549 2012/04/14 16:07:48 tg Exp $"); #endif -#define MKSH_VERSION "R40 2012/04/07" +#define MKSH_VERSION "R40 2012/04/14" /* arithmetic types: C implementation */ #if !HAVE_CAN_INTTYPES @@ -535,11 +535,6 @@ im_sorry_dave(void) #define free_ossetmode(p) free(p) #endif -#if !HAVE_MKSTEMP -/* tempnam(3) -> free(3) */ -#define free_ostempnam(p) free(p) -#endif - #ifdef NO_PATH_MAX /* GNU libc: get_current_dir_name(3) -> free(3) */ #define free_gnu_gcdn(p) free(p) @@ -704,18 +699,21 @@ EXTERN const char Tgbuiltin[] E_INIT("=builtin"); EXTERN const char T_function[] E_INIT(" function"); #define Tfunction (T_function + 1) /* "function" */ -enum temp_type { - TT_HEREDOC_EXP, /* expanded heredoc */ - TT_HIST_EDIT /* temp file used for history editing (fc -e) */ -}; -typedef enum temp_type Temp_type; +typedef uint8_t Temp_type; +/* expanded heredoc */ +#define TT_HEREDOC_EXP 0 +/* temp file used for history editing (fc -e) */ +#define TT_HIST_EDIT 1 + /* temp/heredoc files. The file is removed when the struct is freed. */ struct temp { struct temp *next; struct shf *shf; - char *name; - int pid; /* pid of process parsed here-doc */ + /* pid of process parsed here-doc */ + pid_t pid; Temp_type type; + /* actually longer: name (variable length) */ + char tffn[3]; }; /*