dtlogin: Resolve 27 compiler warnings
[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 librararies 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         strcpy(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 ( (int) 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           else
1247           {
1248            /*
1249             * Read message from message catalog.
1250             */
1251             string = ReadCatalogXms(MC_ERROR_SET, r->idMC, buf+r->offMessage);
1252           }
1253         }
1254         else
1255         {
1256          /*
1257           * Generate message from provided string. 
1258           */
1259 #ifdef SIA
1260           string = multiline_xmstring(buf+r->offMessage);
1261 #else
1262           string = XmStringCreate(buf+r->offMessage,XmFONTLIST_DEFAULT_TAG);
1263 #endif
1264         }
1265       
1266         _DtShowDialog(error, string);
1267  
1268         XmStringFree(string);
1269       }
1270       break;
1271
1272     case REQUEST_OP_HOSTNAME:
1273 #ifdef VG_TRACE
1274       vg_TRACE_EXECUTION("main:  got REQUEST_OP_HOSTNAME ...");
1275 #endif /* VG_TRACE */
1276       _DtShowDialog(hostname, NULL);
1277       break;
1278
1279     case REQUEST_OP_EXPASSWORD:
1280 #ifdef VG_TRACE
1281       vg_TRACE_EXECUTION("main:  got REQUEST_OP_EXPASSWORD ...");
1282 #endif /* VG_TRACE */
1283       _DtShowDialog(expassword, NULL);
1284       break;
1285
1286     case REQUEST_OP_CHPASS:
1287 #ifdef VG_TRACE
1288       vg_TRACE_EXECUTION("main:  got REQUEST_OP_CHPASS ...");
1289 #endif /* VG_TRACE */
1290       break;
1291
1292     case REQUEST_OP_CHALLENGE:
1293       {
1294         RequestChallenge *r = (RequestChallenge *)phdr;
1295         XmString string;
1296         int i;
1297         LoginTextPtr textdata;
1298         Boolean change;
1299
1300 #ifdef VG_TRACE
1301         vg_TRACE_EXECUTION("main:  got REQUEST_OP_CHALLENGE ...");
1302 #endif /* VG_TRACE */
1303         textdata = GetLoginTextPtr(login_text);
1304
1305         change = (textdata->bEcho != r->bEcho);
1306
1307         XtUnmapWidget(textdata->text[textdata->bEcho]);
1308
1309         textdata->bEcho = r->bEcho;
1310         textdata->noechobuf[0] = '\0';
1311
1312         XtAddEventHandler(textdata->text[textdata->bEcho], ExposureMask, False,
1313                         FakeFocusIn, NULL);
1314
1315         XtMapWidget(textdata->text[textdata->bEcho]);
1316
1317         XtPopup(login_shell, XtGrabNone); 
1318
1319         XGrabKeyboard (dpyinfo.dpy, XtWindow (textdata->text[textdata->bEcho]),
1320         False, GrabModeAsync, GrabModeAsync, CurrentTime); 
1321
1322         XmTextFieldSetString(
1323           textdata->text[textdata->bEcho],
1324           r->offUserNameSeed ? buf+r->offUserNameSeed : "");
1325
1326         XmTextFieldSetSelection (
1327           textdata->text[1],
1328           0, XmTextFieldGetLastPosition(textdata->text[1]),
1329           CurrentTime );
1330
1331         if (r->idMC)
1332         {
1333          /*
1334           * Read message from message catalog.
1335           */
1336           string = ReadCatalogXms(MC_LABEL_SET, r->idMC, buf+r->offChallenge);
1337         }
1338         else
1339         {
1340          /*
1341           * Generate message from provided string.
1342           */
1343           string = XmStringCreate(buf+r->offChallenge,XmFONTLIST_DEFAULT_TAG);
1344         }
1345
1346         i = 0;
1347         XtSetArg(argt[i], XmNlabelString,       string                   ); i++;
1348         XtSetValues(login_label, argt, i);
1349
1350         XmStringFree(string); 
1351
1352         if (change)
1353         {
1354            char buf[256];
1355
1356            i = 0;
1357            if (textdata->bEcho)
1358            {
1359              XtSetArg(argt[i], XmNlabelString, textdata->onGreeting     ); i++;
1360            }
1361            else
1362            {
1363              sprintf(buf, textdata->offGreetingFormat,
1364                      textdata->offGreetingUname);
1365              string = XmStringCreate(buf, XmFONTLIST_DEFAULT_TAG);
1366              XtSetArg(argt[i], XmNlabelString, string    ); i++;
1367              free(textdata->offGreetingUname);
1368            }
1369            XtSetValues(greeting, argt, i);
1370            /* set the dt_label with the session that is enabled */
1371            SetDtLabelAndIcon();
1372
1373         }
1374
1375         XtSetSensitive(ok_button, True);
1376         XtSetSensitive(clear_button, True);
1377         XtSetSensitive(options_button, True);
1378         XtSetSensitive(help_button, True);
1379
1380         XUngrabKeyboard(dpyinfo.dpy,CurrentTime);
1381       }
1382       break;
1383 #ifdef SIA
1384     case REQUEST_OP_FORM:
1385       {
1386       RequestForm *r = (RequestForm *)buf;
1387       int i;
1388       char *prompt_ptr;
1389
1390 #ifdef VG_TRACE
1391       vg_TRACE_EXECUTION("main:  got REQUEST_OP_FORM ...");
1392 #endif /* VG_TRACE */
1393       siaFormInfo.num_prompts = r->num_prompts;
1394       siaFormInfo.rendition = r->rendition;
1395       siaFormInfo.title = XtMalloc(strlen(buf + r->offTitle));
1396       strcpy(siaFormInfo.title, buf + r->offTitle);
1397
1398       prompt_ptr = buf + r->offPrompts;
1399
1400       for (i=0; i < siaFormInfo.num_prompts; i++)
1401           {
1402           siaFormInfo.visible[i] = r->visible[i];
1403           siaFormInfo.prompts[i] = XtMalloc(strlen(prompt_ptr));
1404           siaFormInfo.answers[i] = NULL;
1405           strcpy(siaFormInfo.prompts[i], prompt_ptr);
1406           prompt_ptr += strlen(prompt_ptr) + 1;
1407           }
1408
1409       /*
1410        * Create Widgets:
1411        *  Form
1412        *   Title
1413        *   prompt labels and answer text fields for each prompt
1414        *   OK button
1415        * Add callbacks as needed.  If not visible don't echo.
1416        * On OK callback, collect info and send it.  Destroy widgets.
1417        */
1418        SiaForm(&siaFormInfo);
1419
1420       }
1421       break;
1422 #endif /* SIA */
1423   }
1424
1425
1426 #if 0
1427   {
1428    /*
1429     * Send immediate response to debug.
1430     */
1431     char outbuf[512];
1432     char *p;
1433     ResponseDebug *rdebug = (ResponseDebug *)outbuf;
1434
1435     rdebug->hdr.opcode = REQUEST_OP_DEBUG;
1436     rdebug->hdr.reserved = 0;
1437     rdebug->offString = sizeof(*rdebug);
1438     p = ((char *)(rdebug)) + rdebug->offString;
1439     strcpy(p, "This is my debug string");
1440     rdebug->hdr.length = sizeof(*rdebug) + strlen(p) + 1;
1441     
1442     TellRequester(outbuf, (size_t) rdebug->hdr.length);
1443   } 
1444 #endif
1445 }
1446
1447 /***************************************************************************
1448  *
1449  *  RespondExitCB
1450  *
1451  *  Respond to an exit request from client
1452  ***************************************************************************/
1453
1454 void 
1455 RespondExitCB(
1456         Widget w,
1457         XtPointer client,
1458         XtPointer call)
1459 {
1460   char buf[REQUEST_LIM_MAXLEN];
1461   ResponseExit *r = (ResponseExit *)buf;
1462
1463 #ifdef VG_TRACE
1464   vg_TRACE_EXECUTION("main:  entered RespondExitCB ...");
1465 #endif /* VG_TRACE */
1466
1467   r->hdr.opcode = REQUEST_OP_EXIT;
1468   r->hdr.reserved = 0;
1469   r->hdr.length = sizeof(*r);
1470
1471   TellRequester(buf, (size_t) r->hdr.length);
1472
1473   CleanupAndExit(NULL, NOTIFY_OK);
1474 }
1475 /***************************************************************************
1476  *
1477  *  RespondLangCB
1478  *
1479  *  Respond to a lang item selection from user
1480  ***************************************************************************/
1481 int amChooser = 0;
1482 int orig_argc;
1483 char **orig_argv;
1484
1485 void
1486 RespondLangCB( Widget w, XtPointer client, XtPointer call)
1487 {
1488   XtSetArg(argt[0], XmNset, True);
1489   XtSetValues(w, argt, 1);
1490
1491 #ifdef VG_TRACE
1492   vg_TRACE_EXECUTION("main:  entered RespondLangCB ...");
1493 #endif /* VG_TRACE */
1494
1495   if (amChooser) {
1496         /** this is probably not the ideal way to do this **/
1497         /** but it does work ok.                          **/
1498         /** notice the related code in chooser.c at the   **/
1499         /** beginning of main.                            **/
1500         char buff[128];
1501         if (XmToggleButtonGadgetGetState(w)) {
1502             strcpy(buff, "LANG="); 
1503             strcat(buff, client);
1504             putenv(buff);
1505             execv(orig_argv[0], orig_argv);
1506         }
1507   } else {
1508     char buf[REQUEST_LIM_MAXLEN];
1509     ResponseLang *r = (ResponseLang *)buf;
1510     char *p;
1511   
1512     r->hdr.opcode = REQUEST_OP_LANG;
1513     r->hdr.reserved = 0;
1514     r->offLang = sizeof(*r);
1515     p = ((char *)(r)) + r->offLang;
1516     strcpy(p, XmToggleButtonGadgetGetState(w) ? client : "default");
1517     r->hdr.length = sizeof(*r) + strlen(p) + 1;
1518
1519     TellRequester(buf, (size_t) r->hdr.length);
1520  
1521     CleanupAndExit(NULL, NOTIFY_LANG_CHANGE);
1522   }
1523 }
1524
1525 /***************************************************************************
1526  *
1527  *  RespondChallengeCB
1528  *
1529  *  Respond to a challenge request from client
1530  ***************************************************************************/
1531
1532 void 
1533 RespondChallengeCB(
1534         Widget w,
1535         XtPointer client,
1536         XtPointer call)
1537 {
1538   char buf[REQUEST_LIM_MAXLEN];
1539   ResponseChallenge *r = (ResponseChallenge *)buf;
1540   char *value;
1541   char *p;
1542   LoginTextPtr textdata;
1543
1544 #ifdef VG_TRACE
1545   vg_TRACE_EXECUTION("main:  entered RespondChallengeCB ...");
1546 #endif /* VG_TRACE */
1547
1548   XtSetSensitive(ok_button, False);
1549   XtSetSensitive(clear_button, False);
1550   XtSetSensitive(options_button, False);
1551   XtSetSensitive(help_button, False);
1552
1553   textdata = GetLoginTextPtr(login_text);
1554
1555  /*
1556   * Get username and password. Username is obtained from widget
1557   * while password is stored in global buffer.
1558   */
1559   if (textdata->bEcho)
1560   {
1561     value = XmTextFieldGetString(login_text);
1562     textdata->offGreetingUname = strdup(value);
1563     userName = strdup(value);
1564     if (strlen(textdata->offGreetingUname) > (size_t) 16)
1565     {
1566       textdata->offGreetingUname[16] = '\0';
1567       userName[16] = '\0';
1568     }
1569   }
1570   else
1571   {
1572     value = textdata->noechobuf;
1573   }
1574
1575   r->hdr.opcode = REQUEST_OP_CHALLENGE;
1576   r->hdr.reserved = 0;
1577   r->offResponse = sizeof(*r);
1578   p = buf + r->offResponse;
1579   strcpy(p, value);
1580   r->hdr.length = r->offResponse + strlen(p) + 1; 
1581
1582   if (textdata->bEcho)
1583   {
1584     XtFree(value);
1585     XmTextFieldSetString(login_text, "");
1586   }
1587   else
1588   {
1589    /*
1590     * Clean password memory to foil snoopers.
1591     */
1592     bzero(textdata->noechobuf, strlen(textdata->noechobuf));
1593   }
1594
1595   TellRequester(buf, (size_t) r->hdr.length);
1596 }
1597
1598 /***************************************************************************
1599  *
1600  *  RespondDialogCB
1601  *
1602  *  Respond to a request that displayed a dialog
1603  ***************************************************************************/
1604
1605 void 
1606 RespondDialogCB(
1607         Widget w,
1608         XtPointer client,
1609         XtPointer call_data)
1610 {
1611   char buf[REQUEST_LIM_MAXLEN];
1612   XmAnyCallbackStruct *reason = (XmAnyCallbackStruct *)call_data;
1613
1614 #ifdef VG_TRACE
1615   vg_TRACE_EXECUTION("main:  entered RespondDialogCB ...");
1616 #endif /* VG_TRACE */
1617
1618   if (w == error_message)
1619   {
1620   ResponseMessage *r= (ResponseMessage *)buf;
1621
1622   r->hdr.opcode = REQUEST_OP_MESSAGE;
1623   r->hdr.reserved = 0;
1624   r->hdr.length = sizeof(*r);
1625
1626   TellRequester(buf, (size_t) r->hdr.length);
1627   } 
1628   else if (w == passwd_message)
1629   {
1630     if (reason->reason == XmCR_OK)
1631     {
1632       CleanupAndExit(w, NOTIFY_PASSWD_EXPIRED);
1633     } 
1634     else
1635     {
1636   ResponseExpassword *r= (ResponseExpassword *)buf;
1637
1638   r->hdr.opcode = REQUEST_OP_EXPASSWORD;
1639   r->hdr.reserved = 0;
1640   r->hdr.length = sizeof(*r);
1641
1642   TellRequester(buf, (size_t) r->hdr.length);
1643     }
1644   }
1645   else if (w == hostname_message)
1646   {
1647     if (reason->reason == XmCR_OK)
1648     {
1649       CleanupAndExit(w, NOTIFY_OK);
1650     } 
1651     else
1652     {
1653       CleanupAndExit(w, NOTIFY_NO_WINDOWS);
1654     }
1655   }
1656 }
1657
1658 /***************************************************************************
1659  *
1660  *  SetDefaultDt
1661  *
1662  *  save the default dt widget.
1663  **************************************************************************/
1664 void
1665 SetDefaultDt(Widget w)
1666 {
1667     default_dt = w;
1668 }
1669
1670 /***************************************************************************
1671  *
1672  *  SetDtLabelAndIcon
1673  *
1674  *  label to display in the dt_label widget and 
1675  *  the logo to display in logo_pixmap 
1676  **************************************************************************/
1677 void
1678 SetDtLabelAndIcon()
1679 {
1680   static XmString       blanks = NULL;
1681   int                   i;
1682   char                  *logoFile;
1683   char                  *logoName;
1684   char                  *temp_p;
1685    
1686 #ifdef VG_TRACE
1687   vg_TRACE_EXECUTION("main:  entered SetDtLabelAndIcon ...");
1688 #endif /* VG_TRACE */
1689
1690   if (NULL == blanks)
1691     blanks = XmStringCreateLocalized("       ");
1692
1693   /*
1694    *  if user is logging in, set dt_label desired. No more than
1695    *  one desktop  can be selected at a time ...
1696    */
1697   i = 0;
1698   XtSetArg(argt[0], XmNset, FALSE); i++;
1699  
1700   XtSetValues(options_failsafe, argt, i);
1701   XtSetValues(options_dtlite, argt, i);
1702   XtSetValues(options_dt, argt, i);
1703   if (options_last_dt != NULL)
1704     XtSetValues(options_last_dt, argt, i);
1705  
1706   for(i = 0; i<appInfo.altDts ; ++i)
1707     if(alt_dts[i] != NULL)
1708       XtSetValues(alt_dts[i], argt, i);
1709
1710   if (NULL != default_dt) {
1711       i = 0;
1712       XtSetArg(argt[i], XmNset, True); i++;
1713       XtSetValues(default_dt, argt, i);
1714
1715       if(default_dt == options_last_dt)
1716         xmstr = blanks;
1717       else
1718       {
1719          i = 0;
1720          XtSetArg(argt[i], XmNlabelString, &xmstr); i++;
1721          XtGetValues(default_dt, argt, i);  
1722       }
1723       
1724       i = 0;
1725       XtSetArg(argt[i], XmNuserData, &logoFile); i++;
1726       XtGetValues(default_dt, argt, i);
1727   }
1728   else {
1729       xmstr = blanks;
1730       logoFile = logoInfo.bitmapFile;
1731   }
1732
1733 #ifdef FIX_FOR_DEFECT_CDExc19307
1734   /*
1735    *  This code causes the Session toggle buttons to be reset
1736    *  to the default setting when the user commits a typing error.
1737    *  NOT very user friendly.
1738    *
1739    *  As for setting the defaults after the user is done entering
1740    *  the we could do the same thing by passing in an argument.  For
1741    *  now, I'm not convinced that it is required.
1742    */
1743
1744   /*
1745    * to set the defaults  after the user is done                         
1746    * entering the login .. 
1747    */
1748    if (strcmp(userName,"\0") != 0)
1749      strcpy(userName,"\0");  
1750 #endif
1751
1752   i = 0;
1753   XtSetArg(argt[i], XmNlabelString, xmstr); i++;
1754   XtSetValues(dt_label, argt, i); 
1755
1756   /* 
1757    * remove trailing spaces 
1758    */
1759   if(strchr(logoFile,' '))
1760      temp_p = strtok(logoFile," ");
1761   else
1762      temp_p = logoFile;
1763  
1764   logoName = _DtGetIconFileName(
1765                         DefaultScreenOfDisplay(dpyinfo.dpy),
1766                         temp_p, NULL, NULL, 0);
1767  
1768   if (logoName == NULL) {
1769         LogError(
1770         ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
1771                              logoFile);
1772         logoFile = NULL;
1773   }
1774
1775   i = 0;
1776   XtSetArg(argt[i], XmNimageName, logoName); i++;
1777   XtSetValues(logo_pixmap, argt, i);
1778 }
1779
1780 /***************************************************************************
1781  *
1782  *  _DtShowDialog
1783  *
1784  *  display a dialog message box
1785  ***************************************************************************/
1786
1787 static void 
1788 _DtShowDialog( DialogType dtype, XmString msg)
1789 {
1790     Widget *w;
1791     
1792 #ifdef VG_TRACE
1793     vg_TRACE_EXECUTION("main:  entered _DtShowDialog ...");
1794 #endif /* VG_TRACE */
1795
1796     switch (dtype) {
1797       case copyright:  w = &copyright_msg; break;
1798       case error:      w = &error_message; break;
1799       case expassword: w = &passwd_message; break;
1800       case help:       w = &help_message; break;
1801       case hostname:   w = &hostname_message; break;
1802       case help_chooser: w = &help_message; break;
1803     }
1804
1805     if (*w == NULL)
1806     {
1807       MakeDialog(dtype);
1808     }
1809     
1810     if ( msg != NULL ) {
1811         XtSetArg(argt[0], XmNmessageString, msg );
1812         XtSetValues(*w, argt, 1);
1813     }
1814
1815     XtManageChild(*w);
1816
1817     XSetInputFocus(XtDisplay(*w), XtWindow(*w), 
1818                    RevertToPointerRoot, CurrentTime);
1819 }    
1820
1821
1822
1823
1824 /***************************************************************************
1825  *
1826  *  ShowDialogCB
1827  *
1828  *  callback to display a dialog message box
1829  ***************************************************************************/
1830
1831 void 
1832 ShowDialogCB( Widget w, XtPointer dialog, XtPointer call_data )
1833 {
1834
1835     _DtShowDialog( (DialogType) dialog, NULL);
1836 }
1837
1838
1839
1840
1841 /***************************************************************************
1842  *
1843  *  TextFocusCB
1844  *
1845  *  set focusWidget global variable when focus changes
1846  ***************************************************************************/
1847
1848
1849 void 
1850 TextFocusCB( Widget w, XtPointer client_data, XtPointer call_data )
1851 {
1852     if ( w == login_text )
1853         focusWidget = w;
1854 }
1855
1856 /***************************************************************************
1857  *
1858  *  GetLoginTextPtr
1859  *
1860  *  Return login text widget instance data
1861  ***************************************************************************/
1862
1863 LoginTextPtr
1864 GetLoginTextPtr( Widget w )
1865 {
1866   LoginTextPtr textdata;
1867   int i;
1868
1869   i = 0;
1870   XtSetArg(argt[i], XmNuserData,     &textdata              ); i++;
1871   XtGetValues(w, argt, i);
1872
1873   return(textdata);
1874 }
1875
1876
1877 #ifdef BLS
1878 /***************************************************************************
1879  *
1880  *  PromptSensitivityLevel
1881  *
1882  *  Prompt for B1 Sensitivity Level. The password widget set is reused for
1883  *  this purpose rather than creating another complete widget set. It already
1884  *  has most of the proper size and alignment specifications needed. Using
1885  *  the password set also allows the B1 code changes to be more localized.
1886  *
1887  ***************************************************************************/
1888
1889 static void 
1890 PromptSensitivityLevel( void)
1891 {
1892
1893     Dimension   width;
1894     int         i, width1, width2;
1895
1896     /*
1897      *  Use the password widget set to prompt for the B1 Sensitivity Level.
1898      *  Remember to put it back to normal if the user presses [Clear].
1899      */
1900      
1901     normalPasswordWidget = False;
1902     
1903     XtRemoveAllCallbacks(_text, XmNmodifyVerifyCallback);
1904     XmTextFieldSetString(_text,"");
1905
1906
1907     /*
1908      *  Change the label and resize the password form...
1909      */
1910      
1911     i = 0;
1912     XtSetArg(argt[i], XmNresizable,             True                    ); i++;
1913     XtSetArg(argt[i], XmNresizePolicy,          XmRESIZE_ANY            ); i++;
1914     XtSetValues(_form, argt, i);
1915
1916     i = 0;
1917     xmstr = ReadCatalogXms(MC_LABEL_SET, -1, "Sensitivity Level:");
1918     XtSetArg(argt[i], XmNrecomputeSize,         True                    ); i++;
1919     XtSetArg(argt[i], XmNlabelString,           xmstr                   ); i++;
1920     XtSetValues(_label, argt, i);
1921
1922     XmStringFree(xmstr);
1923     
1924     /*
1925      *  Center the form horizontally in the login_matte...
1926      *
1927      */
1928
1929     CenterForm(matte1, _form);
1930     
1931     ProcessTraversal(_text, XmTRAVERSE_CURRENT);
1932
1933 }
1934
1935 #endif /* BLS */
1936
1937
1938 static void
1939 TellRequester(char * buf, size_t nbytes)
1940 {
1941 #ifdef VG_TRACE
1942   vg_TRACE_EXECUTION("main:  entered TellRequester ...");
1943 #endif /* VG_TRACE */
1944   if(-1 == write(1, buf, nbytes)) {
1945     perror(strerror(errno));
1946   }
1947 }