This is the mail archive of the cygwin@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

How to call cygwin_conv_to_full_win32_path from a Windows app?


Hi list,

Is there a way I can call a cygwin function from a native windows
application?
I tried the obvious approach of linking against libcygwin.a, but after
hitting
a long string of conflicts, I gave up.

Is there a way to do this?

Geoff

p.s. what I'm trying to do is create a *wrapper* program that serves as
  a bridge between the Cygwin world, and the Windows world, to convert
  command line parameters from cygpath to win32.  Specifically, below is
  the wrapper.  If it's run, it takes it's name, say it was perl.exe, and
  first tries to locate the *real* "perl.exe" someplace in the PATH, and
  then it will *exec* that guy with all the parameter file names converted
  to win32 format.

I tried making this a pure CYGWIN application, but the problem is the "exec"
call in CYGWIN isn't a real exec - I get left with two processes.  Which
means
CTRL-C processing only kills the parent, leaving the orphaned child happily
continuing (which I don't want :).  The Windows docs claim their _exec
truely
replaces the parent process (like UNIX).  I'm trying to see if that's really
true.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <process.h>

extern "C" {
  void cygwin_conv_to_full_win32_path(const char *path, char *win32_path);
}

void main (int argc, char** argv) {

  struct _stat stbuf;

  char* name = argv[0];
  for (char* pp = argv[0]; *pp; pp++) {
    if (*pp == '\\' || *pp == '/') name = ++pp;
  }

  char cmd[2048] = "";

    /* Find the *real* version of this command (argv[0]) */

    char path[2048];
    strcpy (path, getenv("PATH"));
    char* path_end = path + strlen (path);
    {for (char* pp = path; pp < path_end; pp++) {
      if (*pp == ';') {*pp = 0;}
    }}

    char pathext[2048] = ";", *pPATHEXT = getenv("PATHEXT");
    strcpy (pathext+1, pPATHEXT ? pPATHEXT : ".EXE;.COM;.BAT");
    char* pathext_end = pathext + 1 + strlen (pathext+1);
    {for (char* ppe = pathext; ppe < pathext_end; ppe++) {
      if (*ppe == ';') {*ppe = 0;}
    }}

    /* Now build the command.  I would have liked to use "_execv",
     * with the cmd_args array below, but CYGWIN tty handling
     * seems to be a problem, so we'll just build a "system"
     * call which will call the DOS cmd shell first, then our program */

    int my_size = -1;
    {for (char* ppe = pathext; ppe < pathext_end; ppe += strlen (ppe) + 1) {
      sprintf (cmd, "%s%s", argv[0], ppe);
      if (!_stat (cmd, &stbuf)) {
        my_size = stbuf.st_size;
        break;
      }
    }}
    {for (char* pp = path; pp < path_end; pp += strlen (pp) + 1) {
      for (char* ppe = pathext; ppe < pathext_end; ppe += strlen (ppe) + 1)
{
        sprintf (cmd, "%s\\%s%s", pp, name, ppe);
        if (!_stat (cmd, &stbuf)) {
          if (my_size == -1) {
            my_size = 0;
          } else if (stbuf.st_size != my_size) {
            goto FOUND;
          }
        }
      }
    }}
    printf ("Could not find command: %s!  Aborting!!\n", name);
    exit (1);

  /* Build the parameter list */

 FOUND:
  char* cmd_args[256], args_storage[2048], *pas = cmd + strlen(cmd);
  int iarg = 0;
  cmd_args[iarg++] = cmd;
  for (int i = 1; i < argc; i++) {
    *pas++ = 0;
    cmd_args[iarg++] = pas;
    cygwin_conv_to_full_win32_path (argv[i], pas);
    if (!_stat (pas, &stbuf)) {
      pas += strlen(pas);
      goto ARGS;
    }
    strcpy (pas, argv[i]);
    pas += strlen(pas);
  ARGS:;
  }
  cmd_args[iarg] = 0;

  /* Call it */
  _execv (cmd, cmd_args);
  //system(cmd);
}



--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]