Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

For the new version of my package and class standalone I like to call external programs: further (pdf)latex runs to optionally compile included standalone files, and to convert the resulting PDF to PNG (depends on the fact that the PDF created by the last run isn't overwritten at least until \begin{document} or until the first page is flushed out).

I know of course this can be done using \immediate\write18{<command> <arguments>} which requires the command to be either added to the shell_escape_commands variable of texmf.cnf and shell_escape to be set to p or that the user uses the -shell-escape argument.

Now I like to test in my code if the write18 call was successfully, i.e. if it was allowed to be executed. I know that \ifeof18 will return false if the write18 feature is completely disabled (shell_escape = 0 in texmf.cnf or when the -no-shell-escape argument is used), but it returns true if the restricted write18 mode is activated which is the default.

Is there a way to test if the last write18 call was blocked? (I know that I can test manually if the file which should be produced by the write18 call was created or updated.)


Update

In the .log file there its one of the following lines displayed for every write18 call, depending if this feature is disabled, enabled or running in restricted mode with the command allowed or not, respectively:

runsystem(<command>)...disabled.
runsystem(<command>)...executed.
runsystem(<command>)...executed safely (allowed).
runsystem(<command>)...disabled (restricted).

So how can I get this information inside the LaTeX file (without actually reading the .log file in)?

share|improve this question
    
A now posted this question also on c.t.t where Heiko Oberdiek recommended to open a feature request for pdfTeX (and/or other TeX engines). I opened such an request of pdfTeX now. –  Martin Scharrer Mar 18 '11 at 20:47

4 Answers 4

What I did to solve the same task was to use

\ifnum\pdfshellescape=1
% Yes, enabled
\else
% No, disabled
\fi

The control sequence \pdfshellescape is (only?) available in pdftex, i.e. you will also need to check that it exists.

share|improve this answer
1  
Thanks, I didn't know \pdfshellescape yet. The pdftex manual states that it is 0 when write18 is disabled, 1 if enabled and 2 in restricted mode. So it gives you more information than \ifeof18. I can now be sure that the program got executed when it has the value of 1. However, I would also need to know if it got executed in restricted mode (2), i.e. if the program has been added to the list of permitted programs. –  Martin Scharrer Mar 11 '11 at 21:00
    
@Martin I think you'd be pretty safe to assume your users will only use the default set of non-restricted executables. –  Will Robertson Mar 12 '11 at 15:01
    
@Will Robertson: Yes, but I like to add a section in my manual how to allow the specific programs used and support this scenario. –  Martin Scharrer Mar 12 '11 at 15:04
up vote 11 down vote accepted

It seems that pdflatex does not provide any other status variables beyond \ifeof18 and \pgfshellescape. This got confirmed on c.t.t by Heiko Oberdiek. He also recommended to open a feature request for pdfTeX (and/or other TeX engines), which I did.

Here the solution I came up with:

As mentioned in the two answers one good way to check for write18 is the \pdfshellescape macro, available since pdftex 1.30.0. It is 1 if \write18 is enabled, 2 if it is restricted, and 0 otherwise. It is not available in XeTeX or LuaTeX. However, the package pdftexcmds by Heiko Oberdiek adds it to LuaTeX and also checks for pdfTeX >=1.30.0 for you. The macro is then provided as \pdf@shellescape.

In my case I want to check if a conversion command was successful. I had the idea to use \pdffilemoddate (\pdf@filemoddate with pdftexcmds) to check if the to be generated file is newer afterwards or not. Together with \IfFileExists this allows for a very reasonable test which works with pdfLaTeX and LuaLaTeX. For XeLaTeX only a very limited test can be implemented.

The following macro awaits the name of the output file and the command:

 \writesuccess{<output file>}{<command line>}{<success>}{<failure>}

However, if the called command is executed but fails and updates the file modification date in the process the macro would report it as success. There is no way at the moment to check for this.

The full code with an example: conversion of the resulting PDF to PNG, needs two runs, where at least the second one requires -shell-escape:

\documentclass{standalone}

% Use `pdftexcmds` to support LuaTeX and take advantage of
% the included checks like version of pdflatex, existence of \ifeof18, etc.:
\usepackage{pdftexcmds}
\makeatletter
\ifx\pdf@filemoddate\@undefined

% Without filemoddate (e.g. XeLaTeX) only the existence of the file can be tested:
\newcommand{\writesuccess}[2]{%
    \immediate\write18{#2}%
    \IfFileExists{#1}%
}

\else

% Real version:
% Check if to-be-generated file exists afterwards and is newer:
\newcommand{\writesuccess}[2]{%
    \begingroup
    \edef\filemodbefore{\pdf@filemoddate{#1}}%
    \immediate\write18{#2}%
    \IfFileExists{#1}{%
        \edef\filemodafter{\pdf@filemoddate{#1}}%
        \ifx\filemodbefore\filemodafter
            \let\next\@secondoftwo
        \else
            \let\next\@firstoftwo
        \fi
    }{%
        \let\next\@secondoftwo
    }%
    \expandafter
    \endgroup
    \next
}

\fi
\makeatother


\writesuccess{\jobname.png}{convert -density 600 \jobname.pdf \jobname.png}{%
    \message{^^JYes^^J}%
}{%
    \message{^^JNo^^J}%
}

\begin{document}
Test
\end{document}
share|improve this answer

The bashful package may prove useful for your purposes. It does manage \write18 errors, although I am not sure it is exactly in the way you asked for. Here is a small demo:

\documentclass[a6paper]{article}
\usepackage[verbose]{bashful}
\usepackage{graphicx}

\begin{document}
Here I create a small \LaTeX{} file:
\bash[script]
cat > delme.tex << EOF
\documentclass{standalone}
\begin{document}
Lorem ipsum dolor sit amet!
\end{document}
EOF
\END
Now I shall run the file I just created through \LaTeX{},
\bash[script]
pdflatex -shell-escape delme.tex
\END
obtaining the following output

\begin{center}
  \fbox{\includegraphics{delme.pdf}}
\end{center}

\end{document}

Which generates the following output:using the <code>standalone</code> package from within LaTeX

share|improve this answer

You can implement \ifwritexviii condition. This is directly taken verbatim from xepersian (and this again taken from one of the Heiko's packages):

\def\xepersian@cmds@temp#1{%
  \begingroup\expandafter\expandafter\expandafter\endgroup
  \expandafter\ifx\csname xepersian@#1\endcsname\relax
    \begingroup
      \escapechar=-1 %
      \edef\x{\expandafter\meaning\csname#1\endcsname}%
      \def\y{#1}%
      \def\z##1->{}%
      \edef\y{\expandafter\z\meaning\y}%
    \expandafter\endgroup
    \ifx\x\y
      \expandafter\def\csname xepersian@#1\expandafter\endcsname
      \expandafter{%
        \csname#1\endcsname
      }%
    \fi
  \fi
}%
\xepersian@cmds@temp{shellescape}
\newif\ifwritexviii
\ifnum\xepersian@shellescape=1\relax
  \writexviiitrue
\else
\writexviiifalse
\fi

and you can use it as:

\ifwritexviii
   % material if shell scape is enabled
\else
   % material if shell escape is disabled
\fi
share|improve this answer
1  
Thank you Vafa Khalighi, but this doesn't help me in the case when the restricted mode is activated (the shellescape register has then a value 2) and the program I run may or may not be in the list of the permitted programs. You are right, Heiko Oberdiek's package pdftexcmds defines something similar: a register \pdf@shellescape which will use \pdfshellescape if available but also work otherwise as well as with LuaTeX. –  Martin Scharrer Mar 12 '11 at 10:27

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.