855 lines
17 KiB
C
855 lines
17 KiB
C
/* $Xorg: server.c,v 1.5 2000/08/17 19:54:01 cpqbld Exp $ */
|
|
|
|
/************************************************************************/
|
|
/* Copyright (c) 1993 Quarterdeck Office Systems */
|
|
/* */
|
|
/* Permission to use, copy, modify, distribute, and sell this software */
|
|
/* and software and its documentation for any purpose is hereby granted */
|
|
/* without fee, provided that the above copyright notice appear in all */
|
|
/* copies and that both that copyright notice and this permission */
|
|
/* notice appear in supporting documentation, and that the name */
|
|
/* Quarterdeck Office Systems, Inc. not be used in advertising or */
|
|
/* publicity pertaining to distribution of this software without */
|
|
/* specific, written prior permission. */
|
|
/* */
|
|
/* THIS SOFTWARE IS PROVIDED `AS-IS'. QUARTERDECK OFFICE SYSTEMS, */
|
|
/* INC., DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, */
|
|
/* INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF */
|
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR */
|
|
/* NONINFRINGEMENT. IN NO EVENT SHALL QUARTERDECK OFFICE SYSTEMS, */
|
|
/* INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING SPECIAL, */
|
|
/* INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, OR */
|
|
/* PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS */
|
|
/* OF WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT */
|
|
/* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
|
/************************************************************************/
|
|
/* $XFree86: xc/programs/rstart/server.c,v 1.5tsi Exp $ */
|
|
|
|
/* Extended rsh "helper" program */
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <X11/Xos.h>
|
|
#include <errno.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
|
|
#ifdef ODT1_DISPLAY_HACK
|
|
#include <netdb.h>
|
|
#endif /* ODT1_DISPLAY_HACK */
|
|
|
|
#define TRUE 1
|
|
#define FALSE 0
|
|
|
|
extern void squish_out_escapes ( char *s );
|
|
extern char * Strdup ( char *s );
|
|
extern int get_a_line ( FILE *f, int *pargc, char ***pargv );
|
|
extern void nomem ( void );
|
|
static char *Strlwr ( char *s0 );
|
|
extern void do_it ( void );
|
|
extern void process ( FILE *f, int is_the_real_thing );
|
|
extern void detach ( void );
|
|
extern void putenv_with_prefix ( char *prefix, char *name, char *value );
|
|
|
|
/* auth.c */
|
|
extern void do_auth ( void );
|
|
|
|
struct key {
|
|
char *name;
|
|
void (*func)(int ac, char **av);
|
|
};
|
|
|
|
extern void key_cmd(int ac, char **av);
|
|
extern void key_exec(int ac, char **av);
|
|
extern void key_context(int ac, char **av);
|
|
extern void key_misc(int ac, char **av);
|
|
extern void key_generic_cmd(int ac, char **av);
|
|
extern void key_dir(int ac, char **av);
|
|
extern void key_detach(int ac, char **av);
|
|
extern void key_nodetach(int ac, char **av);
|
|
extern void key_posix_umask(int ac, char **av);
|
|
extern void key_auth(int ac, char **av);
|
|
extern void key_internal_registries(int ac, char **av);
|
|
extern void key_internal_local_default(int ac, char **av);
|
|
extern void key_internal_global_contexts(int ac, char **av);
|
|
extern void key_internal_local_contexts(int ac, char **av);
|
|
extern void key_internal_global_commands(int ac, char **av);
|
|
extern void key_internal_local_commands(int ac, char **av);
|
|
extern void key_internal_variable_prefix(int ac, char **av);
|
|
extern void key_internal_print(int ac, char **av);
|
|
extern void key_internal_auth_program(int ac, char **av);
|
|
extern void key_internal_auth_input(int ac, char **av);
|
|
|
|
|
|
struct key keys[] = {
|
|
{ "cmd", key_cmd },
|
|
{ "exec", key_exec },
|
|
{ "context", key_context },
|
|
{ "misc", key_misc },
|
|
{ "generic-cmd", key_generic_cmd },
|
|
{ "dir", key_dir },
|
|
{ "detach", key_detach },
|
|
{ "nodetach", key_nodetach },
|
|
{ "posix-umask", key_posix_umask },
|
|
{ "auth", key_auth },
|
|
{ "internal-registries", key_internal_registries },
|
|
{ "internal-local-default", key_internal_local_default },
|
|
{ "internal-global-contexts", key_internal_global_contexts },
|
|
{ "internal-local-contexts", key_internal_local_contexts },
|
|
{ "internal-global-commands", key_internal_global_commands },
|
|
{ "internal-local-commands", key_internal_local_commands },
|
|
{ "internal-variable-prefix", key_internal_variable_prefix },
|
|
{ "internal-print", key_internal_print },
|
|
{ "internal-auth-program", key_internal_auth_program },
|
|
{ "internal-auth-input", key_internal_auth_input },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
|
|
char **parm_cmd = NULL;
|
|
char **parm_exec = NULL;
|
|
char **parm_generic_cmd = NULL;
|
|
char *parm_dir = NULL;
|
|
char *parm_context = NULL;
|
|
char **parm_internal_registries = NULL;
|
|
char *parm_internal_local_default = NULL;
|
|
char *parm_internal_global_contexts = NULL;
|
|
char *parm_internal_local_contexts = NULL;
|
|
char *parm_internal_global_commands = NULL;
|
|
char *parm_internal_local_commands = NULL;
|
|
char *parm_internal_variable_prefix = NULL;
|
|
int parm_detach = FALSE;
|
|
|
|
char *parm_global_default = DEFAULT_CONFIG;
|
|
char myname[]=SERVERNAME;
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
FILE *f;
|
|
|
|
if(argc == 3 && !strcmp(argv[1], "-c")) parm_global_default = argv[2];
|
|
|
|
setbuf(stdin, NULL);
|
|
|
|
printf(
|
|
"%s: Ready: version 1.0, May 02 1994 X11R6.3\n",
|
|
myname);
|
|
fflush(stdout);
|
|
|
|
f = fopen(parm_global_default, "r");
|
|
if(f) process(f, FALSE);
|
|
|
|
if(parm_internal_local_default) {
|
|
/* We start in $HOME */
|
|
f = fopen(parm_internal_local_default, "r");
|
|
if(f) process(f, FALSE);
|
|
}
|
|
|
|
process(stdin, TRUE);
|
|
|
|
do_it();
|
|
exit(0);
|
|
}
|
|
|
|
void
|
|
squish_out_escapes(s)
|
|
char *s;
|
|
{
|
|
char *p;
|
|
char *o;
|
|
|
|
o = s;
|
|
for(p = s; *p; p++) {
|
|
if(*p == '\\') {
|
|
if(p[1] >= '0' && p[1] <= '3'
|
|
&& p[2] >= '0' && p[2] <= '7'
|
|
&& p[3] >= '0' && p[3] <= '7') {
|
|
*o++ = ((p[1]-'0') << 6)
|
|
+ ((p[2]-'0') << 3)
|
|
+ (p[3]-'0');
|
|
p += 3;
|
|
} else {
|
|
printf(
|
|
"%s: Failure: Improper \\ escape\n",myname);
|
|
exit(255);
|
|
}
|
|
} else *o++ = *p;
|
|
}
|
|
*o = '\0';
|
|
}
|
|
|
|
char *
|
|
Strdup(s)
|
|
char *s;
|
|
{
|
|
char *cs;
|
|
|
|
if (!s)
|
|
return s;
|
|
cs = malloc(strlen(s)+1);
|
|
strcpy(cs, s);
|
|
return cs;
|
|
}
|
|
|
|
int
|
|
get_a_line(f, pargc, pargv)
|
|
FILE *f;
|
|
int *pargc;
|
|
char ***pargv;
|
|
{
|
|
char buf[2048];
|
|
char *p;
|
|
int c;
|
|
char **pa;
|
|
int was_space;
|
|
char *saved;
|
|
|
|
while(1) {
|
|
p = buf;
|
|
while((c = getc(f)) != '\n') {
|
|
switch(c) {
|
|
case '\0':
|
|
case '\r':
|
|
/* Ignored, per spec */
|
|
break;
|
|
case EOF:
|
|
return FALSE;
|
|
default:
|
|
*p++ = c;
|
|
break;
|
|
}
|
|
}
|
|
*p = '\0';
|
|
|
|
saved = Strdup(buf);
|
|
if(!saved) nomem();
|
|
|
|
*pargc = 0;
|
|
was_space = TRUE;
|
|
for(p = saved; *p; p++) {
|
|
if(was_space && !isspace(*p)) (*pargc)++;
|
|
was_space = isspace(*p);
|
|
}
|
|
|
|
*pargv = (char **)malloc((*pargc+1)*sizeof(char *));
|
|
if(!*pargv) nomem();
|
|
|
|
pa = *pargv;
|
|
was_space = TRUE;
|
|
for(p = saved; *p; p++) {
|
|
if(was_space && !isspace(*p)) *pa++ = p;
|
|
was_space = isspace(*p);
|
|
if(isspace(*p)) *p = '\0';
|
|
}
|
|
*pa = NULL;
|
|
|
|
if(*pargc > 0 && (*pargv)[0][0] == '#') {
|
|
/* How embarrassing. All that work for a comment. */
|
|
free(saved);
|
|
free(*pargv);
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
for(pa = *pargv; *pa; pa++) {
|
|
squish_out_escapes(*pa);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
nomem()
|
|
{
|
|
printf("%s: Failure: Out of memory\n",myname);
|
|
exit(255);
|
|
}
|
|
|
|
void
|
|
key_internal_registries(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
parm_internal_registries = av+1;
|
|
}
|
|
|
|
void
|
|
key_internal_variable_prefix(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf(
|
|
"%s: Failure: Malformed INTERNAL-VARIABLE-PREFIX\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_internal_variable_prefix = av[1];
|
|
}
|
|
|
|
void
|
|
key_internal_local_default(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf("%s: Failure: Malformed INTERNAL-LOCAL-DEFAULT\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_internal_local_default = av[1];
|
|
}
|
|
|
|
void
|
|
key_internal_global_commands(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf("%s: Failure: Malformed INTERNAL-GLOBAL-COMMANDS\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_internal_global_commands = av[1];
|
|
}
|
|
|
|
void
|
|
key_internal_local_commands(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf("%s: Failure: Malformed INTERNAL-LOCAL-COMMANDS\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_internal_local_commands = av[1];
|
|
}
|
|
|
|
void
|
|
key_internal_global_contexts(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf("%s: Failure: Malformed INTERNAL-GLOBAL-CONTEXTS\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_internal_global_contexts = av[1];
|
|
}
|
|
|
|
void
|
|
key_internal_local_contexts(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf("%s: Failure: Malformed INTERNAL-LOCAL-CONTEXTS\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_internal_local_contexts = av[1];
|
|
}
|
|
|
|
void
|
|
key_cmd(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(parm_cmd || parm_exec || parm_generic_cmd) {
|
|
printf(
|
|
"%s: Failure: more than one of CMD, EXEC, GENERIC-CMD\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_cmd = av;
|
|
}
|
|
|
|
void
|
|
key_exec(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(parm_cmd || parm_exec || parm_generic_cmd) {
|
|
printf(
|
|
"%s: Failure: more than one of CMD, EXEC, GENERIC-CMD\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_exec = av;
|
|
}
|
|
|
|
static char *
|
|
Strlwr(s0)
|
|
char *s0;
|
|
{
|
|
char *s;
|
|
|
|
for(s = s0; *s; s++) {
|
|
if(isupper(*s)) *s = tolower(*s);
|
|
}
|
|
return s0;
|
|
}
|
|
|
|
|
|
void
|
|
key_context(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
char buf[1024];
|
|
int ok;
|
|
FILE *f;
|
|
|
|
if(ac != 2) {
|
|
printf("%s: Failure: Malformed CONTEXT\n",myname);
|
|
exit(255);
|
|
}
|
|
Strlwr(av[1]);
|
|
parm_context = av[1];
|
|
|
|
ok = FALSE;
|
|
|
|
if(parm_internal_global_contexts) {
|
|
strcpy(buf, parm_internal_global_contexts);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_context);
|
|
if((f = fopen(buf, "r"))) {
|
|
process(f, FALSE);
|
|
ok = TRUE;
|
|
}
|
|
}
|
|
|
|
if(parm_internal_local_contexts) {
|
|
strcpy(buf, parm_internal_local_contexts);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_context);
|
|
if((f = fopen(buf, "r"))) {
|
|
process(f, FALSE);
|
|
ok = TRUE;
|
|
}
|
|
}
|
|
|
|
if(!ok) {
|
|
printf("%s: Error: Unknown context '%s'\n",myname, parm_context);
|
|
exit(255);
|
|
}
|
|
}
|
|
|
|
void
|
|
key_dir(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(ac != 2) {
|
|
printf("%s: Failure: malformed DIR line\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_dir = av[1];
|
|
}
|
|
|
|
void
|
|
key_misc(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
char **pp;
|
|
|
|
if(ac != 3) {
|
|
printf("%s: Failure: malformed MISC line\n",myname);
|
|
exit(255);
|
|
}
|
|
|
|
Strlwr(av[1]);
|
|
|
|
if(parm_internal_registries) {
|
|
for(pp = parm_internal_registries; *pp; pp++) {
|
|
if(!strcmp(av[1], *pp)) goto ok;
|
|
}
|
|
}
|
|
printf("%s: Warning: registry %s not recognized\n",myname, av[1]);
|
|
fflush(stdout);
|
|
|
|
ok:
|
|
;
|
|
|
|
#ifdef ODT1_DISPLAY_HACK
|
|
/* The X apps in ODT version 1 don't know how to look up */
|
|
/* host names using DNS. Do it for them. */
|
|
if(!strcmp(av[1], "x")
|
|
&& !strncmp(av[2], "DISPLAY=", 8)
|
|
&& odt1_display_hack(av[2]+8)) return;
|
|
#endif /* ODT1_DISPLAY_HACK */
|
|
|
|
putenv(av[2]);
|
|
}
|
|
|
|
#ifdef ODT1_DISPLAY_HACK
|
|
odt1_display_hack(s)
|
|
char *s;
|
|
{
|
|
char buf[80];
|
|
struct hostent *he;
|
|
char *p;
|
|
int ok;
|
|
|
|
ok = FALSE;
|
|
for(p = s; *p; p++) {
|
|
if(*p == ':') {
|
|
if(!ok) break;
|
|
*p = '\0';
|
|
he = gethostbyname(s);
|
|
*p = ':';
|
|
if(!he) break;
|
|
sprintf(buf, "DISPLAY=%u.%u.%u.%u%s",
|
|
he->h_addr_list[0][0] & 0xff,
|
|
he->h_addr_list[0][1] & 0xff,
|
|
he->h_addr_list[0][2] & 0xff,
|
|
he->h_addr_list[0][3] & 0xff,
|
|
p);
|
|
s = Strdup(buf);
|
|
if(!s) nomem();
|
|
putenv(s);
|
|
return TRUE;
|
|
}
|
|
if(!isdigit(*p) && *p != '.') ok = TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
#endif /* ODT1_DISPLAY_HACK */
|
|
|
|
void
|
|
key_generic_cmd(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
if(parm_cmd || parm_exec || parm_generic_cmd) {
|
|
printf(
|
|
"%s: Failure: more than one of CMD, EXEC, GENERIC-CMD\n",myname);
|
|
exit(255);
|
|
}
|
|
parm_generic_cmd = av;
|
|
}
|
|
|
|
void
|
|
do_it(void)
|
|
{
|
|
if(parm_dir) {
|
|
if(chdir(parm_dir)) {
|
|
printf("%s: Error: %s - %s\n",myname,
|
|
parm_dir, strerror(errno));
|
|
exit(255);
|
|
}
|
|
}
|
|
|
|
if(parm_internal_variable_prefix) {
|
|
putenv_with_prefix(parm_internal_variable_prefix,
|
|
"CONTEXT", parm_context);
|
|
putenv_with_prefix(parm_internal_variable_prefix,
|
|
"LOCAL_COMMANDS", parm_internal_local_commands);
|
|
putenv_with_prefix(parm_internal_variable_prefix,
|
|
"GLOBAL_COMMANDS", parm_internal_global_commands);
|
|
putenv_with_prefix(parm_internal_variable_prefix,
|
|
"LOCAL_CONTEXTS", parm_internal_local_contexts);
|
|
putenv_with_prefix(parm_internal_variable_prefix,
|
|
"GLOBAL_CONTEXTS", parm_internal_global_contexts);
|
|
}
|
|
|
|
do_auth();
|
|
|
|
if(parm_cmd) {
|
|
char *shell;
|
|
char *buf;
|
|
int len;
|
|
char **pa;
|
|
|
|
if(!(shell = getenv("SHELL"))) shell = "/bin/sh";
|
|
|
|
len = 0;
|
|
for(pa = parm_cmd+1; *pa; pa++) {
|
|
len += strlen(*pa) + 1;
|
|
}
|
|
|
|
buf = malloc(len+1);
|
|
if(!buf) nomem();
|
|
|
|
buf[0] = '\0';
|
|
for(pa = parm_cmd+1; *pa; pa++) {
|
|
strcat(buf, " ");
|
|
strcat(buf, *pa);
|
|
}
|
|
|
|
printf("%s: Success: about to exec %s -c %s\n",myname,
|
|
shell, buf+1);
|
|
fflush(stdout);
|
|
|
|
if(parm_detach) detach();
|
|
|
|
execl(shell, shell, "-c", buf+1, (char *)NULL);
|
|
printf("%s: Error: %s - %s\n",myname,
|
|
shell, strerror(errno));
|
|
exit(255);
|
|
}
|
|
|
|
if(parm_exec) {
|
|
printf("%s: Success: about to exec %s with args\n",myname,
|
|
parm_exec[1]);
|
|
fflush(stdout);
|
|
|
|
if(parm_detach) detach();
|
|
|
|
execvp(parm_exec[1], parm_exec+2);
|
|
printf("%s: Error: %s - %s\n",myname,
|
|
parm_exec[0], strerror(errno));
|
|
exit(255);
|
|
}
|
|
|
|
if(parm_generic_cmd) {
|
|
char buf[1024];
|
|
|
|
if(!parm_internal_local_commands
|
|
&& !parm_internal_global_commands) {
|
|
printf(
|
|
"%s: Failure: No generic command directory!\n",myname);
|
|
exit(255);
|
|
}
|
|
|
|
printf("%s: Success: about to exec generic command\n",myname);
|
|
fflush(stdout);
|
|
|
|
if(parm_detach) detach();
|
|
|
|
/* Try context-specific generic commands first */
|
|
if(parm_context) {
|
|
if(parm_internal_local_commands) {
|
|
strcpy(buf, parm_internal_local_commands);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_context);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_generic_cmd[1]);
|
|
execv(buf, parm_generic_cmd+1);
|
|
}
|
|
|
|
if(parm_internal_global_commands) {
|
|
strcpy(buf, parm_internal_global_commands);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_context);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_generic_cmd[1]);
|
|
execv(buf, parm_generic_cmd+1);
|
|
}
|
|
}
|
|
|
|
/* Failing that, try non-context-specific */
|
|
if(parm_internal_local_commands) {
|
|
strcpy(buf, parm_internal_local_commands);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_generic_cmd[1]);
|
|
execv(buf, parm_generic_cmd+1);
|
|
}
|
|
|
|
if(parm_internal_global_commands) {
|
|
strcpy(buf, parm_internal_global_commands);
|
|
strcat(buf, "/");
|
|
strcat(buf, parm_generic_cmd[1]);
|
|
execv(buf, parm_generic_cmd+1);
|
|
}
|
|
|
|
printf("%s: Error: %s - %s\n",myname,
|
|
buf, strerror(errno));
|
|
exit(255);
|
|
}
|
|
|
|
printf("%s: Failure: No CMD, EXEC, or GENERIC-CMD.\n",myname);
|
|
exit(255);
|
|
}
|
|
|
|
void
|
|
process(f, is_the_real_thing)
|
|
FILE *f;
|
|
int is_the_real_thing;
|
|
{
|
|
int line_argc;
|
|
char **line_argv;
|
|
struct key *pk;
|
|
|
|
while(1) {
|
|
if(!get_a_line(f, &line_argc, &line_argv)) {
|
|
if(is_the_real_thing) {
|
|
printf(
|
|
"%s: Failure: No blank line after request\n",myname);
|
|
exit(255);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if(line_argc == 0) {
|
|
if(is_the_real_thing) return;
|
|
continue;
|
|
}
|
|
|
|
Strlwr(line_argv[0]);
|
|
for(pk = keys; pk->name; pk++) {
|
|
if(!strcmp(line_argv[0], pk->name)) {
|
|
(*pk->func)(line_argc, line_argv);
|
|
goto ok;
|
|
}
|
|
}
|
|
printf("%s: Failure: %s not recognized\n",myname, line_argv[0]);
|
|
exit(255);
|
|
ok:
|
|
;
|
|
}
|
|
}
|
|
|
|
void
|
|
key_internal_print(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
printf("%s: Debug:",myname);
|
|
while(*++av) printf(" %s", *av);
|
|
printf("\n");
|
|
}
|
|
|
|
void
|
|
key_detach(ac,av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
parm_detach = TRUE;
|
|
}
|
|
|
|
void
|
|
key_nodetach(ac,av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
parm_detach = FALSE;
|
|
}
|
|
|
|
void
|
|
detach(void)
|
|
{
|
|
/* I'm not exactly sure how you're supposed to handle stdio here */
|
|
switch(fork()) {
|
|
case -1:
|
|
printf("%s: Error: fork - %s\n",myname, strerror(errno));
|
|
exit(255);
|
|
case 0:
|
|
/* Child */
|
|
close(0);
|
|
close(1);
|
|
close(2);
|
|
dup(dup(open("/dev/null", O_RDWR)));
|
|
return;
|
|
default:
|
|
/* Parent */
|
|
_exit(0);
|
|
}
|
|
}
|
|
|
|
void
|
|
putenv_with_prefix(prefix, name, value)
|
|
char *prefix;
|
|
char *name;
|
|
char *value;
|
|
{
|
|
char *s;
|
|
|
|
if(!value) return;
|
|
|
|
s = malloc(strlen(prefix) + strlen(name) + strlen(value) + 3);
|
|
|
|
if(!s) nomem();
|
|
|
|
sprintf(s, "%s_%s=%s", prefix, name, value);
|
|
|
|
putenv(s);
|
|
}
|
|
|
|
void
|
|
key_posix_umask(ac, av)
|
|
int ac;
|
|
char **av;
|
|
{
|
|
int i;
|
|
char *s;
|
|
|
|
if(ac != 2) {
|
|
printf(
|
|
"%s: Failure: Malformed POSIX-UMASK - wrong number of args\n",myname);
|
|
exit(255);
|
|
}
|
|
|
|
i = strtol(av[1], &s, 8);
|
|
|
|
if(*s || i < 0 || i > 0777) {
|
|
printf(
|
|
"%s: Failure: Malformed POSIX-UMASK - bad arg\n",myname);
|
|
exit(255);
|
|
}
|
|
|
|
umask(i);
|
|
}
|
|
|
|
#ifdef NOPUTENV
|
|
/*
|
|
* define our own putenv() if the system doesn't have one.
|
|
* putenv(s): place s (a string of the form "NAME=value") in
|
|
* the environment; replacing any existing NAME. s is placed in
|
|
* environment, so if you change s, the environment changes (like
|
|
* putenv on a sun). Binding removed if you putenv something else
|
|
* called NAME.
|
|
*/
|
|
int
|
|
putenv(s)
|
|
char *s;
|
|
{
|
|
char *v;
|
|
int varlen, idx;
|
|
extern char **environ;
|
|
char **newenv;
|
|
static int virgin = 1; /* true while "environ" is a virgin */
|
|
|
|
v = index(s, '=');
|
|
if(v == 0)
|
|
return 0; /* punt if it's not of the right form */
|
|
varlen = (v + 1) - s;
|
|
|
|
for (idx = 0; environ[idx] != 0; idx++) {
|
|
if (strncmp(environ[idx], s, varlen) == 0) {
|
|
if(v[1] != 0) { /* true if there's a value */
|
|
environ[idx] = s;
|
|
return 0;
|
|
} else {
|
|
do {
|
|
environ[idx] = environ[idx+1];
|
|
} while(environ[++idx] != 0);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* add to environment (unless no value; then just return) */
|
|
if(v[1] == 0)
|
|
return 0;
|
|
if(virgin) {
|
|
register i;
|
|
|
|
newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*)));
|
|
if(newenv == 0)
|
|
return -1;
|
|
for(i = idx-1; i >= 0; --i)
|
|
newenv[i] = environ[i];
|
|
virgin = 0; /* you're not a virgin anymore, sweety */
|
|
} else {
|
|
newenv = (char **) realloc((char *) environ,
|
|
(unsigned) ((idx + 2) * sizeof(char*)));
|
|
if (newenv == 0)
|
|
return -1;
|
|
}
|
|
|
|
environ = newenv;
|
|
environ[idx] = s;
|
|
environ[idx+1] = 0;
|
|
|
|
return 0;
|
|
}
|
|
#endif /* NOPUTENV */
|