SourceForge has been redesigned. Learn more.

#213 Temp file issues building on cygwin without GUI

Ian Rees

Needed to build ngspice for a windows 7 machine using cygwin, and without the GUI as ngspice is being run from a python script. Ran into a few issues before I could get it working, the included patch (against the latest version from git) seems to fix those.

* Added "AM_PROG_AR" to let work. I'm not sure what exactly this does, took a guess based on the errors autogen spat out and it worked...

* Once the program would configure and build, there were errors relating to a temp file not being created. Traced this back to the #ifdefs in main.c around line 1170 - the original call to tmpfile() was failing, but since HAS_WINDOWS wasn't defined (didn't want the GUI built), the alternative smktemp() and fopen() weren't getting built.

* Adjusting some #ifdefs and #defines to get smktemp() to produce a valid windows temp file name, which got ngspice to create temp files and run as desired.

* Unfortunately, this smktemp() + fopen() mechanism didn't delete the temp files after ngspice closed, so added a call to remove() to get rid of them.

I haven't tested this beyond one windows 7 machine (at work), but it does appear to work just fine for my purposes.


1 2 > >> (Page 1 of 2)
  • Holger Vogt

    Holger Vogt - 2012-09-20
    • assigned_to: nobody --> h_vogt
  • Holger Vogt

    Holger Vogt - 2012-09-20


    thanks for the input.

    To be honest, I have not used CYGWIN for some time now.

    If possible, use the console application (no GUI) created with MINGW. I will check the CYGWIN issue nevertheless.


  • Holger Vogt

    Holger Vogt - 2012-09-22

    Why is tmpfile() failing?

  • Holger Vogt

    Holger Vogt - 2012-09-22

    In my setup I am using a directory c:\cygwin\tmp which is used (automatically) to store the temporary file. When I remove this directory, ngspice fails with error message
    tmpfile(): No such file or directory.

    Please check, if possible, if this will allow to run ngspice without your patch.


  • Ian Rees

    Ian Rees - 2012-09-22

    Hi Holger,

    Thanks for the quick response! Sorry I was not clear in the first post that we needed the ngspice executable to run from windows, rather than from the cygwin terminal. That dependency comes from the python script, which has some other problems if it's run from within cygwin. Mingw is probably the right tool for the job as you suggested, I just had cygwin handy and was in a hurry.

    I have replicated your experiment with current git sources on a new windows 7 + cygwin install, and found that the executable made in cygwin works fine within cygwin (and fails when c:\cygwin\tmp is missing). When run from a windows prompt though, it gives "tmpfile(): No such file or directory".

    Looking at this again, I wonder whether some of the "#if define..."s in main.c are required, eg:

    FILE *tempfile = tmpfile();

    #if defined(HAS_WINDOWS) || defined(BUILDING_ON_WINDOWS)
    char *dname = NULL; /* input file*/
    char *tpf = NULL; /* temporary file */

    Maybe it is OK to leave the fopen() alternative if tmpfile() fails for all platforms?

    Apologies for the poor quality patch and post! -Ian-

  • Robert Larice

    Robert Larice - 2012-09-23

    Hello Ian

    > and found that the executable made in cygwin works fine
    > within cygwin (and fails when c:\cygwin\tmp is missing). When run from a
    > windows prompt though, it gives "tmpfile(): No such file or directory".

    please start a cygwin shell and examine the output of the command
    is there some environment variable named like TEMP or TMP or somesuch ?
    then try to find out which environment variables are defined if you start
    a process from a windows prompt.
    is the TEMP or TMP or whatever missing there ?
    if so try to set it, and repeat our experiment.


  • Ian Rees

    Ian Rees - 2012-09-23

    Hi Robert,


    windows terminal:

    It seems cygwin copies the temp variable names from windows and re-uses them with their names changed to lower case. Other environment variables in windows get replicated in cygwin with case preserved. So, there must be something special going on in the case of TEMP and TMP? Thanks! -Ian-

  • Robert Larice

    Robert Larice - 2012-09-23

    Hello Ian, Holger,

    googling a bit around it seems to me the tmpfile() implementation which is used here in Ian's cygwin might be
    and this boils down to _tmpnam_r() in
    which doesn't use any environment variable but just uses
    which presumably is "/tmp"

    this means, if you run the program from within cygwin, "/tmp" will be translated
    per cygwin services to something like c:\cygwin\tmp
    which obviously exists in your case.

    and if you run it outside, "/tmp" will we interpreted as something like
    where the /->\ translation is done in windows itself, and the c: is
    coming from thin air, being your "current working drive"

    please create c:\tmp make it world writeable, and tell me
    whether tmpfile() is working then.


  • Ian Rees

    Ian Rees - 2012-09-23

    Hi Robert,

    I've created c:\tmp and c:\temp with everyone allowed write access, but still get the same issue with tmpfile() not working when ngspice is run from the windows prompt. I think the issue there is that tmpfile is trying to use a '/' in the temp file name, but windows doesn't like that. That's why my original patch had a modification in defines.h - smktemp() was generating file names that do not work in windows.

    If I make a simple test program that just calls fopen("/tmp/somefile.txt", "w"), it works fine in a cygwin terminal, but fails (fopen() returns 0) in a windows terminal. If I change it to "\\tmp\\somefile.txt" and run it in windows, then the files is created, but cygwin spits out a warning about "MS-DOS style path detected".

    Interestingly, the windows terminal works using / instead of \ at least in some cases. For example, I can do "echo hello > /tmp/file.txt" or "echo hello > \tmp\file.txt" and get equivalent results (text file c:\tmp\file.txt containing "hello").

    Thanks! -Ian-

  • Robert Larice

    Robert Larice - 2012-09-24

    Hello Ian,

    I'm out of ideas know.
    probably this is a cygwin issue.
    I'd suggest to write a tiny single c-file
    with a main() and a failing tmpfile() invocation,
    and then to post this to the cygwin mailing list.


  • Holger Vogt

    Holger Vogt - 2012-09-24

    Ian, Robert, says:
    The standard does not specify the directory that tmpfile() will use. Glibc will try the path prefix P_tmpdir defined in <stdio.h>, and if that fails the directory /tmp.

    I do not know what CYGWIN tmpfile() is supposed to do, but maybe it sticks to that.

    / is probably mounted to c:\cygwin

    Under MINGW (with ngspice in some subdirectory of d:) tmpfile tries to write to d:, which is not allowed. P_tmpdir is defined as \\.

    Ian, so you may try creating a directory d:\tmp (if ngspice is somewhere in d:).


  • Holger Vogt

    Holger Vogt - 2012-09-24

    Some more experiments:

    Put ngspice.exe (and a lot of dlls required) into
    D:\ng\cyg\ and create tmp directory (one step up) in
    then it is o.k. starting ngspice from a MS Windows console.

    Most recent CYGWIN update (from yesterday) unfortunately leads to seg fault upon quitting ngspice.


  • Holger Vogt

    Holger Vogt - 2012-09-24

    Well, to be honest, the crash may also be caused by an ngspice update. I have an old ngspice build from 27 May 2012, which run o.k. with the upgraded CYGWIN dlls.


  • marco atzeri

    marco atzeri - 2012-09-25

    # TMP and TEMP as defined in the Windows environment must be kept
    FYI, currently on cygwin the tmp variables are defined in /etc/profile
    as following
    # for windows apps, even if started from cygwin. However, leaving
    # them set to the default Windows temporary directory or unset
    # can have unexpected consequences for cygwin apps, so we define
    # our own to match GNU/Linux behaviour.
    unset TMP TEMP
    tmp=$(cygpath -w "$ORIGINAL_TMP" 2> /dev/null)
    temp=$(cygpath -w "$ORIGINAL_TEMP" 2> /dev/null)

    This patch is looking for troubles

    -#if defined(__MINGW32__) || defined(_MSC_VER)
    +#if defined (__MINGW32__) || defined (__CYGWIN__) || defined (_MSC_VER) || defined (__CYGWIN32__)

    do not try to mix cygwin and windows build. Unlikely to work fine

  • Nobody/Anonymous

    built ngspice-24 without X. No need of patches , just used automake-1.11 for stability.
    configured with
    --prefix=/usr \ --disable-xgraph --disable-x \ --without-x \ --enable-xspice --enable-cider \ --with-editline=yes

    Test running, I see no issue until now.

    Are we sure that there is a problem in ngspice and not in trying to use a too thin cygwin enviroment ?

  • Ian Rees

    Ian Rees - 2012-09-26

    Quick demo of tmpfile()

  • Ian Rees

    Ian Rees - 2012-09-26

    Hi all,

    Looks like at least part of original patch I submitted wasn't a good idea - I did not understand what cygwin does well enough and was just getting something to work for what I needed.

    For whatever reason, cygwin's implementation of tmpfile() does not seem to work when the executable is called from a windows shell (unless ..\tmp exists - see below).

    Since ngspice already has code to handle tmpfile() failing when it's built with mingw, is there anything wrong with changing the #ifdefs around to enable that code when ngspice is built in a cygwin environment? Of course, smktemp() will need to either be modified or replaced to completely resolve the issue, but the comments there imply it needs to be removed anyways.

    Anonymous - Are you running ngspice from the windows command shell or from cygwin's shell? The issue I'm seeing is that it doesn't work properly when run from a windows shell.

    matzeri - I don't understand your comment about mixing cygwin and windows builds; from what I can tell, a cygwin build implies that the executable is going to be run on a windows machine. The ngspice --with-windows option builds a windows GUI version, and makes some other changes that would seem relevant to a cygwin build as well (eg handling tmpfile() returning NULL). What's the problem with exploring ways to let ngspice work whether it's run from a cygwin or a windows shell? I do agree that my original patch wasn't polished enough to use as is.

    Holger - Thanks for the tip! If I make a directory ../tmp (ahem, ..\tmp) from wherever I'm trying to run ngspice, it works. I'll look into this more and maybe ask the cygwin people.

    Out of interest, when I run the attached tmpfiletest.c from a windows shell:

    filePtr is 0x0
    A temporary file name is /tmp/taac.2

    C:\cygwin\home\ian>mkdir ..\tmp

    filePtr is 0x20040da4
    A temporary file name is /tmp/t42c.2

    Thanks everyone! -Ian-

  • marco atzeri

    marco atzeri - 2012-09-26

    Hi Ian,
    cygwin provide a unix-like enviroment through a posix layer (the cygwin1.dll)
    To build a pure cygwin program WIN32 is not defined, while for a pure windows build WIN32 is defined, mixed solution are problematic not easy to handle.
    If a program tries to use both the posix call and directly the windows call, the result
    can be unexpected; so this way is not recommended and at your own risk.

    Marco Atzeri
    (cygwin package maintainer)

  • Robert Larice

    Robert Larice - 2012-09-26

    Hello Marco, Ian,

    can we please concentrate on the "tmpfiletest.c"
    which Ian has attached to this bug tracker.

    Does It fail ?

    If so, then I think we have a cygwin bug which needs to be fixed.
    Or is there something miconfigured with Ians Windows machine,
    and or environment vars ?


  • Ian Rees

    Ian Rees - 2012-09-27

    Hi Robert,

    I'm not sure whether the results from tmpfiletest.c are a "fail" or not, but it's not the behavior I would've expected. Maybe my expectation that cygwin binaries should generally be usable from a windows shell is misplaced?

    The windows+cygwin install used for the tmpfiletest results below is quite standard - a fresh install of windows and cygwin (in a virtual machine).

    GCC 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)


  • Holger Vogt

    Holger Vogt - 2012-09-27

    Looking into the CYGWIN sources at

    tmpfile uses tmpnam to define path and name.
    tmpnam creates a name with directory prefix given by P_tmpdir (and only that), which is set to "/tmp" in stdio.h. It does not look for environmental variables.

    In a CYGWIN shell this translates to C:/CYGWIN/tmp/ for a standard installation.

    From a plain Windows console this, as we have experienced, translates to ..\tmp (which I currently do not understand).


  • marco atzeri

    marco atzeri - 2012-10-05

    Sorry for delay in followup. Due to a HD crash I was busy ...

    the expected tree directory for cygwin is

    /bin (where cygwin1.dll stays)

    so when ngspice is in bin, the temp directly is /bin/../tmp -> /tmp

    Newlib (the C library) define P_tmpdir as "/tmp" so not only cygwin has
    this hardcoded definition.
    I could agree it is a "bug" but the workaround for Ian is very simple,
    use the file structure:


    No particular interest from my side to add additional code on newlib
    to verify that "/tmp" really exists.

  • Ian Rees

    Ian Rees - 2012-11-20

    Should I close this out, or is it worth making up a new patch to try making a local temporary file if tmpfile() has failed? Thanks! -Ian-

  • Robert Larice

    Robert Larice - 2012-11-20

    Hello Ian,

    I read this discussion that way:
    tmpfile() works well in cygwin
    if ngspice is called in the expected way,
    that is from inside a running cygwin environment.
    (the cygwin bash or for example)
    It fails if you run the program from outside.

    Marco, speaking for cygwin,
    doesn't show interest to fix this,
    but says such usage is simply not supported.

    I have no interest to add workarounds
    for non working tmpfile() implementations.

    The idea with `remove' is weak anyway.
    You want a contract with the OS, that this
    file will disappear under all circumstances.

    On unix, this is done with an open() instantly
    followed by unlink(), (there you can still use
    a unlinked file handle)
    This technique is abstracted away in the tmpfile() function.

    This technique does not work on windows,
    there microsoft has additional flags for
    the fopen() calls, namely "T" and "D"


    patch has been uploaded to git.

    Thank You

1 2 > >> (Page 1 of 2)

Log in to post a comment.