1b0e065a29eec1742813dcdd00db7ab1193f718f
[oweals/cde.git] / cde / programs / dtlogin / session.c
1 /* (c) Copyright 1997 The Open Group */
2 /*                                                                      *
3  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
4  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
5  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
6  * (c) Copyright 1993, 1994 Novell, Inc.                                *
7  */
8 /*
9  * Xdm - display manager daemon
10  *
11  * $TOG: session.c /main/21 1998/11/02 14:32:42 mgreess $
12  *
13  * Copyright 1988 Massachusetts Institute of Technology
14  *
15  * Permission to use, copy, modify, and distribute this software and its
16  * documentation for any purpose and without fee is hereby granted, provided
17  * that the above copyright notice appear in all copies and that both that
18  * copyright notice and this permission notice appear in supporting
19  * documentation, and that the name of M.I.T. not be used in advertising or
20  * publicity pertaining to distribution of the software without specific,
21  * written prior permission.  M.I.T. makes no representations about the
22  * suitability of this software for any purpose.  It is provided "as is"
23  * without express or implied warranty.
24  *
25  * Author:  Keith Packard, MIT X Consortium
26  */
27
28 /*
29  * session.c
30  */
31
32 #ifdef _AIX
33 #ifdef _POWER
34 #include <stdio.h>
35 #include <sys/file.h>
36 #endif /* _POWER */
37 # include <usersec.h>
38 #endif /* _AIX */
39
40
41 # include "dm.h"
42 # include "vgmsg.h"
43 # include <signal.h>
44 # include <X11/Xatom.h>
45 # include <setjmp.h>
46 # include <utmp.h>
47 #include <unistd.h>
48 #include <pwd.h>
49 #include <dirent.h>
50 #include <limits.h>
51
52 #ifdef SIA
53 #include <sia.h>
54 #include <siad.h>
55 #include <X11/Intrinsic.h>
56 #endif
57
58 # include <X11/Xresource.h>
59
60 # include "vgproto.h"
61 # include "sysauth.h"
62
63
64 #ifdef sun
65 # include "solaris.h"
66 #endif
67
68 #ifdef BLS
69 # include <sys/security.h>
70 # include <prot.h>
71 #endif
72
73 #ifdef __KERBEROS
74 # include <krb.h>
75 #endif /*  __KERBEROS  */
76
77 #ifdef __PASSWD_ETC
78 #include "rgy_base.h"
79 #endif
80
81 #ifdef SIA
82
83 static  SIAENTITY *siaHandle = NULL;
84 static Boolean        dt_in_sia_ses_authent = False;
85
86 static struct sia_greeter_info {
87     struct display *d;
88     struct greet_info *greet;
89     struct verify_info *verify;
90     struct greet_state *state;
91     int       status;
92     } siaGreeterInfo;
93
94 static int SiaManageGreeter(
95     int timeout,
96     int rendition,
97     unsigned char *title,
98     int num_prompts,
99     prompt_t *prompt);
100
101 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet);
102
103 static void KillGreeter( void );
104
105 static int sia_greeter_pid;
106 static int sia_exit_proc_reg = FALSE;
107
108 #endif /* SIA */
109
110
111 #ifdef __apollo
112   extern char *getenv();
113 #endif  
114
115 #define GREET_STATE_LOGIN             0
116 #define GREET_STATE_AUTHENTICATE      1
117 #define GREET_STATE_EXIT              2
118 #define GREET_STATE_EXPASSWORD        3
119 #define GREET_STATE_ERRORMESSAGE      4
120 #define GREET_STATE_LANG              5
121 #define GREET_STATE_BAD_HOSTNAME      6
122 #define GREET_STATE_ENTER             7
123 #define GREET_STATE_TERMINATEGREET    8
124 #define GREET_STATE_USERNAME          9
125 #define GREET_STATE_CHALLENGE        10
126 #define GREET_STATE_FORM             11
127
128 #ifndef DEF_SESSION
129 #define DEF_SESSION CDE_INSTALLATION_TOP "/bin/Xsession"
130 #endif
131
132 #define DOT             "."
133 #define DOTDOT          ".."
134
135 struct greet_state {
136   int id;               /* state */
137   int waitForResponse;  /* TRUE=wait for response from dtgreet */
138   RequestHeader *request;      /* request buffer */
139   ResponseHeader *response;    /* response buffer */
140   int authenticated;    /* TRUE=user is authenticated */
141   int vf;               /* last return code from Authenticate() */
142   int loginReset;       /* reset flag for LOGIN state */
143   char *msg;            /* message for VF_MESSAGE */
144 };
145
146 char *globalDisplayName;
147
148 /***************************************************************************
149  *
150  *  Local procedure declarations
151  *
152  ***************************************************************************/
153
154 static int  AbortClient( int pid) ;
155 static void DeleteXloginResources( struct display *d, Display *dpy) ;
156        int  LoadXloginResources( struct display *d) ;
157 static int  ErrorHandler( Display *dpy, XErrorEvent *event) ;
158 static int  IOErrorHandler( Display *dpy) ;
159 static int  ManageGreeter( struct display *d, struct greet_info *greet,
160                         struct verify_info *verify, struct greet_state *state) ;
161 static void RunGreeter( struct display *d, struct greet_info *greet,
162                         struct verify_info *verify) ;
163 static void SessionExit( struct display *d, int status) ;
164 static void SessionPingFailed( struct display *d) ;
165 static int  StartClient(struct verify_info *verify, struct display *d,
166                         int *pidp) ;
167 static SIGVAL catchAlrm( int arg ) ;
168 static SIGVAL catchHUP( int arg ) ;
169 static SIGVAL catchTerm( int arg ) ;
170 static SIGVAL waitAbort( int arg ) ;
171 static void SetupDisplay(struct display *d);
172
173 static void TellGreeter(RequestHeader *phdr);
174 static int AskGreeter(RequestHeader *preqhdr, char *b, int blen);
175 #if defined (DEBUG)
176 static void PrintResponse(ResponseHeader *phdr, int count);
177 #endif /* DEBUG */
178
179 #if defined (_AIX) && defined (_POWER)
180 static void release_aix_lic(void);
181 #endif
182
183 #if defined (_AIX) && !defined (_POWER)
184 static int session_execve(char *path, char *argv[], char *envp[]);
185 #else
186 #define session_execve(A,B,C) execve(A,B,C)
187 #endif 
188
189 #  ifdef __KERBEROS
190       static void SetTicketFileName(uid_t uid);
191 #  endif /* __KERBEROS */
192
193 static void LoadAltDtsResources( struct display *d);
194 char * _ExpandLang(char *string, char *lang);
195
196
197
198 /***************************************************************************
199  *
200  *  Global variables
201  *
202  ***************************************************************************/
203
204 static int                      clientPid;
205 static struct greet_info        greet;
206 static struct verify_info       verify;
207 static char                     *defaultLanguage = NULL;
208
209 static jmp_buf  abortSession;
210
211 #ifdef BLS
212   static char *sensitivityLevel;
213 #endif
214
215 #ifdef __KERBEROS
216   static char krb_ticket_string[MAXPATHLEN];
217 #endif /* __KERBEROS */
218
219
220 XrmDatabase XresourceDB;
221 XrmDatabase XDB;
222
223
224 static SIGVAL
225 catchTerm( int arg )
226 {
227     longjmp (abortSession, 1);
228 }
229
230 static jmp_buf  pingTime;
231
232 static SIGVAL
233 catchAlrm( int arg )
234 {
235     longjmp (pingTime, 1);
236 }
237
238 static int
239 FileNameCompare (a, b)
240 #if defined(__STDC__)
241         const void *a, *b;
242 #else
243         char *a, *b;
244 #endif
245 {
246     return strcoll (*(char **)a, *(char **)b);
247 }
248
249 static void
250 SessionPingFailed( struct display *d )
251 {
252     if (clientPid > 1)
253     {
254         AbortClient (clientPid);
255         source (&verify, d->reset);
256
257 #if defined (PAM) || defined(SUNAUTH) 
258         {
259             char* user = getEnv (verify.userEnviron, "USER");
260             char* ttyLine = d->gettyLine;
261             
262 #ifdef DEF_NETWORK_DEV
263             /* 
264              * If location is not local (remote XDMCP dtlogin) and 
265              * remote accouting is enabled (networkDev start with /dev/...)
266              * Set tty line name to match network device for accouting.  
267              * Unless the resource was specifically set, default is value 
268              * of DEF_NETWORK_DEV define (/dev/dtremote) 
269              */
270                
271             if ( d->displayType.location != Local && 
272                  networkDev && !strncmp(networkDev,"/dev/",5)) {
273                 ttyLine = networkDev+5;
274             }
275 #endif 
276
277 #   ifdef PAM 
278             PamAccounting( verify.argv[0], d->name, d->utmpId, user, 
279                            ttyLine, clientPid, ACCOUNTING, NULL);
280 #   else
281             solaris_accounting( verify.argv[0], d->name, d->utmpId, user, 
282                                 ttyLine, clientPid, ACCOUNTING, NULL);
283 #   endif
284
285 #   ifdef sun
286             solaris_resetdevperm(ttyLine);
287 #   endif
288         }
289 #endif
290
291     }
292     SessionExit (d, RESERVER_DISPLAY);
293 }
294
295
296 /*
297  * We need our own error handlers because we can't be sure what exit code Xlib
298  * will use, and our Xlib does exit(1) which matches REMANAGE_DISPLAY, which
299  * can cause a race condition leaving the display wedged.  We need to use
300  * RESERVER_DISPLAY for IO errors, to ensure that the manager waits for the
301  * server to terminate.  For other X errors, we should give up.
302  */
303
304 static int 
305 IOErrorHandler( Display *dpy )
306 {
307
308     char *s = ((errno >= 0 && errno < sys_nerr) ? sys_errlist[errno]
309                                                 : "unknown error");
310
311     LogError(ReadCatalog(
312                        MC_LOG_SET,MC_LOG_FATAL_IO,MC_DEF_LOG_FATAL_IO),
313         errno,s);
314     exit(RESERVER_DISPLAY);
315     return 0;
316 }
317
318 static int 
319 ErrorHandler( Display *dpy, XErrorEvent *event )
320 {
321     LogError(ReadCatalog(MC_LOG_SET,MC_LOG_X_ERR,MC_DEF_LOG_X_ERR));
322     if (XmuPrintDefaultErrorMessage (dpy, event, stderr) == 0) return 0;
323     exit(UNMANAGE_DISPLAY);
324 }
325
326     Display             *dpy;
327
328 void
329 ManageSession( struct display *d )
330 {
331     int                 pid;
332     Window              root;
333    /* Display           *dpy; */
334 #ifdef BYPASSLOGIN
335     char        *BypassUsername;
336     char        *BypassLogin();
337 #endif /* BYPASSLOGIN */
338         
339
340     Debug ("ManageSession():\n");
341
342     /***********************************/
343     /** remember the default language **/
344     /***********************************/
345     if (defaultLanguage == NULL) {
346         if ( (d->language != NULL) && (strlen(d->language) > 0) ) {
347             defaultLanguage = strdup(d->language);
348         } else {
349             defaultLanguage = "C";
350         }
351     }
352
353 #ifdef BYPASSLOGIN
354     d->bypassLogin = 0;
355     if ((BypassUsername = BypassLogin(d->name)) != NULL) {
356         d->bypassLogin = 1;
357         Debug("Login bypassed, running as %s\n",BypassUsername);
358         greet.name = BypassUsername;
359         if (!Verify (d, &greet, &verify)) {
360             Debug ("Login bypass verify failed!\n");
361             SessionExit (d, GREETLESS_FAILED);
362         }
363         Debug("Login bypass verify succeded!\n");
364     } else
365 #endif /* BYPASSLOGIN */
366
367     {
368         int i;
369
370         (void)XSetIOErrorHandler(IOErrorHandler);
371         (void)XSetErrorHandler(ErrorHandler);
372         SetTitle(d->name, (char *) 0);
373
374         /*
375          * set root background to black...
376          */
377
378         dpy = XOpenDisplay(d->name);
379         for (i = ScreenCount(dpy) - 1; i >= 0; i--)
380         {
381             Window      tmproot = RootWindow(dpy, i);
382
383             if (i == DefaultScreen(dpy))
384               root = tmproot;
385             
386             XSetWindowBackground(dpy, tmproot, BlackPixel(dpy, i));
387             XClearWindow(dpy, tmproot);
388         }
389         XFlush(dpy);
390
391         /*
392         ** Step 5:  
393         ** Invoke Greet program, wait for completion.
394         ** If this routine returns, the user will have been
395         ** verified, otherwise the routine will exit inter-
396         ** nally with an appropriate exit code for the master
397         ** Dtlogin process.
398         */
399      
400
401         greet.name = greet.string = NULL;
402
403         while (greet.name == NULL) {
404             SetHourGlassCursor(dpy, root);
405             LoadXloginResources (d);
406             SetupDisplay(d);
407             ApplyFontPathMods(d, dpy);
408             (void)XSetErrorHandler(ErrorHandler);
409             RunGreeter(d, &greet, &verify);
410
411             DeleteXloginResources (d, dpy);
412         }
413         XSetInputFocus(dpy, root, RevertToNone, CurrentTime);
414         XCloseDisplay(dpy);
415     }
416
417 #ifdef __KERBEROS
418     /*
419      *  Generate Kerberos ticket file name. Put in system and user
420      *  environments...
421      */
422
423     if ( IsVerifyName(VN_KRB)) {
424         SetTicketFileName(verify.uid);
425         krb_set_tkt_string(krb_ticket_string);
426         verify.systemEnviron = setEnv (verify.systemEnviron, 
427                                    "KRBTKFILE",
428                                    krb_ticket_string);
429
430         verify.userEnviron   = setEnv (verify.userEnviron, 
431                                    "KRBTKFILE",
432                                    krb_ticket_string);
433     }
434 #endif /* __KERBEROS */
435
436    /* set LOCATION env var */
437     if(d->displayType.location == Local)  {
438         verify.systemEnviron = setEnv (verify.systemEnviron,
439                                    LOCATION,
440                                    "local");
441         /* ITE is needed only for Local displays */
442         /* set ITE env var */
443         if(d->gettyLine)
444            verify.systemEnviron = setEnv (verify.systemEnviron,
445                                   "ITE",
446                                   d->gettyLine);
447     }
448     else
449         verify.systemEnviron = setEnv (verify.systemEnviron,
450                                    LOCATION,
451                                    "remote");
452
453     {
454         struct passwd *pwd;
455         char   gid[25];
456         sprintf(gid,"%ld",(long)getgid());
457         /* set user group id (USER_GID) env var */
458         verify.systemEnviron = setEnv (verify.systemEnviron,
459                                    "USER_GID",
460                                    gid);
461
462         /* set root group id (ROOT_GID) env var */
463         pwd = getpwnam("root");
464         if(pwd)  {
465            sprintf(gid,"%ld",(long)pwd->pw_gid);
466            verify.systemEnviron = setEnv (verify.systemEnviron,
467                                       "ROOT_GID",
468                                       gid);
469         }
470     }
471
472     /*
473      * Run system-wide initialization file
474      */
475     if (source (&verify, d->startup) != 0)
476     {
477         Debug ("Startup program %s exited with non-zero status\n",
478                 d->startup);
479         SessionExit (d, OBEYSESS_DISPLAY);
480     }
481
482 #ifdef sun
483     if ( solaris_setdevperm(d->gettyLine, verify.uid, verify.gid) == 0 ) {
484         SessionExit (d, OBEYSESS_DISPLAY);
485     }
486 #endif
487
488     clientPid = 0;
489     if (!setjmp (abortSession)) {
490         signal (SIGTERM, catchTerm);
491         /*
492          * Start the clients, changing uid/groups
493          *         setting up environment and running the session
494          */
495         if (StartClient (&verify, d, &clientPid)) {
496             Debug ("Client started\n");
497
498             /*
499              * We've changed dtlogin to pass HUP's down to the children
500              * so ignore any HUP's once the client has started.
501              */
502             signal(SIGHUP, SIG_IGN);
503
504             /*
505              * Wait for session to end,
506              */
507             for (;;) {
508                 if (d->pingInterval)
509                 {
510                     if (!setjmp (pingTime))
511                     {
512                         signal (SIGALRM, catchAlrm);
513                         alarm (d->pingInterval * 60);
514                         pid = wait ((waitType *) 0);
515                         alarm (0);
516                     }
517                     else
518                     {
519                         alarm (0);
520                         if (!PingServer (d, (Display *) NULL))
521                             SessionPingFailed (d);
522                     }
523                 }
524                 else
525                 {
526                     pid = wait ((waitType *) 0);
527                 }
528                 if (pid == clientPid)
529                     break;
530             }
531
532             /*
533              * We've changed dtlogin to pass HUP's down to the children
534              * so ignore any HUP's once the client has started.
535              */
536             signal(SIGHUP, SIG_DFL);
537         } else {
538             LogError(ReadCatalog(
539                 MC_LOG_SET,MC_LOG_FAIL_START,MC_DEF_LOG_FAIL_START));
540         }
541     } else {
542         /*
543          * when terminating the session, nuke
544          * the child and then run the reset script
545          */
546         AbortClient (clientPid);
547     }
548
549     /*
550      * on foreign displays without XDMCP, send a SIGTERM to the process
551      * group of the session manager. This augments the "resetServer()"
552      * routine and helps get all clients killed. It is possible for a client
553      * to have a connection to the server, but not have a window.
554      */
555
556     if (d->displayType.location == Foreign   &&
557         d->displayType.origin   != FromXDMCP    )
558         AbortClient(clientPid);
559
560
561 #ifdef __KERBEROS
562     /*
563      * remove ticket file...
564      */
565
566     if ( IsVerifyName(VN_KRB) ) {
567         dest_tkt();
568     }
569
570 #endif /* __KERBEROS */
571
572         
573     /*
574      * run system-wide reset file
575      */
576     Debug ("Source reset program %s\n", d->reset);
577     source (&verify, d->reset);
578
579 #if defined(PAM) || defined(SUNAUTH)
580     {
581         char* user = getEnv (verify.userEnviron, "USER");
582         char* ttyLine = d->gettyLine;
583             
584 #   ifdef DEF_NETWORK_DEV
585             /* 
586              * If location is not local (remote XDMCP dtlogin) and 
587              * remote accouting is enabled (networkDev start with /dev/...)
588              * Set tty line name to match network device for accouting.  
589              * Unless the resource was specifically set, default is value 
590              * of DEF_NETWORK_DEV define (/dev/dtremote) 
591              */
592                
593             if ( d->displayType.location != Local && 
594                  networkDev && !strncmp(networkDev,"/dev/",5)) {
595                 ttyLine = networkDev+5;
596             }
597 #   endif 
598
599 #   ifdef PAM
600         PamAccounting( verify.argv[0], d->name, d->utmpId, user, 
601                        ttyLine, clientPid, ACCOUNTING, NULL);
602 #   else
603         solaris_accounting( verify.argv[0], d->name, d->utmpId, user, 
604                             ttyLine, clientPid, ACCOUNTING, NULL);
605 #   endif
606
607 #   ifdef sun
608         solaris_resetdevperm(ttyLine);
609 #   endif
610     }
611 #endif
612
613     SessionExit (d, OBEYSESS_DISPLAY);
614 }
615
616
617 int
618 LoadXloginResources( struct display *d )
619 {
620     char        cmd[1024];
621     char        *language="";
622     char        *lang_key="";
623     char        *authority="";
624     char        *auth_key="";
625     char        *resources = NULL;
626     char        *p;
627     char        tmpname[32];
628
629     if (d->resources && d->resources[0]) { 
630         resources = _ExpandLang(d->resources, d->language);
631         if (access (resources, R_OK) != 0) {
632             /** fallback to the C locale for resources **/
633             Debug("LoadXloginResources - cant access %s\n", resources);
634             Debug("\t %s.  Falling back to C.\n", sys_errlist[errno]);
635             free(resources);
636             resources = _ExpandLang(d->resources, "C");
637             if (access (resources, R_OK) != 0) {
638                 /** can't find a resource file, so bail **/
639                 Debug("LoadXloginResources - cant access %s.\n", resources);
640                 Debug("\t %s.  Unable to find resource file.\n",
641                       sys_errlist[errno]);
642                 free(resources);
643                 return(-1);
644             }
645         }
646
647         if (d->authFile && strlen(d->authFile) > 0 ) {
648                 authority = d->authFile;
649                 auth_key = "XAUTHORITY=";
650         }
651
652         if (d->language && strlen(d->language) > 0 ) {
653                 language = strdup(d->language);
654                 lang_key = "-D";
655         }
656
657         /*
658          *  replace any "-" or "." in the language name with "_". The C
659          *  preprocessor used by xrdb does not accept "-" or "." in a name.
660          */
661          
662         while ( (p = strchr(language, '-')) != NULL ) {
663             *p = '_';
664         }
665          
666         while ( (p = strchr(language, '.')) != NULL ) {
667             *p = '_';
668         }
669                     
670         if ( strlen(language) > 0 )
671             free(language);
672
673
674         Debug("LoadXloginResources - loading resource db from %s\n", resources);
675         if((XresourceDB = XrmGetFileDatabase(resources)) == NULL)
676           Debug("LoadXloginResources - Loading resource db from %s failed\n",
677                 resources);
678
679         LoadAltDtsResources(d); 
680
681         strcpy(tmpname,"/var/dt/dtlogin_XXXXXX");
682         (void) mktemp(tmpname);
683
684         XrmPutFileDatabase(XresourceDB, tmpname);
685
686         sprintf (cmd, "%s%s %s -display %s -load %s",
687                         auth_key, authority, d->xrdb, d->name, tmpname);
688         Debug ("Loading resource file: %s\n", cmd);
689
690         system (cmd);  
691
692         if (debugLevel <= 10)
693           if (unlink (tmpname) == -1)
694             Debug ("unlink() on %s failed\n", tmpname);
695     }
696
697     if (resources) free (resources);
698
699     return (0);
700 }
701
702 /***************************************************************************
703  *
704  *  LoadAltDtsResources 
705  *
706  *
707  *  set up alternate desktop resources..
708  *
709  ***************************************************************************/
710  
711 static void
712 LoadAltDtsResources(struct display *d)
713 {
714     DIR         *dirp;
715     struct dirent *dp;
716     char        dirname[2][MAXPATHLEN];
717     char        res_file[MAXPATHLEN];
718     char        *rmtype;        /* for XrmGetResource()                    */
719     XrmValue    rmvalue;        /* for XrmGetResource()                    */
720     char        buf[MAXPATHLEN];
721     char        tempbuf[MAXPATHLEN];
722     XrmDatabase defDb;
723     XrmDatabase userDb;
724     char        altdtres[MAXPATHLEN];
725     char        Altdtres[MAXPATHLEN];
726     int         i = 0;
727     int         j = 0;
728     char        *resources = NULL;
729     int         file_count = 0;
730     int         num_allocated = 0;
731     char        **file_list = NULL;
732     int         list_incr = 10;
733
734     if ( XrmGetResource(XresourceDB,
735                    "Dtlogin*altDts",  "Dtlogin*AltDts",
736                    &rmtype, &rmvalue ) ) {
737                 strcpy(tempbuf,rmvalue.addr);
738                 i = atoi(tempbuf);
739     }
740
741     strcpy(dirname[0],CDE_INSTALLATION_TOP "/config/%L/Xresources.d/");
742     strcpy(dirname[1],CDE_CONFIGURATION_TOP "/config/%L/Xresources.d/");
743
744     for(j = 0; j < 2 ; ++j)
745     {
746         resources = _ExpandLang(dirname[j], d->language);
747         if (access (resources, R_OK) != 0)
748         {
749             Debug("LoadAltDtsResources- cant access %s.\n", resources);
750             Debug("\t %s.  Falling back to C.\n", sys_errlist[errno]);
751
752             if (resources)
753             {
754                 free (resources);
755                 resources = NULL;
756             }
757
758             resources = _ExpandLang(dirname[j], "C");
759             if (access (resources, R_OK) != 0)
760             {
761                 Debug("LoadAltDtsResources- cant access %s.\n", resources);
762                 Debug("\t %s.\n", sys_errlist[errno]);
763             }
764             else
765               strcpy(dirname[j], resources);
766         }
767         else {
768             strcpy(dirname[j],resources);
769             Debug("LoadAltDtsResources- found resource dir %s\n", dirname[j]);
770         }
771
772         if (resources)
773         {
774             free (resources);
775             resources = NULL;
776         }
777     }
778
779
780     /*
781      * Create a list of the alt DT files
782      *
783      * NOTE - an assumption made here is that files in /etc/dt
784      * should take precedence over files in /usr/dt.  This precedence
785      * is maintained during the sort becase /etc/dt will come before
786      * /usr/dt
787      */
788
789     for(j = 0; j < 2 ; ++j) {
790
791         if((dirp = opendir(dirname[j])) != NULL) {
792
793             while((dp = readdir(dirp)) != NULL) {
794
795                 if ((strcmp(dp->d_name, DOT)    != 0) &&
796                     (strcmp(dp->d_name, DOTDOT) != 0)) {
797
798                     sprintf (res_file, "%s%s", dirname[j],dp->d_name);
799                     if ((access (res_file, R_OK)) != 0)
800                     {
801                         Debug("LoadAltDtsResources- cant access %s.\n",
802                               resources);
803                         Debug("\t %s.\n", sys_errlist[errno]);
804                         continue;
805                     }
806
807                     if (file_count == 0) {
808                         file_list = malloc (list_incr * sizeof(char **));
809                         num_allocated += list_incr;
810                     }
811                     if (file_count + 1 > num_allocated) {
812                         num_allocated += list_incr;
813                         file_list = realloc (file_list,
814                                              num_allocated * sizeof(char **));
815                     }
816                     file_list[file_count] = strdup (res_file);
817                     file_count++;
818                 }
819             }
820             closedir(dirp);
821         }
822     }
823
824     if (file_count > 0)
825         qsort (file_list, file_count, sizeof (char *), FileNameCompare);
826
827     for (j = 0; j < file_count ; j++) {
828
829         userDb = XrmGetFileDatabase(file_list[j]);
830         XrmMergeDatabases(userDb,&XresourceDB);
831  
832         if ( XrmGetResource(XresourceDB, "Dtlogin*altDtsIncrement",
833                         "Dtlogin*AltDtsIncrement", &rmtype, &rmvalue ) ) {
834
835             /* 
836              * remove the trailing spaces 
837              */
838             if(strchr(rmvalue.addr,' '))
839                 strcpy(tempbuf, strtok(rmvalue.addr," "));
840             else
841                 strcpy(tempbuf, rmvalue.addr);
842
843             if ((strcmp(tempbuf, "True") == 0) || 
844                 (strcmp(tempbuf, "TRUE") == 0))  {
845  
846                 if ( XrmGetResource(XresourceDB,
847                                 "Dtlogin*altDtKey",  "Dtlogin*AltDtKey",
848                                 &rmtype, &rmvalue ) ) {
849                      ++i;
850                      sprintf(altdtres,"Dtlogin*altDtKey%d",i);
851                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
852                  }
853                  else
854                     continue;
855  
856                  if ( XrmGetResource(XresourceDB,
857                                 "Dtlogin*altDtName",  "Dtlogin*AltDtName",
858                                 &rmtype, &rmvalue ) ) {
859                      sprintf(altdtres,"Dtlogin*altDtName%d",i);
860                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
861                  }
862                  if ( XrmGetResource(XresourceDB,
863                                 "Dtlogin*altDtStart",  "Dtlogin*AltDtStart",
864                                 &rmtype, &rmvalue ) ) {
865                      sprintf(altdtres,"Dtlogin*altDtStart%d",i);
866                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
867                  }
868                  if ( XrmGetResource(XresourceDB,
869                                 "Dtlogin*altDtLogo",  "Dtlogin*AltDtLogo",
870                                 &rmtype, &rmvalue ) ) {
871                      sprintf(altdtres,"Dtlogin*altDtLogo%d",i);
872                      XrmPutStringResource(&XresourceDB, altdtres, rmvalue.addr);
873                  }
874             }
875         }
876     }
877
878     sprintf(tempbuf,"%d",i);
879     XrmPutStringResource(&XresourceDB, "Dtlogin*altDts", tempbuf); 
880
881     if (file_count > 0) {
882         for (i = 0; i < file_count; i++) {
883             Debug ("Loading resource file: %s\n", file_list[i]);
884             free (file_list[i]);
885         }
886         free (file_list);
887     }
888 }
889
890
891 /******************
892  *
893  * Function Name:  _ExpandLang
894  *
895  * Description:
896  *
897  *      This function takes the string "string", searches for occurences of
898  *      "%L" in the string and if found, the "%L" is substituted with
899  *      the value of the $LANG environment variable.
900  *
901  *      If $LANG is not defined, the %L is replace with NULL.
902  *
903  * Note: 
904  *
905  *      _ExpandLang() is based on the DtSvc _DtExpandLang() static routine.
906  *
907  * Synopsis:
908  *
909  *      ret_string = _ExpandLang (string);
910  *
911  *      char *ret_string;       Returns NULL if "string" is NULL or it points
912  *                              to the expanded string.
913  *
914  *      char *string;           The first part of the pathname.  Typically
915  *                              the directory containing the item of interest.
916  *
917  * Note: The caller is responsible for free'ing the returned string.
918  *
919  ******************/
920
921
922 char *
923 _ExpandLang(
924         char *string,
925         char *lang )
926 {
927    char         *tmp;
928    char         *pch;
929    char         *trail;
930    int          n = 0;
931    int          lang_len = 0;
932    int          tmp_len;
933    int          i = 0;
934
935    if (string == NULL)
936       return (NULL);
937
938    /*
939     * Count the number of expansions that will occur.
940     */
941
942
943    for (n = 0, pch = string ; pch != NULL ; ) {
944       if ((pch = strchr (pch, '%')) != NULL) {
945          n++;
946          pch++;
947       }
948    }
949
950    if (n == 0)
951       return (strdup(string));
952
953 /*
954  * We should really be calling setlocale to determine the "default"
955  * locale but setlocale's return value is not standardized across
956  * the various vendor platforms nor is it consistent within differnt
957  * revs of individual OS's. (e.g. its changing between HP-UX 9.0 and
958  * HP-UX 10.0).   The "right" call would be the following line:
959  *
960  *  if ((lang = getenv ("LANG")) || (lang = setlocale(LC_C_TYPE,NULL)))
961  *
962  * Here we hard code the default to "C" instead of leaving it NULL.
963  */
964    if (lang || (lang = getenv ("LANG")) || (lang = "C"))
965       lang_len = strlen (lang);
966
967    /*
968     * Create the space needed.
969     */
970    tmp_len = strlen (string) + (n * lang_len) + n + 1;
971    tmp = (char *) malloc (tmp_len);
972    for (i = 0; i < tmp_len; tmp[i] = '\0', i++);
973
974    pch = string;
975
976    while (pch != NULL) {
977       trail = pch;
978
979       if ((pch = strchr (pch, '%')) != NULL) {
980
981          pch++;
982
983          if (pch == NULL) {
984             (void) strncat (tmp, trail, ((pch - 1) - trail) + 1);
985          }
986          else if ((pch != NULL) && *pch == 'L') {
987             if (lang_len == 0) {
988                if (((pch - trail) >=2) && (*(pch-2) == '/'))
989                   /*
990                    * Remove the "/" as well as the "%L".
991                    */
992                   (void) strncat (tmp, trail, (pch - trail) - 2);
993                else
994                   (void) strncat (tmp, trail, (pch - trail) - 1);
995             }
996             else {
997                /*
998                 * Remove the "%L" and then append the LANG.
999                 */
1000                (void) strncat (tmp, trail, (pch - trail) - 1);
1001                (void) strcat (tmp, lang);
1002             }
1003          }
1004          else {
1005             (void) strncat (tmp, trail, (pch - trail) + 1);
1006          }
1007          if (pch != NULL)
1008             pch++;
1009       }
1010       else {
1011          /*
1012           * A '%' was not found.
1013           */
1014          (void) strcat (tmp, trail);
1015       }
1016    }
1017
1018    return (tmp);
1019 }
1020
1021
1022 static void
1023 SetupDisplay (struct display *d)
1024 {
1025     char **env = 0, **crt_systemEnviron;
1026
1027     if (d->setup && d->setup[0] && (access(d->setup, R_OK ) == 0))
1028     {
1029         crt_systemEnviron = verify.systemEnviron;
1030         env = systemEnv (d, (char *) 0, (char *) 0);
1031         if (d->authFile && strlen(d->authFile) > 0 )
1032             env = setEnv( env, "XAUTHORITY", d->authFile );
1033         if(d->displayType.location == Local)  
1034             env = setEnv (env, LOCATION, "local");
1035         else
1036             env = setEnv (env, LOCATION, "remote");
1037         verify.systemEnviron = env;
1038         source (&verify, d->setup);
1039         verify.systemEnviron = crt_systemEnviron;
1040         freeEnv (env);
1041     }
1042 }
1043
1044 /*ARGSUSED*/
1045 static void 
1046 DeleteXloginResources( struct display *d, Display *dpy )
1047 {
1048     XDeleteProperty(dpy, RootWindow (dpy, 0), XA_RESOURCE_MANAGER);
1049 }
1050
1051 #if  0                    /* dead code: transferred to Dtgreet */
1052
1053 static jmp_buf syncJump;
1054
1055 static SIGVAL
1056 syncTimeout ()
1057 {
1058     longjmp (syncJump, 1);
1059 }
1060
1061
1062 SecureDisplay (d, dpy)
1063 struct display  *d;
1064 Display         *dpy;
1065 {
1066     Debug ("SecureDisplay():\n");
1067     signal (SIGALRM, syncTimeout);
1068     if (setjmp (syncJump)) {
1069         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECDPY,MC_DEF_LOG_NO_SECDPY),
1070                    d->name);
1071         SessionExit (d, RESERVER_DISPLAY);
1072     }
1073     alarm ((unsigned) d->grabTimeout);
1074     Debug ("Before XGrabServer()\n");
1075     XGrabServer (dpy);
1076     if (XGrabKeyboard (dpy, DefaultRootWindow (dpy), True, GrabModeAsync,
1077                        GrabModeAsync, CurrentTime) != GrabSuccess)
1078     {
1079         alarm (0);
1080         signal (SIGALRM, SIG_DFL);
1081         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SECKEY,MC_DEF_LOG_NO_SECKEY),
1082                   d->name);
1083         SessionExit (d, RESERVER_DISPLAY);
1084     }
1085     Debug ("XGrabKeyboard() succeeded\n");
1086     alarm (0);
1087     signal (SIGALRM, SIG_DFL);
1088     pseudoReset (dpy);
1089     if (!d->grabServer)
1090     {
1091         XUngrabServer (dpy);
1092         XSync (dpy, 0);
1093     }
1094     Debug ("Done secure %s\n", d->name);
1095 }
1096
1097 UnsecureDisplay (d, dpy)
1098 struct display  *d;
1099 Display         *dpy;
1100 {
1101     Debug ("Unsecure display %s\n", d->name);
1102     if (d->grabServer)
1103         XUngrabServer (dpy);
1104     XSync (dpy, 0);
1105 }
1106 #endif
1107
1108 #ifdef _AIX
1109 #ifdef _POWER
1110
1111 static void
1112 release_aix_lic(void)
1113 {
1114  /*
1115   * Release AIX iFOR/LS license (if any)
1116   */
1117   int fd;
1118   struct pipeinfo {
1119     int request_type;
1120     pid_t login_pid;
1121   } release_me;
1122   
1123   release_me.request_type = -1;
1124   release_me.login_pid = getpid();
1125   if ((fd = open("/etc/security/monitord_pipe", O_RDWR, 0600)) >= 0)
1126   {
1127     write(fd, &release_me, sizeof(release_me));
1128     close(fd);
1129   }
1130   Debug("release message to monitord: %s\n", (fd >= 0) ? "OK" : "failed");
1131 }
1132
1133 #endif /* _POWER */
1134 #endif /* _AIX */
1135
1136
1137 static void
1138 SessionExit( struct display *d, int status )
1139 {
1140
1141 #ifdef _AIX
1142 #ifdef _POWER
1143     release_aix_lic();
1144 #endif /* _POWER */
1145 #endif /* _AIX */
1146
1147     /* make sure the server gets reset after the session is over */
1148     if (d->serverPid >= 2) {
1149         Debug("Reseting server:  pid %d signal %d\n",
1150               d->serverPid, d->resetSignal);
1151
1152         if (d->terminateServer == 0 && d->resetSignal)
1153             kill (d->serverPid, d->resetSignal);
1154     }
1155     else
1156         ResetServer (d);
1157
1158     Debug("Exiting Session with status:  %d\n", status);
1159     exit (status);
1160 }
1161
1162 static int 
1163 StartClient( struct verify_info *verify, struct display *d, int *pidp )
1164 {
1165     char        **f, *home;
1166     char        currentdir[PATH_MAX+1];
1167     char        *failsafeArgv[20];
1168     char        *user;                  /* users name                      */
1169     char        *lang, *font;           /* failsafe LANG and font          */
1170
1171     int pid;
1172     int         failsafe = FALSE;       /* do we run the failsafe session? */
1173     int         password = FALSE;       /* do we run /bin/passwd?          */
1174     int         i;
1175     FILE        *lastsession;
1176     char        lastsessfile[MAXPATHLEN];
1177
1178 #ifdef BLS
1179    struct pr_passwd     *b1_pwd;
1180 #endif
1181
1182 #ifdef __AFS
1183 #define NOPAG 0xffffffff
1184     long        pagval, j;
1185     long        ngroups, groups[NGROUPS];
1186 #endif /* __AFS */
1187
1188     waitType  status;
1189
1190     if (verify->argv) {
1191         Debug ("StartSession %s: ", verify->argv[0]);
1192         for (f = verify->argv; *f; f++) {
1193                 Debug ("%s ", *f);
1194                 if ( strcmp(*f, "failsafe") == 0) failsafe = TRUE;
1195                 if ( strcmp(*f, "password") == 0) failsafe = password = TRUE;
1196         }
1197         Debug ("; ");
1198     }
1199     if (verify->userEnviron) {
1200         for (f = verify->userEnviron; *f; f++)
1201                 Debug ("%s ", *f);
1202         Debug ("\n");
1203     }
1204
1205     user = getEnv (verify->userEnviron, "USER");
1206     
1207     switch (pid = fork ()) {
1208     case 0:
1209 #ifdef SIA
1210         /* Force a failsafe session if we can't touch the home directory 
1211          * SIA has already attempted to chdir to HOME, and the current dir 
1212          * will be set to / if it failed. We just check to see if the HOME
1213          * path is our current directory or not.
1214          */
1215         home = getEnv (verify->userEnviron, "HOME");
1216         getcwd(currentdir, PATH_MAX+1);
1217         Debug("Current directory is: %s\n", currentdir);
1218 #if 0
1219         /*
1220          * CDExc17917
1221          * The following little check doesn't really work.  For example,
1222          * here at the XC, NIS reports my home directory as
1223          * "/site/guests/montyb" while getcwd comes up with
1224          * "/net/nexus/site/guests/montyb".
1225          */
1226         if (strcmp(home, currentdir)) {
1227             Debug("Can't access home directory, setting failsafe to TRUE\n");
1228             failsafe = TRUE;
1229             LogError (ReadCatalog(
1230                       MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1231                       home, getEnv (verify->userEnviron, "USER"));
1232             verify->userEnviron = setEnv(verify->userEnviron, "HOME", "/");
1233         }
1234 #endif
1235 #endif /* SIA */
1236
1237         CleanUpChild ();
1238
1239         /*
1240          *  do process accounting...
1241          */
1242 #if defined(PAM) || defined(SUNAUTH)
1243         {
1244             char* ttyLine = d->gettyLine;
1245             
1246 #   ifdef DEF_NETWORK_DEV
1247             /* 
1248              * If location is not local (remote XDMCP dtlogin) and 
1249              * remote accouting is enabled (networkDev start with /dev/...)
1250              * Set tty line name to match network device for accouting.  
1251              * Unless the resource was specifically set, default is value 
1252              * of DEF_NETWORK_DEV define (/dev/dtremote) 
1253              */
1254                
1255             if ( d->displayType.location != Local && 
1256                  networkDev && !strncmp(networkDev,"/dev/",5)) {
1257                 ttyLine = networkDev+5;
1258             }
1259 #   endif 
1260
1261 #   ifdef PAM
1262             PamAccounting(verify->argv[0], d->name, d->utmpId, user, 
1263                           ttyLine, getpid(), USER_PROCESS, NULL);
1264 #   else
1265             solaris_accounting(verify->argv[0], d->name, d->utmpId, user, 
1266                                ttyLine, getpid(), USER_PROCESS, NULL);
1267 #   endif
1268         }
1269 #endif
1270
1271 #ifndef sun
1272         Account(d, user, NULL, getpid(), USER_PROCESS, status);
1273 #endif
1274
1275 #ifdef AIXV3
1276          /*
1277           * In _AIX _POWER, the PENV_NOEXEC flag was added. This tells
1278           * setpenv() to set up the user's process environment and return
1279           * without execing. This allows us to set up the process environment
1280           * and proceed to the execute() call as do the other platforms. 
1281           *
1282           * Unfortunately, for AIXV3, the PENV_NOEXEC does not exist, so
1283           * we have to pospone the setpenv() to the actual execute().
1284           */
1285
1286          /*
1287           * These defines are the tag locations in userEnviron.
1288           * IMPORTANT: changes to the locations of these tags in verify.c
1289           * must be reflected here by adjusting SYS_ENV_TAG or USR_ENV_TAG.
1290           */
1291           #define SYS_ENV_TAG 0
1292           #define USR_ENV_TAG 3
1293
1294         /*
1295          * Set the user's credentials: uid, gid, groups,
1296          * audit classes, user limits, and umask.
1297          * RK 09.13.93
1298          */
1299         if (setpcred(user, NULL) == -1)
1300         {
1301             Debug("Can't set User's Credentials (user=%s)\n",user);
1302             return (0);
1303         }
1304 #ifdef _POWER
1305         {
1306           char *usrTag, *sysTag;
1307           extern char **newenv;
1308
1309          /*
1310           * Save pointers to tags. The setpenv() function clears the pointers
1311           * to the tags in userEnviron as a side-effect.
1312           */
1313           sysTag = verify->userEnviron[SYS_ENV_TAG];
1314           usrTag = verify->userEnviron[USR_ENV_TAG];
1315
1316          /*
1317           * Set the users process environment. Store protected variables and
1318           * obtain updated user environment list. This call will initialize
1319           * global 'newenv'.
1320           */
1321           #define SESSION_PENV (PENV_INIT | PENV_ARGV | PENV_NOEXEC)
1322           if (setpenv(user, SESSION_PENV, verify->userEnviron, NULL) != 0)
1323           {
1324               Debug("Can't set process environment (user=%s)\n",user);
1325               return(0);
1326           }
1327
1328          /*
1329           * Restore pointers to tags.
1330           */
1331           verify->userEnviron[SYS_ENV_TAG] = sysTag;
1332           verify->userEnviron[USR_ENV_TAG] = usrTag;
1333
1334          /*
1335           * Free old userEnviron and replace with newenv from setpenv().
1336           */
1337           freeEnv(verify->userEnviron);
1338           verify->userEnviron = newenv;
1339         }
1340 #endif /* _POWER */
1341         
1342
1343 #endif /* AIXV3 */
1344
1345
1346
1347 #if defined(PAM)
1348         if (PamSetCred( verify->argv[0], 
1349                              user, verify->uid, verify->gid) > 0 ) {
1350             Debug("Can't set User's Credentials (user=%s)\n",user);
1351             return(0);
1352         } 
1353 #endif
1354
1355 #ifdef SUNAUTH 
1356         if ( solaris_setcred(verify->argv[0], 
1357                              user, verify->uid, verify->gid) > 0 ) {
1358             Debug("Can't set User's Credentials (user=%s)\n",user);
1359             return(0);
1360         }
1361 #endif /* SUNAUTH */
1362
1363
1364 #ifndef sun
1365
1366 #ifdef BLS
1367     /*
1368      *  HP BLS B1 session setup...
1369      *
1370      *   1. look up user's protected account information.
1371      *   2. set the session sensitivity/clearance levels 
1372      *   3. set the logical UID (LUID)
1373      */
1374
1375     if ( ISSECURE ) {
1376         Debug("BLS - Setting user's clearance, security level and luid.\n");
1377         set_auth_parameters(1, verify->argv);
1378         init_security();
1379
1380         verify->user_name = user;
1381         strncpy(verify->terminal,d->name,15);
1382         verify->terminal[15]='\0';
1383         verify->pwd = getpwnam(user);
1384
1385         if ( verify->pwd == NULL || strlen(user) == 0 ) {
1386             LogError(ReadCatalog(
1387                 MC_LOG_SET,MC_LOG_NO_BLSACCT,MC_DEF_LOG_NO_BLSACCT));
1388             exit (1);
1389         }
1390         verify->prpwd= b1_pwd = getprpwnam(user);
1391         verify->uid = b1_pwd->ufld.fd_uid;
1392     
1393         if ( b1_pwd == NULL || strlen(user) == 0 ) {
1394             LogError(ReadCatalog(
1395                 MC_LOG_SET,MC_LOG_NO_BLSPACCT,MC_DEF_LOG_NO_BLSPACCT));
1396             exit (1);
1397         }
1398
1399         /*
1400          * This has already been done successfully by dtgreet
1401          * but we need to get all the information again for the
1402          * dtlogin process.
1403          */
1404         if ( verify_user_seclevel(verify,sensitivityLevel) != 1 ) {
1405             Debug("BLS - Could not verify sensitivity level.\n");
1406             LogError(ReadCatalog(
1407                 MC_LOG_SET,MC_LOG_NO_VFYLVL,MC_DEF_LOG_NO_VFYLVL));
1408             exit (1);
1409         }
1410
1411         if ( change_to_user(verify) != 1 ) {
1412             Debug("BLS - Could not change to user: %s.\n",verify->user_name);
1413             LogError(ReadCatalog(
1414                 MC_LOG_SET,MC_LOG_NO_BLSUSR,MC_DEF_LOG_NO_BLSUSR),
1415                 verify->user_name);
1416             exit (1);
1417         }
1418
1419         Debug("BLS - Session setup complete.\n");
1420     } else {
1421 #endif /* BLS */
1422                         
1423 #ifdef __apollo
1424
1425         /* 
1426          * This should never fail since everything has been verified already.
1427          * If it does it must mean registry strangeness, so exit, and try
1428          * again...
1429          */
1430
1431         if (!DoLogin (user, greet.password, d->name)) exit (1);
1432         
1433         /*
1434          * extract the SYSTYPE and ISP environment values and set into user's 
1435          * environment. This is necessary since we do an execve below...
1436          */
1437          
1438         verify->userEnviron = setEnv(verify->userEnviron, "SYSTYPE",
1439                                      getenv("SYSTYPE"));
1440
1441         verify->userEnviron = setEnv(verify->userEnviron, "ISP",
1442                                      getenv("ISP"));
1443
1444 #else /* ! __apollo */
1445
1446
1447 #  ifdef __AFS
1448         if ( IsVerifyName(VN_AFS) ) {
1449             pagval = get_pag_from_groups(verify->groups[0], verify->groups[1]);
1450             Debug("AFS - get_pag_from_groups() returned pagval = %d\n", pagval);
1451
1452             initgroups(greet.name, verify->groups[2]);
1453             ngroups = getgroups(NGROUPS, groups);
1454             Debug("AFS - getgroups() returned ngroups = %d\n", ngroups);
1455             for (i=0; i < ngroups; i++)
1456                 Debug("AFS - groups[%d] = %d\n", i, groups[i]);
1457
1458             if ((pagval != NOPAG) &&
1459                 (get_pag_from_groups(groups[0], groups[1])) == NOPAG ) {
1460                 /* we will have to shift grouplist to make room for pag */
1461                 if (ngroups+2 > NGROUPS)
1462                     ngroups=NGROUPS-2;
1463                 for (j=ngroups-1; j >= 0; j--) {
1464                     groups[j+2] = groups[j];
1465                 }
1466                 ngroups += 2;
1467                 get_groups_from_pag(pagval, &groups[0], &groups[1]);
1468                 if (setgroups(ngroups, groups) == -1) {
1469                     LogError(
1470                         ReadCatalog(
1471                           MC_LOG_SET,MC_LOG_AFS_FAIL,MC_DEF_LOG_AFS_FAIL));
1472                     exit(1);
1473                 }
1474             }
1475         }
1476 #  else /* ! __AFS */
1477 /* If SIA is enabled, the initgroups and setgid calls are redundant
1478  * so skip them.
1479  */
1480 #  ifndef SIA
1481 #    ifdef NGROUPS
1482
1483         /*
1484          * if your system does not support "initgroups(3C)", use
1485          * the "setgroups()" call instead...
1486          */
1487          
1488 #      if (defined(__hpux) || defined(__osf__))
1489         initgroups(user, -1);
1490 #      else
1491         setgroups (verify->ngroups, verify->groups);
1492 #      endif
1493
1494 /* setpenv() will set gid for AIX */
1495 #if !defined (_AIX)
1496         setgid (verify->groups[0]);
1497 #endif
1498
1499 #    else  /* ! NGROUPS */
1500
1501 /* setpenv() will set gid for AIX */
1502 #if !defined (_AIX)
1503         setgid (verify->gid);
1504 #endif
1505
1506 #    endif /* NGROUPS */
1507 #  endif /* !SIA */
1508 #  endif /* __AFS */
1509
1510
1511 #  ifdef AUDIT
1512         setaudid(verify->audid);
1513         setaudproc(verify->audflg);
1514 #  endif
1515
1516 /* setpenv() will set uid for AIX */
1517 #if !defined(_AIX)
1518         if (setuid(verify->uid) != 0) {
1519             Debug(   "Setuid failed for user %s, errno = %d\n", user, errno);
1520             LogError(ReadCatalog(
1521                 MC_LOG_SET,MC_LOG_FAIL_SETUID,MC_DEF_LOG_FAIL_SETUID),
1522                 user,errno);
1523             exit (1);
1524         }
1525 #endif
1526
1527 #endif /* __apollo */
1528
1529 #ifdef BLS
1530     }  /* ends the else clause of if ( ISSECURE ) */
1531 #endif /* BLS */
1532
1533 #endif /* ! sun */
1534                     
1535         /*
1536          *  check home directory again...
1537          */
1538
1539 #ifndef SIA
1540 /* Don't need to do this if SIA is enabled, already been done.
1541  */
1542         home = getEnv (verify->userEnviron, "HOME");
1543         if (home) {
1544                 if (chdir (home) == -1) {
1545                         LogError (ReadCatalog(
1546                                 MC_LOG_SET,MC_LOG_NO_HMDIR,MC_DEF_LOG_NO_HMDIR),
1547                                 home, getEnv (verify->userEnviron, "USER"));
1548                         chdir ("/");
1549                         verify->userEnviron = setEnv(verify->userEnviron, 
1550                                                      "HOME", "/");
1551                 }
1552                 else if(!failsafe) {
1553                         strcpy(lastsessfile,home);                      /* save user's last session */
1554                         strcat(lastsessfile,LAST_SESSION_FILE);
1555                         if((lastsession = fopen(lastsessfile,"w")) == NULL)
1556                                 Debug("Unable to open file for writing: %s\n",lastsessfile);
1557                         else{
1558                                 fputs(verify->argv[0],lastsession);
1559                                 fclose(lastsession);
1560                          }
1561                 }
1562         }
1563 #endif
1564
1565
1566         SetUserAuthorization (d, verify);
1567
1568         /*
1569          * clear password...
1570          */
1571         if (greet.password)
1572             bzero(greet.password, strlen(greet.password));
1573
1574 #ifdef  BLS
1575         /*
1576          * Write login information to a file
1577          * The file name should really be settable by some kind of resource
1578          * but time is short so we hard-wire it to ".dtlogininfo".
1579          */
1580         if ( ! writeLoginInfo( ".dtlogininfo" , verify ) )
1581                 Debug("Unable to write \".dtlogininfo\"\n");
1582 #  ifndef NDEBUG
1583         /* extra debugging */
1584         if(!dump_sec_debug_info(verify)) {
1585             Debug("Something wrong with environment\n");
1586             exit(1);
1587         }
1588 #  endif  /* ! NDEBUG */
1589 #endif  /* BLS */
1590
1591         /*
1592          *  exec session...
1593          */
1594         if (verify->argv) {
1595             if ( !failsafe) {
1596                 Debug ("Executing session %s\n", verify->argv[0]);
1597                 execute (verify->argv, verify->userEnviron);
1598                 LogError(ReadCatalog(
1599                         MC_LOG_SET,MC_LOG_SES_EXEFAIL,MC_DEF_LOG_SES_EXEFAIL),
1600                         verify->argv[0]);
1601             }
1602         } else {
1603                 LogError(ReadCatalog(
1604                         MC_LOG_SET,MC_LOG_NO_CMDARG,MC_DEF_LOG_NO_CMDARG));
1605         }
1606         
1607         
1608
1609
1610         /*
1611          * specify a font for the multi-byte languages...
1612          */
1613             
1614         font = NULL;
1615         lang = getEnv (verify->userEnviron, "LANG");
1616
1617
1618
1619         i = 0;
1620         if ( password ) {
1621 #if defined(_AIX)
1622             failsafeArgv[i++] = "/usr/bin/X11/aixterm";
1623 #elif defined(sun)
1624             failsafeArgv[i++] = "/usr/openwin/bin/xterm";
1625 #elif defined (USL) || defined(__uxp__)
1626             failsafeArgv[i++] = "/usr/X/bin/xterm";
1627 #elif defined(__hpux)
1628             failsafeArgv[i++] = "/usr/bin/X11/hpterm";
1629 #else
1630             failsafeArgv[i++] = "/usr/bin/X11/xterm";
1631 #endif
1632             failsafeArgv[i++] = "-geometry";
1633             failsafeArgv[i++] = "80x10";
1634             failsafeArgv[i++] = "-bg";
1635             failsafeArgv[i++] = "white";
1636             failsafeArgv[i++] = "-fg";
1637             failsafeArgv[i++] = "black";
1638 #ifdef _AIX
1639             /* aixterm requires -lang option. */
1640             failsafeArgv[i++] = "-lang";
1641             failsafeArgv[i++] = lang;
1642 #else /* _AIX */
1643             failsafeArgv[i++] = "-fn";
1644
1645             if (font == NULL) font = "fixed";
1646             failsafeArgv[i++] = font;
1647 #endif /* _AIX */
1648
1649             failsafeArgv[i++] = "-e";
1650             failsafeArgv[i++] = "/bin/passwd";
1651 #if defined (__apollo) || defined(__PASSWD_ETC)
1652             failsafeArgv[i++] = "-n";
1653 #endif
1654             failsafeArgv[i++] = getEnv (verify->userEnviron, "USER");
1655         }
1656         else {
1657             failsafeArgv[i++] = d->failsafeClient;
1658 #ifdef sun 
1659             failsafeArgv[i++] = "-C";
1660 #endif
1661             failsafeArgv[i++] = "-ls";
1662
1663             if (font != NULL) {
1664                 failsafeArgv[i++] = "-fn";
1665                 failsafeArgv[i++] = font;
1666             }
1667         }
1668
1669         failsafeArgv[i] = 0;
1670         Debug ("Executing failsafe session\n", failsafeArgv[0]);
1671         execute (failsafeArgv, verify->userEnviron);
1672         exit (1);
1673     case -1:
1674         Debug ("StartSession(): fork failed\n");
1675         LogError(ReadCatalog(MC_LOG_SET,MC_LOG_NO_SESFORK,MC_DEF_LOG_NO_SESFORK),
1676                 d->name);
1677         return 0;
1678     default:
1679         Debug ("StartSession(): fork succeeded, pid = %d\n", pid);
1680         *pidp = pid;
1681
1682         return 1;
1683     }
1684 }
1685
1686 static jmp_buf  tenaciousClient;
1687
1688 static SIGVAL
1689 waitAbort( int arg )
1690 {
1691         longjmp (tenaciousClient, 1);
1692 }
1693
1694 #if defined(SYSV) || defined(SVR4)
1695 # include       <ctype.h>
1696 #define killpg(pgrp, sig) kill(-(pgrp), sig)
1697 #endif /* SYSV */
1698
1699 static int 
1700 AbortClient( int pid )
1701 {
1702     int sig = SIGTERM;
1703 #ifdef __STDC__
1704     volatile int        i;
1705 #else
1706     int i;
1707 #endif
1708     int retId;
1709     for (i = 0; i < 4; i++) {
1710         if (killpg (pid, sig) == -1) {
1711             switch (errno) {
1712             case EPERM:
1713                 LogError(ReadCatalog(
1714                         MC_LOG_SET,MC_LOG_NO_KILLCL,MC_DEF_LOG_NO_KILLCL));
1715             case EINVAL:
1716             case ESRCH:
1717                 return;
1718             }
1719         }
1720         if (!setjmp (tenaciousClient)) {
1721             (void) signal (SIGALRM, waitAbort);
1722             (void) alarm ((unsigned) 10);
1723             retId = wait ((waitType *) 0);
1724             (void) alarm ((unsigned) 0);
1725             (void) signal (SIGALRM, SIG_DFL);
1726             if (retId == pid)
1727                 break;
1728         } else
1729             signal (SIGALRM, SIG_DFL);
1730         sig = SIGKILL;
1731     }
1732 }
1733
1734 int 
1735 source( struct verify_info *verify, char *file )
1736 {
1737     char        *args[2];
1738     int         pid;
1739     waitType    result;
1740
1741     if (file && file[0]) {
1742         Debug ("Source(): %s\n", file);
1743         switch (pid = fork ()) {
1744         case 0:
1745             CleanUpChild ();
1746             args[0] = file;
1747             args[1] = NULL;
1748             execute (args, verify->systemEnviron);
1749             LogError(ReadCatalog(
1750                 MC_LOG_SET,MC_LOG_NO_EXE,MC_DEF_LOG_NO_EXE),args[0]);
1751             exit (1);
1752         case -1:
1753             Debug ("Source(): fork failed\n");
1754             LogError(ReadCatalog(
1755                 MC_LOG_SET,MC_LOG_NO_FORK,MC_DEF_LOG_NO_FORK),file);
1756             return 1;
1757             break;
1758         default:
1759             while (wait (&result) != pid)
1760                     ;
1761             break;
1762         }
1763         return waitVal (result);
1764     }
1765     return 0;
1766 }
1767
1768 int 
1769 execute(char **argv, char **environ )
1770 {
1771
1772     /*
1773      *  make stdout follow stderr to the log file...
1774      */
1775
1776     dup2 (2,1);
1777     
1778     session_execve (argv[0], argv, environ);
1779
1780     /*
1781      * In case this is a shell script which hasn't been made executable
1782      * (or this is a SYSV box), do a reasonable thing...
1783      */
1784
1785 #ifdef _AIX
1786     /* errno is EACCES if not executable */
1787     if (errno == ENOEXEC || errno == EACCES) {
1788 #else /* _AIX */
1789     if (errno == ENOEXEC) {
1790 #endif /* _AIX */
1791         char    program[1024], *e, *p, *optarg;
1792         FILE    *f;
1793         char    **newargv, **av;
1794         int     argc;
1795
1796         /*
1797          * emulate BSD kernel behaviour -- read
1798          * the first line; check if it starts
1799          * with "#!", in which case it uses
1800          * the rest of the line as the name of
1801          * program to run.  Else use "/bin/sh".
1802          */
1803         f = fopen (argv[0], "r");
1804         if (!f)
1805             return;
1806         if (fgets (program, sizeof (program) - 1, f) == NULL)
1807         {
1808             fclose (f);
1809             return;
1810         }
1811         fclose (f);
1812         e = program + strlen (program) - 1;
1813         if (*e == '\n')
1814             *e = '\0';
1815         if (!strncmp (program, "#!", 2)) {
1816             p = program + 2;
1817             while (*p && isspace (*p))
1818                 ++p;
1819             optarg = p;
1820             while (*optarg && !isspace (*optarg))
1821                 ++optarg;
1822             if (*optarg) {
1823                 *optarg = '\0';
1824                 do
1825                     ++optarg;
1826                 while (*optarg && isspace (*optarg));
1827             } else
1828                 optarg = 0;
1829         } else {
1830             p = "/bin/sh";
1831             optarg = 0;
1832         }
1833         Debug ("Shell script execution: %s (optarg %s)\n",
1834                 p, optarg ? optarg : "(null)");
1835         for (av = argv, argc = 0; *av; av++, argc++)
1836                 ;
1837         newargv = (char **) malloc ((argc + (optarg ? 3 : 2)) * sizeof (char *));
1838         if (!newargv)
1839             return -1;
1840         av = newargv;
1841         *av++ = p;
1842         if (optarg)
1843             *av++ = optarg;
1844         while (*av++ = *argv++)
1845             ;
1846         session_execve (newargv[0], newargv, environ);
1847     }
1848 }
1849
1850
1851
1852
1853 /*****************************************************************************
1854 *    RunGreeter
1855 *    
1856 *    Invoke the Greeter process and wait for completion. If the user was 
1857 *    successfully verified, return to the calling process. If the user
1858 *    selected a restart or abort option, or there was an error invoking the
1859 *    Greeter, exit this entire process with appropriate status.
1860 *
1861 *****************************************************************************/
1862
1863 #define MSGSIZE 512
1864
1865 extern int session_set; 
1866 extern char *progName;  /* Global argv[0]; dtlogin name and path */
1867
1868 int         response[2], request[2];
1869
1870 /* Fixes problem with dtlogin signal handling */
1871 static int greeterPid = 0;
1872 static struct display *greeter_d = NULL;
1873
1874 static SIGVAL
1875 catchHUP(int arg)
1876 {
1877     Debug("Caught SIGHUP\n");
1878     if (greeterPid) 
1879     {
1880         Debug("Killing greeter process:  %d\n", greeterPid);
1881         kill(greeterPid, SIGHUP);
1882     }
1883     if (greeter_d)
1884       SessionExit(greeter_d, REMANAGE_DISPLAY);
1885     else
1886       exit(REMANAGE_DISPLAY);
1887 }
1888
1889 static void 
1890 RunGreeter( struct display *d, struct greet_info *greet,
1891             struct verify_info *verify )
1892 {
1893
1894     int       pid;
1895     waitType    status;
1896     
1897     int         rbytes;
1898     static char msg[MSGSIZE];
1899     char        *p;
1900     char        **env;
1901     char        *path;
1902     struct greet_state state;
1903     int         notify_dt;
1904
1905 #ifdef __PASSWD_ETC
1906 #  ifndef U_NAMELEN
1907 #    define U_NAMELEN   sizeof(rgy_$name_t)
1908 #  endif
1909
1910     int i;
1911     static char name_short[U_NAMELEN];
1912 #endif
1913
1914 #ifdef SIA
1915
1916     int argc = 1;
1917     char *argv[] = { "dtlogin", 0 };
1918     char *hostName = NULL;
1919     char *loginName = NULL;
1920     int siaStatus = -1;
1921
1922     /*
1923      * Initialize SIA
1924      */
1925     
1926     if (d->serverPid == -1)
1927       hostName = d->name;
1928
1929     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
1930                               loginName, d->name, 1, NULL);
1931     if (siaStatus != SIASUCCESS)
1932       {
1933       Debug("sia_ses_init failure status %d\n", siaStatus);
1934       exit(1);
1935       }
1936
1937 #endif
1938
1939     greeterPid = 0;
1940     if (!setjmp (abortSession)) {
1941         signal(SIGTERM, catchTerm);
1942
1943         /*
1944          * We've changed dtlogin to pass HUP's down to the children
1945          * so ignore any HUP's once the client has started.
1946          */
1947         greeter_d = d;
1948         signal(SIGHUP, catchHUP);
1949
1950         /*
1951          *  set up communication pipes...
1952          */
1953          
1954         pipe(response);
1955         pipe(request);
1956         rbytes = 0;
1957
1958
1959         switch (greeterPid = fork ()) {
1960         case 0:
1961
1962             /*
1963              *  pass some information in the environment...
1964              */
1965                    
1966             env = 0;
1967             sprintf(msg,"%d", d->grabServer);
1968             env = setEnv(env, GRABSERVER,  msg);
1969         
1970             sprintf(msg,"%d", d->grabTimeout);
1971             env = setEnv(env, GRABTIMEOUT, msg);
1972
1973
1974             if (timeZone && strlen(timeZone) > 0 )
1975                 env = setEnv(env, "TZ", timeZone);
1976
1977             if (errorLogFile && errorLogFile[0])
1978                 env = setEnv(env, ERRORLOG,  errorLogFile);
1979
1980             if (d->authFile)
1981                 env = setEnv(env, "XAUTHORITY", d->authFile);
1982
1983             if (d->dtlite)
1984                 env = setEnv(env, DTLITE,  "True");
1985
1986             if (d->session)  
1987                 env = setEnv(env, SESSION,  d->session);
1988
1989             if(session_set)
1990                 env = setEnv(env, SESSION_SET, "True");
1991
1992             if (d->pmSearchPath)
1993                 env = setEnv(env, "XMICONSEARCHPATH", d->pmSearchPath);
1994
1995             if (d->bmSearchPath)
1996                 env = setEnv(env, "XMICONBMSEARCHPATH", d->bmSearchPath);
1997
1998 #if defined (__KERBEROS) || defined (__AFS)
1999             if (d->verifyName) {
2000                 if ( (strcmp(d->verifyName, VN_AFS) == 0) ||
2001                      (strcmp(d->verifyName, VN_KRB) == 0)    ) {
2002                      
2003                     env = setEnv(env, VERIFYNAME, d->verifyName );
2004                 }
2005                 else {
2006                     LogError(ReadCatalog(
2007                         MC_LOG_SET,MC_LOG_IMPROP_AUTH,MC_DEF_LOG_IMPROP_AUTH),
2008                         d->verifyName);
2009                     d->verifyName = NULL;
2010                 }
2011             }
2012 #endif
2013                         
2014             if((path = getenv("NLSPATH")) != NULL)
2015                 env = setEnv(env, "NLSPATH", path);
2016 #ifdef __hp_osf
2017             env = setEnv(env, "NLSPATH", "/usr/lib/nls/msg/%L/%N.cat");
2018 #endif
2019
2020             
2021             /*
2022              *  ping remote displays...
2023              *
2024              */
2025
2026             if (d->displayType.location == Local) {
2027                 GettyRunning(d); /* refresh gettyState */
2028                 if (d->gettyState != DM_GETTY_USER)
2029                     env = setEnv(env, LOCATION, "local");
2030             }
2031             else {
2032                 sprintf(msg,"%d", d->pingInterval);
2033                 env = setEnv(env, PINGINTERVAL,  msg);
2034         
2035                 sprintf(msg,"%d", d->pingTimeout);
2036                 env = setEnv(env, PINGTIMEOUT, msg);
2037             }
2038
2039
2040             if ( d->langList && strlen(d->langList) > 0 )
2041                 env = setEnv(env, LANGLIST,  d->langList);
2042 #if !defined (ENABLE_DYNAMIC_LANGLIST)
2043             else if (languageList && strlen(languageList) > 0 )
2044                 env = setEnv(env, LANGLIST, languageList);
2045 #endif /* ENABLE_DYNAMIC_LANGLIST */
2046
2047             {
2048                 char *language = NULL;
2049
2050 #if defined (ENABLE_DYNAMIC_LANGLIST)
2051                 language = d->language;
2052 #endif /* ENABLE_DYNAMIC_LANGLIST */
2053
2054                 if ( d->language && strlen(d->language) > 0 )
2055                   env = setLang(d, env, language);
2056             }
2057
2058             if((path = getenv("XKEYSYMDB")) != NULL)
2059                 env = setEnv(env, "XKEYSYMDB", path);
2060
2061 #ifdef sun
2062             if((path = getenv("OPENWINHOME")) != NULL)
2063                 env = setEnv(env, "OPENWINHOME", path);
2064 #endif
2065
2066 #ifdef __apollo
2067             /*
2068              *  set environment for Domain machines...
2069              */
2070             env = setEnv(env, "ENVIRONMENT", "bsd");
2071             env = setEnv(env, "SYSTYPE", "bsd4.3");
2072 #endif
2073                 
2074
2075             Debug ("Greeter environment:\n");
2076             printEnv(env);
2077             Debug ("End of Greeter environment:\n");
2078
2079            /*
2080             * Writing to file descriptor 1 goes to response pipe instead.
2081             */
2082             close(1);
2083             dup(response[1]);
2084             close(response[0]);
2085             close(response[1]);
2086
2087            /*
2088             * Reading from file descriptor 0 reads from request pipe instead.
2089             */
2090             close(0);
2091             dup(request[0]);
2092             close(request[0]);
2093             close(request[1]);
2094
2095             CleanUpChild ();
2096
2097             /*
2098              * figure out path to dtgreet...
2099              */
2100
2101             strcpy(msg, progName);
2102     
2103             if ((p = (char *) strrchr(msg, '/')) == NULL)
2104                 strcpy(msg,"./");
2105             else
2106                 *(++p) = NULL;
2107
2108             strcat(msg,"dtgreet");
2109
2110             execle(msg, "dtgreet", "-display", d->name, (char *)0, env);
2111             LogError(ReadCatalog(
2112                 MC_LOG_SET,MC_LOG_NO_DTGREET,MC_DEF_LOG_NO_DTGREET),
2113                  msg, d->name);
2114             exit (NOTIFY_ABORT_DISPLAY);
2115
2116         case -1:
2117             Debug ("Fork of Greeter failed.\n");
2118             LogError(ReadCatalog(
2119                 MC_LOG_SET,MC_LOG_NO_FORKCG,MC_DEF_LOG_NO_FORKCG),d->name);
2120             close(request[0]);
2121             close(request[1]);
2122             close(response[0]);
2123             close(response[1]);
2124             exit (UNMANAGE_DISPLAY);
2125
2126         default:
2127             Debug ("Greeter started\n");
2128
2129             close(response[1]); /* Close write end of response pipe */
2130             close(request[0]); /* Close read end of request pipe */
2131
2132
2133             /*
2134              * Retrieve information from greeter and authenticate.
2135              */
2136             globalDisplayName = d->name;
2137             state.id = GREET_STATE_ENTER;
2138             state.waitForResponse = FALSE;
2139 #ifdef SIA
2140            
2141             /*
2142              * atexit() registers this function to be called if exit() is
2143              * called.  This is needed because in enhanced security mode, SIA
2144              * may call exit() whn the user fails to enter or change a
2145              * password.
2146              */
2147             sia_greeter_pid = greeterPid;
2148             if (!sia_exit_proc_reg)
2149                 {
2150                 atexit(KillGreeter);
2151                 sia_exit_proc_reg = TRUE;
2152                 }
2153   
2154             siaGreeterInfo.d = d;
2155             siaGreeterInfo.greet = greet;
2156             siaGreeterInfo.verify = verify;
2157             siaGreeterInfo.state = &state;
2158             siaGreeterInfo.status = TRUE;
2159   
2160             siaStatus =  -1;
2161             while(siaStatus != SIASUCCESS)
2162                 {
2163                 while(siaStatus != SIASUCCESS && siaGreeterInfo.status)
2164                     {
2165                     Debug ("RunGreeter: before sia_ses_authent\n");
2166                     dt_in_sia_ses_authent = True;
2167                     siaStatus = sia_ses_authent(SiaManageGreeter, NULL, 
2168                                                 siaHandle);
2169                     dt_in_sia_ses_authent = False;
2170                     Debug ("RunGreeter: after sia_ses_authent status = %d\n",
2171                                 siaStatus);
2172                     if (siaStatus == SIAFAIL && siaGreeterInfo.status)
2173                         {
2174                         state.id = GREET_STATE_ERRORMESSAGE;
2175                         state.vf = VF_INVALID;
2176                         ManageGreeter(d, greet, verify, &state);
2177                         }
2178                     if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2179                         break;
2180                     }
2181                 if (!siaGreeterInfo.status || siaStatus == SIASTOP)
2182                     {
2183                     sia_ses_release(&siaHandle);
2184                     break;
2185                     }
2186   
2187                 Debug("RunGreeter: before sia_ses_estab\n");
2188                 siaStatus = sia_ses_estab(SiaManageGreeter, siaHandle);
2189                 Debug ("RunGreeter: after sia_ses_estab status = %d\n",
2190                                 siaStatus);
2191   
2192                 if (!siaGreeterInfo.status)
2193                     break;
2194   
2195                 if (siaStatus == SIASUCCESS)
2196                     {
2197                     Debug("RunGreeter: before sia_ses_launch\n");
2198                     siaStatus = sia_ses_launch(SiaManageGreeter, siaHandle);
2199                     Debug("RunGreeter: after sia_ses_launch status = %d\n",
2200                                 siaStatus);
2201                     }
2202                 if (!siaGreeterInfo.status)
2203                     break;
2204   
2205                 if (siaStatus != SIASUCCESS)
2206                     {
2207                     Debug("RunGreeter: sia_ses_launch failure\n");
2208                     /* establish & launch failures do a release */
2209                     siaHandle = NULL;
2210                     siaStatus = sia_ses_init(&siaHandle, argc, argv, hostName, 
2211                                                 loginName, d->name, 1, NULL);
2212                     if (siaStatus != SIASUCCESS)
2213                         {
2214                         Debug("sia_ses_init failure status %d\n", siaStatus);
2215                         exit(RESERVER_DISPLAY);
2216                         }
2217                     }
2218                 }
2219             /*
2220              * sia_ses_launch() wil probably seteuid to that of the
2221              * user, but we don't want that now.
2222              */
2223             seteuid(0);
2224             /*
2225              * extract necessary info from SIA context struct
2226              */
2227             if (siaHandle)
2228                 {
2229                 if (siaStatus == SIASUCCESS)
2230                     CopySiaInfo(siaHandle, greet);
2231                 sia_ses_release(&siaHandle);
2232                 }
2233             state.id = GREET_STATE_TERMINATEGREET;
2234             if (siaGreeterInfo.status)
2235                 {
2236                 while (ManageGreeter(d, greet, verify, &state))
2237                   ;
2238                 }
2239             sia_greeter_pid = 0;
2240 #else
2241             while (ManageGreeter(d, greet, verify, &state))
2242               ;
2243 #endif /* SIA */
2244
2245             /*
2246              * Wait for Greeter to end...
2247              */
2248             for (;;) {
2249                 pid = wait (&status);
2250                 if (pid == greeterPid)
2251                     break;
2252             }
2253
2254
2255             /*
2256              *  Greeter exited. Check return code...
2257              */
2258              
2259             Debug("Greeter return status; exit = %d, signal = %d\n", 
2260                    waitCode(status), waitSig(status));
2261
2262
2263             /*
2264              * remove authorization file if used...
2265              */
2266      
2267             if (d->authorizations && d->authFile &&
2268                 waitVal(status) != NOTIFY_LANG_CHANGE
2269 #ifdef BLS
2270                 && waitVal(status) != NOTIFY_BAD_SECLEVEL
2271 #endif
2272                ) {
2273
2274 /***
2275                 Debug ("Done with authorization file %s, removing\n",
2276                         d->authFile);
2277                 (void) unlink (d->authFile);
2278 ***/
2279             }
2280
2281
2282                 if(waitVal(status) > NOTIFY_ALT_DTS) 
2283                       d->sessionType = waitVal(status);
2284
2285
2286             switch (waitVal(status)) {
2287             case NOTIFY_FAILSAFE:
2288                 greet->string = "failsafe";
2289                 break;
2290             case NOTIFY_PASSWD_EXPIRED:
2291                 greet->string = "password";
2292                 break;
2293             case NOTIFY_DTLITE:
2294             case NOTIFY_DT:
2295             case NOTIFY_OK:
2296             case NOTIFY_LAST_DT:
2297                 d->sessionType = waitVal(status);
2298                 break;
2299             default:
2300                 break;
2301             }
2302
2303           Debug("waitVal - status is  %d\n", waitVal(status));
2304            if(waitVal(status) > NOTIFY_ALT_DTS)
2305                 notify_dt = NOTIFY_ALT_DTS; /* It is alt desktops */
2306             else
2307                 notify_dt = waitVal(status);
2308
2309             switch (notify_dt) {
2310             case NOTIFY_FAILSAFE:
2311             case NOTIFY_PASSWD_EXPIRED:
2312             case NOTIFY_DTLITE:
2313             case NOTIFY_DT:
2314             case NOTIFY_OK:
2315             case NOTIFY_LAST_DT:
2316             case NOTIFY_ALT_DTS:
2317
2318                if (NULL == greet->name) return;
2319
2320                /*
2321                 *  greet->name, greet->password set in ManageGreeter().
2322                 */
2323                 Debug("Greeter returned name '%s'\n", greet->name);
2324
2325 #ifdef __PASSWD_ETC
2326                 greet->name_full = greet->name;
2327                            /* get just person name out of full SID */
2328                 i = 0;
2329                 while (i < sizeof(rgy_$name_t) 
2330                      && greet->name_full[i] != '.'
2331                      && greet->name_full[i] != '\0') {
2332                      name_short[i] = greet->name_full[i];
2333                      i++;
2334                 }
2335                 name_short[i] = '\0';
2336                 greet->name = name_short;
2337 #endif
2338                     
2339 #ifdef __AFS
2340                /*
2341                 * groups[] set in Authenticate().
2342                 */
2343                 if ( IsVerifyName(VN_AFS) ) {
2344                   verify->groups[0] = groups[0];
2345                   verify->groups[1] = groups[1];
2346                   Debug("Greeter returned groups[0] '%d'\n", verify->groups[0]);
2347                   Debug("Greeter returned groups[1] '%d'\n", verify->groups[1]);
2348                 }
2349 #endif
2350                     
2351 #ifdef BLS
2352                /*
2353                 * sensitivityLevel set in BLS_Verify()
2354                 */
2355                 greet->b1security = sensitivityLevel;
2356 #endif
2357
2358                 Verify(d, greet, verify);
2359                 return;
2360
2361             case NOTIFY_ABORT:
2362                 Debug ("Greeter Xlib error or SIGTERM\n");
2363                 SessionExit(d, OPENFAILED_DISPLAY);
2364
2365             case NOTIFY_RESTART:
2366                 Debug ("Greeter requested RESTART_DISPLAY\n");
2367                 SessionExit(d, RESERVER_DISPLAY);
2368
2369             case NOTIFY_ABORT_DISPLAY:
2370                 Debug ("Greeter requested UNMANAGE_DISPLAY\n");
2371                 SessionExit(d, UNMANAGE_DISPLAY);
2372
2373             case NOTIFY_NO_WINDOWS:
2374                 Debug ("Greeter requested NO_WINDOWS mode\n");
2375                 if (d->serverPid >= 2)
2376                     /*
2377                      *  Don't do a SessionExit() here since that causes
2378                      *  the X-server to be reset. We know we are going to
2379                      *  terminate it anyway, so just go do that...
2380                      */
2381                     exit(SUSPEND_DISPLAY);
2382                 else
2383                     return;
2384
2385             case NOTIFY_LANG_CHANGE:
2386                 Debug ("Greeter requested LANG_CHANGE\n");
2387
2388                /*
2389                 * copy requested language into display struct "d". Note,
2390                 * this only happens in this child's copy of "d", not in
2391                 * the master struct. When the user logs out, the
2392                 * resource-specified language (if any) will reactivate.
2393                 */
2394                 Debug("Greeter returned language '%s'\n", d->language);
2395
2396                 if (strcmp(d->language, "default") == 0) {
2397                     int len = strlen(defaultLanguage) + 1;
2398                     d->language = (d->language == NULL  ?
2399                                    malloc(len) : realloc (d->language, len));
2400                     strcpy(d->language, defaultLanguage);
2401                 }
2402                 return;
2403 #ifdef  BLS
2404             case NOTIFY_BAD_SECLEVEL:
2405                 return;
2406 #endif
2407             case waitCompose (SIGTERM,0,0):
2408                 Debug ("Greeter exited on SIGTERM\n");
2409                 SessionExit(d, OPENFAILED_DISPLAY);
2410                 
2411             default:
2412                 Debug ("Greeter returned unknown status %d\n", 
2413                         waitVal(status));
2414                 SessionExit(d, REMANAGE_DISPLAY);
2415             }
2416         }
2417         signal(SIGHUP, SIG_DFL);
2418     }
2419     else {
2420         AbortClient(greeterPid);
2421         SessionExit(d, UNMANAGE_DISPLAY);
2422     }
2423 }
2424
2425 /*****************************************************************************
2426 * ManageGreeter
2427  
2428   State transitions
2429  
2430   enter -> ENTER: 
2431     This is the entry into greeter state processing. Allocate and initialize
2432     state structure.
2433
2434   ENTER -> LOGIN:
2435     Display the login screen. Upon display, the login screen can be 'reset'. If
2436     reset is true, the username and password fields are cleared and the focus
2437     is set to the username field. If reset is false, the username and password
2438     field is untouched and the focus is set to the password field.
2439
2440   LOGIN -> AUTHENTICATE:
2441     Authenticate the username entered on login screen. 
2442
2443   AUTHENTICATE -> TERMINATEGREET:
2444     User passed authentication so terminate the greeter.
2445
2446   AUTHENTICATE -> EXPASSWORD: 
2447     User passed authentication, but the their password has expired.
2448     Display old password message. This message allows the user to 
2449     change their password by starting a getty and running passwd(1).  
2450
2451   AUTHENTICATE -> BAD_HOSTNAME:
2452     User passed authentication, but the their hostname is empty.
2453     Display a dialog that allows the user to run a getty to fix the
2454     problem, or start the desktop anyway.
2455
2456   AUTHENTICATE -> ERRORMESSAGE:
2457     User failed authentication, so display error message. 
2458
2459   AUTHENTICATE -> LOGIN
2460     User failed authentication, but did not enter a password. Instead
2461     of displaying an error message, redisplay the login screen with
2462     the focus set to the password field. If the user authenticates again
2463     without the password field set, display an error. This allows a user
2464     to type the ubiquitous "username<ENTER>password<ENTER>" sequence.
2465
2466   EXIT -> exit
2467     Free state structure and return false to stop state transitions.
2468
2469   ERRORMESSAGE -> LOGIN
2470     Display error message base on return code from last authentication
2471     attempt. Redisplay login screen with reset set to true.
2472
2473   (state) -> LANG -> (state)
2474     User has chosen a new language. Transition to LANG state to save off
2475     the new language, and transition back to original state. 
2476   
2477 *****************************************************************************/
2478
2479 #define SETMC(M, ID) M.id = MC_##ID; M.def = MC_DEF_##ID
2480
2481 static int
2482 ManageGreeter( struct display *d, struct greet_info *greet,
2483             struct verify_info *verify, struct greet_state *state )
2484 {
2485   struct {
2486     int id;
2487     char *def;
2488   } msg;
2489
2490   if (state->waitForResponse)
2491   {
2492     if (!AskGreeter(NULL, (char *)state->response, REQUEST_LIM_MAXLEN))
2493     {
2494      /*
2495       * Dtgreet has terminated. 
2496       */
2497       state->id = GREET_STATE_EXIT;
2498       state->waitForResponse = FALSE;
2499       return(TRUE);
2500     }
2501
2502     if (state->request->opcode != state->response->opcode)
2503     {
2504      /*
2505       * An unrequested event arrived. See if it's one we
2506       * are expecting.
2507       */
2508       switch(state->response->opcode)
2509       {
2510         case REQUEST_OP_LANG:
2511           {
2512            /*
2513             * User has changed language. Recursively handle this state
2514             * and return to current state.
2515             */
2516             struct greet_state lang_state;
2517
2518             lang_state = *state;
2519             lang_state.id = GREET_STATE_LANG;
2520             lang_state.waitForResponse = FALSE;
2521             ManageGreeter(d, greet, verify, &lang_state);
2522             Debug("Response opcode REQUEST_OP_LANG\n");
2523             return(TRUE);
2524           }
2525           break;
2526
2527         case REQUEST_OP_CLEAR:
2528           {
2529            /*
2530             * User has requested the screen be cleared.
2531             */
2532             state->id = GREET_STATE_USERNAME;
2533             state->waitForResponse = TRUE;
2534             Debug("Response opcode REQUEST_OP_CLEAR\n");
2535           }
2536           break;
2537     
2538         default:
2539           Debug("Response opcode UNEXPECTED RESPONSE!\n");
2540 #ifndef SIA
2541           return(TRUE);
2542 #endif
2543           break;
2544       }
2545     }
2546     else
2547     {
2548      /*
2549       * Got the response we were expecting.
2550       */
2551       state->waitForResponse = FALSE;
2552     }
2553   }
2554
2555   switch(state->id)
2556   {
2557     case GREET_STATE_ENTER:
2558       {
2559        /*
2560         * Enter - initialize state
2561         */
2562         Debug("GREET_STATE_ENTER\n");
2563
2564         state->request = (RequestHeader *)malloc(REQUEST_LIM_MAXLEN);
2565         state->response= (ResponseHeader *)malloc(REQUEST_LIM_MAXLEN);
2566         state->authenticated = FALSE;
2567         state->msg = NULL;
2568
2569         state->id = GREET_STATE_USERNAME;
2570       }
2571       break;
2572
2573     case GREET_STATE_USERNAME:
2574       {
2575        /*
2576         * Get user name
2577         */
2578         RequestChallenge *r;
2579
2580         Debug("GREET_STATE_USERNAME\n");
2581
2582         Authenticate(d, NULL, NULL, NULL);
2583
2584         SETMC(msg, LOGIN_LABEL);
2585
2586         r = (RequestChallenge *)state->request;
2587         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2588         r->hdr.reserved = 0;
2589         r->bEcho = TRUE;
2590         r->idMC = msg.id;
2591         r->hdr.length = sizeof(*r);
2592
2593         r->offChallenge = sizeof(*r);
2594         strcpy(((char *)r) + r->offChallenge, msg.def);
2595         r->hdr.length += strlen(msg.def) + 1;
2596
2597         if (greet->name)
2598         {
2599           r->offUserNameSeed = r->hdr.length;
2600           strcpy(((char *)r) + r->offUserNameSeed, greet->name);
2601           r->hdr.length += strlen(greet->name) + 1;
2602           Debug("Greet name:  %s\n", greet->name);
2603         }
2604         else
2605         {
2606           r->offUserNameSeed = 0;
2607         }
2608
2609         if (greet->name)
2610         {
2611           free(greet->name); greet->name = NULL;
2612         }
2613         if (greet->password)
2614         {
2615           free(greet->password); greet->password = NULL;
2616         }
2617
2618         TellGreeter((RequestHeader *)r);
2619         state->waitForResponse = TRUE;
2620
2621         state->id = GREET_STATE_AUTHENTICATE;
2622       }
2623       break;
2624
2625     case GREET_STATE_CHALLENGE:
2626       {
2627        /*
2628         * Get user name
2629         */
2630         RequestChallenge *r;
2631
2632         Debug("GREET_STATE_CHALLENGE\n");
2633
2634         if (greet->password)
2635         {
2636           free(greet->password); greet->password = NULL;
2637         }
2638
2639         SETMC(msg, PASSWD_LABEL);
2640
2641         r = (RequestChallenge *)state->request;
2642         r->hdr.opcode = REQUEST_OP_CHALLENGE;
2643         r->hdr.reserved = 0;
2644         r->bEcho = FALSE;
2645         r->idMC = msg.id;
2646         r->offUserNameSeed = 0;
2647         r->offChallenge = sizeof(*r);
2648         strcpy(((char *)r) + r->offChallenge, msg.def);
2649         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2650
2651         TellGreeter((RequestHeader *)r);
2652         state->waitForResponse = TRUE;
2653
2654         state->id = GREET_STATE_AUTHENTICATE;
2655       }
2656       break;
2657
2658     case GREET_STATE_AUTHENTICATE:
2659       {
2660        /*
2661         * Attempt to authenticate.
2662         */
2663         ResponseChallenge *r;
2664    
2665         Debug("GREET_STATE_AUTHENTICATE\n"); 
2666
2667         r = (ResponseChallenge *)state->response;
2668      
2669         if (greet->name == NULL)
2670         {
2671           greet->name = strdup(((char *)r) + r->offResponse);
2672           if (strlen(greet->name) == 0)
2673           {
2674             state->id = GREET_STATE_USERNAME;
2675             break;
2676           }
2677         }
2678         else 
2679         { 
2680           greet->password = strdup(((char *)r) + r->offResponse);
2681         }
2682
2683         if (state->msg)
2684         {
2685           free(state->msg);
2686           state->msg = NULL;
2687         }
2688
2689        /*
2690         * Attempt to authenticate user. 'username' should be a 
2691         * non-empty string. 'password' may be an empty string.
2692         */
2693         state->vf = Authenticate(d, greet->name, greet->password, &state->msg);
2694
2695         if (state->vf == VF_OK || 
2696             state->vf == VF_PASSWD_AGED || 
2697             state->vf == VF_BAD_HOSTNAME)
2698         {
2699           state->authenticated = TRUE;
2700         }
2701
2702        /*
2703         * General transitions.
2704         */
2705         switch (state->vf)
2706         {
2707           case VF_OK:           state->id = GREET_STATE_TERMINATEGREET; break; 
2708           case VF_PASSWD_AGED:  state->id = GREET_STATE_EXPASSWORD; break; 
2709           case VF_BAD_HOSTNAME: state->id = GREET_STATE_BAD_HOSTNAME; break; 
2710           case VF_CHALLENGE:    state->id = GREET_STATE_CHALLENGE; break; 
2711           default:              state->id = GREET_STATE_ERRORMESSAGE; break; 
2712         }
2713       }
2714       break;
2715
2716     case GREET_STATE_EXIT: 
2717       {
2718        /*
2719         * Free resources and leave.
2720         */
2721         Debug("GREET_STATE_EXIT\n");
2722
2723         if (state->msg)
2724         {
2725           free(state->msg);
2726         }
2727  
2728         if (!state->authenticated)
2729         {
2730           if (greet->name)
2731           {
2732             free(greet->name); greet->name = NULL;
2733           }
2734           if (greet->password)
2735           {
2736             free(greet->password); greet->password = NULL;
2737           }
2738         }
2739
2740         free(state->request);
2741         free(state->response);
2742         return(FALSE);
2743       }
2744       break;
2745
2746     case GREET_STATE_ERRORMESSAGE:
2747       {
2748        /* 
2749         * Display error message.
2750         */
2751         RequestMessage *r;
2752
2753         Debug("GREET_STATE_ERRORMESSAGE\n");
2754
2755         r = (RequestMessage *)state->request;
2756
2757         switch(state->vf)
2758         {
2759           case VF_INVALID:       SETMC(msg, LOGIN); break;
2760           case VF_HOME:          SETMC(msg, HOME); break;
2761           case VF_MAX_USERS:     SETMC(msg, MAX_USERS); break;
2762           case VF_BAD_UID:       SETMC(msg, BAD_UID); break;
2763           case VF_BAD_GID:       SETMC(msg, BAD_GID); break;
2764           case VF_BAD_AID:       SETMC(msg, BAD_AID); break;
2765           case VF_BAD_AFLAG:     SETMC(msg, BAD_AFLAG); break;
2766           case VF_NO_LOGIN:      SETMC(msg, NO_LOGIN); break;
2767 #ifdef BLS
2768           case VF_BAD_SEN_LEVEL: SETMC(msg, BAD_SEN_LEVEL); break;
2769 #endif
2770           case VF_MESSAGE: msg.id=0; msg.def=state->msg; break;
2771           default: msg.id=0; msg.def=""; break;
2772         }
2773
2774         r->hdr.opcode = REQUEST_OP_MESSAGE;
2775         r->hdr.reserved = 0;
2776         r->idMC = msg.id;
2777         r->offMessage = sizeof(*r);
2778         strcpy(((char *)r) + r->offMessage, msg.def);
2779         r->hdr.length = sizeof(*r) + strlen(msg.def) + 1;
2780
2781         TellGreeter((RequestHeader *)r);
2782         state->waitForResponse = TRUE;
2783
2784         state->id = GREET_STATE_USERNAME;
2785       }
2786       break;
2787
2788     case GREET_STATE_LANG:
2789       {
2790        /*
2791         * User selected new language.
2792         */
2793         ResponseLang *r;
2794         char *lang;
2795         int len;
2796
2797         Debug("GREET_STATE_LANG\n");
2798
2799         r = (ResponseLang *)state->response;
2800         lang = ((char *)r) + r->offLang;
2801         len = strlen(lang) + 1;
2802
2803         d->language = (d->language == NULL ?
2804                        malloc(len) : realloc(d->language, len));
2805         strcpy(d->language, lang);
2806         Debug("Language returned:  %s\n", d->language);
2807       }
2808       break;
2809
2810     case GREET_STATE_TERMINATEGREET:
2811       {
2812        /*
2813         * Terminate dtgreet.
2814         */
2815         RequestExit *r;
2816
2817         Debug("GREET_STATE_TERMINATEGREET\n");
2818
2819         r = (RequestExit *)state->request;
2820
2821         r->hdr.opcode = REQUEST_OP_EXIT;
2822         r->hdr.reserved = 0;
2823         r->hdr.length = sizeof(*r);
2824
2825         TellGreeter((RequestHeader *)r);
2826         state->waitForResponse = TRUE;
2827
2828         state->id = GREET_STATE_EXIT;
2829       }
2830       break;
2831
2832     case GREET_STATE_EXPASSWORD:
2833       {
2834        /*
2835         * Display password expired message.
2836         */
2837         RequestExpassword *r;
2838
2839         Debug("GREET_STATE_EXPASSWORD\n");
2840
2841         r = (RequestExpassword *)state->request;
2842
2843         r->hdr.opcode = REQUEST_OP_EXPASSWORD;
2844         r->hdr.reserved = 0;
2845         r->hdr.length = sizeof(*r);
2846
2847         TellGreeter((RequestHeader *)r);
2848         state->waitForResponse = TRUE;
2849
2850         state->id = GREET_STATE_USERNAME;
2851       }
2852       break;
2853
2854     case GREET_STATE_BAD_HOSTNAME:
2855       {
2856        /*
2857         * Display password expired message.
2858         */
2859         RequestHostname *r;
2860
2861         Debug("GREET_STATE_BAD_HOSTNAME\n");
2862
2863         r = (RequestHostname *)state->request;
2864
2865         r->hdr.opcode = REQUEST_OP_HOSTNAME;
2866         r->hdr.reserved = 0;
2867         r->hdr.length = sizeof(*r);
2868
2869         TellGreeter((RequestHeader *)r);
2870         state->waitForResponse = TRUE;
2871
2872         state->id = GREET_STATE_USERNAME;
2873       }
2874       break;
2875
2876 #ifdef SIA
2877     case GREET_STATE_FORM:
2878       {
2879        /*
2880         * Get arbitrary number of answers.
2881         */
2882
2883         Debug("GREET_STATE_FORM\n");
2884  
2885         AskGreeter(state->request, (char *)state->response, REQUEST_LIM_MAXLEN);
2886  
2887         state->waitForResponse = FALSE;
2888         state->id = GREET_STATE_USERNAME;
2889       }
2890       break;
2891 #endif /* SIA */
2892   }
2893
2894   return(TRUE);
2895 }
2896
2897
2898 static void
2899 TellGreeter(
2900   RequestHeader *phdr)
2901 {
2902   write(request[1], phdr, phdr->length);
2903 }
2904
2905 static int
2906 AskGreeter(
2907   RequestHeader *preqhdr,
2908   char *buf,
2909   int blen)
2910 {
2911   int count;
2912   int remainder;
2913   ResponseHeader *phdr = (ResponseHeader *)buf;
2914
2915   if (preqhdr) TellGreeter(preqhdr);
2916
2917   phdr->opcode = REQUEST_OP_NONE;
2918
2919   count = read(response[0], buf, sizeof(*phdr));
2920
2921   if (count == sizeof(*phdr))
2922   {
2923    /*
2924     * Calculate amount of data after header.
2925     */
2926     remainder =  phdr->length - sizeof(*phdr);
2927     if (remainder > 0)
2928     {
2929      /*
2930       * Read remainder of response.
2931       */
2932       count += read(response[0], buf+sizeof(*phdr), remainder);
2933     }
2934   }
2935
2936 #if defined (DEBUG)
2937   if (debugLevel) PrintResponse(phdr, count);
2938 #endif /* DEBUG */
2939
2940   return(count);
2941 }
2942
2943 #if defined (DEBUG)
2944 static void
2945 PrintResponse(
2946   ResponseHeader *phdr,
2947   int count)
2948 {
2949   char *opstr = "UNKNOWN";
2950
2951   if (!count)
2952   {
2953     Debug("opcode = (EOF)\n");
2954     return;
2955   }
2956
2957   switch(phdr->opcode)
2958   {
2959     case REQUEST_OP_EXIT: opstr = "EXIT"; break;
2960     case REQUEST_OP_MESSAGE: opstr = "MESSAGE"; break;
2961     case REQUEST_OP_CHPASS: opstr = "CHPASS"; break;
2962     case REQUEST_OP_CHALLENGE: opstr = "CHALLENGE"; break;
2963     case REQUEST_OP_LANG: opstr = "LANG"; break;
2964     case REQUEST_OP_DEBUG: opstr = "DEBUG"; break;
2965   }
2966
2967   Debug("opcode = %d (%s)\n", phdr->opcode, opstr);
2968   Debug("  reserved = %d\n", phdr->reserved);
2969   Debug("  length = %d\n", phdr->length);
2970
2971   switch(phdr->opcode)
2972   {
2973     case REQUEST_OP_EXIT: break;
2974     case REQUEST_OP_LANG:
2975       Debug("  offLang=%d\n", ((ResponseLang *)phdr)->offLang);
2976       Debug("  lang='%s'\n",
2977         ((char *)phdr)+((ResponseLang *)phdr)->offLang);
2978       break;
2979     case REQUEST_OP_MESSAGE: break;
2980     case REQUEST_OP_CHPASS: break;
2981     case REQUEST_OP_CHALLENGE:
2982       Debug("  offResponse=%d\n", ((ResponseChallenge *)phdr)->offResponse);
2983       Debug("  response='%s'\n",
2984         ((char *)phdr)+((ResponseChallenge *)phdr)->offResponse);
2985       break;
2986     case REQUEST_OP_DEBUG:
2987       Debug("  offString=%d\n", ((ResponseDebug *)phdr)->offString);
2988       Debug("  string='%s'\n",
2989         ((char *)phdr)+((ResponseDebug *)phdr)->offString);
2990       break;
2991   }
2992 }
2993 #endif /* DEBUG */
2994
2995 #ifdef __KERBEROS
2996
2997 /***************************************************************************
2998  *
2999  *  SetTicketFileName
3000  *
3001  *  generate kerberos ticket file name. Name is returned in the static
3002  *  global variable "krb_ticket_string".
3003  *  
3004  ***************************************************************************/
3005
3006 static void 
3007 SetTicketFileName(uid_t uid)
3008 {
3009
3010
3011     char *env;
3012     char lhost[64], *p;
3013
3014
3015     /*
3016      *  generate ticket file pathname  (/tmp/tkt<uid>.<host>) ...
3017      */
3018
3019     if (env = (char *)getenv("KRBTKFILE")) {
3020         (void) strncpy(krb_ticket_string, env, sizeof(krb_ticket_string)-1);
3021         krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0';
3022
3023     } else {
3024         if (gethostname(lhost, sizeof(lhost)) != -1) {
3025             if (p = index(lhost, '.')) *p = '\0';
3026             (void)sprintf(krb_ticket_string, "%s%ld.%s", TKT_ROOT, (long)uid, lhost);
3027         } else {
3028             /* 32 bits of signed integer will always fit in 11 characters
3029                (including the sign), so no need to worry about overflow */
3030             (void) sprintf(krb_ticket_string, "%s%ld", TKT_ROOT, (long)uid);
3031         }
3032     }
3033 }
3034
3035 #endif /* __KERBEROS */
3036
3037 #if defined (_AIX) && !defined (_POWER)
3038
3039 /***************************************************************************
3040  *
3041  *  session_execve
3042  *
3043  *  If this is an authenticated process (LOGNAME set), set user's 
3044  *  process environment by calling setpenv().
3045  *
3046  *  If this is not an authenticated process, just call execve()
3047  *  
3048  ***************************************************************************/
3049
3050 static int
3051 session_execve(
3052   char *path,
3053   char *argv[],
3054   char *envp[])
3055 {
3056   int rc;
3057   char *user = getEnv (envp, "LOGNAME");
3058  
3059   if (user == NULL)
3060   {
3061     rc = execve(path, argv, envp);
3062   }
3063   else
3064   {
3065     char *usrTag, *sysTag;
3066
3067    /*
3068     * Save pointers to tags. The setpenv() function clears the pointers
3069     * to the tags in userEnviron as a side-effect.
3070     */
3071     sysTag = envp[SYS_ENV_TAG];
3072     usrTag = envp[USR_ENV_TAG];
3073
3074    /*
3075     * Set the users process environment. This call execs arvg so it 
3076     * should not return. It it should return, restore the envp tags.
3077     */
3078     rc = setpenv(user, PENV_INIT | PENV_ARGV, envp, argv);
3079
3080    /*
3081     * Restore pointers to tags.
3082     */
3083     envp[SYS_ENV_TAG] = sysTag;
3084     envp[USR_ENV_TAG] = usrTag;
3085   }
3086
3087   return(rc);
3088 }
3089 #endif /* _AIX && !_POWER */
3090
3091 #ifdef SIA
3092
3093 /* collect the SIA parameters from a window system. */
3094
3095 static int SiaManageGreeter(
3096     int timeout,
3097     int rendition,
3098     unsigned char *title,
3099     int num_prompts,
3100     prompt_t *prompt)
3101 {
3102     int i;
3103     struct {
3104       RequestMessage  greeter_message;
3105       char            msg_buffer[256];
3106       } greeter_msg_and_buffer;
3107     RequestForm *request_form;
3108
3109     switch(rendition) 
3110       {
3111         case SIAMENUONE:
3112         case SIAMENUANY:
3113         case SIAONELINER:
3114         case SIAFORM:
3115           if (rendition == SIAFORM && dt_in_sia_ses_authent 
3116                                   && (num_prompts == 2))
3117               {
3118               /* Normal login, Password case */
3119               Debug ("SIAFORM Normal login, Password case\n");
3120               while (siaGreeterInfo.state->id != GREET_STATE_TERMINATEGREET
3121                     && siaGreeterInfo.state->id != GREET_STATE_EXIT
3122                     && (siaGreeterInfo.status = ManageGreeter(
3123                               siaGreeterInfo.d, siaGreeterInfo.greet, 
3124                               siaGreeterInfo.verify, siaGreeterInfo.state)))
3125                   ;
3126
3127               if (!siaGreeterInfo.status 
3128                       || siaGreeterInfo.state->id == GREET_STATE_EXIT)
3129                   return(SIACOLABORT);
3130
3131               strncpy((char *)prompt[0].result, siaGreeterInfo.greet->name, 
3132                       prompt[0].max_result_length);
3133               strncpy((char *)prompt[1].result,siaGreeterInfo.greet->password,
3134                       prompt[1].max_result_length);
3135               }
3136           else
3137               {
3138               char *res_ptr;
3139               char *pmpt_ptr;
3140               int req_form_size;
3141               ResponseForm *response_form;
3142
3143               switch(rendition) 
3144                   {
3145                   case SIAMENUONE:
3146                       Debug("SIAMENUONE num_prompts = %d\n", num_prompts);
3147                       break;
3148                   case SIAMENUANY:
3149                       Debug("SIAMENUANY num_prompts = %d\n", num_prompts);
3150                       break;
3151                   case SIAONELINER:
3152                       Debug("SIAONELINER num_prompts = %d\n", num_prompts);
3153                       break;
3154                   case SIAFORM:
3155                       Debug("SIAFORM num_prompts = %d\n", num_prompts);
3156                       break;
3157                   }
3158
3159               /* need to display form */
3160
3161               req_form_size = sizeof(RequestForm) 
3162                                       + strlen((const char *)title) + 1;
3163               for (i=0; i<num_prompts; i++)
3164                   req_form_size += strlen((const char *)prompt[i].prompt) + 1;
3165               request_form = (RequestForm *) alloca(req_form_size);
3166
3167               siaGreeterInfo.state->id = GREET_STATE_FORM;
3168               siaGreeterInfo.state->request = (RequestHeader *)request_form;
3169               /* siaGreeterInfo.state->vf = VF_MESSAGE; */
3170
3171               request_form->hdr.opcode = REQUEST_OP_FORM;
3172               request_form->hdr.reserved = 0;
3173               request_form->hdr.length = req_form_size;
3174               request_form->num_prompts = num_prompts;
3175               request_form->rendition = rendition;
3176               request_form->offTitle = sizeof(RequestForm);
3177               request_form->offPrompts = sizeof(RequestForm) +
3178                                           strlen((const char *)title) + 1;
3179               strcpy((char *)request_form + request_form->offTitle, 
3180                       (const char *)title);
3181
3182               pmpt_ptr = (char *)request_form + request_form->offPrompts;
3183               for (i=0; i<num_prompts; i++)
3184                   {
3185                   if (!prompt[i].prompt || prompt[i].prompt[0] == '\0')
3186                       *pmpt_ptr++ = '\0';
3187                   else
3188                       {
3189                       Debug("  prompt[%d]: %s\n", i, prompt[i].prompt);
3190                       strcpy(pmpt_ptr, (const char *)prompt[i].prompt);
3191                       pmpt_ptr += strlen((const char *)prompt[i].prompt);
3192                       }
3193                   request_form->visible[i] = 
3194                       (prompt[i].control_flags & SIARESINVIS) ? False : True;
3195                   }
3196
3197               siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3198                                                   siaGreeterInfo.greet,
3199                                                   siaGreeterInfo.verify, 
3200                                                   siaGreeterInfo.state);
3201
3202               response_form = (ResponseForm *)siaGreeterInfo.state->response;
3203               res_ptr = (char *)response_form + response_form->offAnswers;
3204               for (i = 0; i < response_form->num_answers; i++)
3205                   {
3206                   if (rendition == SIAMENUONE || rendition == SIAMENUANY)
3207                       {
3208                       if (res_ptr[0])
3209                           prompt[i].result = (unsigned char *)1;
3210                       else
3211                           prompt[i].result = NULL;
3212                       }
3213                   else
3214                       {
3215                       strcpy((char *)prompt[0].result, res_ptr);
3216                       }
3217                   res_ptr += strlen(res_ptr) + 1;
3218                   }
3219               if (!response_form->collect_status)
3220                   siaGreeterInfo.status = FALSE;
3221               }
3222             break;
3223         case SIAINFO:
3224         case SIAWARNING:
3225
3226           Debug("SIAINFO or SIAWARNING %s\n", prompt[0].prompt);
3227
3228           siaGreeterInfo.state->id = GREET_STATE_ERRORMESSAGE;
3229           siaGreeterInfo.state->request = (RequestHeader *) 
3230                               &greeter_msg_and_buffer.greeter_message;
3231           siaGreeterInfo.state->vf = VF_MESSAGE;
3232           siaGreeterInfo.state->msg = (char *)prompt[0].prompt;
3233
3234           siaGreeterInfo.status = ManageGreeter(siaGreeterInfo.d, 
3235                                               siaGreeterInfo.greet,
3236                                               siaGreeterInfo.verify, 
3237                                               siaGreeterInfo.state);
3238             break;
3239         default:
3240             return(SIACOLABORT);
3241             break;
3242       }
3243     if (!siaGreeterInfo.status)
3244       return(SIACOLABORT);
3245     return(SIACOLSUCCESS);
3246 }
3247
3248 static CopySiaInfo(SIAENTITY *siaHandle, struct greet_info *greet)
3249 {
3250
3251     greet->name = malloc(strlen(siaHandle->name) + 1);
3252     strcpy (greet->name, siaHandle->name);
3253
3254     greet->password = malloc(strlen(siaHandle->password) + 1);
3255     strcpy (greet->password, siaHandle->password);
3256     
3257
3258 }
3259
3260 static void KillGreeter( void )
3261 {
3262     if (sia_greeter_pid)
3263       AbortClient(sia_greeter_pid);
3264     sia_greeter_pid = 0;
3265 }
3266 #endif /* SIA */