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