(See the next iteration.)From time to time, while working with a command line in *nix family of operating systems, we have to write those scripts doing a rather specific task. Usually we use bash + utility programs to do the job. However, I had to ask myself: how to implement such a script in C? After an invocation of such a script, it should perform the following:Create a temporary source file \$S\$,Dump the C code to \$S\$,Compile \$S\$ to the program \$P\$,Run \$P\$ passing the arguments to it and caching its exit status,Remove \$S\$ and \$P\$,Return the cached exit status of \$P\$.Code#! /bin/bash# Below, XXXX asks for random characters in order to make a unique file name. # Mac OSX seems to ignore XXXX, yet Ubuntu requires them.# Create a temporary file name for the source code:TMP_SOURCE_FILE=$(mktemp -t sourceXXXX).c# Create a temporary file name for the executable file:TMP_PROGRAM_FILE=$(mktemp -t programXXXX)# Write the source code into the temporary source file:cat > $TMP_SOURCE_FILE <<- END_OF_SOURCE#include <stdio.h>int main(int argc, char* argv[]) {    int i;    puts(Hello, world! I am a pseudoportable C program.);    for (i = 1; i < argc; ++i)     {        printf(Argument %d: %s\n, i, argv[i]);    }    return argc - 1;}END_OF_SOURCE# Compile and run:gcc $TMP_SOURCE_FILE -o $TMP_PROGRAM_FILE$TMP_PROGRAM_FILE $@EXIT_STATUS=$?# Clean the source and the binary:rm $TMP_SOURCE_FILErm $TMP_PROGRAM_FILE# Delegate the exit status of the C program to calling bash:exit $EXIT_STATUSSo, what do you think? How can I improve anything? Also, can you come with an example of the situation where this C script pattern is more preferable than bash + command line utilities, Python, etc.?
Pseudoportable C script pattern
c;bash;portability;unix;compiler
It's not guaranteed that $TMP_PROGRAM_FILE is on the $PATH, so you need to either set the $PATH or use an absolute path for $TMP_PROGRAM_FILE.You have problems with mktemp.-t option: It means different things on GNU/Linux mktemp(1) and Mac OS X mktemp(1).On GNU/Linux:-t    interpret TEMPLATE as a single file name component,      relative to a directory: $TMPDIR, if set; else the      directory specified via -p; else /tmp [deprecated]On OS X:mktemp [-t prefix] template mktemp -t prefix    -t prefix            Generate a template (using the supplied prefix and TMPDIR if set) to create a filename tem-plate. template.            plate.Perhaps the confusion is the reason why the GNU/Linux man page indicates that it is deprecated.  I think you just want to run mktemp TEMPLATE without the -t option.Cleanup: Use trap rm $TMP_SOURCE_FILE $TMP_PROGRAM_FILE EXIT as a more robust way to delete the temporary files, in case your script aborts before reaching the rm commands..c suffix:  By writing TMP_SOURCE_FILE=$(mktemp -t sourceXXXX).c, you end up getting mktemp to create the file sourceXXXX.  That file does not get cleaned up.  Also, when you do cat > $TMP_SOURCE_FILE, you may be creating sourceXXXX.c, or worse, truncating an existing file.On GNU/Linux, a remedy would be to use the --suffix .c option.  Unfortunately, the BSD/OS X version doesn't support it.  One workaround is to rename the file after creation using mv -i  which might fail, but at least it's secure.A better workaround would be to use gcc -x c to tell GCC that it is C source code, without considering the filename extension.An even better solution would beAvoid $TMP_SOURCE_FILE altogether: gcc can take its source code from its standard input!  Use - as the filename.gcc -o $TMP_PROGRAM_FILE -x c - <<- END_OF_SOURCEEND_OF_SOURCE