Previous: Sysval, Up: Shell commands [Contents][Index]
Commands specified to syscmd or esyscmd might need a
temporary file, for output or for some other purpose. There is a
builtin macro, mkstemp, for making a temporary file:
Expands to the quoted name of a new, empty file, made from the string
template, which should end with the string ‘XXXXXX’. The six
‘X’ characters are then replaced with random characters matching
the regular expression ‘[a-zA-Z0-9._-]’, in order to make the file
name unique. If fewer than six ‘X’ characters are found at the end
of template, the result will be longer than the template. The
created file will have access permissions as if by chmod =rw,go=,
meaning that the current umask of the m4 process is taken into
account, and at most only the current user can read and write the file.
The traditional behavior, standardized by POSIX, is that
maketemp merely replaces the trailing ‘X’ with the process
id, without creating a file or quoting the expansion, and without
ensuring that the resulting
string is a unique file name. In part, this means that using the same
template twice in the same input file will result in the same
expansion. This behavior is a security hole, as it is very easy for
another process to guess the name that will be generated, and thus
interfere with a subsequent use of syscmd trying to manipulate
that file name. Hence, POSIX has recommended that all new
implementations of m4 provide the secure mkstemp builtin,
and that users of m4 check for its existence.
The expansion is void and an error issued if a temporary file could not be created.
The macros mkstemp and maketemp are recognized only with
parameters.
If you try this next example, you will most likely get different output for the two file names, since the replacement characters are randomly chosen:
$ m4
define(`tmp', `oops')
⇒
maketemp(`/tmp/fooXXXXXX')
⇒/tmp/fooa07346
ifdef(`mkstemp', `define(`maketemp', defn(`mkstemp'))',
`define(`mkstemp', defn(`maketemp'))dnl
errprint(`warning: potentially insecure maketemp implementation
')')
⇒
mkstemp(`doc')
⇒docQv83Uw
Unless you use the --traditional command line option (or
-G, see Invoking m4), the GNU
version of maketemp is secure. This means that using the same
template to multiple calls will generate multiple files. However, we
recommend that you use the new mkstemp macro, introduced in
GNU M4 1.4.8, which is secure even in traditional mode. Also,
as of M4 1.4.11, the secure implementation quotes the resulting file
name, so that you are guaranteed to know what file was created even if
the random file name happens to match an existing macro. Notice that
this example is careful to use defn to avoid unintended expansion
of ‘foo’.
$ m4
define(`foo', `errprint(`oops')')
⇒
syscmd(`rm -f foo-??????')sysval
⇒0
define(`file1', maketemp(`foo-XXXXXX'))dnl
ifelse(esyscmd(`echo \` foo-?????? \''), ` foo-?????? ',
`no file', `created')
⇒created
define(`file2', maketemp(`foo-XX'))dnl
define(`file3', mkstemp(`foo-XXXXXX'))dnl
ifelse(len(defn(`file1')), len(defn(`file2')),
`same length', `different')
⇒same length
ifelse(defn(`file1'), defn(`file2'), `same', `different file')
⇒different file
ifelse(defn(`file2'), defn(`file3'), `same', `different file')
⇒different file
ifelse(defn(`file1'), defn(`file3'), `same', `different file')
⇒different file
syscmd(`rm 'defn(`file1') defn(`file2') defn(`file3'))
⇒
sysval
⇒0
Previous: Sysval, Up: Shell commands [Contents][Index]