Home | History | Annotate | Line # | Download | only in xdm
      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