2007-12-04 05:20:05 +01:00
|
|
|
/* main.c -- X application launcher
|
2007-02-27 02:06:53 +01:00
|
|
|
|
2007-12-04 05:20:05 +01:00
|
|
|
Copyright (c) 2007 Jeremy Huddleston
|
|
|
|
Copyright (c) 2007 Apple Inc
|
2007-02-27 02:06:53 +01:00
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person
|
|
|
|
obtaining a copy of this software and associated documentation files
|
|
|
|
(the "Software"), to deal in the Software without restriction,
|
|
|
|
including without limitation the rights to use, copy, modify, merge,
|
|
|
|
publish, distribute, sublicense, and/or sell copies of the Software,
|
|
|
|
and to permit persons to whom the Software is furnished to do so,
|
|
|
|
subject to the following conditions:
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be
|
|
|
|
included in all copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
|
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
|
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
|
|
NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
|
|
|
|
HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
|
|
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
DEALINGS IN THE SOFTWARE.
|
|
|
|
|
|
|
|
Except as contained in this notice, the name(s) of the above
|
|
|
|
copyright holders shall not be used in advertising or otherwise to
|
|
|
|
promote the sale, use or other dealings in this Software without
|
2007-12-04 05:20:05 +01:00
|
|
|
prior written authorization. */
|
2007-02-27 02:06:53 +01:00
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
2007-12-04 05:20:05 +01:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2007-12-21 02:33:38 +01:00
|
|
|
#include <stdlib.h>
|
2007-02-27 02:06:53 +01:00
|
|
|
|
2007-12-21 02:33:38 +01:00
|
|
|
#include <CoreFoundation/CoreFoundation.h>
|
|
|
|
|
2007-12-21 03:08:40 +01:00
|
|
|
#define DEFAULT_CLIENT "/usr/X11/bin/xterm"
|
|
|
|
#define DEFAULT_STARTX "/usr/X11/bin/startx"
|
2008-01-12 20:35:48 +01:00
|
|
|
#define DEFAULT_SHELL "/bin/sh"
|
2007-12-21 02:33:38 +01:00
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
static int execute(const char *command);
|
|
|
|
static char *command_from_prefs(const char *key, const char *default_value);
|
2007-02-27 02:06:53 +01:00
|
|
|
|
2007-12-04 05:20:05 +01:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
Display *display;
|
2008-02-19 09:00:11 +01:00
|
|
|
const char *s;
|
2007-12-04 05:20:05 +01:00
|
|
|
|
2007-12-21 02:33:38 +01:00
|
|
|
size_t i;
|
|
|
|
fprintf(stderr, "X11.app: main(): argc=%d\n", argc);
|
|
|
|
for(i=0; i < argc; i++) {
|
|
|
|
fprintf(stderr, "\targv[%u] = %s\n", (unsigned)i, argv[i]);
|
|
|
|
}
|
2007-12-21 10:57:43 +01:00
|
|
|
|
2007-12-04 05:20:05 +01:00
|
|
|
/* If we have a process serial number and it's our only arg, act as if
|
|
|
|
* the user double clicked the app bundle: launch app_to_run if possible
|
|
|
|
*/
|
|
|
|
if(argc == 1 || (argc == 2 && !strncmp(argv[1], "-psn_", 5))) {
|
|
|
|
/* Now, try to open a display, if so, run the launcher */
|
|
|
|
display = XOpenDisplay(NULL);
|
|
|
|
if(display) {
|
2007-12-21 03:08:40 +01:00
|
|
|
fprintf(stderr, "X11.app: Closing the display and sleeping for 2s to allow the X server to start up.\n");
|
2007-12-04 05:20:05 +01:00
|
|
|
/* Could open the display, start the launcher */
|
|
|
|
XCloseDisplay(display);
|
2007-12-21 10:57:43 +01:00
|
|
|
|
2007-12-04 05:20:05 +01:00
|
|
|
/* Give 2 seconds for the server to start...
|
|
|
|
* TODO: *Really* fix this race condition
|
|
|
|
*/
|
|
|
|
usleep(2000);
|
2007-12-21 10:57:43 +01:00
|
|
|
return execute(command_from_prefs("app_to_run", DEFAULT_CLIENT));
|
2007-12-04 05:20:05 +01:00
|
|
|
}
|
|
|
|
}
|
2007-12-21 10:57:43 +01:00
|
|
|
|
2007-12-08 09:13:47 +01:00
|
|
|
/* Start the server */
|
2008-02-19 09:00:11 +01:00
|
|
|
if(s = getenv("DISPLAY")) {
|
|
|
|
fprintf(stderr, "X11.app: Could not connect to server (DISPLAY=\"%s\", unsetting). Starting X server.\n", s);
|
|
|
|
unsetenv("DISPLAY");
|
|
|
|
} else {
|
|
|
|
fprintf(stderr, "X11.app: Could not connect to server (DISPLAY is not set). Starting X server.\n");
|
|
|
|
}
|
2007-12-21 10:57:43 +01:00
|
|
|
return execute(command_from_prefs("startx_script", DEFAULT_STARTX));
|
2007-02-27 02:06:53 +01:00
|
|
|
}
|
2007-12-08 09:13:47 +01:00
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
static int execute(const char *command) {
|
2007-12-21 02:33:38 +01:00
|
|
|
const char *newargv[7];
|
|
|
|
const char **s;
|
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
newargv[0] = "/usr/bin/login";
|
|
|
|
newargv[1] = "-fp";
|
|
|
|
newargv[2] = getlogin();
|
2008-01-12 20:35:48 +01:00
|
|
|
newargv[3] = command_from_prefs("login_shell", DEFAULT_SHELL);
|
2007-12-21 10:57:43 +01:00
|
|
|
newargv[4] = "-c";
|
|
|
|
newargv[5] = command;
|
|
|
|
newargv[6] = NULL;
|
|
|
|
|
2007-12-21 03:08:40 +01:00
|
|
|
fprintf(stderr, "X11.app: Launching %s:\n", command);
|
2007-12-21 02:33:38 +01:00
|
|
|
for(s=newargv; *s; s++) {
|
|
|
|
fprintf(stderr, "\targv[%d] = %s\n", s - newargv, *s);
|
|
|
|
}
|
|
|
|
|
2008-02-19 09:00:11 +01:00
|
|
|
execvp (newargv[0], (char * const *) newargv);
|
2007-12-21 02:33:38 +01:00
|
|
|
perror ("X11.app: Couldn't exec.");
|
|
|
|
return(1);
|
|
|
|
}
|
2007-12-21 03:08:40 +01:00
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
static char *command_from_prefs(const char *key, const char *default_value) {
|
|
|
|
char *command = NULL;
|
2007-12-21 03:08:40 +01:00
|
|
|
|
2007-12-21 11:06:47 +01:00
|
|
|
CFStringRef cfKey = CFStringCreateWithCString(NULL, key, kCFStringEncodingASCII);
|
2007-12-21 10:57:43 +01:00
|
|
|
CFPropertyListRef PlistRef = CFPreferencesCopyAppValue(cfKey, kCFPreferencesCurrentApplication);
|
|
|
|
|
|
|
|
if ((PlistRef == NULL) || (CFGetTypeID(PlistRef) != CFStringGetTypeID())) {
|
2007-12-21 11:09:01 +01:00
|
|
|
CFStringRef cfDefaultValue = CFStringCreateWithCString(NULL, default_value, kCFStringEncodingASCII);
|
2007-12-21 03:08:40 +01:00
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
CFPreferencesSetAppValue(cfKey, cfDefaultValue, kCFPreferencesCurrentApplication);
|
|
|
|
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
|
|
|
|
|
|
|
|
int len = strlen(default_value) + 1;
|
|
|
|
command = (char *)malloc(len * sizeof(char));
|
|
|
|
if(!command)
|
|
|
|
return NULL;
|
|
|
|
strcpy(command, default_value);
|
|
|
|
} else {
|
|
|
|
int len = CFStringGetLength((CFStringRef)PlistRef) + 1;
|
|
|
|
command = (char *)malloc(len * sizeof(char));
|
|
|
|
if(!command)
|
|
|
|
return NULL;
|
|
|
|
CFStringGetCString((CFStringRef)PlistRef, command, len, kCFStringEncodingASCII);
|
2007-12-21 03:08:40 +01:00
|
|
|
}
|
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
if (PlistRef)
|
2007-12-21 03:08:40 +01:00
|
|
|
CFRelease(PlistRef);
|
|
|
|
|
2007-12-21 10:57:43 +01:00
|
|
|
return command;
|
2007-12-21 03:08:40 +01:00
|
|
|
}
|