* src/vm/vm.c [WITH_JRE_LAYOUT] (libgen.h, unistd.h): Removed.
[cacao.git] / src / vm / properties.c
1 /* src/vm/properties.c - handling commandline properties
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: properties.c 8401 2007-08-22 18:45:31Z twisti $
26
27 */
28
29
30 #include "config.h"
31
32 #include <errno.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <sys/utsname.h>
38
39 #if defined(WITH_JRE_LAYOUT)
40 # include <libgen.h>
41 #endif
42
43 #include "vm/types.h"
44
45 #include "mm/memory.h"
46
47 #include "native/jni.h"
48
49 #include "vm/global.h"                      /* required by java_lang_String.h */
50 #include "native/include/java_lang_String.h"
51
52 #include "toolbox/list.h"
53 #include "toolbox/util.h"
54
55 #include "vm/properties.h"
56 #include "vm/stringlocal.h"
57 #include "vm/vm.h"
58
59 #include "vm/jit/asmpart.h"
60
61 #include "vmcore/method.h"
62 #include "vmcore/options.h"
63
64
65 /* internal property structure ************************************************/
66
67 typedef struct list_properties_entry_t list_properties_entry_t;
68
69 struct list_properties_entry_t {
70         char       *key;
71         char       *value;
72         listnode_t  linkage;
73 };
74
75
76 /* global variables ***********************************************************/
77
78 static list_t *list_properties = NULL;
79
80
81 /* properties_init *************************************************************
82
83    Initialize the properties list and fill the list with default
84    values.
85
86 *******************************************************************************/
87
88 void properties_init(void)
89 {
90         list_properties = list_create(OFFSET(list_properties_entry_t, linkage));
91 }
92
93
94 /* properties_set **************************************************************
95
96    Fill the properties list with default values.
97
98 *******************************************************************************/
99
100 void properties_set(void)
101 {
102 #if defined(ENABLE_JAVASE)
103         int             len;
104         char           *p;
105
106         char           *java_home;
107         char           *boot_library_path;
108         char           *boot_class_path;
109         char           *class_path;
110
111 # if defined(WITH_CLASSPATH_GNU)
112         char           *cwd;
113         char           *env_user;
114         char           *env_home;
115         char           *env_lang;
116         char           *extdirs;
117         char           *lang;
118         char           *country;
119         struct utsname *utsnamebuf;
120
121         char           *java_library_path;
122 # endif
123 #endif
124
125 #if defined(WITH_JRE_LAYOUT)
126         /* SUN also uses a buffer of 4096-bytes (strace is your friend). */
127
128         p = MNEW(char, 4096);
129
130         if (readlink("/proc/self/exe", p, 4095) == -1)
131                 vm_abort("properties_set: readlink failed: %s\n", strerror(errno));
132
133         /* Get the path of the current executable. */
134
135         p = dirname(p);
136
137 # if defined(WITH_CLASSPATH_GNU)
138
139         /* Set java.home. */
140
141         len = strlen(path) + strlen("/..") + strlen("0");
142
143         java_home = MNEW(char, len);
144
145         strcpy(java_home, p);
146         strcat(java_home, "/..");
147
148         /* Set the path to Java core native libraries. */
149
150         len = strlen(cacao_prefix) + strlen("/lib/classpath") + strlen("0");
151
152         boot_library_path = MNEW(char, len);
153
154         strcpy(boot_library_path, java_home);
155         strcat(boot_library_path, "/lib/classpath");
156
157 # elif defined(WITH_CLASSPATH_SUN)
158
159         /* Find correct java.home.  We check if there is a JRE
160            co-located. */
161
162         /* NOTE: We use the server VM here as it should be available on
163            all architectures. */
164
165         len =
166                 strlen(p) +
167                 strlen("/../jre/lib/"JAVA_ARCH"/server/libjvm.so") +
168                 strlen("0");
169
170         java_home = MNEW(char, len);
171
172         strcpy(java_home, p);
173         strcat(java_home, "/../jre/lib/"JAVA_ARCH"/server/libjvm.so");
174
175         /* Check if that libjvm.so exists. */
176
177         if (access(java_home, F_OK) == 0) {
178                 /* Yes, we add /jre to java.home. */
179
180                 strcpy(java_home, p);
181                 strcat(java_home, "/../jre");
182         }
183         else {
184                 /* No, java.home is parent directory. */
185
186                 strcpy(java_home, p);
187                 strcat(java_home, "/..");
188         }
189
190         /* Set the path to Java core native libraries. */
191
192         len = strlen(java_home) + strlen("/lib/"JAVA_ARCH) + strlen("0");
193
194         boot_library_path = MNEW(char, len);
195
196         strcpy(boot_library_path, java_home);
197         strcat(boot_library_path, "/lib/"JAVA_ARCH);
198
199 # else
200 #  error unknown classpath configuration
201 # endif
202
203         /* Free path. */
204
205         MFREE(p, char, len);
206
207 #else
208         java_home         = CACAO_PREFIX;
209
210 # if defined(WITH_CLASSPATH_GNU)
211         boot_library_path = CLASSPATH_LIBDIR"/classpath";
212 # else
213         boot_library_path = CLASSPATH_LIBDIR;
214 # endif
215 #endif
216
217         properties_add("java.home", java_home);
218
219         /* Set the bootclasspath. */
220
221         p = getenv("BOOTCLASSPATH");
222
223         if (p != NULL) {
224                 boot_class_path = MNEW(char, strlen(p) + strlen("0"));
225                 strcpy(boot_class_path, p);
226         }
227         else {
228 #if defined(WITH_JRE_LAYOUT)
229 # if defined(WITH_CLASSPATH_GNU)
230
231                 len =
232                         strlen(java_home) + strlen("/share/cacao/vm.zip:") +
233                         strlen(java_home) + strlen("/share/classpath/glibj.zip") +
234                         strlen("0");
235
236                 boot_class_path = MNEW(char, len);
237
238                 strcpy(boot_class_path, java_home);
239                 strcat(boot_class_path, "/share/cacao/vm.zip");
240                 strcat(boot_class_path, ":");
241                 strcat(boot_class_path, java_home);
242                 strcat(boot_class_path, "/share/classpath/glibj.zip");
243
244 # elif defined(WITH_CLASSPATH_SUN)
245
246                 /* This is the bootclasspath taken from HotSpot (see
247                    hotspot/src/share/vm/runtime/os.cpp
248                    (os::set_boot_path)). */
249
250                 len =
251                         strlen(java_home) + strlen("/lib/resources.jar:") +
252                         strlen(java_home) + strlen("/lib/rt.jar:") +
253                         strlen(java_home) + strlen("/lib/sunrsasign.jar:") +
254                         strlen(java_home) + strlen("/lib/jsse.jar:") +
255                         strlen(java_home) + strlen("/lib/jce.jar:") +
256                         strlen(java_home) + strlen("/lib/charsets.jar:") +
257                         strlen(java_home) + strlen("/classes") +
258                         strlen("0");
259
260                 boot_class_path = MNEW(char, len);
261
262                 strcpy(boot_class_path, java_home);
263                 strcat(boot_class_path, "/lib/resources.jar:");
264                 strcat(boot_class_path, java_home);
265                 strcat(boot_class_path, "/lib/rt.jar:");
266                 strcat(boot_class_path, java_home);
267                 strcat(boot_class_path, "/lib/sunrsasign.jar:");
268                 strcat(boot_class_path, java_home);
269                 strcat(boot_class_path, "/lib/jsse.jar:");
270                 strcat(boot_class_path, java_home);
271                 strcat(boot_class_path, "/lib/jce.jar:");
272                 strcat(boot_class_path, java_home);
273                 strcat(boot_class_path, "/lib/charsets.jar:");
274                 strcat(boot_class_path, java_home);
275                 strcat(boot_class_path, "/classes");
276
277 # else
278 #  error unknown classpath configuration
279 # endif
280 #else
281 # if defined(WITH_CLASSPATH_GNU)
282
283                 len =
284                         strlen(CACAO_VM_ZIP) +
285                         strlen(":") +
286                         strlen(CLASSPATH_CLASSES) +
287                         strlen("0");
288
289                 boot_class_path = MNEW(char, len);
290
291                 strcpy(boot_class_path, CACAO_VM_ZIP);
292                 strcat(boot_class_path, ":");
293                 strcat(boot_class_path, CLASSPATH_CLASSES);
294
295 # elif defined(WITH_CLASSPATH_SUN)
296
297                 /* This is the bootclasspath taken from HotSpot (see
298                    hotspot/src/share/vm/runtime/os.cpp
299                    (os::set_boot_path)). */
300
301                 len =
302                         strlen(CLASSPATH_PREFIX"/lib/resources.jar:") +
303                         strlen(CLASSPATH_PREFIX"/lib/rt.jar:") +
304                         strlen(CLASSPATH_PREFIX"/lib/sunrsasign.jar:") +
305                         strlen(CLASSPATH_PREFIX"/lib/jsse.jar:") +
306                         strlen(CLASSPATH_PREFIX"/lib/jce.jar:") +
307                         strlen(CLASSPATH_PREFIX"/lib/charsets.jar:") +
308                         strlen(CLASSPATH_PREFIX"/classes") +
309                         strlen("0");
310
311                 boot_class_path = MNEW(char, len);
312
313                 strcpy(boot_class_path, CLASSPATH_PREFIX"/lib/resources.jar:");
314                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/rt.jar:");
315                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/sunrsasign.jar:");
316                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jsse.jar:");
317                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/jce.jar:");
318                 strcat(boot_class_path, CLASSPATH_PREFIX"/lib/charsets.jar:");
319                 strcat(boot_class_path, CLASSPATH_PREFIX"/classes");
320
321 # elif defined(WITH_CLASSPATH_CLDC1_1)
322
323                 len =
324                         strlen(CLASSPATH_CLASSES) +
325                         strlen("0");
326
327                 boot_class_path = MNEW(char, len);
328
329                 strcat(boot_class_path, CLASSPATH_CLASSES);
330
331 # else
332 #  error unknown classpath configuration
333 # endif
334 #endif
335         }
336
337         properties_add("java.boot.class.path", boot_class_path);
338         properties_add("sun.boot.class.path", boot_class_path);
339
340         /* Set the classpath. */
341
342         p = getenv("CLASSPATH");
343
344         if (p != NULL) {
345                 class_path = MNEW(char, strlen(p) + strlen("0"));
346                 strcpy(class_path, p);
347         }
348         else {
349                 class_path = MNEW(char, strlen(".") + strlen("0"));
350                 strcpy(class_path, ".");
351         }
352
353         properties_add("java.class.path", class_path);
354
355 #if defined(ENABLE_JAVASE)
356
357         /* get properties from system */
358
359         p = getenv("JAVA_HOME");
360
361         /* fill in system properties */
362
363         properties_add("java.vm.specification.version", "1.0");
364         properties_add("java.vm.specification.vendor", "Sun Microsystems Inc.");
365         properties_add("java.vm.specification.name", "Java Virtual Machine Specification");
366         properties_add("java.vm.version", VERSION);
367         properties_add("java.vm.vendor", "CACAO Team");
368         properties_add("java.vm.name", "CACAO");
369
370 # if defined(ENABLE_INTRP)
371         if (opt_intrp) {
372                 /* XXX We don't support java.lang.Compiler */
373 /*              properties_add("java.compiler", "cacao.intrp"); */
374                 properties_add("java.vm.info", "interpreted mode");
375         }
376         else
377 # endif
378         {
379                 /* XXX We don't support java.lang.Compiler */
380 /*              properties_add("java.compiler", "cacao.jit"); */
381                 properties_add("java.vm.info", "JIT mode");
382         }
383
384 # if defined(WITH_CLASSPATH_GNU)
385
386         /* Get properties from system. */
387
388         cwd      = _Jv_getcwd();
389
390         env_user = getenv("USER");
391         env_home = getenv("HOME");
392         env_lang = getenv("LANG");
393
394         utsnamebuf = NEW(struct utsname);
395
396         uname(utsnamebuf);
397
398         properties_add("java.runtime.version", VERSION);
399         properties_add("java.runtime.name", "CACAO");
400
401         properties_add("java.specification.version", "1.5");
402         properties_add("java.specification.vendor", "Sun Microsystems Inc.");
403         properties_add("java.specification.name", "Java Platform API Specification");
404
405         properties_add("java.version", JAVA_VERSION);
406         properties_add("java.vendor", "GNU Classpath");
407         properties_add("java.vendor.url", "http://www.gnu.org/software/classpath/");
408
409         properties_add("java.class.version", CLASS_VERSION);
410
411 #  if defined(WITH_STATIC_CLASSPATH)
412         properties_add("gnu.classpath.boot.library.path", ".");
413         properties_add("java.library.path" , ".");
414 #  else
415         properties_add("gnu.classpath.boot.library.path", boot_library_path);
416
417         /* Get and set java.library.path. */
418
419         java_library_path = getenv("LD_LIBRARY_PATH");
420
421         if (java_library_path == NULL)
422                 java_library_path = "";
423
424         properties_add("java.library.path", java_library_path);
425 #  endif
426
427         properties_add("java.io.tmpdir", "/tmp");
428
429 #  if defined(ENABLE_INTRP)
430         if (opt_intrp) {
431                 properties_add("gnu.java.compiler.name", "cacao.intrp");
432         }
433         else
434 #  endif
435         {
436                 properties_add("gnu.java.compiler.name", "cacao.jit");
437         }
438
439         /* set the java.ext.dirs property */
440
441         len = strlen(java_home) + strlen("/jre/lib/ext") + strlen("0");
442
443         extdirs = MNEW(char, len);
444
445         strcpy(extdirs, java_home);
446         strcat(extdirs, "/jre/lib/ext");
447
448         properties_add("java.ext.dirs", extdirs);
449
450         properties_add("java.endorsed.dirs", ""CACAO_PREFIX"/jre/lib/endorsed");
451
452 #  if defined(DISABLE_GC)
453         /* When we disable the GC, we mmap the whole heap to a specific
454            address, so we can compare call traces. For this reason we have
455            to add the same properties on different machines, otherwise
456            more memory may be allocated (e.g. strlen("i386")
457            vs. strlen("alpha"). */
458
459         properties_add("os.arch", "unknown");
460         properties_add("os.name", "unknown");
461         properties_add("os.version", "unknown");
462 #  else
463         properties_add("os.arch", JAVA_ARCH);
464         properties_add("os.name", utsnamebuf->sysname);
465         properties_add("os.version", utsnamebuf->release);
466 #  endif
467
468 #  if defined(WITH_STATIC_CLASSPATH)
469         /* This is just for debugging purposes and can cause troubles in
470        GNU Classpath. */
471
472         properties_add("gnu.cpu.endian", "unknown");
473 #  else
474 #   if WORDS_BIGENDIAN == 1
475         properties_add("gnu.cpu.endian", "big");
476 #   else
477         properties_add("gnu.cpu.endian", "little");
478 #   endif
479 #  endif
480
481         properties_add("file.separator", "/");
482         properties_add("path.separator", ":");
483         properties_add("line.separator", "\n");
484
485         properties_add("user.name", env_user ? env_user : "null");
486         properties_add("user.home", env_home ? env_home : "null");
487         properties_add("user.dir", cwd ? cwd : "null");
488
489         /* get locale */
490
491         if (env_lang != NULL) {
492                 /* get the local stuff from the environment */
493
494                 if (strlen(env_lang) <= 2) {
495                         properties_add("user.language", env_lang);
496                 }
497                 else {
498                         if ((env_lang[2] == '_') && (strlen(env_lang) >= 5)) {
499                                 lang = MNEW(char, 3);
500                                 strncpy(lang, (char *) &env_lang[0], 2);
501                                 lang[2] = '\0';
502
503                                 country = MNEW(char, 3);
504                                 strncpy(country, (char *) &env_lang[3], 2);
505                                 country[2] = '\0';
506
507                                 properties_add("user.language", lang);
508                                 properties_add("user.country", country);
509                         }
510                 }
511         }
512         else {
513                 /* if no default locale was specified, use `en_US' */
514
515                 properties_add("user.language", "en");
516                 properties_add("user.country", "US");
517         }
518
519 # elif defined(WITH_CLASSPATH_SUN)
520
521         /* Actually this property is set by OpenJDK, but we need it in
522            nativevm_preinit(). */
523
524         properties_add("sun.boot.library.path", boot_library_path);
525
526 # else
527
528 #  error unknown classpath configuration
529
530 # endif
531
532 #elif defined(ENABLE_JAVAME_CLDC1_1)
533
534     properties_add("microedition.configuration", "CLDC-1.1");
535     properties_add("microedition.platform", "generic");
536     properties_add("microedition.encoding", "ISO8859_1");
537     properties_add("microedition.profiles", "");
538
539 #else
540
541 # error unknown Java configuration
542
543 #endif
544 }
545
546
547 /* properties_add **************************************************************
548
549    Adds a property entry to the internal property list.  If there's
550    already an entry with the same key, replace it.
551
552 *******************************************************************************/
553
554 void properties_add(char *key, char *value)
555 {
556         list_properties_entry_t *pe;
557
558         /* search for the entry */
559
560         for (pe = list_first_unsynced(list_properties); pe != NULL;
561                  pe = list_next_unsynced(list_properties, pe)) {
562                 if (strcmp(pe->key, key) == 0) {
563                         /* entry was found, replace the value */
564
565                         pe->value = value;
566
567                         return;
568                 }
569         }
570
571         /* entry was not found, insert a new one */
572
573         pe = NEW(list_properties_entry_t);
574
575         pe->key   = key;
576         pe->value = value;
577
578         list_add_last_unsynced(list_properties, pe);
579 }
580
581
582 /* properties_get **************************************************************
583
584    Get a property entry from the internal property list.
585
586 *******************************************************************************/
587
588 char *properties_get(char *key)
589 {
590         list_properties_entry_t *pe;
591
592         for (pe = list_first_unsynced(list_properties); pe != NULL;
593                  pe = list_next_unsynced(list_properties, pe)) {
594                 if (strcmp(pe->key, key) == 0)
595                         return pe->value;
596         }
597
598         return NULL;
599 }
600
601
602 /* properties_system_add *******************************************************
603
604    Adds a given property to the Java system properties.
605
606 *******************************************************************************/
607
608 void properties_system_add(java_handle_t *p, char *key, char *value)
609 {
610         methodinfo    *m;
611         java_handle_t *k;
612         java_handle_t *v;
613
614         /* search for method to add properties */
615
616         m = class_resolveclassmethod(p->vftbl->class,
617                                                                  utf_put,
618                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
619                                                                  NULL,
620                                                                  true);
621
622         if (m == NULL)
623                 return;
624
625         /* add to the Java system properties */
626
627         k = javastring_new_from_utf_string(key);
628         v = javastring_new_from_utf_string(value);
629
630         (void) vm_call_method(m, p, k, v);
631 }
632
633
634 /* properties_system_add_all ***************************************************
635
636    Adds all properties from the properties list to the Java system
637    properties.
638
639    ARGUMENTS:
640        p.... is actually a java_util_Properties structure
641
642 *******************************************************************************/
643
644 #if defined(ENABLE_JAVASE)
645 void properties_system_add_all(java_handle_t *p)
646 {
647         list_properties_entry_t *pe;
648         methodinfo              *m;
649         java_handle_t           *key;
650         java_handle_t           *value;
651
652         /* search for method to add properties */
653
654         m = class_resolveclassmethod(p->vftbl->class,
655                                                                  utf_put,
656                                                                  utf_new_char("(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"),
657                                                                  NULL,
658                                                                  true);
659
660         if (m == NULL)
661                 return;
662
663         /* process all properties stored in the internal table */
664
665         for (pe = list_first(list_properties); pe != NULL;
666                  pe = list_next(list_properties, pe)) {
667                 /* add to the Java system properties */
668
669                 key   = javastring_new_from_utf_string(pe->key);
670                 value = javastring_new_from_utf_string(pe->value);
671
672                 (void) vm_call_method(m, (java_handle_t *) p, key, value);
673         }
674 }
675 #endif /* defined(ENABLE_JAVASE) */
676
677
678 /*
679  * These are local overrides for various environment variables in Emacs.
680  * Please do not remove this and leave it at the end of the file, where
681  * Emacs will automagically detect them.
682  * ---------------------------------------------------------------------
683  * Local variables:
684  * mode: c
685  * indent-tabs-mode: t
686  * c-basic-offset: 4
687  * tab-width: 4
688  * End:
689  */