/*1* Environment management routines for the CUPS scheduler.2*3* Copyright © 2021 by OpenPrinting.4* Copyright © 2007-2016 by Apple Inc.5* Copyright © 1997-2006 by Easy Software Products, all rights reserved.6*7* Licensed under Apache License v2.0. See the file "LICENSE" for more8* information.9*/1011/*12* Include necessary headers...13*/1415#include "cupsd.h"161718/*19* Local globals...20*/2122static int num_common_env = 0; /* Number of common env vars */23static char *common_env[MAX_ENV]; /* Common env vars */242526/*27* Local functions...28*/2930static void clear_env(void);31static int find_env(const char *name);323334/*35* 'cupsdInitEnv()' - Initialize the current environment with standard variables.36*/3738void39cupsdInitEnv(void)40{41/*42* Clear existing environment variables...43*/4445clear_env();4647#if defined(__APPLE__)48/*49* Add special voodoo magic for macOS - this allows macOS50* programs to access their bundle resources properly...51*52* This string is replaced in cupsdStartProcess()...53*/5455cupsdSetString(common_env, "<CFProcessPath>");56num_common_env = 1;57#endif /* __APPLE__ */58}596061/*62* 'cupsdLoadEnv()' - Copy common environment variables into an array.63*/6465int /* O - Number of environment variables */66cupsdLoadEnv(char *envp[], /* I - Environment array */67int envmax) /* I - Maximum number of elements */68{69int i; /* Looping var */707172/*73* Leave room for a NULL pointer at the end...74*/7576envmax --;7778/*79* Copy pointers to the environment...80*/8182for (i = 0; i < num_common_env && i < envmax; i ++)83envp[i] = common_env[i];8485/*86* NULL terminate the environment array and return the number of87* elements we added...88*/8990envp[i] = NULL;9192return (i);93}949596/*97* 'cupsdSetEnv()' - Set a common environment variable.98*/99100void101cupsdSetEnv(const char *name, /* I - Name of variable */102const char *value) /* I - Value of variable */103{104int i; /* Index into environment array */105106107/*108* If "value" is NULL, try getting value from current environment...109*/110111if (!value)112value = getenv(name);113114if (!value)115return;116117/*118* Do not allow dynamic linker variables when running as root outside a Snap...119*/120121#if !CUPS_SNAP122if (!RunUser && (!strncmp(name, "DYLD_", 5) || !strncmp(name, "LD_", 3)))123return;124#endif /* !CUPS_SNAP */125126/*127* See if this variable has already been defined...128*/129130if ((i = find_env(name)) < 0)131{132/*133* Check for room...134*/135136if (num_common_env >= (int)(sizeof(common_env) / sizeof(common_env[0])))137{138cupsdLogMessage(CUPSD_LOG_ERROR,139"cupsdSetEnv: Too many environment variables set!");140return;141}142143i = num_common_env;144num_common_env ++;145}146147/*148* Set the new environment variable...149*/150151cupsdSetStringf(common_env + i, "%s=%s", name, value);152153cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSetEnv: %s", common_env[i]);154}155156157/*158* 'cupsdSetEnvf()' - Set a formatted common environment variable.159*/160161void162cupsdSetEnvf(const char *name, /* I - Name of variable */163const char *value, /* I - Printf-style value of variable */164...) /* I - Additional args as needed */165{166char v[4096]; /* Formatting string value */167va_list ap; /* Argument pointer */168169170/*171* Format the value string...172*/173174va_start(ap, value);175vsnprintf(v, sizeof(v), value, ap);176va_end(ap);177178/*179* Set the env variable...180*/181182cupsdSetEnv(name, v);183}184185186/*187* 'cupsdUpdateEnv()' - Update the environment for the configured directories.188*/189190void191cupsdUpdateEnv(void)192{193/*194* Set common variables...195*/196197#define set_if_undefined(name,value) if (find_env(name) < 0) cupsdSetEnv(name,value)198199set_if_undefined("CUPS_CACHEDIR", CacheDir);200set_if_undefined("CUPS_DATADIR", DataDir);201set_if_undefined("CUPS_DOCROOT", DocumentRoot);202set_if_undefined("CUPS_REQUESTROOT", RequestRoot);203set_if_undefined("CUPS_SERVERBIN", ServerBin);204set_if_undefined("CUPS_SERVERROOT", ServerRoot);205set_if_undefined("CUPS_STATEDIR", StateDir);206set_if_undefined("DYLD_INSERT_LIBRARIES", NULL);207set_if_undefined("DYLD_LIBRARY_PATH", NULL);208set_if_undefined("HOME", TempDir);209set_if_undefined("LD_ASSUME_KERNEL", NULL);210set_if_undefined("LD_LIBRARY_PATH", NULL);211set_if_undefined("LD_PRELOAD", NULL);212set_if_undefined("NLSPATH", NULL);213if (find_env("PATH") < 0)214{215#if CUPS_SNAP216const char *path; // PATH environment variable217218if ((path = getenv("PATH")) != NULL)219cupsdSetEnvf("PATH", "%s/filter:%s", ServerBin, path);220else221#endif /* CUPS_SNAP */222cupsdSetEnvf("PATH", "%s/filter:" CUPS_BINDIR ":" CUPS_SBINDIR ":/bin:/usr/bin", ServerBin);223}224set_if_undefined("SERVER_ADMIN", ServerAdmin);225set_if_undefined("SHLIB_PATH", NULL);226set_if_undefined("SOFTWARE", CUPS_MINIMAL);227set_if_undefined("TMPDIR", TempDir);228set_if_undefined("TZ", NULL);229set_if_undefined("USER", "root");230set_if_undefined("VG_ARGS", NULL);231232cupsdSetEnvf("CUPS_MAX_MESSAGE", "%d", CUPSD_SB_BUFFER_SIZE - 1);233}234235236/*237* 'clear_env()' - Clear common environment variables.238*/239240static void241clear_env(void)242{243int i; /* Looping var */244245246for (i = 0; i < num_common_env; i ++)247cupsdClearString(common_env + i);248249num_common_env = 0;250}251252253/*254* 'find_env()' - Find a common environment variable.255*/256257static int /* O - Index or -1 if not found */258find_env(const char *name) /* I - Variable name */259{260int i; /* Looping var */261size_t namelen; /* Length of name */262263264for (i = 0, namelen = strlen(name); i < num_common_env; i ++)265if (!strncmp(common_env[i], name, namelen) && common_env[i][namelen] == '=')266return (i);267268return (-1);269}270271272