1 /* 2 3 Copyright 1989, 1998 The Open Group 4 5 Permission to use, copy, modify, distribute, and sell this software and its 6 documentation for any purpose is hereby granted without fee, provided that 7 the above copyright notice appear in all copies and that both that 8 copyright notice and this permission notice appear in supporting 9 documentation. 10 11 The above copyright notice and this permission notice shall be included 12 in all copies or substantial portions of the Software. 13 14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 OTHER DEALINGS IN THE SOFTWARE. 21 22 Except as contained in this notice, the name of The Open Group shall 23 not be used in advertising or otherwise to promote the sale, use or 24 other dealings in this Software without prior written authorization 25 from The Open Group. 26 27 */ 28 29 /* 30 * xdm - display manager daemon 31 * Author: Keith Packard, MIT X Consortium 32 * 33 * util.c 34 * 35 * various utility routines 36 */ 37 38 #include "dm.h" 39 #include "dm_error.h" 40 41 #include <X11/Xmu/SysUtil.h> /* for XmuGetHostname */ 42 43 #ifdef X_POSIX_C_SOURCE 44 # define _POSIX_C_SOURCE X_POSIX_C_SOURCE 45 # include <signal.h> 46 # undef _POSIX_C_SOURCE 47 #else 48 # if defined(X_NOT_POSIX) || defined(_POSIX_SOURCE) 49 # include <signal.h> 50 # else 51 # define _POSIX_SOURCE 52 # include <signal.h> 53 # undef _POSIX_SOURCE 54 # endif 55 #endif 56 57 #ifndef HAVE_ASPRINTF 58 # include <stdarg.h> 59 /* Allocating sprintf found in many newer libc's 60 * Since xdm is single threaded, assumes arguments don't change 61 * between initial length calculation and copy to result buffer. 62 */ 63 int 64 Asprintf(char ** ret, const char *restrict format, ...) 65 { 66 va_list ap; 67 int len; 68 char buf[256]; 69 70 va_start(ap, format); 71 len = vsnprintf(buf, sizeof(buf), format, ap); 72 if (len >= 0) { 73 *ret = malloc(len + 1); 74 if (*ret) { 75 if (len < sizeof(buf)) { 76 memcpy(*ret, buf, len + 1); 77 } else { 78 vsnprintf(*ret, len + 1, format, ap); 79 } 80 } else { 81 len = -1; 82 } 83 } else { 84 *ret = NULL; 85 } 86 va_end(ap); 87 88 return len; 89 } 90 #endif /* !HAVE_ASPRINTF */ 91 92 void 93 printEnv (char **e) 94 { 95 while (*e) 96 Debug ("%s\n", *e++); 97 } 98 99 static char * 100 makeEnv (const char *name, const char *value) 101 { 102 char *result; 103 104 asprintf(&result, "%s=%s", name, value); 105 106 if (!result) { 107 LogOutOfMem ("makeEnv"); 108 return NULL; 109 } 110 return result; 111 } 112 113 char * 114 getEnv (char **e, const char *name) 115 { 116 int l = strlen (name); 117 118 if (!e) return NULL; 119 120 while (*e) { 121 if ((int)strlen (*e) > l && !strncmp (*e, name, l) && 122 (*e)[l] == '=') 123 return (*e) + l + 1; 124 ++e; 125 } 126 return NULL; 127 } 128 129 char ** 130 setEnv (char **e, const char *name, const char *value) 131 { 132 char **new, **old; 133 char *newe; 134 int envsize; 135 int l; 136 137 l = strlen (name); 138 newe = makeEnv (name, value); 139 if (!newe) { 140 LogOutOfMem ("setEnv"); 141 return e; 142 } 143 if (e) { 144 for (old = e; *old; old++) 145 if ((int)strlen (*old) > l && !strncmp (*old, name, l) && (*old)[l] == '=') 146 break; 147 if (*old) { 148 free (*old); 149 *old = newe; 150 return e; 151 } 152 envsize = old - e; 153 new = realloc ((char *) e, 154 (unsigned) ((envsize + 2) * sizeof (char *))); 155 } else { 156 envsize = 0; 157 new = malloc (2 * sizeof (char *)); 158 } 159 if (!new) { 160 LogOutOfMem ("setEnv"); 161 free (newe); 162 return e; 163 } 164 new[envsize] = newe; 165 new[envsize+1] = NULL; 166 return new; 167 } 168 169 char ** 170 putEnv(const char *string, char **env) 171 { 172 char *v, *b, *n; 173 int nl; 174 175 if ((b = strchr(string, '=')) == NULL) 176 return NULL; 177 v = b + 1; 178 179 nl = b - string; 180 if ((n = malloc(nl + 1)) == NULL) 181 { 182 LogOutOfMem ("putAllEnv"); 183 return NULL; 184 } 185 186 strncpy(n, string,nl + 1); 187 n[nl] = 0; 188 189 env = setEnv(env,n,v); 190 free(n); 191 return env; 192 } 193 194 void 195 freeEnv (char **env) 196 { 197 char **e; 198 199 if (env) 200 { 201 for (e = env; *e; e++) 202 free (*e); 203 free (env); 204 } 205 } 206 207 #define isblank(c) ((c) == ' ' || c == '\t') 208 209 char ** 210 parseArgs (char **argv, const char *string) 211 { 212 const char *word; 213 char *save; 214 char **newargv; 215 int i; 216 217 i = 0; 218 while (argv && argv[i]) 219 ++i; 220 if (!argv) { 221 argv = malloc (sizeof (char *)); 222 if (!argv) { 223 LogOutOfMem ("parseArgs"); 224 return NULL; 225 } 226 } 227 word = string; 228 for (;;) { 229 if (!*string || isblank (*string)) { 230 if (word != string) { 231 newargv = realloc ((char *) argv, 232 (unsigned) ((i + 2) * sizeof (char *))); 233 save = malloc ((unsigned) (string - word + 1)); 234 if (!newargv || !save) { 235 LogOutOfMem ("parseArgs"); 236 /* free whichever survived realloc() */ 237 free (newargv ? newargv : argv); 238 free (save); 239 return NULL; 240 } else { 241 argv = newargv; 242 } 243 argv[i] = strncpy (save, word, string-word); 244 argv[i][string-word] = '\0'; 245 i++; 246 } 247 if (!*string) 248 break; 249 word = string + 1; 250 } 251 ++string; 252 } 253 argv[i] = NULL; 254 return argv; 255 } 256 257 void 258 freeArgs (char **argv) 259 { 260 char **a; 261 262 if (!argv) 263 return; 264 265 for (a = argv; *a; a++) 266 free (*a); 267 free (argv); 268 } 269 270 void 271 CleanUpChild (void) 272 { 273 setsid(); 274 #ifdef SIGCHLD 275 (void) Signal (SIGCHLD, SIG_DFL); 276 #endif 277 (void) Signal (SIGTERM, SIG_DFL); 278 (void) Signal (SIGPIPE, SIG_DFL); 279 (void) Signal (SIGALRM, SIG_DFL); 280 (void) Signal (SIGHUP, SIG_DFL); 281 CloseOnFork (); 282 } 283 284 static char localHostbuf[256]; 285 static int gotLocalHostname; 286 287 char * 288 localHostname (void) 289 { 290 if (!gotLocalHostname) 291 { 292 XmuGetHostname (localHostbuf, sizeof (localHostbuf) - 1); 293 gotLocalHostname = 1; 294 } 295 return localHostbuf; 296 } 297 298 void (*Signal (int sig, SIGFUNC handler))(int) 299 { 300 #ifdef HAVE_SIGACTION 301 struct sigaction sigact, osigact; 302 sigact.sa_handler = handler; 303 sigemptyset(&sigact.sa_mask); 304 sigact.sa_flags = 0; 305 sigaction(sig, &sigact, &osigact); 306 return osigact.sa_handler; 307 #else 308 return signal(sig, handler); 309 #endif 310 } 311