1/** -*-objc-*-
2 *
3 *   $Id: main_0.3.m 979 2006-05-29 01:18:25Z hisa $
4 *
5 *   Copyright (c) 2001 FUJIMOTO Hisakuni
6 *
7 **/
8
9#import <unistd.h>
10#import <string.h>
11#import <stdlib.h>
12#import <Foundation/NSAutoreleasePool.h>
13#import <Foundation/NSString.h>
14#import <Foundation/NSBundle.h>
15#import <Foundation/NSDictionary.h>
16
17#define DEFAULT_RUBY_PROGRAM "/usr/bin/ruby"
18#define DEFAULT_MAIN_SCRIPT  "rb_main.rb"
19
20struct ruby_cocoa_app_config {
21  char* ruby_program;
22  char* main_script;
23  char* resource_dir;
24};
25
26static void
27exit_with_msg (const char* msg)
28{
29  NSLog (@"%s", msg);
30  exit (1);
31}
32
33static void
34load_config(struct ruby_cocoa_app_config* conf)
35{
36  NSAutoreleasePool* pool;
37  NSBundle* bundle;
38  NSDictionary* dic;
39  NSString* str;
40
41  pool = [[NSAutoreleasePool alloc] init];
42  bundle = [NSBundle mainBundle];
43
44  /* ruby application config */
45  dic = [bundle objectForInfoDictionaryKey: @"RubyAppConfig"];
46
47  if (dic == nil) {
48    /* default ruby program */
49    conf->ruby_program = DEFAULT_RUBY_PROGRAM;
50
51    /* default main script path */
52    str = [NSString stringWithCString: DEFAULT_MAIN_SCRIPT];
53    str = [bundle pathForResource: str ofType: nil];
54    if (str == nil) exit_with_msg ("config error: DEFAULT_MAIN_SCRIPT missing");
55    conf->main_script = strdup ([str cString]);
56  }
57
58  else {
59    /* ruby program */
60    str = [dic objectForKey: @"RubyProgram"];
61    if (str == nil) exit_with_msg ("config error: RubyProgram missing.");
62    conf->ruby_program = strdup ([str cString]);
63
64    /* main script path */
65    str = [dic objectForKey: @"MainScript"];
66    if (str == nil) exit_with_msg ("config error: MainScript missing.");
67    str = [bundle pathForResource: str ofType: nil];
68    if (str == nil) exit_with_msg ("config error: path of MainScript missing.");
69    conf->main_script = strdup ([str cString]);
70  }
71
72  /* resource dir */
73  str = [bundle resourcePath];
74  if (str == nil) exit_with_msg ("config error: resourcePath missing.");
75  conf->resource_dir = strdup ([str cString]);
76
77  [pool release];
78}
79
80static char**
81create_ruby_argv(const struct ruby_cocoa_app_config* conf, int argc, char* argv[])
82{
83  int i;
84  int ruby_argc;
85  char** ruby_argv;
86  int my_argc;
87  char* my_argv[] = {
88    "-I",
89    conf->resource_dir,
90    conf->main_script
91  };
92
93  my_argc = sizeof(my_argv) / sizeof(char*);
94
95  ruby_argc = 0;
96  ruby_argv = malloc (sizeof(char*) * (argc + my_argc + 1));
97  for (i = 0; i < argc; i++) {
98    if (strncmp(argv[i], "-psn_", 5) == 0) continue;
99    ruby_argv[ruby_argc++] = argv[i];
100  }
101  for (i = 0; i < my_argc; i++) ruby_argv[ruby_argc++] = my_argv[i];
102  ruby_argv[ruby_argc] = NULL;
103
104  return ruby_argv;
105}
106
107static int
108execvp_p (const char* ruby_program)
109{
110  while (*ruby_program != NULL) {
111    if (*ruby_program == '/') return 0;
112    ruby_program++;
113  }
114  return 1;
115}
116
117int
118main(int argc, char* argv[])
119{
120  char** ruby_argv;
121  struct ruby_cocoa_app_config conf;
122
123  load_config (&conf);
124  ruby_argv = create_ruby_argv(&conf, argc, argv);
125
126  if (execvp_p (conf.ruby_program))
127    return execvp (conf.ruby_program, ruby_argv);
128  else
129    return execv (conf.ruby_program, ruby_argv);
130}
131