2 * Copyright (c) 2006,2009 Charles S. Wilson
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
40 # include <sys/types.h>
46 # include <sys/stat.h>
55 # include <sys/cygwin.h>
57 #if HAVE_WINDOWS_H && HAVE_OPENCLIPBOARD
58 # define WIN32_LEAD_AND_MEAN
68 char *program_name
= NULL
;
70 static int gui_mode
= 1; /* enabled */
71 static int tty_mode
= 1; /* enabled */
72 static int verbose_level
= 0; /* only FATAL errors, by default */
74 int run2_gui_is_allowed(void) { return gui_mode
; }
75 int run2_tty_is_allowed(void) { return tty_mode
; }
76 int run2_get_verbose_level(void) { return verbose_level
; }
78 void run2_set_gui_mode(int mode
) { gui_mode
= mode
; }
79 void run2_set_tty_mode(int mode
) { tty_mode
= mode
; }
80 void run2_set_verbose_level(int level
){ verbose_level
= level
;}
83 run2_get_program_name (void)
85 if (!program_name
|| !*program_name
)
91 run2_set_program_name (const char *p
)
95 program_name
= run2_strdup (run2_basename (p
));
99 run2_basename (const char *name
)
103 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
104 /* Skip over the disk name in MSDOS pathnames. */
105 if (isalpha ((unsigned char) name
[0]) && name
[1] == ':')
109 for (base
= name
; *name
; name
++)
111 #if defined(__CYGWIN__) || defined(__MINGW32__) || defined(_MSC_VER)
120 run2_ends_with(const char* s1
, const char* s2
)
127 if (len1
- len2
>= 0)
128 if (strcasecmp(&(s1
[len1
-len2
]),s2
) == 0)
134 run2_strip_exe(char* s
)
136 size_t slen
= strlen(s
);
137 if ((slen
> 4) && /* long enough to have .exe extension */
138 /* second part not evaluated (short circuit) if exec_arg too short */
139 (strcasecmp(&(s
[slen
-4]),".exe") == 0))
145 * This function attempts to locate a file which may be in any of
146 * several directories. Unlike the original pfopen, it does not
147 * return a FILE pointer to the opened file, but rather returns
148 * the fully-qualified filename of the first match found. Returns
152 run2_pfopen (const Ustr
*name
, const Ustr
*dirs
)
156 Ustr
*returnVal
= NULL
;
157 Ustr
*tok
= USTR_NULL
;
162 if (dirs
== NULL
|| ustr_len (dirs
) == 0)
165 tname
= USTR_CHECK (ustr_dup (name
));
166 tdirs
= USTR_CHECK (ustr_dup (dirs
));
167 while ((tok
= ustr_split_cstr (tdirs
, &off
, SEP_CHARS
, USTR_NULL
, USTR_FLAG_SPLIT_DEF
)) &&
170 foundit
= run2_fileExists (&returnVal
, tok
, tname
);
171 ustr_free(tok
); /* have to free to avoid mem leaks */
180 run2_fileExists (Ustr
**fullname
, const Ustr
* path
, const Ustr
* name
)
189 worku
= ustr_dup (path
);
190 len
= ustr_len (worku
);
191 workc
= ustr_wstr (worku
);
192 if (len
&& workc
[len
-1] != '/' && workc
[len
-1] != '\\')
194 USTR_ADD_OSTR (&worku
, PATH_SEP_CHAR_STR
);
198 worku
= ustr_dup_empty ();
200 ustr_add (&worku
, name
);
202 workc
= (char *) cygwin_create_path (CCP_WIN_A_TO_POSIX
| CCP_RELATIVE
, ustr_cstr (worku
));
205 errorMsg ("Unable to convert \"%s\" to posix format: %s",
206 ustr_cstr (worku
), strerror (errno
));
210 debugMsg (3, "(%s) looking for...\t%s", __func__
, workc
);
212 file
= fopen (workc
, "rb");
216 if (fullname
!= NULL
)
217 *fullname
= USTR_CHECK (ustr_dup_cstr (workc
));
228 ustr_check (Ustr
* s
, const char * fn
, int ln
)
232 run2_error (EXIT_FAILURE
, ENOMEM
,
233 "Unable to allocate memory for ustr: %s:%d",
237 if ((ustr_ro (s
) == USTR_FALSE
) &&
238 (ustr_enomem (s
) == USTR_TRUE
))
240 run2_error (EXIT_FAILURE
, ENOMEM
,
241 "Unable to allocate memory for ustr: %s:%d",
247 #else /* ORIGINAL_RUN */
249 * This function attempts to locate a file which may be in any of
250 * several directories. Unlike the original pfopen, it does not
251 * return a FILE pointer to the opened file, but rather returns
252 * the fully-qualified filename of the first match found. Returns
256 run2_pfopen (const char *name
, const char *dirs
)
260 char *returnVal
= NULL
;
266 if (dirs
== NULL
|| *dirs
== '\0')
269 tname
= run2_strdup (name
);
270 tdirs
= run2_strdup (dirs
);
271 for (tok
= strtok (tdirs
, SEP_CHARS
);
272 (foundit
== 0) && (tok
!= NULL
);
273 tok
= strtok (NULL
, SEP_CHARS
))
275 foundit
= run2_fileExists (&returnVal
, tok
, tname
);
284 run2_fileExists (char **fullname
, const char* path
, const char* name
)
293 worku
= run2_strdup (path
);
294 len
= strlen (worku
);
295 if (len
&& worku
[len
-1] != '/' && worku
[len
-1] != '\\')
297 workc
= run2_extend_str(worku
, PATH_SEP_CHAR_STR
, 1);
302 worku
= run2_strdup("");
304 workc
= run2_extend_str(worku
, name
, 1);
308 workc
= (char *) cygwin_create_path (CCP_WIN_A_TO_POSIX
| CCP_RELATIVE
, worku
);
311 errorMsg ("Unable to convert \"%s\" to posix format: %s",
312 worku
, strerror (errno
));
317 debugMsg (3, "(%s) looking for...\t%s", __func__
, workc
);
319 file
= fopen (workc
, "rb");
323 if (fullname
!= NULL
)
324 *fullname
= run2_strdup (workc
);
328 /* on non-cygwin, worku and workc point to the same location */
335 #endif /* ORIGINAL_RUN */
338 void run2_message_(int level
, const char* fmt
, ...)
342 run2_vmessage_(level
, fmt
, args
);
346 void run2_vmessage_(int level
, const char* fmt
, va_list args
)
351 const char *pn
= program_name
;
355 j
= vsprintf(buf
,fmt
,args
);
356 buf
[j
] = '\0'; /* paranoia */
357 if (ENABLE_TTY
&& (run2_tty_is_allowed()))
359 if (level
>= RUN2_LOG_DEBUG
)
360 fprintf(stderr
, "%s DEBUG: %s\n", pn
, buf
);
361 else if (level
< RUN2_LOG_FATAL
)
362 fprintf (stdout
, buf
);
366 case RUN2_LOG_FATAL
: fprintf(stderr
, "%s FATAL: %s\n", pn
, buf
); break;
367 case RUN2_LOG_ERROR
: fprintf(stderr
, "%s Error: %s\n", pn
, buf
); break;
368 case RUN2_LOG_WARN
: fprintf(stderr
, "%s Warning: %s\n", pn
, buf
); break;
369 case RUN2_LOG_INFO
: fprintf(stderr
, "%s Info: %s\n", pn
, buf
); break;
370 default: fprintf(stderr
, "%s <unknown criticality>: %s\n", pn
, buf
); break;
374 if (ENABLE_GUI
&& (run2_gui_is_allowed()))
377 if (level
>= RUN2_LOG_DEBUG
)
378 i
= sprintf(titlebuf
, "%s DEBUG", pn
);
379 else if (level
< RUN2_LOG_FATAL
)
380 i
= sprintf(titlebuf
, "%s", pn
);
384 case RUN2_LOG_FATAL
: i
= sprintf(titlebuf
, "%s FATAL", pn
); break;
385 case RUN2_LOG_ERROR
: i
= sprintf(titlebuf
, "%s Error", pn
); break;
386 case RUN2_LOG_WARN
: i
= sprintf(titlebuf
, "%s Warning", pn
); break;
387 case RUN2_LOG_INFO
: i
= sprintf(titlebuf
, "%s Info", pn
); break;
388 default: i
= sprintf(titlebuf
, "%s <unknown criticality>", pn
); break;
390 titlebuf
[i
] = '\0'; /* paranoia */
392 if (level
>= RUN2_LOG_DEBUG
)
393 MessageBox(NULL
, buf
, titlebuf
, MB_ICONINFORMATION
);
394 else if (level
< RUN2_LOG_FATAL
)
395 MessageBox(NULL
, buf
, titlebuf
, MB_ICONINFORMATION
);
399 case RUN2_LOG_FATAL
: MessageBox(NULL
, buf
, titlebuf
, MB_ICONERROR
); break;
400 case RUN2_LOG_ERROR
: MessageBox(NULL
, buf
, titlebuf
, MB_ICONERROR
); break;
401 case RUN2_LOG_WARN
: MessageBox(NULL
, buf
, titlebuf
, MB_ICONWARNING
); break;
402 case RUN2_LOG_INFO
: MessageBox(NULL
, buf
, titlebuf
, MB_ICONINFORMATION
); break;
403 default: MessageBox(NULL
, buf
, titlebuf
, MB_ICONERROR
); break;
410 run2_dupargv (char **vector
)
418 for (argc
= 0; vector
[argc
] != NULL
; argc
++)
420 rval
= (char **) run2_malloc ((argc
+ 1) * sizeof (char *));
422 for (argc
= 0; vector
[argc
] != NULL
; argc
++)
424 int len
= strlen (vector
[argc
]);
425 rval
[argc
] = run2_strdup (vector
[argc
]);
432 run2_countargv (char **vector
)
437 for (scan
= vector
; *scan
!= NULL
; scan
++)
443 run2_freeargv (char **vector
)
448 for (scan
= vector
; *scan
!= NULL
; scan
++)
458 run2_verror (int status
, int errnum
, const char *message
, va_list args
)
462 /* grow the message to hold error info */
463 char const *s
= strerror (errnum
);
465 if (!s
) s
= "Unknown system error";
466 newmsg
= run2_extend_str (message
, ": ", 1);
467 newmsg
= run2_extend_str (newmsg
, s
, 1);
468 verrorMsg (newmsg
, args
);
472 verrorMsg (message
, args
);
479 run2_error (int status
, int errnum
, const char *message
, ...)
482 va_start (args
, message
);
483 run2_verror (status
, errnum
, message
, args
);
488 run2_malloc_exit (void)
490 run2_error (EXIT_FAILURE
, 0, "Unable to allocate memory");
495 run2_malloc (size_t sz
)
497 void *p
= malloc (sz
);
504 run2_realloc (void *p
, size_t sz
)
513 run2_strdup (const char *s
)
515 size_t len
= strlen (s
);
516 char * d
= (char *) run2_malloc (len
+ 1);
519 strncpy (d
, s
, len
+ 1);
527 run2_quote_strdup (const char *s
, int quote
)
529 size_t len
= strlen (s
);
532 if (quote
&& (len
> strcspn (s
, " \t\v\"\\")))
535 char * d
= (char *) run2_malloc (2*len
+ 3);
537 for (i
=0; i
<len
; i
++)
556 return run2_strdup (s
);
560 run2_extend_str (const char *orig_value
, const char *add
, int to_end
)
563 if (orig_value
&& *orig_value
)
565 int orig_value_len
= strlen (orig_value
);
566 int add_len
= strlen (add
);
567 new_value
= (char *) run2_malloc (add_len
+ orig_value_len
+ 1);
570 strcpy (new_value
, orig_value
);
571 strcpy (new_value
+ orig_value_len
, add
);
575 strcpy (new_value
, add
);
576 strcpy (new_value
+ add_len
, orig_value
);
581 new_value
= run2_strdup (add
);
587 run2_strtol(char *arg
, long *value
)
590 int errno_save
= errno
;
594 *value
= strtol(arg
, &endptr
, 0);
595 if (errno
!= 0 || *endptr
!='\0' || endptr
==arg
) {
604 run2_get_homedir (const char *user
)
611 home
= getenv("HOME");
613 return run2_strdup (home
);
615 pwd
= getpwuid (getuid());
617 return run2_strdup (pwd
->pw_dir
);
618 errorMsg ("Could not determine home directory for current user");
623 pwd
= getpwnam (user
);
625 return run2_strdup (pwd
->pw_dir
);
626 errorMsg ("Could not determine home directory for user %s", user
);
631 run2_get_homedir (const char *user
)
637 home
= getenv("HOME");
639 return run2_strdup (home
);
640 errorMsg ("Could not determine home directory for current user");
644 errorMsg ("Could not determine home directory for user %s", user
);