Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtlogin / vgcallback.c
1 /* $TOG: vgcallback.c /main/16 1998/11/02 18:34:55 mgreess $ */
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  ****************************************************************************
10  **
11  **   File:        vgcallback.c
12  **
13  **   Project:     HP Visual User Environment (DT)
14  **
15  **   Description: Callback routines Dtgreet application.
16  **
17  **                These routines handle the callbacks from the widgets.
18  **
19  **
20  **   (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company
21  **
22  **
23  **
24  ****************************************************************************
25  ************************************<+>*************************************/
26
27
28 /***************************************************************************
29  *
30  *  Includes
31  *
32  ***************************************************************************/
33
34 #include        <stdio.h>
35 #include        <unistd.h>
36 #include        <setjmp.h>
37 #include        <signal.h>
38 #include        <sys/signal.h>
39 #include        <sys/param.h>
40
41 #include        <Xm/Xm.h>
42 #include        <Xm/MessageB.h>
43 #include        <Xm/TextF.h>
44 #include        <Xm/TextFP.h>
45 #include        <Xm/PushBG.h>
46 #include        <Xm/ToggleBG.h>
47 #include    <Dt/IconFile.h>
48 #include    <Dt/Icon.h>
49 #include        <pwd.h>
50
51
52 #ifdef AUDIT
53 #    include <sys/audit.h>
54 #endif
55
56 /* necessary for bzero */
57 #ifdef SVR4
58 #include        <X11/Xfuncs.h>
59 #endif
60
61 #include        "vg.h"
62 #include        "vgmsg.h"
63
64
65 /***************************************************************************
66  *
67  *  External declarations
68  *
69  ***************************************************************************/
70
71 extern  LogoInfo        logoInfo; /* information about the logo            */
72
73
74
75 /***************************************************************************
76  *
77  *  Procedure declarations
78  *
79  ***************************************************************************/
80
81 static void CenterForm( Widget w1, Widget w2);
82 static void PingLost( void ) ;
83 static SIGVAL PingBlocked( int arg ) ;
84 static void ProcessTraversal( Widget w, int direction) ;
85 static void _DtShowDialog(DialogType dtype, XmString msg);
86 static void TellRequester(char * buf, size_t nbytes);
87
88 #  ifdef BLS
89 static  void PromptSensitivityLevel(void); /* prompt for B1 Sen. Level     */
90         int  VerifySensitivityLevel(void); /* verify B1 Sensitivity Level  */
91 #  endif
92
93 static int session_selected = False;
94 static Widget default_dt = NULL;
95
96
97 /***************************************************************************
98  *
99  *  Global variables
100  *
101  ***************************************************************************/
102
103        Widget   focusWidget = NULL;
104
105 char    *userName = "\0";
106 struct passwd *user_p;
107
108
109 #ifdef BLS
110 static  int     normalPasswordWidget = True;
111         char    *sensitivityLevel = NULL;
112 #endif
113
114 #ifndef SVR4
115         long    groups[NGROUPS];
116 #endif
117
118 #ifdef SIA
119   
120 #include <alloca.h>
121
122 SiaFormInfo siaFormInfo;
123
124
125 XmString multiline_xmstring(char *text)
126 {
127
128     char *start, *end;
129     Boolean done;
130     XmString string = NULL;
131     XmString tmp_string;
132     XmString separator = NULL;
133     char *buffer;
134
135     if (!text) return (NULL);
136
137
138     buffer = alloca(strlen((const char *)text) + 1);
139
140     start = text;
141     done = FALSE;
142
143
144     while ( ! done)           /* loop thu local copy */
145       {                               /* looking for \n */
146       end = start;
147
148       while ((*end != '\0') && (*end != '\n'))  end++;
149
150       if (*end == '\0')
151           done = TRUE;                /* we are at the end */
152
153       /* Don't convert empty string unless it's an initial newline. */
154       if ((start != end) || (start == text))
155           {
156           strncpy(buffer, start, end - start);
157           buffer[end - start] = '\0';
158           if (!string)
159               string = XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG);
160           else
161               {
162               tmp_string = XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG);
163               string = XmStringConcat(string, tmp_string);
164               XmStringFree(tmp_string);
165               }
166           }
167
168       /* Make a separator if this isn't the last segment. */
169       if (!done) 
170           {
171           if (!separator)
172               separator = XmStringSeparatorCreate();
173           string = XmStringConcat(string, separator);
174           start = ++end;              /* start at next char */
175           }
176       }
177
178     if (separator)
179       XmStringFree(separator);
180
181     return (string);
182 }
183
184 #endif /* SIA */
185
186
187 /***************************************************************************
188  *
189  *  CenterForm
190  *
191  *  Utility function to center one form horizontally within another.
192  ***************************************************************************/
193
194 static void 
195 CenterForm( Widget w1, Widget w2 )
196 {
197
198     Dimension   width;
199     int         i, width1, width2;
200    
201     XtSetArg(argt[0], XmNwidth,  &width);
202     XtGetValues(w1, argt, 1);
203     width1 = (int)width;    
204
205     XtSetArg(argt[0], XmNwidth,  &width);
206     XtGetValues(w2, argt, 1);
207     width2 = (int)width;
208     
209     i = 0;
210     XtSetArg(argt[i], XmNleftAttachment,        XmATTACH_FORM           ); i++;
211     XtSetArg(argt[i], XmNleftOffset,            (width1 - width2) / 2   ); i++;
212     XtSetValues(w2,  argt, i);
213 }
214
215
216
217  
218 /***************************************************************************
219  *
220  *  CleanupAndExit
221  *
222  *  close things down gracefully and exit
223  ***************************************************************************/
224
225 void 
226 CleanupAndExit( Widget w, int exit_code )
227 {
228     int i;
229     Boolean  toggleon;          /* status of session toggle buttons     */
230     
231 #ifdef VG_TRACE
232     vg_TRACE_EXECUTION("main:  entered CleanupAndExit ...");
233 #endif /* VG_TRACE */
234
235     if (w != NULL)
236       XtDestroyWidget(w);
237     
238     /*
239      *  if user is logging in, set type of session desired. No more than
240      *  one session type can be selected at a time (if any) ...
241      */
242
243     if ( exit_code == NOTIFY_OK ) {
244         XtSetArg(argt[0], XmNset,       &toggleon               );
245
246         XtGetValues(options_failsafe, argt, 1);
247         if ( toggleon ) exit_code = NOTIFY_FAILSAFE;
248
249         XtGetValues(options_dtlite, argt, 1);
250         if ( toggleon ) exit_code = NOTIFY_DTLITE;
251
252
253         XtGetValues(options_dt, argt, 1);
254         if ( toggleon ) exit_code = NOTIFY_DT;
255
256
257         if(options_last_dt != NULL) {
258         XtGetValues(options_last_dt, argt, 1);
259         if ( toggleon ) exit_code = NOTIFY_LAST_DT;
260         }
261
262         for(i = 0; i < appInfo.altDts ; ++i) {
263           if(alt_dts[i] != NULL) {
264            XtGetValues(alt_dts[i], argt, 1);
265               if ( toggleon ) exit_code = NOTIFY_ALT_DTS + i + 1; /* alt desktops start  at 1 */ 
266            }    
267
268         }
269
270     }
271
272     if (!session_selected)
273         exit_code = NOTIFY_OK;
274
275     CloseCatalog();
276
277     ChangeBell("on");
278     UnsecureDisplay();
279     XSync (dpyinfo.dpy, 0);
280
281     XtCloseDisplay(dpyinfo.dpy);
282     exit (exit_code);
283 }
284
285
286 /***************************************************************************
287  *
288  *  ClearDtlabel
289  *
290  ***************************************************************************/
291
292 static void
293 ClearDtlabel(void)
294 {
295     int i;
296     XmString xms;
297
298 #ifdef VG_TRACE
299     vg_TRACE_EXECUTION("ClearDtlabel:  entered ...");
300 #endif /* VG_TRACE */
301
302     i = 0;
303     xms = XmStringCreateLocalized("       ");
304     XtSetArg(argt[i], XmNlabelString, xms); i++;
305     XtSetValues(dt_label, argt, i);
306     XmStringFree(xms);
307 }
308
309
310 /***************************************************************************
311  *
312  *  ClearDtlabel
313  *
314  ***************************************************************************/
315
316 static void
317 ClearDtButtons(void)
318 {
319     int i;
320
321     /*
322      *  Clear Dt toggles...
323      */
324     XtSetArg(argt[0], XmNset, False);
325
326     for (i=0; i<appInfo.altDts; ++i)
327       if (alt_dts[i] != NULL)
328         XtSetValues(alt_dts[i], argt, 1);
329
330     if (options_failsafe) XtSetValues(options_failsafe, argt, 1);
331     if (options_dtlite) XtSetValues(options_dtlite, argt, 1);
332     if (options_dt) XtSetValues(options_dt, argt, 1);
333     if (options_last_dt) XtSetValues(options_last_dt, argt, 1);
334 }
335
336
337
338  
339 /***************************************************************************
340  *
341  *  RespondClearCB
342  *
343  *  clear name/password text fields
344  ***************************************************************************/
345
346 void 
347 RespondClearCB( Widget w, XtPointer client, XtPointer call )
348 {
349   char buf[REQUEST_LIM_MAXLEN];
350   ResponseClear *r = (ResponseClear *)buf;
351
352 #ifdef VG_TRACE
353   vg_TRACE_EXECUTION("main:  entered RespondClearCB ...");
354 #endif /* VG_TRACE */
355
356   ClearDtlabel();
357   ClearDtButtons();
358   SetDefaultDt(NULL);
359
360   r->hdr.opcode = REQUEST_OP_CLEAR;
361   r->hdr.reserved = 0;
362   r->hdr.length = sizeof(*r);
363
364   TellRequester(buf, (size_t) r->hdr.length);
365 }
366
367
368  
369 /***************************************************************************
370  *
371  *  CopyrightCB
372  *
373  *  move the highlight back to login or password fields AFTER the copyright
374  *  dialog is unposted.
375  *
376  ***************************************************************************/
377
378 void 
379 CopyrightCB( Widget w, XtPointer client_data, XtPointer call_data )
380 {
381
382 #ifdef VG_TRACE
383     vg_TRACE_EXECUTION("main:  entered CopyrightCB ...");
384 #endif /* VG_TRACE */
385
386     if ( focusWidget != NULL)
387         ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT);
388
389 }
390
391
392
393 /***************************************************************************
394  *
395  *  EditPasswdCB
396  *
397  *  implement no-echo and no-cursor motion of the password
398  ***************************************************************************/
399
400 void 
401 EditPasswdCB(Widget w, XtPointer client, XtPointer call_data)
402 {
403     LoginTextPtr        textdata;
404     XmTextVerifyPtr     cbs = (XmTextVerifyPtr) call_data;
405     int                 i;
406     static char         buffer[MAXPATHLEN];
407     register char       *s, *t;
408
409 #ifdef VG_TRACE
410     vg_TRACE_EXECUTION("main:  entered EditPasswdCB ...");
411     vg_TRACE_EXECUTION(
412             "currInsert=%d newInsert=%d startPos=%d endPos=%d\n",
413             cbs->currInsert,cbs->newInsert,cbs->startPos, cbs->endPos);
414     if (cbs->text->ptr) vg_TRACE_EXECUTION("text->ptr=%s\n", cbs->text->ptr);
415     vg_TRACE_EXECUTION("noechobuf=%s\n", textdata->noechobuf);
416 #endif /* VG_TRACE */
417
418     textdata = GetLoginTextPtr(w);
419     if (NULL == textdata || textdata->bEcho) return;
420     if (cbs->reason == XmCR_MOVING_INSERT_CURSOR) return;
421
422     for (i=0, s=buffer, t=textdata->noechobuf;
423          (*t && i<cbs->startPos);
424          i++, s++, t++)
425       *s = *t;
426
427     if (cbs->text->ptr)
428     {
429         strcpy(s, cbs->text->ptr);
430         s += cbs->text->length;
431     }
432     else
433       *s = '\0';
434
435     if (strlen(textdata->noechobuf) >= cbs->endPos)
436     {
437         t = textdata->noechobuf+cbs->endPos;
438         if (strlen(t))
439           strcpy(s, t);
440     }
441
442     strcpy(textdata->noechobuf, buffer);
443
444     if (cbs->text->ptr)
445       for (i=0, s=cbs->text->ptr; i<cbs->text->length; i++, s++)
446         *s = '*';
447
448 #ifdef VG_TRACE
449     vg_TRACE_EXECUTION("textdata->noechobuf=%s\n", textdata->noechobuf);
450 #endif
451 }
452
453
454 /***************************************************************************
455  *
456  *  FakeFocusIn
457  *
458  *  simulate a FocusIn event to the login_shell in order to turn on
459  *  traversal. There is a bug in the Toolkit that is normally masked by 
460  *  the window manager. Since we have no window manager, we need to simulate
461  *  the FocusIn event it sends to the application.
462  *
463  *  Also force the initial focus to the login_text widget.
464  ***************************************************************************/
465
466 void
467 FakeFocusIn( Widget focus_widget, XtPointer client_data, XEvent *eventprm,
468              Boolean *continue_to_dispatch )
469 {
470    XEvent event;
471    XEvent * eventPtr = &event;
472
473 #ifdef VG_TRACE
474    vg_TRACE_EXECUTION("main:  entered FakeFocusIn ...");
475 #endif /* VG_TRACE */
476
477    /*
478     * set the input focus to the login text widget...
479     */
480     
481    XSetInputFocus( XtDisplay(focus_widget),
482                    XtWindow(focus_widget),
483                    RevertToNone,
484                    CurrentTime);
485
486    /*
487     *  create a synthetic focus-in event. 
488     *
489     *  Note: The above call to XSetInputFocus() was not originally included
490     *        in this routine. A bug fix to Motif made it necessary to add
491     *        the call. The synthetic focus-in event is probably now
492     *        unnecessary but is left in for caution's sake. (12/08/92)
493     */
494     
495    /* focus_widget = login_shell; */
496    
497    eventPtr->type = FocusIn;
498    eventPtr->xfocus.serial = LastKnownRequestProcessed(XtDisplay(focus_widget));
499    eventPtr->xfocus.send_event = True;
500    eventPtr->xfocus.display = XtDisplay(focus_widget);
501    eventPtr->xfocus.window = XtWindow(focus_widget);
502    eventPtr->xfocus.mode = NotifyNormal;
503    eventPtr->xfocus.detail = NotifyAncestor;
504
505    XtDispatchEvent (eventPtr);
506
507    ProcessTraversal(focus_widget, XmTRAVERSE_CURRENT);
508    
509    XtRemoveEventHandler(focus_widget, ExposureMask, FALSE,
510                    FakeFocusIn, NULL);
511 }
512
513 /***************************************************************************
514  *
515  *  LayoutCB
516  *
517  *  do final layout adjustments right before windows are mapped. This is
518  *  necessary because the size of managers (Forms, etc) is not known until
519  *  their window has been created (XtRealize). We want to make adjustments
520  *  before the windows become visible
521  *
522  *  1. squeeze dialog width to fit on screen.
523  *  2. increase dialog height if widgets overlap.
524  *  3. center the main matte horizontally and vertically
525  *  4. position the pushbuttons
526  *  5. position the copyright
527  *
528  ***************************************************************************/
529
530 void
531 LayoutCB( Widget w, XtPointer client_data, XtPointer call_data )
532 {
533     register int        i, j;
534     Dimension   width, height;  /* size values returned by XtGetValues     */
535     Dimension   shadowThickness;/* size values returned by XtGetValues     */
536     Position    x, y;           /* position values returned by XtGetValues */
537     
538     struct {                    /* position, size of widgets (pixels)      */
539     int x, y;
540     int width;
541     int height;
542     }           mw, pw; /* matte, logo, drop shadow, login matte
543                                        and greeting widgets                */
544
545     int         width1, width2; /* general width variable                  */
546     int         height1;        /* general height variable                 */
547     Position    x1, y1;         /* general position variables              */
548     int         offsety;        /* general offset variable                 */
549     int         shadow_offsetx; /* offset for drop shadow (pixels)         */
550     int         shadow_offsety; /* offset for drop shadow (pixels)         */
551     int         spacing;        /* spacing between login & matte bottoms   */
552     
553     Widget      buttons[4];     /* pushbutton widgets                      */
554
555     XtWidgetGeometry  geometry; /* geometry of a widget                    */
556     
557     int         max_width;      /* maximum width  of a set of widgets      */
558     int         origin;         /* horizontal origin for button placement  */
559     int         space;          /* total available space left between buttons */
560     int         overlap;        /* possible widget overlap                 */
561
562 #ifdef VG_TRACE
563     vg_TRACE_EXECUTION("main:  entered LayoutCB ...");
564 #endif /* VG_TRACE */
565
566     /*
567      * - squeeze dialog to fit onto screen (if necessary)
568      */
569     i = 0;
570     XtSetArg(argt[i], XmNwidth,                 &width                  ); i++;
571     XtGetValues(matte, argt, i);
572     mw.width  = ToPixel(matte, XmHORIZONTAL, (int)width  );
573 #define HMARGIN 4 /* min sum horizontal margin of matte */
574     if (mw.width+HMARGIN > dpyinfo.width)
575     {
576       int delta = mw.width + HMARGIN - dpyinfo.width;
577      /*
578       * Matte width greater than screen so shrink matteFrame
579       * and matte1 width to compensate.
580       */
581       i=0;
582       XtSetArg(argt[i], XmNwidth,       &width          ); i++;
583       XtGetValues(matteFrame, argt, i);
584
585       width1 = ToPixel(matteFrame, XmHORIZONTAL, (int)width  );
586       width1 -= delta;
587       width1 = FromPixel(matteFrame, XmHORIZONTAL, width1 );
588
589       i=0;
590       XtSetArg(argt[i], XmNwidth,       width1          ); i++;
591       XtSetValues(matteFrame, argt, i);
592
593       width1 = dpyinfo.width - HMARGIN;
594       mw.width = FromPixel(matte, XmHORIZONTAL, width1 );
595
596       i=0;
597       XtSetArg(argt[i], XmNwidth,       mw.width        ); i++;
598       XtSetValues(matte, argt, i);
599     }
600
601     /*
602      * - Make sure the login widgets don't overlap.
603      */
604     if (login_form) {
605         i = 0;
606         XtSetArg(argt[i], XmNy,                 &y                      ); i++;
607         XtSetArg(argt[i], XmNheight,            &height                 ); i++;
608         XtGetValues(greeting, argt, i);
609
610         i = 0;
611         XtSetArg(argt[i], XmNy,                 &y1                     ); i++;
612         XtGetValues(login_form, argt, i);
613
614         overlap = y + height - y1;
615
616         if (overlap > -10) {
617             i = 0;
618             XtSetArg(argt[i], XmNbottomAttachment, XmATTACH_WIDGET);    i++;
619             XtSetArg(argt[i], XmNbottomWidget,     login_form);         i++;
620             XtSetArg(argt[i], XmNbottomOffset,     10);                 i++;
621             XtSetValues(greeting, argt, i);
622         }
623     }
624  
625
626     /*
627      *  - center the main matte horizontally and vertically...
628      */
629      
630     i = 0;
631     XtSetArg(argt[i], XmNx,                     &x                      ); i++;
632     XtSetArg(argt[i], XmNy,                     &y                      ); i++;
633     XtSetArg(argt[i], XmNwidth,                 &width                  ); i++;
634     XtSetArg(argt[i], XmNheight,                &height                 ); i++;
635     XtSetArg(argt[i], XmNshadowThickness,       &shadowThickness        ); i++;
636     XtGetValues(matte, argt, i);
637
638     mw.width  = ToPixel(matte, XmHORIZONTAL, (int)width  );
639     mw.height = ToPixel(matte, XmVERTICAL,   (int)height );
640
641     mw.x = ( x > 0 ? ToPixel(matte, XmHORIZONTAL, (int) x)
642             : (dpyinfo.width - mw.width)/2 );
643     
644     mw.y = ( y > 0 ? ToPixel(matte, XmVERTICAL, (int) y)
645             : (dpyinfo.height - mw.height)/2 );
646  
647     if ( mw.x < 0 ) mw.x = 0;
648     if ( mw.y < 0 ) mw.y = 0;
649
650     x1 = FromPixel(matte, XmHORIZONTAL, mw.x );
651     y1 = FromPixel(matte, XmVERTICAL,   mw.y );
652
653     i = 0;
654     XtSetArg(argt[i], XmNx,                     x1                      ); i++;
655     XtSetArg(argt[i], XmNy,                     y1                      ); i++;
656     XtSetValues(matte, argt, i);
657
658
659     /*
660      * space the buttons horizontally. Start at the center of the matte
661      * and allow them to grow towards the edges...
662      */
663
664     i = 0;
665     XtSetArg(argt[i], XmNwidth,         &width                          ); i++;
666     XtGetValues(matte1, argt, i);
667
668     max_width = width;
669
670     i = 0;
671     XtSetArg(argt[i], XmNwidth,         &width                          ); i++;
672     XtGetValues(clear_button, argt, i);
673     
674     space = max_width - 4*width;
675     spacing = space/4;
676     
677     if (spacing < 12) spacing = 12;
678
679     i = 0;
680     XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM); i++;
681     XtSetArg(argt[i], XmNleftOffset, spacing/2); i++;
682     XtSetValues(ok_button,  argt, i);
683
684     i = 0;
685     XtSetArg(argt[i], XmNleftAttachment,        XmATTACH_WIDGET         ); i++;
686     XtSetArg(argt[i], XmNleftWidget, ok_button); i++;
687     XtSetArg(argt[i], XmNleftOffset, spacing); i++;
688     XtSetValues(clear_button,  argt, i);
689
690     i = 0;
691     XtSetArg(argt[i], XmNleftAttachment,        XmATTACH_WIDGET         ); i++;
692     XtSetArg(argt[i], XmNleftWidget, clear_button); i++;
693     XtSetArg(argt[i], XmNleftOffset, spacing); i++;
694     XtSetValues(options_button,  argt, i);
695     
696     i = 0;
697     XtSetArg(argt[i], XmNleftAttachment,        XmATTACH_WIDGET         ); i++;
698     XtSetArg(argt[i], XmNleftWidget, options_button); i++;
699     XtSetArg(argt[i], XmNleftOffset, spacing); i++;
700     XtSetValues(help_button,  argt, i);
701     
702     /*
703      *  - adjust the copyright vertically to align top with login_matte...
704      */
705
706     if (copyright_msg) {
707         XtQueryGeometry(copyright_msg, NULL, &geometry);
708     
709         i = 0;
710         XtSetArg(argt[i], XmNshadowThickness,   &width                  ); i++;
711         XtGetValues(copyright_msg, argt, i);
712
713         width1 = ToPixel(copyright_msg, XmHORIZONTAL, width);
714         width1 = (dpyinfo.width - (int) geometry.width - 2 * width1)/2;
715
716         x1 = FromPixel(copyright_msg, XmHORIZONTAL, width1);
717         y1 = FromPixel(copyright_msg, XmVERTICAL, mw.y);
718
719         i = 0;
720         XtSetArg(argt[i], XmNdefaultPosition,   False                   ); i++;
721         XtSetArg(argt[i], XmNx,                 x1                      ); i++;
722         XtSetArg(argt[i], XmNy,                 y1                      ); i++;
723         XtSetValues(copyright_msg, argt, i);
724     }
725 }
726
727
728
729
730 /***************************************************************************
731  *
732  *  MenuItemCB
733  *
734  *  callback for options menu items
735  ***************************************************************************/
736
737 void 
738 MenuItemCB( Widget w, XtPointer client_data, XtPointer call_data )
739 {
740         int i;
741         char     *logoFile;
742         char     *logoName;
743         char    *temp_p;
744         char    temp[MAXPATHLEN];
745
746 #ifdef VG_TRACE
747     vg_TRACE_EXECUTION("main:  entered MenuItemCB ...");
748 #endif /* VG_TRACE */
749
750     session_selected = True;
751
752     switch ( (int) client_data) {
753
754     case OB_RESTART_SERVER:
755         CleanupAndExit(NULL, NOTIFY_RESTART);
756         break;
757
758     case OB_NO_WINDOWS:
759         CleanupAndExit(NULL, NOTIFY_NO_WINDOWS);
760         break;
761
762     case OB_COPYRIGHT:
763         _DtShowDialog(copyright, NULL);
764         break;
765
766     case OB_ALT_DTS:
767     case OB_FAILSAFE:
768     case OB_DTLITE:
769     case OB_DT: 
770     case OB_LAST_DT:
771         /*
772          * set the label on the dt_label widget..
773          */ 
774
775         if(w != options_last_dt) {
776           XtSetArg(argt[0], XmNlabelString, &xmstr);
777           XtGetValues(w, argt, 1);
778
779           XtSetArg(argt[0], XmNlabelString, xmstr);
780           XtSetValues(dt_label, argt, 1);
781         }
782         else
783           ClearDtlabel();
784
785         i = 0;
786         XtSetArg(argt[i], XmNuserData,          &logoFile          ); i++;
787         XtGetValues(w, argt, i);
788
789         /* 
790          * remove trailing spaces 
791          */
792         if(strchr(logoFile,' '))
793             temp_p = strtok(logoFile," ");      
794         else
795             temp_p = logoFile;
796  
797         logoName = _DtGetIconFileName(DefaultScreenOfDisplay(dpyinfo.dpy),
798                           temp_p, NULL, NULL, NULL);
799  
800         if (logoName == NULL) {
801            LogError( 
802              ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
803                              logoFile);
804            logoFile = NULL;
805         }
806         i = 0;
807         XtSetArg(argt[i], XmNimageName, logoName); i++;
808         XtSetValues(logo_pixmap, argt, i);
809
810         /*
811          *  Clear Dt toggles...
812          */
813         ClearDtButtons();
814
815         /* 
816          * set the selected toggle button...
817          */
818         XtSetArg(argt[0], XmNset, True);
819         XtSetValues(w, argt, 1);
820
821         SetDefaultDt(w);
822
823         /*
824          *  return focus to name/password widgets...
825          */
826          
827         if ( focusWidget != NULL)
828             ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT);
829
830         break;
831     }
832
833 }
834
835
836
837
838 /***************************************************************************
839  *
840  *  OptionsUnmapCB
841  *
842  *  callback when options menu unmaps
843  ***************************************************************************/
844
845 void 
846 OptionsUnmapCB( Widget wd, XtPointer client_data, XtPointer call_data )
847 {
848
849     int         i;
850     Dimension   width, height;
851
852     Widget      w;
853     XEvent      event;
854     
855 #ifdef VG_TRACE
856     vg_TRACE_EXECUTION("main:  entered OptionsUnmapCB ...");
857 #endif /* VG_TRACE */
858
859     /*
860      *  simulate an exposure event over the Options pushbutton to make sure
861      *  the pushbutton elevates. (there is a bug in the toolkit where this
862      *  doesn't always happen on some servers)...
863      */
864
865     w = options_button;
866     
867     i = 0;
868     XtSetArg(argt[i], XmNwidth,                 &width                  ); i++;
869     XtSetArg(argt[i], XmNheight,                &height                 ); i++;
870     XtGetValues(w, argt, i);
871
872     event.type                = Expose;
873     event.xexpose.serial      = LastKnownRequestProcessed(XtDisplay(w));
874     event.xexpose.send_event  = True;
875     event.xexpose.display     = XtDisplay(w);
876     event.xexpose.window      = XtWindow(w);
877     event.xexpose.x           = 0;
878     event.xexpose.y           = 0;
879     event.xexpose.width       = 1;   /* one pixel seems to be good enough, */
880     event.xexpose.height      = 1;   /* but time will tell...              */
881 #if 0
882     event.xexpose.width       = ToPixel(matte, XmHORIZONTAL, (int)width  );
883     event.xexpose.height      = ToPixel(matte, XmVERTICAL,   (int)height );
884 #endif
885     event.xexpose.count       = 0;
886    
887     XtDispatchEvent (&event);
888 }
889
890
891  
892 /***************************************************************************
893  *
894  *  PingServerCB
895  *
896  *  Ping the server occasionally with an Xsync to see if it is still there.
897  *  We do this here rather than in dtlogin since dtgreet has the server
898  *  grabbed.
899  *
900  ***************************************************************************/
901
902 static jmp_buf  pingTime;
903 static int      serverDead = FALSE;
904 static int      pingInterval = 0;       /* ping interval (sec.)            */
905 static int      pingTimeout;            /* ping timeout (sec.)             */
906
907 static void 
908 PingLost( void )
909 {
910     serverDead = TRUE;
911     longjmp (pingTime, 1);
912 }
913
914
915 static SIGVAL
916 PingBlocked( int arg )
917
918 {
919     serverDead = TRUE;
920     longjmp (pingTime, 1);
921 }
922
923
924 int 
925 PingServer( void )
926 {
927     int     (*oldError)();
928     SIGVAL  (*oldSig)();
929     int     oldAlarm;
930
931     oldError = XSetIOErrorHandler ((XIOErrorHandler)PingLost);
932     oldAlarm = alarm (0);
933     oldSig = signal (SIGALRM, PingBlocked);
934     alarm (pingTimeout * 60);
935     if (!setjmp (pingTime))
936     {
937         XSync (dpyinfo.dpy, 0);
938     }
939     else
940     {
941         if ( serverDead ) {
942             LogError(ReadCatalog(
943                                  MC_LOG_SET,MC_LOG_DEADSRV,MC_DEF_LOG_DEADSRV),
944                 dpyinfo.name);
945             alarm (0);
946             signal (SIGALRM, SIG_DFL);
947             XSetIOErrorHandler (oldError);
948             return 0;
949         }
950     }
951     alarm (0);
952     signal (SIGALRM, oldSig);
953     alarm (oldAlarm);
954     XSetIOErrorHandler (oldError);
955     return 1;
956 }
957
958
959 void 
960 PingServerCB( XtPointer call_data, XtIntervalId *id )
961 {
962
963     char *t;
964     
965
966     /*
967      *  get ping values from the environment...
968      */
969
970     if ( pingInterval == 0 ) {
971         pingInterval  = ((t = (char *)getenv(PINGINTERVAL)) == NULL ? 0 : atoi(t));
972         pingTimeout   = ((t = (char *)getenv(PINGTIMEOUT))  == NULL ? 0 : atoi(t));
973     }
974
975     
976     /*
977      *  ping the server. If successful, set a timer for the next ping,
978      *  otherwise cleanup and exit...
979      */
980
981     if ( pingInterval != 0 ) {
982         if (PingServer())
983             XtAddTimeOut((unsigned long) pingInterval * 60 * 1000, 
984                           PingServerCB, NULL);
985         else
986             exit(NOTIFY_RESTART);
987     }
988 }
989
990
991  
992 /***************************************************************************
993  *
994  *  PostMenuCB
995  *
996  *  post the option_button pop-up menu
997  ***************************************************************************/
998
999 void 
1000 PostMenuCB( Widget w, XtPointer client_data, XtPointer call_data )
1001 {
1002
1003     XmAnyCallbackStruct *p;
1004
1005     p = (XmAnyCallbackStruct *) call_data;
1006
1007 #ifdef VG_TRACE
1008     vg_TRACE_EXECUTION("main:  entered PostMenuCB ...");
1009 #endif /* VG_TRACE */
1010
1011     /*
1012      *  make options menus if they don't yet exist...
1013      */
1014
1015     if (options_menu == NULL)
1016         MakeOptionsMenu();
1017
1018
1019     /*
1020      *  post menu...
1021      */
1022
1023     if (p->reason == XmCR_ARM           &&
1024         p->event->type == ButtonPress) {
1025
1026         XmMenuPosition(options_menu, p->event);
1027         XtManageChild(options_menu);
1028     }
1029 }
1030
1031
1032
1033
1034 /***************************************************************************
1035  *
1036  *  ProcessTraversal
1037  *
1038  *  move the input focus
1039  ***************************************************************************/
1040
1041 static void 
1042 ProcessTraversal( Widget w, int direction )
1043 {
1044     int i;
1045
1046 #ifdef VG_TRACE
1047     vg_TRACE_EXECUTION("main:  entered ProcessTraversal ...");
1048 #endif /* VG_TRACE */
1049
1050     i = XmProcessTraversal(w, direction);
1051
1052 #ifndef __hpux
1053     /*
1054      * Versions of Motif other than HP do not support the XmfocusCallback
1055      * on the TextField widget. We simulate it here by manually invoking the
1056      * callback routine...
1057      */
1058
1059     TextFocusCB(w, NULL, NULL);
1060 #endif    
1061 }
1062
1063
1064
1065  
1066 /***************************************************************************
1067  *
1068  *  RefreshEH
1069  *
1070  *  cause the entire screen to refresh via exposure events
1071  ***************************************************************************/
1072
1073 void 
1074 RefreshEH( Widget w, XtPointer client_data, XEvent *event,
1075              Boolean *continue_to_dispatch )
1076 {
1077
1078     Window      cover;
1079     
1080 #ifdef VG_TRACE
1081     vg_TRACE_EXECUTION("main:  entered RefreshEH ...");
1082 #endif /* VG_TRACE */
1083
1084     /*
1085      *  map/unmap a window that covers the entire screen. The resultant
1086      *  exposure events will refresh the screen. Note, the default
1087      *  background pixmap is NONE.
1088      */
1089      
1090     cover = XCreateWindow ( dpyinfo.dpy,                /* display         */
1091                             dpyinfo.root,               /* root window ID  */
1092                             0,                          /* x origin        */
1093                             0,                          /* y origin        */
1094                             dpyinfo.width,              /* width           */
1095                             dpyinfo.height,             /* height          */
1096                             0,                          /* border width    */
1097                             0,                          /* depth           */
1098                             InputOutput,                /* class           */
1099                             CopyFromParent,             /* visual          */
1100                             0,                          /* value mask      */
1101                             (XSetWindowAttributes *)NULL); /* attributes   */
1102     
1103     XMapWindow(dpyinfo.dpy, cover);
1104     XDestroyWindow(dpyinfo.dpy, cover);
1105     XFlush(dpyinfo.dpy);
1106 }
1107
1108
1109 /***************************************************************************
1110  *
1111  *  RequestCB
1112  *
1113  *  Accept a request from client
1114  ***************************************************************************/
1115
1116 void 
1117 RequestCB(
1118         XtPointer client_data,
1119         int *source,
1120         XtInputId *id)
1121 {
1122   char buf[512];
1123   int count;
1124   int remainder;
1125   RequestHeader *phdr = (RequestHeader *)buf;
1126
1127 #ifdef VG_TRACE
1128   vg_TRACE_EXECUTION("main:  entered RequestCB ...");
1129 #endif /* VG_TRACE */
1130
1131  /*
1132   * There's a request in the pipe. Read the header.
1133   */
1134   count = read(0, buf, sizeof(*phdr));
1135   if (count != sizeof(*phdr))
1136   {
1137     return;
1138   }
1139
1140  /*
1141   * Calculate amount of data after header.
1142   */ 
1143   remainder =  phdr->length - sizeof(*phdr);
1144   if (remainder > 0)
1145   {
1146    /*
1147     * Read remainder of request.
1148     */
1149     count = read(0, buf+sizeof(*phdr), remainder);
1150   }
1151
1152  /* 
1153   * Initiate response to request.
1154   */
1155   switch(phdr->opcode)
1156   {
1157     case REQUEST_OP_EXIT:
1158 #ifdef VG_TRACE
1159       vg_TRACE_EXECUTION("main:  got REQUEST_OP_EXIT ...");
1160 #endif /* VG_TRACE */
1161       RespondExitCB(NULL, NULL, NULL);
1162       break;
1163
1164     case REQUEST_OP_MESSAGE:
1165       {
1166         RequestMessage *r = (RequestMessage *)phdr;
1167         XmString string;
1168
1169 #ifdef VG_TRACE
1170         vg_TRACE_EXECUTION("main:  got REQUEST_OP_MESSAGE ...");
1171 #endif /* VG_TRACE */
1172         if (r->idMC)
1173         {
1174           FILE *fp;
1175
1176          /*
1177           * Caller passed in MC_* message id.
1178           */
1179           if (r->idMC == MC_NO_LOGIN &&
1180               (fp = fopen(NO_LOGIN_FILE,"r")) != NULL)
1181           {
1182            /*
1183             * For MC_NO_LOGIN read message from file.
1184             */
1185             char buffer[256];
1186             int j;
1187
1188             string = NULL;
1189
1190             while (fgets(buffer, 256, fp) != NULL)
1191             {
1192               j = strlen(buffer);
1193               if ( buffer[j-1] == '\n' ) buffer[j-1] = '\0';
1194
1195               string = XmStringConcat(xmstr,
1196                                       XmStringCreate(buffer,
1197                                       XmFONTLIST_DEFAULT_TAG));
1198               string = XmStringConcat(xmstr, XmStringSeparatorCreate());
1199             }
1200           }
1201           else
1202           {
1203            /*
1204             * Read message from message catalog.
1205             */
1206             string = ReadCatalogXms(MC_ERROR_SET, r->idMC, buf+r->offMessage);
1207           }
1208         }
1209         else
1210         {
1211          /*
1212           * Generate message from provided string. 
1213           */
1214 #ifdef SIA
1215           string = multiline_xmstring(buf+r->offMessage);
1216 #else
1217           string = XmStringCreate(buf+r->offMessage,XmFONTLIST_DEFAULT_TAG);
1218 #endif
1219         }
1220       
1221         _DtShowDialog(error, string);
1222  
1223         XmStringFree(string);
1224       }
1225       break;
1226
1227     case REQUEST_OP_HOSTNAME:
1228 #ifdef VG_TRACE
1229       vg_TRACE_EXECUTION("main:  got REQUEST_OP_HOSTNAME ...");
1230 #endif /* VG_TRACE */
1231       _DtShowDialog(hostname, NULL);
1232       break;
1233
1234     case REQUEST_OP_EXPASSWORD:
1235 #ifdef VG_TRACE
1236       vg_TRACE_EXECUTION("main:  got REQUEST_OP_EXPASSWORD ...");
1237 #endif /* VG_TRACE */
1238       _DtShowDialog(expassword, NULL);
1239       break;
1240
1241     case REQUEST_OP_CHPASS:
1242 #ifdef VG_TRACE
1243       vg_TRACE_EXECUTION("main:  got REQUEST_OP_CHPASS ...");
1244 #endif /* VG_TRACE */
1245       break;
1246
1247     case REQUEST_OP_CHALLENGE:
1248       {
1249         RequestChallenge *r = (RequestChallenge *)phdr;
1250         XmString string;
1251         int i;
1252         LoginTextPtr textdata;
1253         Boolean change;
1254
1255 #ifdef VG_TRACE
1256         vg_TRACE_EXECUTION("main:  got REQUEST_OP_CHALLENGE ...");
1257 #endif /* VG_TRACE */
1258         textdata = GetLoginTextPtr(login_text);
1259
1260         change = (textdata->bEcho != r->bEcho);
1261
1262         XtUnmapWidget(textdata->text[textdata->bEcho]);
1263
1264         textdata->bEcho = r->bEcho;
1265         textdata->noechobuf[0] = '\0';
1266
1267         XtAddEventHandler(textdata->text[textdata->bEcho], ExposureMask, False,
1268                         FakeFocusIn, NULL);
1269
1270         XtMapWidget(textdata->text[textdata->bEcho]);
1271
1272         XtPopup(login_shell, XtGrabNone); 
1273
1274         XGrabKeyboard (dpyinfo.dpy, XtWindow (textdata->text[textdata->bEcho]),
1275         False, GrabModeAsync, GrabModeAsync, CurrentTime); 
1276
1277         XmTextFieldSetString(
1278           textdata->text[textdata->bEcho],
1279           r->offUserNameSeed ? buf+r->offUserNameSeed : "");
1280
1281         XmTextFieldSetSelection (
1282           textdata->text[1],
1283           0, XmTextFieldGetLastPosition(textdata->text[1]),
1284           CurrentTime );
1285
1286         if (r->idMC)
1287         {
1288          /*
1289           * Read message from message catalog.
1290           */
1291           string = ReadCatalogXms(MC_LABEL_SET, r->idMC, buf+r->offChallenge);
1292         }
1293         else
1294         {
1295          /*
1296           * Generate message from provided string.
1297           */
1298           string = XmStringCreate(buf+r->offChallenge,XmFONTLIST_DEFAULT_TAG);
1299         }
1300
1301         i = 0;
1302         XtSetArg(argt[i], XmNlabelString,       string                   ); i++;
1303         XtSetValues(login_label, argt, i);
1304
1305         XmStringFree(string); 
1306
1307         if (change)
1308         {
1309            char buf[256];
1310
1311            i = 0;
1312            if (textdata->bEcho)
1313            {
1314              XtSetArg(argt[i], XmNlabelString, textdata->onGreeting     ); i++;
1315            }
1316            else
1317            {
1318              sprintf(buf, textdata->offGreetingFormat,
1319                      textdata->offGreetingUname);
1320              string = XmStringCreate(buf, XmFONTLIST_DEFAULT_TAG);
1321              XtSetArg(argt[i], XmNlabelString, string    ); i++;
1322              free(textdata->offGreetingUname);
1323            }
1324            XtSetValues(greeting, argt, i);
1325            /* set the dt_label with the session that is enabled */
1326            SetDtLabelAndIcon();
1327
1328         }
1329
1330         XtSetSensitive(ok_button, True);
1331         XtSetSensitive(clear_button, True);
1332         XtSetSensitive(options_button, True);
1333         XtSetSensitive(help_button, True);
1334
1335         XUngrabKeyboard(dpyinfo.dpy,CurrentTime);
1336       }
1337       break;
1338 #ifdef SIA
1339     case REQUEST_OP_FORM:
1340       {
1341       RequestForm *r = (RequestForm *)buf;
1342       int i;
1343       char *prompt_ptr;
1344
1345 #ifdef VG_TRACE
1346       vg_TRACE_EXECUTION("main:  got REQUEST_OP_FORM ...");
1347 #endif /* VG_TRACE */
1348       siaFormInfo.num_prompts = r->num_prompts;
1349       siaFormInfo.rendition = r->rendition;
1350       siaFormInfo.title = XtMalloc(strlen(buf + r->offTitle));
1351       strcpy(siaFormInfo.title, buf + r->offTitle);
1352
1353       prompt_ptr = buf + r->offPrompts;
1354
1355       for (i=0; i < siaFormInfo.num_prompts; i++)
1356           {
1357           siaFormInfo.visible[i] = r->visible[i];
1358           siaFormInfo.prompts[i] = XtMalloc(strlen(prompt_ptr));
1359           siaFormInfo.answers[i] = NULL;
1360           strcpy(siaFormInfo.prompts[i], prompt_ptr);
1361           prompt_ptr += strlen(prompt_ptr) + 1;
1362           }
1363
1364       /*
1365        * Create Widgets:
1366        *  Form
1367        *   Title
1368        *   prompt labels and answer text fields for each prompt
1369        *   OK button
1370        * Add callbacks as needed.  If not visible don't echo.
1371        * On OK callback, collect info and send it.  Destroy widgets.
1372        */
1373        SiaForm(&siaFormInfo);
1374
1375       }
1376       break;
1377 #endif /* SIA */
1378   }
1379
1380
1381 #if 0
1382   {
1383    /*
1384     * Send immediate response to debug.
1385     */
1386     char outbuf[512];
1387     char *p;
1388     ResponseDebug *rdebug = (ResponseDebug *)outbuf;
1389
1390     rdebug->hdr.opcode = REQUEST_OP_DEBUG;
1391     rdebug->hdr.reserved = 0;
1392     rdebug->offString = sizeof(*rdebug);
1393     p = ((char *)(rdebug)) + rdebug->offString;
1394     strcpy(p, "This is my debug string");
1395     rdebug->hdr.length = sizeof(*rdebug) + strlen(p) + 1;
1396     
1397     TellRequester(outbuf, (size_t) rdebug->hdr.length);
1398   } 
1399 #endif
1400 }
1401
1402 /***************************************************************************
1403  *
1404  *  RespondExitCB
1405  *
1406  *  Respond to an exit request from client
1407  ***************************************************************************/
1408
1409 void 
1410 RespondExitCB(
1411         Widget w,
1412         XtPointer client,
1413         XtPointer call)
1414 {
1415   char buf[REQUEST_LIM_MAXLEN];
1416   ResponseExit *r = (ResponseExit *)buf;
1417
1418 #ifdef VG_TRACE
1419   vg_TRACE_EXECUTION("main:  entered RespondExitCB ...");
1420 #endif /* VG_TRACE */
1421
1422   r->hdr.opcode = REQUEST_OP_EXIT;
1423   r->hdr.reserved = 0;
1424   r->hdr.length = sizeof(*r);
1425
1426   TellRequester(buf, (size_t) r->hdr.length);
1427
1428   CleanupAndExit(NULL, NOTIFY_OK);
1429 }
1430 /***************************************************************************
1431  *
1432  *  RespondLangCB
1433  *
1434  *  Respond to a lang item selection from user
1435  ***************************************************************************/
1436 int amChooser = 0;
1437 int orig_argc;
1438 char **orig_argv;
1439
1440 void
1441 RespondLangCB( Widget w, XtPointer client, XtPointer call)
1442 {
1443   XtSetArg(argt[0], XmNset, True);
1444   XtSetValues(w, argt, 1);
1445
1446 #ifdef VG_TRACE
1447   vg_TRACE_EXECUTION("main:  entered RespondLangCB ...");
1448 #endif /* VG_TRACE */
1449
1450   if (amChooser) {
1451         /** this is probably not the ideal way to do this **/
1452         /** but it does work ok.                          **/
1453         /** notice the related code in chooser.c at the   **/
1454         /** beginning of main.                            **/
1455         char buff[128];
1456         if (XmToggleButtonGadgetGetState(w)) {
1457             strcpy(buff, "LANG="); 
1458             strcat(buff, client);
1459             putenv(buff);
1460             execv(orig_argv[0], orig_argv);
1461         }
1462   } else {
1463     char buf[REQUEST_LIM_MAXLEN];
1464     ResponseLang *r = (ResponseLang *)buf;
1465     char *p;
1466   
1467     r->hdr.opcode = REQUEST_OP_LANG;
1468     r->hdr.reserved = 0;
1469     r->offLang = sizeof(*r);
1470     p = ((char *)(r)) + r->offLang;
1471     strcpy(p, XmToggleButtonGadgetGetState(w) ? client : "default");
1472     r->hdr.length = sizeof(*r) + strlen(p) + 1;
1473
1474     TellRequester(buf, (size_t) r->hdr.length);
1475  
1476     CleanupAndExit(NULL, NOTIFY_LANG_CHANGE);
1477   }
1478 }
1479
1480 /***************************************************************************
1481  *
1482  *  RespondChallengeCB
1483  *
1484  *  Respond to a challenge request from client
1485  ***************************************************************************/
1486
1487 void 
1488 RespondChallengeCB(
1489         Widget w,
1490         XtPointer client,
1491         XtPointer call)
1492 {
1493   char buf[REQUEST_LIM_MAXLEN];
1494   ResponseChallenge *r = (ResponseChallenge *)buf;
1495   char *value;
1496   char *p;
1497   LoginTextPtr textdata;
1498
1499 #ifdef VG_TRACE
1500   vg_TRACE_EXECUTION("main:  entered RespondChallengeCB ...");
1501 #endif /* VG_TRACE */
1502
1503   XtSetSensitive(ok_button, False);
1504   XtSetSensitive(clear_button, False);
1505   XtSetSensitive(options_button, False);
1506   XtSetSensitive(help_button, False);
1507
1508   textdata = GetLoginTextPtr(login_text);
1509
1510  /*
1511   * Get username and password. Username is obtained from widget
1512   * while password is stored in global buffer.
1513   */
1514   if (textdata->bEcho)
1515   {
1516     value = XmTextFieldGetString(login_text);
1517     textdata->offGreetingUname = strdup(value);
1518     userName = strdup(value);
1519     if (strlen(textdata->offGreetingUname) > (size_t) 16)
1520     {
1521       textdata->offGreetingUname[16] = '\0';
1522       userName[16] = '\0';
1523     }
1524   }
1525   else
1526   {
1527     value = textdata->noechobuf;
1528   }
1529
1530   r->hdr.opcode = REQUEST_OP_CHALLENGE;
1531   r->hdr.reserved = 0;
1532   r->offResponse = sizeof(*r);
1533   p = buf + r->offResponse;
1534   strcpy(p, value);
1535   r->hdr.length = r->offResponse + strlen(p) + 1; 
1536
1537   if (textdata->bEcho)
1538   {
1539     XtFree(value);
1540     XmTextFieldSetString(login_text, "");
1541   }
1542   else
1543   {
1544    /*
1545     * Clean password memory to foil snoopers.
1546     */
1547     bzero(textdata->noechobuf, strlen(textdata->noechobuf));
1548   }
1549
1550   TellRequester(buf, (size_t) r->hdr.length);
1551 }
1552
1553 /***************************************************************************
1554  *
1555  *  RespondDialogCB
1556  *
1557  *  Respond to a request that displayed a dialog
1558  ***************************************************************************/
1559
1560 void 
1561 RespondDialogCB(
1562         Widget w,
1563         XtPointer client,
1564         XtPointer call_data)
1565 {
1566   char buf[REQUEST_LIM_MAXLEN];
1567   XmAnyCallbackStruct *reason = (XmAnyCallbackStruct *)call_data;
1568
1569 #ifdef VG_TRACE
1570   vg_TRACE_EXECUTION("main:  entered RespondDialogCB ...");
1571 #endif /* VG_TRACE */
1572
1573   if (w == error_message)
1574   {
1575   ResponseMessage *r= (ResponseMessage *)buf;
1576
1577   r->hdr.opcode = REQUEST_OP_MESSAGE;
1578   r->hdr.reserved = 0;
1579   r->hdr.length = sizeof(*r);
1580
1581   TellRequester(buf, (size_t) r->hdr.length);
1582   } 
1583   else if (w == passwd_message)
1584   {
1585     if (reason->reason == XmCR_OK)
1586     {
1587       CleanupAndExit(w, NOTIFY_PASSWD_EXPIRED);
1588     } 
1589     else
1590     {
1591   ResponseExpassword *r= (ResponseExpassword *)buf;
1592
1593   r->hdr.opcode = REQUEST_OP_EXPASSWORD;
1594   r->hdr.reserved = 0;
1595   r->hdr.length = sizeof(*r);
1596
1597   TellRequester(buf, (size_t) r->hdr.length);
1598     }
1599   }
1600   else if (w == hostname_message)
1601   {
1602     if (reason->reason == XmCR_OK)
1603     {
1604       CleanupAndExit(w, NOTIFY_OK);
1605     } 
1606     else
1607     {
1608       CleanupAndExit(w, NOTIFY_NO_WINDOWS);
1609     }
1610   }
1611 }
1612
1613 /***************************************************************************
1614  *
1615  *  SetDefaultDt
1616  *
1617  *  save the default dt widget.
1618  **************************************************************************/
1619 void
1620 SetDefaultDt(Widget w)
1621 {
1622     default_dt = w;
1623 }
1624
1625 /***************************************************************************
1626  *
1627  *  SetDtLabelAndIcon
1628  *
1629  *  label to display in the dt_label widget and 
1630  *  the logo to display in logo_pixmap 
1631  **************************************************************************/
1632 void
1633 SetDtLabelAndIcon()
1634 {
1635   static XmString       blanks = NULL;
1636   int                   i;
1637   char                  *logoFile;
1638   char                  *logoName;
1639   char                  *temp_p;
1640    
1641 #ifdef VG_TRACE
1642   vg_TRACE_EXECUTION("main:  entered SetDtLabelAndIcon ...");
1643 #endif /* VG_TRACE */
1644
1645   if (NULL == blanks)
1646     blanks = XmStringCreateLocalized("       ");
1647
1648   /*
1649    *  if user is logging in, set dt_label desired. No more than
1650    *  one desktop  can be selected at a time ...
1651    */
1652   i = 0;
1653   XtSetArg(argt[0], XmNset, FALSE); i++;
1654  
1655   XtSetValues(options_failsafe, argt, i);
1656   XtSetValues(options_dtlite, argt, i);
1657   XtSetValues(options_dt, argt, i);
1658   if (options_last_dt != NULL)
1659     XtSetValues(options_last_dt, argt, i);
1660  
1661   for(i = 0; i<appInfo.altDts ; ++i)
1662     if(alt_dts[i] != NULL)
1663       XtSetValues(alt_dts[i], argt, i);
1664
1665   if (NULL != default_dt) {
1666       i = 0;
1667       XtSetArg(argt[i], XmNset, True); i++;
1668       XtSetValues(default_dt, argt, i);
1669
1670       if(default_dt == options_last_dt)
1671         xmstr = blanks;
1672       else
1673       {
1674          i = 0;
1675          XtSetArg(argt[i], XmNlabelString, &xmstr); i++;
1676          XtGetValues(default_dt, argt, i);  
1677       }
1678       
1679       i = 0;
1680       XtSetArg(argt[i], XmNuserData, &logoFile); i++;
1681       XtGetValues(default_dt, argt, i);
1682   }
1683   else {
1684       xmstr = blanks;
1685       logoFile = logoInfo.bitmapFile;
1686   }
1687
1688 #ifdef FIX_FOR_DEFECT_CDExc19307
1689   /*
1690    *  This code causes the Session toggle buttons to be reset
1691    *  to the default setting when the user commits a typing error.
1692    *  NOT very user friendly.
1693    *
1694    *  As for setting the defaults after the user is done entering
1695    *  the we could do the same thing by passing in an argument.  For
1696    *  now, I'm not convinced that it is required.
1697    */
1698
1699   /*
1700    * to set the defaults  after the user is done                         
1701    * entering the login .. 
1702    */
1703    if (strcmp(userName,"\0") != 0)
1704      strcpy(userName,"\0");  
1705 #endif
1706
1707   i = 0;
1708   XtSetArg(argt[i], XmNlabelString, xmstr); i++;
1709   XtSetValues(dt_label, argt, i); 
1710
1711   /* 
1712    * remove trailing spaces 
1713    */
1714   if(strchr(logoFile,' '))
1715      temp_p = strtok(logoFile," ");
1716   else
1717      temp_p = logoFile;
1718  
1719   logoName = _DtGetIconFileName(
1720                         DefaultScreenOfDisplay(dpyinfo.dpy),
1721                         temp_p, NULL, NULL, NULL);
1722  
1723   if (logoName == NULL) {
1724         LogError(
1725         ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
1726                              logoFile);
1727         logoFile = NULL;
1728   }
1729
1730   i = 0;
1731   XtSetArg(argt[i], XmNimageName, logoName); i++;
1732   XtSetValues(logo_pixmap, argt, i);
1733 }
1734
1735 /***************************************************************************
1736  *
1737  *  _DtShowDialog
1738  *
1739  *  display a dialog message box
1740  ***************************************************************************/
1741
1742 static void 
1743 _DtShowDialog( DialogType dtype, XmString msg)
1744 {
1745     Widget *w;
1746     
1747 #ifdef VG_TRACE
1748     vg_TRACE_EXECUTION("main:  entered _DtShowDialog ...");
1749 #endif /* VG_TRACE */
1750
1751     switch (dtype) {
1752       case copyright:  w = &copyright_msg; break;
1753       case error:      w = &error_message; break;
1754       case expassword: w = &passwd_message; break;
1755       case help:       w = &help_message; break;
1756       case hostname:   w = &hostname_message; break;
1757       case help_chooser: w = &help_message; break;
1758     }
1759
1760     if (*w == NULL)
1761     {
1762       MakeDialog(dtype);
1763     }
1764     
1765     if ( msg != NULL ) {
1766         XtSetArg(argt[0], XmNmessageString, msg );
1767         XtSetValues(*w, argt, 1);
1768     }
1769
1770     XtManageChild(*w);
1771
1772     XSetInputFocus(XtDisplay(*w), XtWindow(*w), 
1773                    RevertToPointerRoot, CurrentTime);
1774 }    
1775
1776
1777
1778
1779 /***************************************************************************
1780  *
1781  *  ShowDialogCB
1782  *
1783  *  callback to display a dialog message box
1784  ***************************************************************************/
1785
1786 void 
1787 ShowDialogCB( Widget w, XtPointer dialog, XtPointer call_data )
1788 {
1789
1790     _DtShowDialog( (DialogType) dialog, NULL);
1791 }
1792
1793
1794
1795
1796 /***************************************************************************
1797  *
1798  *  TextFocusCB
1799  *
1800  *  set focusWidget global variable when focus changes
1801  ***************************************************************************/
1802
1803
1804 void 
1805 TextFocusCB( Widget w, XtPointer client_data, XtPointer call_data )
1806 {
1807     if ( w == login_text )
1808         focusWidget = w;
1809 }
1810
1811 /***************************************************************************
1812  *
1813  *  GetLoginTextPtr
1814  *
1815  *  Return login text widget instance data
1816  ***************************************************************************/
1817
1818 LoginTextPtr
1819 GetLoginTextPtr( Widget w )
1820 {
1821   LoginTextPtr textdata;
1822   int i;
1823
1824   i = 0;
1825   XtSetArg(argt[i], XmNuserData,     &textdata              ); i++;
1826   XtGetValues(w, argt, i);
1827
1828   return(textdata);
1829 }
1830
1831
1832 #ifdef BLS
1833 /***************************************************************************
1834  *
1835  *  PromptSensitivityLevel
1836  *
1837  *  Prompt for B1 Sensitivity Level. The password widget set is reused for
1838  *  this purpose rather than creating another complete widget set. It already
1839  *  has most of the proper size and alignment specifications needed. Using
1840  *  the password set also allows the B1 code changes to be more localized.
1841  *
1842  ***************************************************************************/
1843
1844 static void 
1845 PromptSensitivityLevel( void)
1846 {
1847
1848     Dimension   width;
1849     int         i, width1, width2;
1850
1851     /*
1852      *  Use the password widget set to prompt for the B1 Sensitivity Level.
1853      *  Remember to put it back to normal if the user presses [Clear].
1854      */
1855      
1856     normalPasswordWidget = False;
1857     
1858     XtRemoveAllCallbacks(_text, XmNmodifyVerifyCallback);
1859     XmTextFieldSetString(_text,"");
1860
1861
1862     /*
1863      *  Change the label and resize the password form...
1864      */
1865      
1866     i = 0;
1867     XtSetArg(argt[i], XmNresizable,             True                    ); i++;
1868     XtSetArg(argt[i], XmNresizePolicy,          XmRESIZE_ANY            ); i++;
1869     XtSetValues(_form, argt, i);
1870
1871     i = 0;
1872     xmstr = ReadCatalogXms(MC_LABEL_SET, -1, "Sensitivity Level:");
1873     XtSetArg(argt[i], XmNrecomputeSize,         True                    ); i++;
1874     XtSetArg(argt[i], XmNlabelString,           xmstr                   ); i++;
1875     XtSetValues(_label, argt, i);
1876
1877     XmStringFree(xmstr);
1878     
1879     /*
1880      *  Center the form horizontally in the login_matte...
1881      *
1882      */
1883
1884     CenterForm(matte1, _form);
1885     
1886     ProcessTraversal(_text, XmTRAVERSE_CURRENT);
1887
1888 }
1889
1890 #endif /* BLS */
1891
1892
1893 static void
1894 TellRequester(char * buf, size_t nbytes)
1895 {
1896 #ifdef VG_TRACE
1897   vg_TRACE_EXECUTION("main:  entered TellRequester ...");
1898 #endif /* VG_TRACE */
1899   write(1, buf, nbytes);
1900 }