kern_environment.c (156748) | kern_environment.c (160217) |
---|---|
1/*- 2 * Copyright (c) 1998 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 21 unchanged lines hidden (view full) --- 30 * dynamic array of strings later when the VM subsystem is up. 31 * 32 * We make these available through the kenv(2) syscall for userland 33 * and through getenv()/freeenv() setenv() unsetenv() testenv() for 34 * the kernel. 35 */ 36 37#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1998 Michael Smith 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 21 unchanged lines hidden (view full) --- 30 * dynamic array of strings later when the VM subsystem is up. 31 * 32 * We make these available through the kenv(2) syscall for userland 33 * and through getenv()/freeenv() setenv() unsetenv() testenv() for 34 * the kernel. 35 */ 36 37#include <sys/cdefs.h> |
38__FBSDID("$FreeBSD: head/sys/kern/kern_environment.c 156748 2006-03-15 19:23:08Z netchild $"); | 38__FBSDID("$FreeBSD: head/sys/kern/kern_environment.c 160217 2006-07-09 21:42:58Z scottl $"); |
39 40#include "opt_mac.h" 41 42#include <sys/types.h> 43#include <sys/param.h> 44#include <sys/proc.h> 45#include <sys/queue.h> 46#include <sys/lock.h> 47#include <sys/mac.h> 48#include <sys/malloc.h> 49#include <sys/mutex.h> 50#include <sys/kernel.h> | 39 40#include "opt_mac.h" 41 42#include <sys/types.h> 43#include <sys/param.h> 44#include <sys/proc.h> 45#include <sys/queue.h> 46#include <sys/lock.h> 47#include <sys/mac.h> 48#include <sys/malloc.h> 49#include <sys/mutex.h> 50#include <sys/kernel.h> |
51#include <sys/sx.h> | |
52#include <sys/systm.h> 53#include <sys/sysent.h> 54#include <sys/sysproto.h> 55#include <sys/libkern.h> 56#include <sys/kenv.h> 57 58static MALLOC_DEFINE(M_KENV, "kenv", "kernel environment"); 59 60#define KENV_SIZE 512 /* Maximum number of environment strings */ 61 62/* pointer to the static environment */ 63char *kern_envp; 64static char *kernenv_next(char *); 65 66/* dynamic environment variables */ 67char **kenvp; | 51#include <sys/systm.h> 52#include <sys/sysent.h> 53#include <sys/sysproto.h> 54#include <sys/libkern.h> 55#include <sys/kenv.h> 56 57static MALLOC_DEFINE(M_KENV, "kenv", "kernel environment"); 58 59#define KENV_SIZE 512 /* Maximum number of environment strings */ 60 61/* pointer to the static environment */ 62char *kern_envp; 63static char *kernenv_next(char *); 64 65/* dynamic environment variables */ 66char **kenvp; |
68struct sx kenv_lock; | 67struct mtx kenv_lock; |
69 70/* 71 * No need to protect this with a mutex 72 * since SYSINITS are single threaded. 73 */ 74int dynamic_kenv = 0; 75 76#define KENV_CHECK if (!dynamic_kenv) \ --- 4 unchanged lines hidden (view full) --- 81 struct thread *td; 82 struct kenv_args /* { 83 int what; 84 const char *name; 85 char *value; 86 int len; 87 } */ *uap; 88{ | 68 69/* 70 * No need to protect this with a mutex 71 * since SYSINITS are single threaded. 72 */ 73int dynamic_kenv = 0; 74 75#define KENV_CHECK if (!dynamic_kenv) \ --- 4 unchanged lines hidden (view full) --- 80 struct thread *td; 81 struct kenv_args /* { 82 int what; 83 const char *name; 84 char *value; 85 int len; 86 } */ *uap; 87{ |
89 char *name, *value; | 88 char *name, *value, *buffer = NULL; |
90 size_t len, done, needed; 91 int error, i; 92 93 KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = 0")); 94 95 error = 0; 96 if (uap->what == KENV_DUMP) { 97#ifdef MAC 98 error = mac_check_kenv_dump(td->td_ucred); 99 if (error) 100 return (error); 101#endif 102 done = needed = 0; | 89 size_t len, done, needed; 90 int error, i; 91 92 KASSERT(dynamic_kenv, ("kenv: dynamic_kenv = 0")); 93 94 error = 0; 95 if (uap->what == KENV_DUMP) { 96#ifdef MAC 97 error = mac_check_kenv_dump(td->td_ucred); 98 if (error) 99 return (error); 100#endif 101 done = needed = 0; |
103 sx_slock(&kenv_lock); | 102 if (uap->len > 0 && uap->value != NULL) 103 buffer = malloc(uap->len, M_TEMP, M_WAITOK|M_ZERO); 104 mtx_lock(&kenv_lock); |
104 for (i = 0; kenvp[i] != NULL; i++) { 105 len = strlen(kenvp[i]) + 1; 106 needed += len; 107 len = min(len, uap->len - done); 108 /* 109 * If called with a NULL or insufficiently large 110 * buffer, just keep computing the required size. 111 */ | 105 for (i = 0; kenvp[i] != NULL; i++) { 106 len = strlen(kenvp[i]) + 1; 107 needed += len; 108 len = min(len, uap->len - done); 109 /* 110 * If called with a NULL or insufficiently large 111 * buffer, just keep computing the required size. 112 */ |
112 if (uap->value != NULL && len > 0) { 113 error = copyout(kenvp[i], uap->value + done, 114 len); 115 if (error) 116 break; | 113 if (uap->value != NULL && buffer != NULL && len > 0) { 114 bcopy(kenvp[i], buffer + done, len); |
117 done += len; 118 } 119 } | 115 done += len; 116 } 117 } |
120 sx_sunlock(&kenv_lock); | 118 mtx_unlock(&kenv_lock); 119 if (buffer != NULL) { 120 error = copyout(buffer, uap->value, done); 121 free(buffer, M_TEMP); 122 } |
121 td->td_retval[0] = ((done == needed) ? 0 : needed); 122 return (error); 123 } 124 125 if ((uap->what == KENV_SET) || 126 (uap->what == KENV_UNSET)) { 127 error = suser(td); 128 if (error) --- 86 unchanged lines hidden (view full) --- 215 strcpy(kenvp[i++], cp); 216 } else 217 printf( 218 "WARNING: too many kenv strings, ignoring %s\n", 219 cp); 220 } 221 kenvp[i] = NULL; 222 | 123 td->td_retval[0] = ((done == needed) ? 0 : needed); 124 return (error); 125 } 126 127 if ((uap->what == KENV_SET) || 128 (uap->what == KENV_UNSET)) { 129 error = suser(td); 130 if (error) --- 86 unchanged lines hidden (view full) --- 217 strcpy(kenvp[i++], cp); 218 } else 219 printf( 220 "WARNING: too many kenv strings, ignoring %s\n", 221 cp); 222 } 223 kenvp[i] = NULL; 224 |
223 sx_init(&kenv_lock, "kernel environment"); | 225 mtx_init(&kenv_lock, "kernel environment", NULL, MTX_DEF); |
224 dynamic_kenv = 1; 225} 226SYSINIT(kenv, SI_SUB_KMEM, SI_ORDER_ANY, init_dynamic_kenv, NULL); 227 228void 229freeenv(char *env) 230{ 231 --- 5 unchanged lines hidden (view full) --- 237 * Internal functions for string lookup. 238 */ 239static char * 240_getenv_dynamic(const char *name, int *idx) 241{ 242 char *cp; 243 int len, i; 244 | 226 dynamic_kenv = 1; 227} 228SYSINIT(kenv, SI_SUB_KMEM, SI_ORDER_ANY, init_dynamic_kenv, NULL); 229 230void 231freeenv(char *env) 232{ 233 --- 5 unchanged lines hidden (view full) --- 239 * Internal functions for string lookup. 240 */ 241static char * 242_getenv_dynamic(const char *name, int *idx) 243{ 244 char *cp; 245 int len, i; 246 |
245 sx_assert(&kenv_lock, SX_LOCKED); | 247 mtx_assert(&kenv_lock, MA_OWNED); |
246 len = strlen(name); 247 for (cp = kenvp[0], i = 0; cp != NULL; cp = kenvp[++i]) { 248 if ((strncmp(cp, name, len) == 0) && 249 (cp[len] == '=')) { 250 if (idx != NULL) 251 *idx = i; 252 return (cp + len + 1); 253 } --- 29 unchanged lines hidden (view full) --- 283char * 284getenv(const char *name) 285{ 286 char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1]; 287 char *ret, *cp; 288 int len; 289 290 if (dynamic_kenv) { | 248 len = strlen(name); 249 for (cp = kenvp[0], i = 0; cp != NULL; cp = kenvp[++i]) { 250 if ((strncmp(cp, name, len) == 0) && 251 (cp[len] == '=')) { 252 if (idx != NULL) 253 *idx = i; 254 return (cp + len + 1); 255 } --- 29 unchanged lines hidden (view full) --- 285char * 286getenv(const char *name) 287{ 288 char buf[KENV_MNAMELEN + 1 + KENV_MVALLEN + 1]; 289 char *ret, *cp; 290 int len; 291 292 if (dynamic_kenv) { |
291 sx_slock(&kenv_lock); | 293 mtx_lock(&kenv_lock); |
292 cp = _getenv_dynamic(name, NULL); 293 if (cp != NULL) { 294 strcpy(buf, cp); | 294 cp = _getenv_dynamic(name, NULL); 295 if (cp != NULL) { 296 strcpy(buf, cp); |
295 sx_sunlock(&kenv_lock); | 297 mtx_unlock(&kenv_lock); |
296 len = strlen(buf) + 1; 297 ret = malloc(len, M_KENV, M_WAITOK); 298 strcpy(ret, buf); 299 } else { | 298 len = strlen(buf) + 1; 299 ret = malloc(len, M_KENV, M_WAITOK); 300 strcpy(ret, buf); 301 } else { |
300 sx_sunlock(&kenv_lock); | 302 mtx_unlock(&kenv_lock); |
301 ret = NULL; 302 } 303 } else 304 ret = _getenv_static(name); 305 return (ret); 306} 307 308/* 309 * Test if an environment variable is defined. 310 */ 311int 312testenv(const char *name) 313{ 314 char *cp; 315 316 if (dynamic_kenv) { | 303 ret = NULL; 304 } 305 } else 306 ret = _getenv_static(name); 307 return (ret); 308} 309 310/* 311 * Test if an environment variable is defined. 312 */ 313int 314testenv(const char *name) 315{ 316 char *cp; 317 318 if (dynamic_kenv) { |
317 sx_slock(&kenv_lock); | 319 mtx_lock(&kenv_lock); |
318 cp = _getenv_dynamic(name, NULL); | 320 cp = _getenv_dynamic(name, NULL); |
319 sx_sunlock(&kenv_lock); | 321 mtx_unlock(&kenv_lock); |
320 } else 321 cp = _getenv_static(name); 322 if (cp != NULL) 323 return (1); 324 return (0); 325} 326 327/* --- 11 unchanged lines hidden (view full) --- 339 if (namelen > KENV_MNAMELEN) 340 return (-1); 341 vallen = strlen(value) + 1; 342 if (vallen > KENV_MVALLEN) 343 return (-1); 344 buf = malloc(namelen + vallen, M_KENV, M_WAITOK); 345 sprintf(buf, "%s=%s", name, value); 346 | 322 } else 323 cp = _getenv_static(name); 324 if (cp != NULL) 325 return (1); 326 return (0); 327} 328 329/* --- 11 unchanged lines hidden (view full) --- 341 if (namelen > KENV_MNAMELEN) 342 return (-1); 343 vallen = strlen(value) + 1; 344 if (vallen > KENV_MVALLEN) 345 return (-1); 346 buf = malloc(namelen + vallen, M_KENV, M_WAITOK); 347 sprintf(buf, "%s=%s", name, value); 348 |
347 sx_xlock(&kenv_lock); | 349 mtx_lock(&kenv_lock); |
348 cp = _getenv_dynamic(name, &i); 349 if (cp != NULL) { 350 oldenv = kenvp[i]; 351 kenvp[i] = buf; | 350 cp = _getenv_dynamic(name, &i); 351 if (cp != NULL) { 352 oldenv = kenvp[i]; 353 kenvp[i] = buf; |
352 sx_xunlock(&kenv_lock); | 354 mtx_unlock(&kenv_lock); |
353 free(oldenv, M_KENV); 354 } else { 355 /* We add the option if it wasn't found */ 356 for (i = 0; (cp = kenvp[i]) != NULL; i++) 357 ; 358 359 /* Bounds checking */ 360 if (i < 0 || i >= KENV_SIZE) { 361 free(buf, M_KENV); | 355 free(oldenv, M_KENV); 356 } else { 357 /* We add the option if it wasn't found */ 358 for (i = 0; (cp = kenvp[i]) != NULL; i++) 359 ; 360 361 /* Bounds checking */ 362 if (i < 0 || i >= KENV_SIZE) { 363 free(buf, M_KENV); |
362 sx_xunlock(&kenv_lock); | 364 mtx_unlock(&kenv_lock); |
363 return (-1); 364 } 365 366 kenvp[i] = buf; 367 kenvp[i + 1] = NULL; | 365 return (-1); 366 } 367 368 kenvp[i] = buf; 369 kenvp[i + 1] = NULL; |
368 sx_xunlock(&kenv_lock); | 370 mtx_unlock(&kenv_lock); |
369 } 370 return (0); 371} 372 373/* 374 * Unset an environment variable string. 375 */ 376int 377unsetenv(const char *name) 378{ 379 char *cp, *oldenv; 380 int i, j; 381 382 KENV_CHECK; 383 | 371 } 372 return (0); 373} 374 375/* 376 * Unset an environment variable string. 377 */ 378int 379unsetenv(const char *name) 380{ 381 char *cp, *oldenv; 382 int i, j; 383 384 KENV_CHECK; 385 |
384 sx_xlock(&kenv_lock); | 386 mtx_lock(&kenv_lock); |
385 cp = _getenv_dynamic(name, &i); 386 if (cp != NULL) { 387 oldenv = kenvp[i]; 388 for (j = i + 1; kenvp[j] != NULL; j++) 389 kenvp[i++] = kenvp[j]; 390 kenvp[i] = NULL; | 387 cp = _getenv_dynamic(name, &i); 388 if (cp != NULL) { 389 oldenv = kenvp[i]; 390 for (j = i + 1; kenvp[j] != NULL; j++) 391 kenvp[i++] = kenvp[j]; 392 kenvp[i] = NULL; |
391 sx_xunlock(&kenv_lock); | 393 mtx_unlock(&kenv_lock); |
392 free(oldenv, M_KENV); 393 return (0); 394 } | 394 free(oldenv, M_KENV); 395 return (0); 396 } |
395 sx_xunlock(&kenv_lock); | 397 mtx_unlock(&kenv_lock); |
396 return (-1); 397} 398 399/* 400 * Return a string value from an environment variable. 401 */ 402int 403getenv_string(const char *name, char *data, int size) --- 144 unchanged lines hidden --- | 398 return (-1); 399} 400 401/* 402 * Return a string value from an environment variable. 403 */ 404int 405getenv_string(const char *name, char *data, int size) --- 144 unchanged lines hidden --- |