Mail Archives: cygwin/2006/02/09/10:41:20
--------------010404050702080404040105
Content-Type: text/plain; charset=windows-1252
Content-Transfer-Encoding: 7bit
On 8-Feb-2006 18:49, Michael Schaap wrote:
> On 8-Feb-2006 16:41, Christopher Faylor wrote:
>
>> On Tue, Feb 07, 2006 at 01:25:12PM -0600, Brian Ford wrote:
>>
>>
>>> On Tue, 7 Feb 2006, Christopher Faylor wrote:
>>>
>>>
>>>
>>>> I believe that Brian Ford is looking into modifying the new CW_SETUP_WINENV
>>>> code to perform the proper conversion of POSIX style to Windows style.
>>>>
>>>>
>>> We're still debating aproaches for solving our problem, so it is possible
>>> I won't get to it. If someone else wants to try, feel free.
>>>
>>>
>> Well, that's disappointing. I'm not aware of any debates. I thought
>> just this once we could rely on someone else fixing a problem.
>>
>> I guess I'll look into this when I get a chance.
>>
>>
>>
> Well, the below code works for cygstart, and does the right thing for
> the variables Cygwin converts from POSIX <-> Win32.
> Feel free to adapt this to CW_SETUP_WINENV. (Although it might be more
> elegant to use conv_envvars[] from environ.cc there.)
>
> If I hear no objections, I'm going to submit this as a path for
> cygutils, and ask Chuck to release it. If and when this gets fixed in
> CW_SETUP_WINENV, and released, I'll change it to use that instead.
>
No idea why Thunderbird decided to strip the indentation... Anyway,
I'll just attach cygstart.c instead.
- Michael
--------------010404050702080404040105
Content-Type: text/plain;
name="cygstart.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="cygstart.c"
/*
* cygstart - Let Windows start a program, or open a file or URL
*
* (c) 2002 Michael Schaap <cygstart(at)mscha.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* See the COPYING file for license information.
*/
#if HAVE_CONFIG_H
#include "config.h"
#endif
#include "common.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "cygstart"
#define AUTHORS "Michael Schaap"
/* Predefined actions */
#define ACTION_OPEN "open"
#define ACTION_EXPLORE "explore"
#define ACTION_EDIT "edit"
#define ACTION_FIND "find"
#define ACTION_PRINT "print"
/* MSDN reference URL */
#define MSDN_URL "http://msdn.microsoft.com/library/en-us/shellcc/platform/" \
"Shell/reference/functions/shellexecute.asp"
static const char versionID[] = "1.2";
/* for future CVS */
static const char revID[] =
"$Id: cygstart.c,v 1.4 2005/05/16 20:18:52 cwilson Exp $";
static const char copyrightID[] =
"Copyright (c) 2002,...\n"
"Michael Schaap. All rights reserved.\n"
"Licensed under GPL v2.0\n";
/* The name this program was run with. */
static char *program_name;
static int cygStart(const char *aPath, const char *action, const char *args,
const char *workDir, int show);
static int winStart(const char *aPath, const char *action, const char *args,
const char *workDir, int show);
static char *startError(int err);
static const char *getVersion(void);
static void printTopDescription(FILE *f, char *name);
static void printBottomDescription(FILE *f, char *name);
static void usage(poptContext optCon, FILE *f, char *name);
static void help(poptContext optCon, FILE *f, char *name);
static void version(poptContext optCon, FILE *f, char *name);
static void license(poptContext optCon, FILE *f, char *name);
static void setup_win_environ(void);
int main(int argc, const char **argv)
{
poptContext optCon;
const char *arg;
const char **rest;
int rc;
int ret;
char *action = NULL;
char *file = NULL;
size_t argLength;
const char **tmp;
char *args = NULL;
char *workDir = NULL;
int show = SW_SHOWNORMAL;
/* Action options */
struct poptOption actionOptionsTable[] = {
{ "action", 'a', POPT_ARG_STRING, NULL, 'a', \
"Use specified action instead of default", NULL},
{ "open", 'o', POPT_ARG_NONE, NULL, 'o', \
"Short for: --action open", NULL},
{ "explore", 'x', POPT_ARG_NONE, NULL, 'x', \
"Short for: --action explore", NULL},
{ "edit", 'e', POPT_ARG_NONE, NULL, 'e', \
"Short for: --action edit", NULL},
{ "find", 'f', POPT_ARG_NONE, NULL, 'f', \
"Short for: --action find", NULL},
{ "print", 'p', POPT_ARG_NONE, NULL, 'p', \
"Short for: --action print", NULL},
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
};
/* Directory options */
struct poptOption directoryOptionsTable[] = {
{ "directory", 'd', POPT_ARG_STRING, NULL, 'd', \
"Set working directory", NULL},
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
};
/* Show options */
struct poptOption showOptionsTable[] = {
{ "hide", '\0', POPT_ARG_NONE, NULL, 'H', \
"Hides the window and activates another window", NULL},
{ "maximize", '\0', POPT_ARG_NONE, NULL, 'M', \
"Maximizes the specified window", NULL},
{ "minimize", '\0', POPT_ARG_NONE, NULL, 'N', \
"Minimizes the specified window and activates the next top-level "
"window in the z-order", NULL},
{ "restore", '\0', POPT_ARG_NONE, NULL, 'R', \
"Activates and displays the window. If the window is minimized or "
"maximized, Windows restores it to its original size and position. "
"An application should specify this flag when restoring a minimized "
"window", NULL},
{ "show", '\0', POPT_ARG_NONE, NULL, 'S', \
"Activates the window and displays it in its current size and "
"position", NULL},
{ "showmaximized", '\0', POPT_ARG_NONE, NULL, 'X', \
"Activates the window and displays it as a maximized window", NULL},
{ "showminimized", '\0', POPT_ARG_NONE, NULL, 'Y', \
"Activates the window and displays it as a minimized window", NULL},
{ "showminnoactive", '\0', POPT_ARG_NONE, NULL, 'Z', \
"Displays the window as a minimized window. The active window "
"remains active", NULL},
{ "showna", '\0', POPT_ARG_NONE, NULL, 'A', \
"Displays the window in its current state. The active window "
"remains active", NULL},
{ "shownoactivate", '\0', POPT_ARG_NONE, NULL, 'V', \
"Displays a window in its most recent size and position. The "
"active window remains active", NULL},
{ "shownormal", '\0', POPT_ARG_NONE, NULL, 'O', \
"Activates and displays a window. If the window is minimized or "
"maximized, Windows restores it to its original size and position. "
"An application should specify this flag when displaying the window "
"for the first time", NULL},
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
};
/* Help options */
struct poptOption helpOptionsTable[] = {
{ "help", '?', POPT_ARG_NONE, NULL, '?', \
"Show this help message", NULL},
{ "usage", '\0', POPT_ARG_NONE, NULL, 'u', \
"Display brief usage message", NULL},
{ "version", '\0', POPT_ARG_NONE, NULL, 'v', \
"Display version information", NULL},
{ "license", '\0', POPT_ARG_NONE, NULL, 'l', \
"Display licensing information", NULL},
{ "reference", '\0', POPT_ARG_NONE, NULL, 'r', \
"Open MSDN reference for ShellExecute", NULL},
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
};
struct poptOption opt[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, actionOptionsTable, 0, \
"Action options", NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, directoryOptionsTable, 0, \
"Directory options", NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, showOptionsTable, 0, \
"Show options", NULL },
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, helpOptionsTable, 0, \
"Help options", NULL },
{ NULL, '\0', 0, NULL, 0, NULL, NULL }
};
if ((program_name = strdup(argv[0])) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
/* Parse options */
optCon = poptGetContext(NULL, argc, argv, opt, POPT_CONTEXT_POSIXMEHARDER);
poptSetOtherOptionHelp(optCon, "[OPTION]... FILE [ARGUMENTS]");
while ((rc = poptGetNextOpt(optCon)) > 0) {
switch (rc) {
/* Help options */
case '?':
help(optCon, stdout, program_name);
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (workDir)
free(workDir);
return(0);
case 'u':
usage(optCon, stdout, program_name);
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (workDir)
free(workDir);
return(0);
case 'v':
version(optCon, stdout, program_name);
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (workDir)
free(workDir);
return(0);
case 'l':
license(optCon, stdout, program_name);
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (workDir)
free(workDir);
return(0);
case 'r':
cygStart(MSDN_URL, NULL, NULL, NULL, SW_NORMAL);
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (workDir)
free(workDir);
return(0);
/* Action options */
case 'a':
if (arg = poptGetOptArg(optCon)) {
if ((action = strdup(arg)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n",
argv[0]);
exit(1);
}
}
break;
case 'o':
if ((action = strdup(ACTION_OPEN)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
break;
case 'x':
if ((action = strdup(ACTION_EXPLORE)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
break;
case 'e':
if ((action = strdup(ACTION_EDIT)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
break;
case 'f':
if ((action = strdup(ACTION_FIND)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
break;
case 'p':
if ((action = strdup(ACTION_PRINT)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
break;
/* Directory options */
case 'd':
if (arg = poptGetOptArg(optCon)) {
if ((workDir = strdup(arg)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n",
argv[0]);
exit(1);
}
}
break;
/* Show options */
case 'H':
show = SW_HIDE;
break;
case 'M':
show = SW_MAXIMIZE;
break;
case 'N':
show = SW_MINIMIZE;
break;
case 'R':
show = SW_RESTORE;
break;
case 'S':
show = SW_SHOW;
break;
case 'X':
show = SW_SHOWMAXIMIZED;
break;
case 'Y':
show = SW_SHOWMINIMIZED;
break;
case 'Z':
show = SW_SHOWMINNOACTIVE;
break;
case 'A':
show = SW_SHOWNA;
break;
case 'V':
show = SW_SHOWNOACTIVATE;
break;
case 'O':
show = SW_SHOWNORMAL;
break;
}
}
if (rc < -1 ) {
fprintf(stderr, "%s: bad argument %s: %s\n",
program_name, poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (workDir)
free(workDir);
return(2);
}
rest = poptGetArgs(optCon);
/* Determine file (or program, or URL) to start */
if (rest && *rest) {
if ((file = strdup(*rest)) == NULL ) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
rest++;
} else {
usage(optCon, stdout, program_name);
return(2);
}
/* Retrieve any arguments */
if (rest && *rest) {
tmp = rest;
argLength = strlen(*tmp);
while (tmp++ && *tmp) {
argLength += 1 + strlen(*tmp);
}
if ((args = (char *) malloc(argLength+1)) == NULL) {
fprintf(stderr, "%s: memory allocation error\n", argv[0]);
exit(1);
}
strcpy(args, *rest);
while (rest++ && *rest) {
strcat(args, " ");
strcat(args, *rest);
}
}
/* Start it! */
ret = cygStart(file, action, args, workDir, show);
poptFreeContext(optCon);
free(program_name);
if (action)
free(action);
if (args)
free(args);
if (workDir)
free(workDir);
if (file)
free(file);
return (ret ? 0 : 1);
}
/* Start a program, or open a file or URL, using Cygwin POSIX paths */
static int cygStart(const char *aPath, const char *action, const char *args,
const char *workDir, int show)
{
char winPath[MAX_PATH+1];
char winDir[MAX_PATH+1];
/* Convert file path from POSIX to Windows, unless it looks like a URL */
if (!strstr(aPath, "://")) {
cygwin_conv_to_win32_path(aPath, winPath);
} else {
strncpy(winPath, aPath, MAX_PATH);
}
/* Convert working directory, if any, from POSIX to Windows */
if (workDir) {
cygwin_conv_to_win32_path(workDir, winDir);
return winStart(winPath, action, args, winDir, show);
} else {
return winStart(winPath, action, args, NULL, show);
}
}
/* Start a program, or open a file or URL, using Windows paths */
static int winStart(const char *aPath, const char *action, const char *args,
const char *workDir, int show)
{
int ret;
/* Need to sync the Windows environment when running under "mount -X" */
setup_win_environ();
ret = (int) ShellExecute(NULL, action, aPath, args, workDir, show);
if (ret >= 32) {
return TRUE;
} else {
printf("Unable to start '%s': %s\n", aPath, startError(ret));
return FALSE;
}
}
/* Return an error message, given a ShellExecute return code */
static char *startError(int err)
{
switch (err) {
case 0:
return "The operating system is out of memory or resources.";
case ERROR_FILE_NOT_FOUND:
return "The specified file was not found.";
case ERROR_PATH_NOT_FOUND:
return "The specified path was not found.";
case ERROR_BAD_FORMAT:
return "The .exe file is invalid (non-Win32 .exe or error in "
".exe image).";
case SE_ERR_ACCESSDENIED:
return "The operating system denied access to the specified file.";
case SE_ERR_ASSOCINCOMPLETE:
return "The file name association is incomplete or invalid.";
case SE_ERR_DDEBUSY:
return "The DDE transaction could not be completed because "
"other DDE transactions were being processed.";
case SE_ERR_DDEFAIL:
return "The DDE transaction failed.";
case SE_ERR_DDETIMEOUT:
return "The DDE transaction could not be completed because the "
"request timed out.";
case SE_ERR_DLLNOTFOUND:
return "The specified dynamic-link library was not found.";
case SE_ERR_NOASSOC:
return "There is no application associated with the given file "
"name extension.";
case SE_ERR_OOM:
return "There was not enough memory to complete the operation.";
case SE_ERR_SHARE:
return "A sharing violation occurred.";
default:
return "An unknown error occurred.";
}
}
static const char *getVersion()
{
return versionID;
}
static void printTopDescription(FILE *f, char *name)
{
fprintf(f, "%s version %s, by %s\n", name, getVersion(), AUTHORS);
fprintf(f, "\nLet Windows start a program or open a file or URL.\n\n");
}
static void printBottomDescription(FILE *f, char *name)
{
fprintf(f, "\n");
fprintf(f, "With thanks to MSDN: <%s>\n\n", MSDN_URL);
fprintf(f, "Please report any bugs to <cygwin(at)cygwin.com>.\n");
}
static printLicense(FILE *f, char *name)
{
fprintf(f, "This program is free software; you can redistribute it and/or\n");
fprintf(f, "modify it under the terms of the GNU General Public License\n");
fprintf(f, "as published by the Free Software Foundation; either version 2\n");
fprintf(f, "of the License, or (at your option) any later version.\n");
fprintf(f, "\n");
fprintf(f, "This program is distributed in the hope that it will be useful,\n");
fprintf(f, "but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
fprintf(f, "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
fprintf(f, "GNU General Public License for more details.\n");
fprintf(f, "\n");
fprintf(f, "You should have received a copy of the GNU General Public License\n");
fprintf(f, "along with this program; if not, write to the Free Software\n");
fprintf(f, "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");
fprintf(f, "\n");
fprintf(f, "See the COPYING file for license information.\n");
}
static void usage(poptContext optCon, FILE *f, char *name)
{
poptPrintUsage(optCon, f, 0);
}
static void help(poptContext optCon, FILE *f, char *name)
{
printTopDescription(f, name);
poptPrintHelp(optCon, f, 0);
printBottomDescription(f, name);
}
static void version(poptContext optCon, FILE *f, char *name)
{
printTopDescription(f, name);
}
static void license(poptContext optCon, FILE *f, char *name)
{
printTopDescription(f, name);
printLicense(f, name);
}
/* Copy cygwin environment variables to the Windows environment if they're not
* already there. */
static void setup_win_environ(void)
{
char **envp = environ;
char *var, *val;
char curval[2];
char *winpathlist;
char winpath[MAX_PATH+1];
while (envp && *envp) {
var = strdup(*envp++);
val = strchr(var, '=');
*val++ = '\0';
if (GetEnvironmentVariable(var, curval, 2) == 0
&& GetLastError() == ERROR_ENVVAR_NOT_FOUND) {
/* Convert POSIX to Win32 where necessary */
if (!strcmp(var, "PATH") ||
!strcmp(var, "LD_LIBRARY_PATH")) {
winpathlist = (char *)
malloc(cygwin_posix_to_win32_path_list_buf_size(val));
if (winpathlist) {
cygwin_posix_to_win32_path_list(val, winpathlist);
SetEnvironmentVariable(var, winpathlist);
free(winpathlist);
}
} else if (!strcmp(var, "HOME") ||
!strcmp(var, "TMPDIR") ||
!strcmp(var, "TMP") ||
!strcmp(var, "TEMP")) {
cygwin_conv_to_win32_path(val, winpath);
SetEnvironmentVariable(var, winpath);
} else {
SetEnvironmentVariable(var, val);
}
}
free(var);
}
}
--------------010404050702080404040105
Content-Type: text/plain; charset=us-ascii
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
--------------010404050702080404040105--
- Raw text -