1*c2c66affSColin Finck /* @(#)saveargs.c	1.16 10/11/18 Copyright 1995-2010 J. Schilling */
2*c2c66affSColin Finck /*
3*c2c66affSColin Finck  *	save argc, argv for command error printing routines
4*c2c66affSColin Finck  *
5*c2c66affSColin Finck  *	Copyright (c) 1995-2010 J. Schilling
6*c2c66affSColin Finck  */
7*c2c66affSColin Finck /*
8*c2c66affSColin Finck  * The contents of this file are subject to the terms of the
9*c2c66affSColin Finck  * Common Development and Distribution License, Version 1.0 only
10*c2c66affSColin Finck  * (the "License").  You may not use this file except in compliance
11*c2c66affSColin Finck  * with the License.
12*c2c66affSColin Finck  *
13*c2c66affSColin Finck  * See the file CDDL.Schily.txt in this distribution for details.
14*c2c66affSColin Finck  *
15*c2c66affSColin Finck  * When distributing Covered Code, include this CDDL HEADER in each
16*c2c66affSColin Finck  * file and include the License file CDDL.Schily.txt from this distribution.
17*c2c66affSColin Finck  */
18*c2c66affSColin Finck 
19*c2c66affSColin Finck #include <schily/mconfig.h>
20*c2c66affSColin Finck #include <schily/standard.h>
21*c2c66affSColin Finck #include <schily/string.h>
22*c2c66affSColin Finck #include <schily/stdlib.h>
23*c2c66affSColin Finck #include <schily/avoffset.h>
24*c2c66affSColin Finck #include <schily/schily.h>
25*c2c66affSColin Finck #include <schily/dlfcn.h>
26*c2c66affSColin Finck 
27*c2c66affSColin Finck #if	!defined(AV_OFFSET) || !defined(FP_INDIR)
28*c2c66affSColin Finck #	ifdef	HAVE_SCANSTACK
29*c2c66affSColin Finck #	undef	HAVE_SCANSTACK
30*c2c66affSColin Finck #	endif
31*c2c66affSColin Finck #endif
32*c2c66affSColin Finck 
33*c2c66affSColin Finck #ifdef	HAVE_VAR___PROGNAME
34*c2c66affSColin Finck extern	char	*__progname;
35*c2c66affSColin Finck #ifdef	HAVE_VAR___PROGNAME_FULL
36*c2c66affSColin Finck extern	char	*__progname_full;
37*c2c66affSColin Finck #else
38*c2c66affSColin Finck #define	__progname_full	__progname
39*c2c66affSColin Finck #endif
40*c2c66affSColin Finck #endif
41*c2c66affSColin Finck 
42*c2c66affSColin Finck static	int	ac_saved;
43*c2c66affSColin Finck static	char	**av_saved;
44*c2c66affSColin Finck static	char	*av0_saved;
45*c2c66affSColin Finck static	char	*av0_name_saved;
46*c2c66affSColin Finck static	char	*progpath_saved;
47*c2c66affSColin Finck static	char	*progname_saved;
48*c2c66affSColin Finck 
49*c2c66affSColin Finck static	char	av0_sp[32];	/* av0 space, avoid malloc() in most cases */
50*c2c66affSColin Finck static	char	prn_sp[32];	/* name space, avoid malloc() in most cases */
51*c2c66affSColin Finck static	char	dfl_str[] = "?";
52*c2c66affSColin Finck 
53*c2c66affSColin Finck LOCAL	void	save_av0	__PR((char *av0));
54*c2c66affSColin Finck LOCAL	void	init_progname	__PR((void));
55*c2c66affSColin Finck LOCAL	void	init_arginfo	__PR((void));
56*c2c66affSColin Finck 
57*c2c66affSColin Finck EXPORT void
save_args(ac,av)58*c2c66affSColin Finck save_args(ac, av)
59*c2c66affSColin Finck 	int	ac;
60*c2c66affSColin Finck 	char	*av[];
61*c2c66affSColin Finck {
62*c2c66affSColin Finck 	ac_saved = ac;
63*c2c66affSColin Finck 	av_saved = av;
64*c2c66affSColin Finck 	save_av0(av[0]);
65*c2c66affSColin Finck }
66*c2c66affSColin Finck 
67*c2c66affSColin Finck LOCAL void
save_av0(av0)68*c2c66affSColin Finck save_av0(av0)
69*c2c66affSColin Finck 	char	*av0;
70*c2c66affSColin Finck {
71*c2c66affSColin Finck 	int	slen;
72*c2c66affSColin Finck 	char	*p;
73*c2c66affSColin Finck 
74*c2c66affSColin Finck 	if (av0_saved && av0_saved != av0_sp)
75*c2c66affSColin Finck 		free(av0_saved);
76*c2c66affSColin Finck 
77*c2c66affSColin Finck 	slen = strlen(av0) + 1;
78*c2c66affSColin Finck 
79*c2c66affSColin Finck 	if (slen <= (int)sizeof (av0_sp))
80*c2c66affSColin Finck 		av0_saved = av0_sp;
81*c2c66affSColin Finck 	else
82*c2c66affSColin Finck 		av0_saved = malloc(slen);
83*c2c66affSColin Finck 
84*c2c66affSColin Finck 	if (av0_saved) {
85*c2c66affSColin Finck 		strcpy(av0_saved, av0);
86*c2c66affSColin Finck 		av0 = av0_saved;
87*c2c66affSColin Finck 	}
88*c2c66affSColin Finck 
89*c2c66affSColin Finck 	if ((p = strrchr(av0, '/')) == NULL)
90*c2c66affSColin Finck 		av0_name_saved = av0;
91*c2c66affSColin Finck 	else
92*c2c66affSColin Finck 		av0_name_saved = ++p;
93*c2c66affSColin Finck }
94*c2c66affSColin Finck 
95*c2c66affSColin Finck EXPORT int
saved_ac()96*c2c66affSColin Finck saved_ac()
97*c2c66affSColin Finck {
98*c2c66affSColin Finck 	if (av_saved == NULL)
99*c2c66affSColin Finck 		init_arginfo();
100*c2c66affSColin Finck 
101*c2c66affSColin Finck 	return (ac_saved);
102*c2c66affSColin Finck }
103*c2c66affSColin Finck 
104*c2c66affSColin Finck EXPORT char **
saved_av()105*c2c66affSColin Finck saved_av()
106*c2c66affSColin Finck {
107*c2c66affSColin Finck 	if (av_saved == NULL)
108*c2c66affSColin Finck 		init_arginfo();
109*c2c66affSColin Finck 
110*c2c66affSColin Finck 	return (av_saved);
111*c2c66affSColin Finck }
112*c2c66affSColin Finck 
113*c2c66affSColin Finck EXPORT char *
saved_av0()114*c2c66affSColin Finck saved_av0()
115*c2c66affSColin Finck {
116*c2c66affSColin Finck 	if (av0_saved == NULL)
117*c2c66affSColin Finck 		init_arginfo();
118*c2c66affSColin Finck 
119*c2c66affSColin Finck 	return (av0_saved);
120*c2c66affSColin Finck }
121*c2c66affSColin Finck 
122*c2c66affSColin Finck EXPORT void
set_progname(name)123*c2c66affSColin Finck set_progname(name)
124*c2c66affSColin Finck 	const char	*name;
125*c2c66affSColin Finck {
126*c2c66affSColin Finck 	int	slen;
127*c2c66affSColin Finck 	char	*p;
128*c2c66affSColin Finck 
129*c2c66affSColin Finck 	if (progpath_saved && progpath_saved != prn_sp)
130*c2c66affSColin Finck 		free(progpath_saved);
131*c2c66affSColin Finck 
132*c2c66affSColin Finck 	slen = strlen(name) + 1;
133*c2c66affSColin Finck 
134*c2c66affSColin Finck 	if (slen <= sizeof (prn_sp))
135*c2c66affSColin Finck 		progpath_saved = prn_sp;
136*c2c66affSColin Finck 	else
137*c2c66affSColin Finck 		progpath_saved = malloc(slen);
138*c2c66affSColin Finck 
139*c2c66affSColin Finck 	if (progpath_saved) {
140*c2c66affSColin Finck 		strcpy(progpath_saved, name);
141*c2c66affSColin Finck 		name = progpath_saved;
142*c2c66affSColin Finck 	}
143*c2c66affSColin Finck 
144*c2c66affSColin Finck 	if ((p = strrchr(name, '/')) == NULL)
145*c2c66affSColin Finck 		progname_saved = (char *)name;
146*c2c66affSColin Finck 	else
147*c2c66affSColin Finck 		progname_saved = ++p;
148*c2c66affSColin Finck }
149*c2c66affSColin Finck 
150*c2c66affSColin Finck EXPORT char *
get_progname()151*c2c66affSColin Finck get_progname()
152*c2c66affSColin Finck {
153*c2c66affSColin Finck 	if (progname_saved)
154*c2c66affSColin Finck 		return (progname_saved);
155*c2c66affSColin Finck 	if (av0_name_saved == NULL)
156*c2c66affSColin Finck 		init_progname();
157*c2c66affSColin Finck 	if (av0_name_saved)
158*c2c66affSColin Finck 		return (av0_name_saved);
159*c2c66affSColin Finck 	return (dfl_str);
160*c2c66affSColin Finck }
161*c2c66affSColin Finck 
162*c2c66affSColin Finck EXPORT char *
get_progpath()163*c2c66affSColin Finck get_progpath()
164*c2c66affSColin Finck {
165*c2c66affSColin Finck 	if (progpath_saved)
166*c2c66affSColin Finck 		return (progpath_saved);
167*c2c66affSColin Finck 	if (av0_saved == NULL)
168*c2c66affSColin Finck 		init_progname();
169*c2c66affSColin Finck 	if (av0_saved)
170*c2c66affSColin Finck 		return (av0_saved);
171*c2c66affSColin Finck 	return (dfl_str);
172*c2c66affSColin Finck }
173*c2c66affSColin Finck 
174*c2c66affSColin Finck LOCAL void
init_progname()175*c2c66affSColin Finck init_progname()
176*c2c66affSColin Finck {
177*c2c66affSColin Finck #if defined(HAVE_SCANSTACK) || defined(HAVE_GETPROGNAME)
178*c2c66affSColin Finck 	char	*progname;
179*c2c66affSColin Finck #endif
180*c2c66affSColin Finck 
181*c2c66affSColin Finck 	if (av0_name_saved == NULL)
182*c2c66affSColin Finck 		init_arginfo();
183*c2c66affSColin Finck 	if (av0_name_saved)
184*c2c66affSColin Finck 		return;
185*c2c66affSColin Finck #ifdef	HAVE_GETPROGNAME
186*c2c66affSColin Finck 	progname = (char *)getprogname();
187*c2c66affSColin Finck 	if (progname) {
188*c2c66affSColin Finck 		save_av0(progname);
189*c2c66affSColin Finck 		return;
190*c2c66affSColin Finck 	}
191*c2c66affSColin Finck #endif
192*c2c66affSColin Finck #ifdef	HAVE_VAR___PROGNAME
193*c2c66affSColin Finck 	if (__progname_full) {
194*c2c66affSColin Finck 		save_av0(__progname_full);
195*c2c66affSColin Finck 		return;
196*c2c66affSColin Finck 	}
197*c2c66affSColin Finck #endif
198*c2c66affSColin Finck #ifdef	HAVE_SCANSTACK
199*c2c66affSColin Finck 	progname = getav0();		/* scan stack to get argv[0] */
200*c2c66affSColin Finck 	if (progname) {
201*c2c66affSColin Finck 		save_av0(progname);
202*c2c66affSColin Finck 		return;
203*c2c66affSColin Finck 	}
204*c2c66affSColin Finck #endif
205*c2c66affSColin Finck }
206*c2c66affSColin Finck 
207*c2c66affSColin Finck LOCAL void
init_arginfo()208*c2c66affSColin Finck init_arginfo()
209*c2c66affSColin Finck {
210*c2c66affSColin Finck #if defined(HAVE_DLINFO) && defined(HAVE_DLOPEN_IN_LIBC) && defined(RTLD_DI_ARGSINFO)
211*c2c66affSColin Finck 	Dl_argsinfo	args;
212*c2c66affSColin Finck 
213*c2c66affSColin Finck 	if (dlinfo(RTLD_SELF, RTLD_DI_ARGSINFO, &args) < 0 ||
214*c2c66affSColin Finck 	    args.dla_argc <= 0 ||
215*c2c66affSColin Finck 	    args.dla_argv[0] == NULL)
216*c2c66affSColin Finck 		return;
217*c2c66affSColin Finck 
218*c2c66affSColin Finck 	if (av_saved == NULL)
219*c2c66affSColin Finck 		save_args(args.dla_argc, args.dla_argv);
220*c2c66affSColin Finck #endif
221*c2c66affSColin Finck }
222