1 /* LINTLIBRARY */
2 /*-
3  * Copyright 1996-1998 John D. Polstra.
4  * Copyright 2012 Konstantin Belousov <kib@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <stdlib.h>
29 
30 #include <sys/cdefs.h>
31 
32 extern int main(int, char **);
33 
34 extern void (*__preinit_array_start[])(int, char **, char **) __hidden;
35 extern void (*__preinit_array_end[])(int, char **, char **) __hidden;
36 extern void (*__init_array_start[])(int, char **, char **) __hidden;
37 extern void (*__init_array_end[])(int, char **, char **) __hidden;
38 extern void (*__fini_array_start[])(void) __hidden;
39 extern void (*__fini_array_end[])(void) __hidden;
40 extern void _fini(void) __hidden;
41 extern void _init(void) __hidden;
42 
43 char **environ;
44 const char *__progname = "";
45 
46 static void
finalizer(void)47 finalizer(void)
48 {
49 	void (*fn)(void);
50 	size_t array_size, n;
51 
52 	array_size = __fini_array_end - __fini_array_start;
53 	for (n = array_size; n > 0; n--) {
54 		fn = __fini_array_start[n - 1];
55 		if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
56 			(fn)();
57 	}
58 	_fini();
59 }
60 
61 static inline void
handle_static_init(int argc,char ** argv,char ** env)62 handle_static_init(int argc, char **argv, char **env)
63 {
64 	void (*fn)(int, char **, char **);
65 	size_t array_size, n;
66 
67 	atexit(finalizer);
68 
69 	array_size = __preinit_array_end - __preinit_array_start;
70 	for (n = 0; n < array_size; n++) {
71 		fn = __preinit_array_start[n];
72 		if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
73 			fn(argc, argv, env);
74 	}
75 	_init();
76 	array_size = __init_array_end - __init_array_start;
77 	for (n = 0; n < array_size; n++) {
78 		fn = __init_array_start[n];
79 		if ((uintptr_t)fn != 0 && (uintptr_t)fn != 1)
80 			fn(argc, argv, env);
81 	}
82 }
83 
84 static inline void
handle_argv(int argc,char * argv[],char ** env)85 handle_argv(int argc, char *argv[], char **env)
86 {
87 	const char *s;
88 
89 	if (environ == NULL)
90 		environ = env;
91 	if (argc > 0 && argv[0] != NULL) {
92 		__progname = argv[0];
93 		for (s = __progname; *s != '\0'; s++) {
94 			if (*s == '/')
95 				__progname = s + 1;
96 		}
97 	}
98 }
99 
100 void
_start(char ** ap)101 _start(char **ap)
102 {
103 	int status;
104 	int argc = 0;
105 	char **argv = NULL;
106 	char **env = NULL;
107 
108 	argc = *(long *)(void *)ap;
109 	argv = ap + 1;
110 	//env = ap + 2 + argc;
111 	handle_argv(argc, argv, env);
112 
113 	handle_static_init(argc, argv, env);
114 
115 	status = main(argc, argv);
116 
117 	finalizer();
118 
119 	exit(status);
120 }
121 
122