1
/* $Xorg: server.c,v 1.5 2000/08/17 19:54:01 cpqbld Exp $ */
3
/************************************************************************/
4
/* Copyright (c) 1993 Quarterdeck Office Systems */
6
/* Permission to use, copy, modify, distribute, and sell this software */
7
/* and software and its documentation for any purpose is hereby granted */
8
/* without fee, provided that the above copyright notice appear in all */
9
/* copies and that both that copyright notice and this permission */
10
/* notice appear in supporting documentation, and that the name */
11
/* Quarterdeck Office Systems, Inc. not be used in advertising or */
12
/* publicity pertaining to distribution of this software without */
13
/* specific, written prior permission. */
15
/* THIS SOFTWARE IS PROVIDED `AS-IS'. QUARTERDECK OFFICE SYSTEMS, */
16
/* INC., DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, */
17
/* INCLUDING WITHOUT LIMITATION ALL IMPLIED WARRANTIES OF */
18
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR */
19
/* NONINFRINGEMENT. IN NO EVENT SHALL QUARTERDECK OFFICE SYSTEMS, */
20
/* INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING SPECIAL, */
21
/* INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, OR */
22
/* PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS */
23
/* OF WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT */
24
/* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
25
/************************************************************************/
26
/* $XFree86: xc/programs/rstart/server.c,v 1.5 2001/07/25 15:05:15 dawes Exp $ */
28
/* Extended rsh "helper" program */
36
#ifdef ODT1_DISPLAY_HACK
38
#endif /* ODT1_DISPLAY_HACK */
43
extern void squish_out_escapes ( char *s );
44
extern char * Strdup ( char *s );
45
extern int get_a_line ( FILE *f, int *pargc, char ***pargv );
46
extern void nomem ( void );
47
static char *Strlwr ( char *s0 );
48
extern void do_it ( void );
49
extern void process ( FILE *f, int is_the_real_thing );
50
extern void detach ( void );
51
extern void putenv_with_prefix ( char *prefix, char *name, char *value );
54
extern void do_auth ( void );
58
void (*func)(int ac, char **av);
61
extern void key_cmd(int ac, char **av);
62
extern void key_exec(int ac, char **av);
63
extern void key_context(int ac, char **av);
64
extern void key_misc(int ac, char **av);
65
extern void key_generic_cmd(int ac, char **av);
66
extern void key_dir(int ac, char **av);
67
extern void key_detach(int ac, char **av);
68
extern void key_nodetach(int ac, char **av);
69
extern void key_posix_umask(int ac, char **av);
70
extern void key_auth(int ac, char **av);
71
extern void key_internal_registries(int ac, char **av);
72
extern void key_internal_local_default(int ac, char **av);
73
extern void key_internal_global_contexts(int ac, char **av);
74
extern void key_internal_local_contexts(int ac, char **av);
75
extern void key_internal_global_commands(int ac, char **av);
76
extern void key_internal_local_commands(int ac, char **av);
77
extern void key_internal_variable_prefix(int ac, char **av);
78
extern void key_internal_print(int ac, char **av);
79
extern void key_internal_auth_program(int ac, char **av);
80
extern void key_internal_auth_input(int ac, char **av);
86
{ "context", key_context },
88
{ "generic-cmd", key_generic_cmd },
90
{ "detach", key_detach },
91
{ "nodetach", key_nodetach },
92
{ "posix-umask", key_posix_umask },
94
{ "internal-registries", key_internal_registries },
95
{ "internal-local-default", key_internal_local_default },
96
{ "internal-global-contexts", key_internal_global_contexts },
97
{ "internal-local-contexts", key_internal_local_contexts },
98
{ "internal-global-commands", key_internal_global_commands },
99
{ "internal-local-commands", key_internal_local_commands },
100
{ "internal-variable-prefix", key_internal_variable_prefix },
101
{ "internal-print", key_internal_print },
102
{ "internal-auth-program", key_internal_auth_program },
103
{ "internal-auth-input", key_internal_auth_input },
108
char **parm_cmd = NULL;
109
char **parm_exec = NULL;
110
char **parm_generic_cmd = NULL;
111
char *parm_dir = NULL;
112
char *parm_context = NULL;
113
char **parm_internal_registries = NULL;
114
char *parm_internal_local_default = NULL;
115
char *parm_internal_global_contexts = NULL;
116
char *parm_internal_local_contexts = NULL;
117
char *parm_internal_global_commands = NULL;
118
char *parm_internal_local_commands = NULL;
119
char *parm_internal_variable_prefix = NULL;
120
int parm_detach = FALSE;
122
char *parm_global_default = DEFAULT_CONFIG;
123
char myname[]=SERVERNAME;
126
main(int argc, char *argv[])
130
if(argc == 3 && !strcmp(argv[1], "-c")) parm_global_default = argv[2];
135
"%s: Ready: version 1.0, May 02 1994 X11R6.3\n",
139
f = fopen(parm_global_default, "r");
140
if(f) process(f, FALSE);
142
if(parm_internal_local_default) {
143
/* We start in $HOME */
144
f = fopen(parm_internal_local_default, "r");
145
if(f) process(f, FALSE);
148
process(stdin, TRUE);
155
squish_out_escapes(s)
162
for(p = s; *p; p++) {
164
if(p[1] >= '0' && p[1] <= '3'
165
&& p[2] >= '0' && p[2] <= '7'
166
&& p[3] >= '0' && p[3] <= '7') {
167
*o++ = ((p[1]-'0') << 6)
173
"%s: Failure: Improper \\ escape\n",myname);
189
cs = malloc(strlen(s)+1);
195
get_a_line(f, pargc, pargv)
209
while((c = getc(f)) != '\n') {
213
/* Ignored, per spec */
229
for(p = saved; *p; p++) {
230
if(was_space && !isspace(*p)) (*pargc)++;
231
was_space = isspace(*p);
234
*pargv = (char **)malloc((*pargc+1)*sizeof(char *));
239
for(p = saved; *p; p++) {
240
if(was_space && !isspace(*p)) *pa++ = p;
241
was_space = isspace(*p);
242
if(isspace(*p)) *p = '\0';
246
if(*pargc > 0 && (*pargv)[0][0] == '#') {
247
/* How embarrassing. All that work for a comment. */
256
for(pa = *pargv; *pa; pa++) {
257
squish_out_escapes(*pa);
266
printf("%s: Failure: Out of memory\n",myname);
271
key_internal_registries(ac, av)
275
parm_internal_registries = av+1;
279
key_internal_variable_prefix(ac, av)
285
"%s: Failure: Malformed INTERNAL-VARIABLE-PREFIX\n",myname);
288
parm_internal_variable_prefix = av[1];
292
key_internal_local_default(ac, av)
297
printf("%s: Failure: Malformed INTERNAL-LOCAL-DEFAULT\n",myname);
300
parm_internal_local_default = av[1];
304
key_internal_global_commands(ac, av)
309
printf("%s: Failure: Malformed INTERNAL-GLOBAL-COMMANDS\n",myname);
312
parm_internal_global_commands = av[1];
316
key_internal_local_commands(ac, av)
321
printf("%s: Failure: Malformed INTERNAL-LOCAL-COMMANDS\n",myname);
324
parm_internal_local_commands = av[1];
328
key_internal_global_contexts(ac, av)
333
printf("%s: Failure: Malformed INTERNAL-GLOBAL-CONTEXTS\n",myname);
336
parm_internal_global_contexts = av[1];
340
key_internal_local_contexts(ac, av)
345
printf("%s: Failure: Malformed INTERNAL-LOCAL-CONTEXTS\n",myname);
348
parm_internal_local_contexts = av[1];
356
if(parm_cmd || parm_exec || parm_generic_cmd) {
358
"%s: Failure: more than one of CMD, EXEC, GENERIC-CMD\n",myname);
369
if(parm_cmd || parm_exec || parm_generic_cmd) {
371
"%s: Failure: more than one of CMD, EXEC, GENERIC-CMD\n",myname);
383
for(s = s0; *s; s++) {
384
if(isupper(*s)) *s = tolower(*s);
400
printf("%s: Failure: Malformed CONTEXT\n",myname);
404
parm_context = av[1];
408
if(parm_internal_global_contexts) {
409
strcpy(buf, parm_internal_global_contexts);
411
strcat(buf, parm_context);
412
if((f = fopen(buf, "r"))) {
418
if(parm_internal_local_contexts) {
419
strcpy(buf, parm_internal_local_contexts);
421
strcat(buf, parm_context);
422
if((f = fopen(buf, "r"))) {
429
printf("%s: Error: Unknown context '%s'\n",myname, parm_context);
440
printf("%s: Failure: malformed DIR line\n",myname);
454
printf("%s: Failure: malformed MISC line\n",myname);
460
if(parm_internal_registries) {
461
for(pp = parm_internal_registries; *pp; pp++) {
462
if(!strcmp(av[1], *pp)) goto ok;
465
printf("%s: Warning: registry %s not recognized\n",myname, av[1]);
471
#ifdef ODT1_DISPLAY_HACK
472
/* The X apps in ODT version 1 don't know how to look up */
473
/* host names using DNS. Do it for them. */
474
if(!strcmp(av[1], "x")
475
&& !strncmp(av[2], "DISPLAY=", 8)
476
&& odt1_display_hack(av[2]+8)) return;
477
#endif /* ODT1_DISPLAY_HACK */
482
#ifdef ODT1_DISPLAY_HACK
492
for(p = s; *p; p++) {
496
he = gethostbyname(s);
499
sprintf(buf, "DISPLAY=%u.%u.%u.%u%s",
500
he->h_addr_list[0][0] & 0xff,
501
he->h_addr_list[0][1] & 0xff,
502
he->h_addr_list[0][2] & 0xff,
503
he->h_addr_list[0][3] & 0xff,
510
if(!isdigit(*p) && *p != '.') ok = TRUE;
514
#endif /* ODT1_DISPLAY_HACK */
517
key_generic_cmd(ac, av)
521
if(parm_cmd || parm_exec || parm_generic_cmd) {
523
"%s: Failure: more than one of CMD, EXEC, GENERIC-CMD\n",myname);
526
parm_generic_cmd = av;
533
if(chdir(parm_dir)) {
534
printf("%s: Error: %s - %s\n",myname,
535
parm_dir, strerror(errno));
540
if(parm_internal_variable_prefix) {
541
putenv_with_prefix(parm_internal_variable_prefix,
542
"CONTEXT", parm_context);
543
putenv_with_prefix(parm_internal_variable_prefix,
544
"LOCAL_COMMANDS", parm_internal_local_commands);
545
putenv_with_prefix(parm_internal_variable_prefix,
546
"GLOBAL_COMMANDS", parm_internal_global_commands);
547
putenv_with_prefix(parm_internal_variable_prefix,
548
"LOCAL_CONTEXTS", parm_internal_local_contexts);
549
putenv_with_prefix(parm_internal_variable_prefix,
550
"GLOBAL_CONTEXTS", parm_internal_global_contexts);
561
if(!(shell = getenv("SHELL"))) shell = "/bin/sh";
564
for(pa = parm_cmd+1; *pa; pa++) {
565
len += strlen(*pa) + 1;
572
for(pa = parm_cmd+1; *pa; pa++) {
577
printf("%s: Success: about to exec %s -c %s\n",myname,
581
if(parm_detach) detach();
583
execl(shell, shell, "-c", buf+1, (char *)NULL);
584
printf("%s: Error: %s - %s\n",myname,
585
shell, strerror(errno));
590
printf("%s: Success: about to exec %s with args\n",myname,
594
if(parm_detach) detach();
596
execvp(parm_exec[1], parm_exec+2);
597
printf("%s: Error: %s - %s\n",myname,
598
parm_exec[0], strerror(errno));
602
if(parm_generic_cmd) {
605
if(!parm_internal_local_commands
606
&& !parm_internal_global_commands) {
608
"%s: Failure: No generic command directory!\n",myname);
612
printf("%s: Success: about to exec generic command\n",myname);
615
if(parm_detach) detach();
617
/* Try context-specific generic commands first */
619
if(parm_internal_local_commands) {
620
strcpy(buf, parm_internal_local_commands);
622
strcat(buf, parm_context);
624
strcat(buf, parm_generic_cmd[1]);
625
execv(buf, parm_generic_cmd+1);
628
if(parm_internal_global_commands) {
629
strcpy(buf, parm_internal_global_commands);
631
strcat(buf, parm_context);
633
strcat(buf, parm_generic_cmd[1]);
634
execv(buf, parm_generic_cmd+1);
638
/* Failing that, try non-context-specific */
639
if(parm_internal_local_commands) {
640
strcpy(buf, parm_internal_local_commands);
642
strcat(buf, parm_generic_cmd[1]);
643
execv(buf, parm_generic_cmd+1);
646
if(parm_internal_global_commands) {
647
strcpy(buf, parm_internal_global_commands);
649
strcat(buf, parm_generic_cmd[1]);
650
execv(buf, parm_generic_cmd+1);
653
printf("%s: Error: %s - %s\n",myname,
654
buf, strerror(errno));
658
printf("%s: Failure: No CMD, EXEC, or GENERIC-CMD.\n",myname);
663
process(f, is_the_real_thing)
665
int is_the_real_thing;
672
if(!get_a_line(f, &line_argc, &line_argv)) {
673
if(is_the_real_thing) {
675
"%s: Failure: No blank line after request\n",myname);
682
if(is_the_real_thing) return;
686
Strlwr(line_argv[0]);
687
for(pk = keys; pk->name; pk++) {
688
if(!strcmp(line_argv[0], pk->name)) {
689
(*pk->func)(line_argc, line_argv);
693
printf("%s: Failure: %s not recognized\n",myname, line_argv[0]);
701
key_internal_print(ac, av)
705
printf("%s: Debug:",myname);
706
while(*++av) printf(" %s", *av);
729
/* I'm not exactly sure how you're supposed to handle stdio here */
732
printf("%s: Error: fork - %s\n",myname, strerror(errno));
739
dup(dup(open("/dev/null", O_RDWR)));
748
putenv_with_prefix(prefix, name, value)
757
s = malloc(strlen(prefix) + strlen(name) + strlen(value) + 3);
761
sprintf(s, "%s_%s=%s", prefix, name, value);
767
key_posix_umask(ac, av)
776
"%s: Failure: Malformed POSIX-UMASK - wrong number of args\n",myname);
780
i = strtol(av[1], &s, 8);
782
if(*s || i < 0 || i > 0777) {
784
"%s: Failure: Malformed POSIX-UMASK - bad arg\n",myname);
793
* define our own putenv() if the system doesn't have one.
794
* putenv(s): place s (a string of the form "NAME=value") in
795
* the environment; replacing any existing NAME. s is placed in
796
* environment, so if you change s, the environment changes (like
797
* putenv on a sun). Binding removed if you putenv something else
806
extern char **environ;
808
static int virgin = 1; /* true while "environ" is a virgin */
812
return 0; /* punt if it's not of the right form */
813
varlen = (v + 1) - s;
815
for (idx = 0; environ[idx] != 0; idx++) {
816
if (strncmp(environ[idx], s, varlen) == 0) {
817
if(v[1] != 0) { /* true if there's a value */
822
environ[idx] = environ[idx+1];
823
} while(environ[++idx] != 0);
829
/* add to environment (unless no value; then just return) */
835
newenv = (char **) malloc((unsigned) ((idx + 2) * sizeof(char*)));
838
for(i = idx-1; i >= 0; --i)
839
newenv[i] = environ[i];
840
virgin = 0; /* you're not a virgin anymore, sweety */
842
newenv = (char **) realloc((char *) environ,
843
(unsigned) ((idx + 2) * sizeof(char*)));
854
#endif /* NOPUTENV */