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