2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $TOG: vgcallback.c /main/16 1998/11/02 18:34:55 mgreess $ */
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. *
30 /************************************<+>*************************************
31 ****************************************************************************
35 ** Project: HP Visual User Environment (DT)
37 ** Description: Callback routines Dtgreet application.
39 ** These routines handle the callbacks from the widgets.
42 ** (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company
46 ****************************************************************************
47 ************************************<+>*************************************/
50 /***************************************************************************
54 ***************************************************************************/
60 #include <sys/signal.h>
61 #include <sys/param.h>
64 #include <Xm/MessageB.h>
66 #include <Xm/TextFP.h>
67 #include <Xm/PushBG.h>
68 #include <Xm/ToggleBG.h>
69 #include <Dt/IconFile.h>
75 # include <sys/audit.h>
78 /* necessary for bzero */
80 #include <X11/Xfuncs.h>
87 /***************************************************************************
89 * External declarations
91 ***************************************************************************/
93 extern LogoInfo logoInfo; /* information about the logo */
97 /***************************************************************************
99 * Procedure declarations
101 ***************************************************************************/
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);
111 static void PromptSensitivityLevel(void); /* prompt for B1 Sen. Level */
112 int VerifySensitivityLevel(void); /* verify B1 Sensitivity Level */
115 static int session_selected = False;
116 static Widget default_dt = NULL;
119 /***************************************************************************
123 ***************************************************************************/
125 Widget focusWidget = NULL;
127 char *userName = "\0";
128 struct passwd *user_p;
132 static int normalPasswordWidget = True;
133 char *sensitivityLevel = NULL;
137 long groups[NGROUPS];
144 SiaFormInfo siaFormInfo;
147 XmString multiline_xmstring(char *text)
152 XmString string = NULL;
154 XmString separator = NULL;
157 if (!text) return (NULL);
160 buffer = alloca(strlen((const char *)text) + 1);
166 while ( ! done) /* loop thu local copy */
167 { /* looking for \n */
170 while ((*end != '\0') && (*end != '\n')) end++;
173 done = TRUE; /* we are at the end */
175 /* Don't convert empty string unless it's an initial newline. */
176 if ((start != end) || (start == text))
178 strncpy(buffer, start, end - start);
179 buffer[end - start] = '\0';
181 string = XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG);
184 tmp_string = XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG);
185 string = XmStringConcat(string, tmp_string);
186 XmStringFree(tmp_string);
190 /* Make a separator if this isn't the last segment. */
194 separator = XmStringSeparatorCreate();
195 string = XmStringConcat(string, separator);
196 start = ++end; /* start at next char */
201 XmStringFree(separator);
209 /***************************************************************************
213 * Utility function to center one form horizontally within another.
214 ***************************************************************************/
217 CenterForm( Widget w1, Widget w2 )
221 int i, width1, width2;
223 XtSetArg(argt[0], XmNwidth, &width);
224 XtGetValues(w1, argt, 1);
227 XtSetArg(argt[0], XmNwidth, &width);
228 XtGetValues(w2, argt, 1);
232 XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM ); i++;
233 XtSetArg(argt[i], XmNleftOffset, (width1 - width2) / 2 ); i++;
234 XtSetValues(w2, argt, i);
240 /***************************************************************************
244 * close things down gracefully and exit
245 ***************************************************************************/
248 CleanupAndExit( Widget w, int exit_code )
251 Boolean toggleon; /* status of session toggle buttons */
254 vg_TRACE_EXECUTION("main: entered CleanupAndExit ...");
255 #endif /* VG_TRACE */
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) ...
265 if ( exit_code == NOTIFY_OK ) {
266 XtSetArg(argt[0], XmNset, &toggleon );
268 XtGetValues(options_failsafe, argt, 1);
269 if ( toggleon ) exit_code = NOTIFY_FAILSAFE;
271 XtGetValues(options_dtlite, argt, 1);
272 if ( toggleon ) exit_code = NOTIFY_DTLITE;
275 XtGetValues(options_dt, argt, 1);
276 if ( toggleon ) exit_code = NOTIFY_DT;
279 if(options_last_dt != NULL) {
280 XtGetValues(options_last_dt, argt, 1);
281 if ( toggleon ) exit_code = NOTIFY_LAST_DT;
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 */
294 if (!session_selected)
295 exit_code = NOTIFY_OK;
301 XSync (dpyinfo.dpy, 0);
303 XtCloseDisplay(dpyinfo.dpy);
308 /***************************************************************************
312 ***************************************************************************/
321 vg_TRACE_EXECUTION("ClearDtlabel: entered ...");
322 #endif /* VG_TRACE */
325 xms = XmStringCreateLocalized(" ");
326 XtSetArg(argt[i], XmNlabelString, xms); i++;
327 XtSetValues(dt_label, argt, i);
332 /***************************************************************************
336 ***************************************************************************/
344 * Clear Dt toggles...
346 XtSetArg(argt[0], XmNset, False);
348 for (i=0; i<appInfo.altDts; ++i)
349 if (alt_dts[i] != NULL)
350 XtSetValues(alt_dts[i], argt, 1);
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);
361 /***************************************************************************
365 * clear name/password text fields
366 ***************************************************************************/
369 RespondClearCB( Widget w, XtPointer client, XtPointer call )
371 char buf[REQUEST_LIM_MAXLEN];
372 ResponseClear *r = (ResponseClear *)buf;
375 vg_TRACE_EXECUTION("main: entered RespondClearCB ...");
376 #endif /* VG_TRACE */
382 r->hdr.opcode = REQUEST_OP_CLEAR;
384 r->hdr.length = sizeof(*r);
386 TellRequester(buf, (size_t) r->hdr.length);
391 /***************************************************************************
395 * move the highlight back to login or password fields AFTER the copyright
396 * dialog is unposted.
398 ***************************************************************************/
401 CopyrightCB( Widget w, XtPointer client_data, XtPointer call_data )
405 vg_TRACE_EXECUTION("main: entered CopyrightCB ...");
406 #endif /* VG_TRACE */
408 if ( focusWidget != NULL)
409 ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT);
415 /***************************************************************************
419 * implement no-echo and no-cursor motion of the password
420 ***************************************************************************/
423 EditPasswdCB(Widget w, XtPointer client, XtPointer call_data)
425 LoginTextPtr textdata;
426 XmTextVerifyPtr cbs = (XmTextVerifyPtr) call_data;
428 static char buffer[MAXPATHLEN];
429 register char *s, *t;
432 vg_TRACE_EXECUTION("main: entered EditPasswdCB ...");
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 */
440 textdata = GetLoginTextPtr(w);
441 if (NULL == textdata || textdata->bEcho) return;
442 if (cbs->reason == XmCR_MOVING_INSERT_CURSOR) return;
444 for (i=0, s=buffer, t=textdata->noechobuf;
445 (*t && i<cbs->startPos);
451 strcpy(s, cbs->text->ptr);
452 s += cbs->text->length;
457 if (strlen(textdata->noechobuf) >= cbs->endPos)
459 t = textdata->noechobuf+cbs->endPos;
464 strcpy(textdata->noechobuf, buffer);
467 for (i=0, s=cbs->text->ptr; i<cbs->text->length; i++, s++)
471 vg_TRACE_EXECUTION("textdata->noechobuf=%s\n", textdata->noechobuf);
476 /***************************************************************************
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.
485 * Also force the initial focus to the login_text widget.
486 ***************************************************************************/
489 FakeFocusIn( Widget focus_widget, XtPointer client_data, XEvent *eventprm,
490 Boolean *continue_to_dispatch )
493 XEvent * eventPtr = &event;
496 vg_TRACE_EXECUTION("main: entered FakeFocusIn ...");
497 #endif /* VG_TRACE */
500 * set the input focus to the login text widget...
503 XSetInputFocus( XtDisplay(focus_widget),
504 XtWindow(focus_widget),
509 * create a synthetic focus-in event.
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)
517 /* focus_widget = login_shell; */
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;
527 XtDispatchEvent (eventPtr);
529 ProcessTraversal(focus_widget, XmTRAVERSE_CURRENT);
531 XtRemoveEventHandler(focus_widget, ExposureMask, FALSE,
535 /***************************************************************************
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
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
550 ***************************************************************************/
553 LayoutCB( Widget w, XtPointer client_data, XtPointer call_data )
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 */
560 struct { /* position, size of widgets (pixels) */
564 } mw, pw; /* matte, logo, drop shadow, login matte
565 and greeting widgets */
567 int width1, width2; /* general width variable */
568 int height1; /* general height variable */
569 Position x1, y1; /* general position variables */
570 int offsety; /* general offset variable */
571 int shadow_offsetx; /* offset for drop shadow (pixels) */
572 int shadow_offsety; /* offset for drop shadow (pixels) */
573 int spacing; /* spacing between login & matte bottoms */
575 Widget buttons[4]; /* pushbutton widgets */
577 XtWidgetGeometry geometry; /* geometry of a widget */
579 int max_width; /* maximum width of a set of widgets */
580 int origin; /* horizontal origin for button placement */
581 int space; /* total available space left between buttons */
582 int overlap; /* possible widget overlap */
585 vg_TRACE_EXECUTION("main: entered LayoutCB ...");
586 #endif /* VG_TRACE */
589 * - squeeze dialog to fit onto screen (if necessary)
592 XtSetArg(argt[i], XmNwidth, &width ); i++;
593 XtGetValues(matte, argt, i);
594 mw.width = ToPixel(matte, XmHORIZONTAL, (int)width );
595 #define HMARGIN 4 /* min sum horizontal margin of matte */
596 if (mw.width+HMARGIN > dpyinfo.width)
598 int delta = mw.width + HMARGIN - dpyinfo.width;
600 * Matte width greater than screen so shrink matteFrame
601 * and matte1 width to compensate.
604 XtSetArg(argt[i], XmNwidth, &width ); i++;
605 XtGetValues(matteFrame, argt, i);
607 width1 = ToPixel(matteFrame, XmHORIZONTAL, (int)width );
609 width1 = FromPixel(matteFrame, XmHORIZONTAL, width1 );
612 XtSetArg(argt[i], XmNwidth, width1 ); i++;
613 XtSetValues(matteFrame, argt, i);
615 width1 = dpyinfo.width - HMARGIN;
616 mw.width = FromPixel(matte, XmHORIZONTAL, width1 );
619 XtSetArg(argt[i], XmNwidth, mw.width ); i++;
620 XtSetValues(matte, argt, i);
624 * - Make sure the login widgets don't overlap.
628 XtSetArg(argt[i], XmNy, &y ); i++;
629 XtSetArg(argt[i], XmNheight, &height ); i++;
630 XtGetValues(greeting, argt, i);
633 XtSetArg(argt[i], XmNy, &y1 ); i++;
634 XtGetValues(login_form, argt, i);
636 overlap = y + height - y1;
640 XtSetArg(argt[i], XmNbottomAttachment, XmATTACH_WIDGET); i++;
641 XtSetArg(argt[i], XmNbottomWidget, login_form); i++;
642 XtSetArg(argt[i], XmNbottomOffset, 10); i++;
643 XtSetValues(greeting, argt, i);
649 * - center the main matte horizontally and vertically...
653 XtSetArg(argt[i], XmNx, &x ); i++;
654 XtSetArg(argt[i], XmNy, &y ); i++;
655 XtSetArg(argt[i], XmNwidth, &width ); i++;
656 XtSetArg(argt[i], XmNheight, &height ); i++;
657 XtSetArg(argt[i], XmNshadowThickness, &shadowThickness ); i++;
658 XtGetValues(matte, argt, i);
660 mw.width = ToPixel(matte, XmHORIZONTAL, (int)width );
661 mw.height = ToPixel(matte, XmVERTICAL, (int)height );
663 mw.x = ( x > 0 ? ToPixel(matte, XmHORIZONTAL, (int) x)
664 : (dpyinfo.width - mw.width)/2 );
666 mw.y = ( y > 0 ? ToPixel(matte, XmVERTICAL, (int) y)
667 : (dpyinfo.height - mw.height)/2 );
669 if ( mw.x < 0 ) mw.x = 0;
670 if ( mw.y < 0 ) mw.y = 0;
672 x1 = FromPixel(matte, XmHORIZONTAL, mw.x );
673 y1 = FromPixel(matte, XmVERTICAL, mw.y );
676 XtSetArg(argt[i], XmNx, x1 ); i++;
677 XtSetArg(argt[i], XmNy, y1 ); i++;
678 XtSetValues(matte, argt, i);
682 * space the buttons horizontally. Start at the center of the matte
683 * and allow them to grow towards the edges...
687 XtSetArg(argt[i], XmNwidth, &width ); i++;
688 XtGetValues(matte1, argt, i);
693 XtSetArg(argt[i], XmNwidth, &width ); i++;
694 XtGetValues(clear_button, argt, i);
696 space = max_width - 4*width;
699 if (spacing < 12) spacing = 12;
702 XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM); i++;
703 XtSetArg(argt[i], XmNleftOffset, spacing/2); i++;
704 XtSetValues(ok_button, argt, i);
707 XtSetArg(argt[i], XmNleftAttachment, XmATTACH_WIDGET ); i++;
708 XtSetArg(argt[i], XmNleftWidget, ok_button); i++;
709 XtSetArg(argt[i], XmNleftOffset, spacing); i++;
710 XtSetValues(clear_button, argt, i);
713 XtSetArg(argt[i], XmNleftAttachment, XmATTACH_WIDGET ); i++;
714 XtSetArg(argt[i], XmNleftWidget, clear_button); i++;
715 XtSetArg(argt[i], XmNleftOffset, spacing); i++;
716 XtSetValues(options_button, argt, i);
719 XtSetArg(argt[i], XmNleftAttachment, XmATTACH_WIDGET ); i++;
720 XtSetArg(argt[i], XmNleftWidget, options_button); i++;
721 XtSetArg(argt[i], XmNleftOffset, spacing); i++;
722 XtSetValues(help_button, argt, i);
725 * - adjust the copyright vertically to align top with login_matte...
729 XtQueryGeometry(copyright_msg, NULL, &geometry);
732 XtSetArg(argt[i], XmNshadowThickness, &width ); i++;
733 XtGetValues(copyright_msg, argt, i);
735 width1 = ToPixel(copyright_msg, XmHORIZONTAL, width);
736 width1 = (dpyinfo.width - (int) geometry.width - 2 * width1)/2;
738 x1 = FromPixel(copyright_msg, XmHORIZONTAL, width1);
739 y1 = FromPixel(copyright_msg, XmVERTICAL, mw.y);
742 XtSetArg(argt[i], XmNdefaultPosition, False ); i++;
743 XtSetArg(argt[i], XmNx, x1 ); i++;
744 XtSetArg(argt[i], XmNy, y1 ); i++;
745 XtSetValues(copyright_msg, argt, i);
752 /***************************************************************************
756 * callback for options menu items
757 ***************************************************************************/
760 MenuItemCB( Widget w, XtPointer client_data, XtPointer call_data )
766 char temp[MAXPATHLEN];
769 vg_TRACE_EXECUTION("main: entered MenuItemCB ...");
770 #endif /* VG_TRACE */
772 session_selected = True;
774 switch ( (int) client_data) {
776 case OB_RESTART_SERVER:
777 CleanupAndExit(NULL, NOTIFY_RESTART);
781 CleanupAndExit(NULL, NOTIFY_NO_WINDOWS);
785 _DtShowDialog(copyright, NULL);
794 * set the label on the dt_label widget..
797 if(w != options_last_dt) {
798 XtSetArg(argt[0], XmNlabelString, &xmstr);
799 XtGetValues(w, argt, 1);
801 XtSetArg(argt[0], XmNlabelString, xmstr);
802 XtSetValues(dt_label, argt, 1);
808 XtSetArg(argt[i], XmNuserData, &logoFile ); i++;
809 XtGetValues(w, argt, i);
812 * remove trailing spaces
814 if(strchr(logoFile,' '))
815 temp_p = strtok(logoFile," ");
819 logoName = _DtGetIconFileName(DefaultScreenOfDisplay(dpyinfo.dpy),
820 temp_p, NULL, NULL, NULL);
822 if (logoName == NULL) {
824 ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
829 XtSetArg(argt[i], XmNimageName, logoName); i++;
830 XtSetValues(logo_pixmap, argt, i);
833 * Clear Dt toggles...
838 * set the selected toggle button...
840 XtSetArg(argt[0], XmNset, True);
841 XtSetValues(w, argt, 1);
846 * return focus to name/password widgets...
849 if ( focusWidget != NULL)
850 ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT);
860 /***************************************************************************
864 * callback when options menu unmaps
865 ***************************************************************************/
868 OptionsUnmapCB( Widget wd, XtPointer client_data, XtPointer call_data )
872 Dimension width, height;
878 vg_TRACE_EXECUTION("main: entered OptionsUnmapCB ...");
879 #endif /* VG_TRACE */
882 * simulate an exposure event over the Options pushbutton to make sure
883 * the pushbutton elevates. (there is a bug in the toolkit where this
884 * doesn't always happen on some servers)...
890 XtSetArg(argt[i], XmNwidth, &width ); i++;
891 XtSetArg(argt[i], XmNheight, &height ); i++;
892 XtGetValues(w, argt, i);
895 event.xexpose.serial = LastKnownRequestProcessed(XtDisplay(w));
896 event.xexpose.send_event = True;
897 event.xexpose.display = XtDisplay(w);
898 event.xexpose.window = XtWindow(w);
901 event.xexpose.width = 1; /* one pixel seems to be good enough, */
902 event.xexpose.height = 1; /* but time will tell... */
904 event.xexpose.width = ToPixel(matte, XmHORIZONTAL, (int)width );
905 event.xexpose.height = ToPixel(matte, XmVERTICAL, (int)height );
907 event.xexpose.count = 0;
909 XtDispatchEvent (&event);
914 /***************************************************************************
918 * Ping the server occasionally with an Xsync to see if it is still there.
919 * We do this here rather than in dtlogin since dtgreet has the server
922 ***************************************************************************/
924 static jmp_buf pingTime;
925 static int serverDead = FALSE;
926 static int pingInterval = 0; /* ping interval (sec.) */
927 static int pingTimeout; /* ping timeout (sec.) */
933 longjmp (pingTime, 1);
938 PingBlocked( int arg )
942 longjmp (pingTime, 1);
953 oldError = XSetIOErrorHandler ((XIOErrorHandler)PingLost);
954 oldAlarm = alarm (0);
955 oldSig = signal (SIGALRM, PingBlocked);
956 alarm (pingTimeout * 60);
957 if (!setjmp (pingTime))
959 XSync (dpyinfo.dpy, 0);
964 LogError(ReadCatalog(
965 MC_LOG_SET,MC_LOG_DEADSRV,MC_DEF_LOG_DEADSRV),
968 signal (SIGALRM, SIG_DFL);
969 XSetIOErrorHandler (oldError);
974 signal (SIGALRM, oldSig);
976 XSetIOErrorHandler (oldError);
982 PingServerCB( XtPointer call_data, XtIntervalId *id )
989 * get ping values from the environment...
992 if ( pingInterval == 0 ) {
993 pingInterval = ((t = (char *)getenv(PINGINTERVAL)) == NULL ? 0 : atoi(t));
994 pingTimeout = ((t = (char *)getenv(PINGTIMEOUT)) == NULL ? 0 : atoi(t));
999 * ping the server. If successful, set a timer for the next ping,
1000 * otherwise cleanup and exit...
1003 if ( pingInterval != 0 ) {
1005 XtAddTimeOut((unsigned long) pingInterval * 60 * 1000,
1006 PingServerCB, NULL);
1008 exit(NOTIFY_RESTART);
1014 /***************************************************************************
1018 * post the option_button pop-up menu
1019 ***************************************************************************/
1022 PostMenuCB( Widget w, XtPointer client_data, XtPointer call_data )
1025 XmAnyCallbackStruct *p;
1027 p = (XmAnyCallbackStruct *) call_data;
1030 vg_TRACE_EXECUTION("main: entered PostMenuCB ...");
1031 #endif /* VG_TRACE */
1034 * make options menus if they don't yet exist...
1037 if (options_menu == NULL)
1045 if (p->reason == XmCR_ARM &&
1046 p->event->type == ButtonPress) {
1048 XmMenuPosition(options_menu, p->event);
1049 XtManageChild(options_menu);
1056 /***************************************************************************
1060 * move the input focus
1061 ***************************************************************************/
1064 ProcessTraversal( Widget w, int direction )
1069 vg_TRACE_EXECUTION("main: entered ProcessTraversal ...");
1070 #endif /* VG_TRACE */
1072 i = XmProcessTraversal(w, direction);
1076 * Versions of Motif other than HP do not support the XmfocusCallback
1077 * on the TextField widget. We simulate it here by manually invoking the
1078 * callback routine...
1081 TextFocusCB(w, NULL, NULL);
1088 /***************************************************************************
1092 * cause the entire screen to refresh via exposure events
1093 ***************************************************************************/
1096 RefreshEH( Widget w, XtPointer client_data, XEvent *event,
1097 Boolean *continue_to_dispatch )
1103 vg_TRACE_EXECUTION("main: entered RefreshEH ...");
1104 #endif /* VG_TRACE */
1107 * map/unmap a window that covers the entire screen. The resultant
1108 * exposure events will refresh the screen. Note, the default
1109 * background pixmap is NONE.
1112 cover = XCreateWindow ( dpyinfo.dpy, /* display */
1113 dpyinfo.root, /* root window ID */
1116 dpyinfo.width, /* width */
1117 dpyinfo.height, /* height */
1118 0, /* border width */
1120 InputOutput, /* class */
1121 CopyFromParent, /* visual */
1123 (XSetWindowAttributes *)NULL); /* attributes */
1125 XMapWindow(dpyinfo.dpy, cover);
1126 XDestroyWindow(dpyinfo.dpy, cover);
1127 XFlush(dpyinfo.dpy);
1131 /***************************************************************************
1135 * Accept a request from client
1136 ***************************************************************************/
1140 XtPointer client_data,
1147 RequestHeader *phdr = (RequestHeader *)buf;
1150 vg_TRACE_EXECUTION("main: entered RequestCB ...");
1151 #endif /* VG_TRACE */
1154 * There's a request in the pipe. Read the header.
1156 count = read(0, buf, sizeof(*phdr));
1157 if (count != sizeof(*phdr))
1163 * Calculate amount of data after header.
1165 remainder = phdr->length - sizeof(*phdr);
1169 * Read remainder of request.
1171 count = read(0, buf+sizeof(*phdr), remainder);
1175 * Initiate response to request.
1177 switch(phdr->opcode)
1179 case REQUEST_OP_EXIT:
1181 vg_TRACE_EXECUTION("main: got REQUEST_OP_EXIT ...");
1182 #endif /* VG_TRACE */
1183 RespondExitCB(NULL, NULL, NULL);
1186 case REQUEST_OP_MESSAGE:
1188 RequestMessage *r = (RequestMessage *)phdr;
1192 vg_TRACE_EXECUTION("main: got REQUEST_OP_MESSAGE ...");
1193 #endif /* VG_TRACE */
1199 * Caller passed in MC_* message id.
1201 if (r->idMC == MC_NO_LOGIN &&
1202 (fp = fopen(NO_LOGIN_FILE,"r")) != NULL)
1205 * For MC_NO_LOGIN read message from file.
1212 while (fgets(buffer, 256, fp) != NULL)
1215 if ( buffer[j-1] == '\n' ) buffer[j-1] = '\0';
1217 string = XmStringConcat(xmstr,
1218 XmStringCreate(buffer,
1219 XmFONTLIST_DEFAULT_TAG));
1220 string = XmStringConcat(xmstr, XmStringSeparatorCreate());
1226 * Read message from message catalog.
1228 string = ReadCatalogXms(MC_ERROR_SET, r->idMC, buf+r->offMessage);
1234 * Generate message from provided string.
1237 string = multiline_xmstring(buf+r->offMessage);
1239 string = XmStringCreate(buf+r->offMessage,XmFONTLIST_DEFAULT_TAG);
1243 _DtShowDialog(error, string);
1245 XmStringFree(string);
1249 case REQUEST_OP_HOSTNAME:
1251 vg_TRACE_EXECUTION("main: got REQUEST_OP_HOSTNAME ...");
1252 #endif /* VG_TRACE */
1253 _DtShowDialog(hostname, NULL);
1256 case REQUEST_OP_EXPASSWORD:
1258 vg_TRACE_EXECUTION("main: got REQUEST_OP_EXPASSWORD ...");
1259 #endif /* VG_TRACE */
1260 _DtShowDialog(expassword, NULL);
1263 case REQUEST_OP_CHPASS:
1265 vg_TRACE_EXECUTION("main: got REQUEST_OP_CHPASS ...");
1266 #endif /* VG_TRACE */
1269 case REQUEST_OP_CHALLENGE:
1271 RequestChallenge *r = (RequestChallenge *)phdr;
1274 LoginTextPtr textdata;
1278 vg_TRACE_EXECUTION("main: got REQUEST_OP_CHALLENGE ...");
1279 #endif /* VG_TRACE */
1280 textdata = GetLoginTextPtr(login_text);
1282 change = (textdata->bEcho != r->bEcho);
1284 XtUnmapWidget(textdata->text[textdata->bEcho]);
1286 textdata->bEcho = r->bEcho;
1287 textdata->noechobuf[0] = '\0';
1289 XtAddEventHandler(textdata->text[textdata->bEcho], ExposureMask, False,
1292 XtMapWidget(textdata->text[textdata->bEcho]);
1294 XtPopup(login_shell, XtGrabNone);
1296 XGrabKeyboard (dpyinfo.dpy, XtWindow (textdata->text[textdata->bEcho]),
1297 False, GrabModeAsync, GrabModeAsync, CurrentTime);
1299 XmTextFieldSetString(
1300 textdata->text[textdata->bEcho],
1301 r->offUserNameSeed ? buf+r->offUserNameSeed : "");
1303 XmTextFieldSetSelection (
1305 0, XmTextFieldGetLastPosition(textdata->text[1]),
1311 * Read message from message catalog.
1313 string = ReadCatalogXms(MC_LABEL_SET, r->idMC, buf+r->offChallenge);
1318 * Generate message from provided string.
1320 string = XmStringCreate(buf+r->offChallenge,XmFONTLIST_DEFAULT_TAG);
1324 XtSetArg(argt[i], XmNlabelString, string ); i++;
1325 XtSetValues(login_label, argt, i);
1327 XmStringFree(string);
1334 if (textdata->bEcho)
1336 XtSetArg(argt[i], XmNlabelString, textdata->onGreeting ); i++;
1340 sprintf(buf, textdata->offGreetingFormat,
1341 textdata->offGreetingUname);
1342 string = XmStringCreate(buf, XmFONTLIST_DEFAULT_TAG);
1343 XtSetArg(argt[i], XmNlabelString, string ); i++;
1344 free(textdata->offGreetingUname);
1346 XtSetValues(greeting, argt, i);
1347 /* set the dt_label with the session that is enabled */
1348 SetDtLabelAndIcon();
1352 XtSetSensitive(ok_button, True);
1353 XtSetSensitive(clear_button, True);
1354 XtSetSensitive(options_button, True);
1355 XtSetSensitive(help_button, True);
1357 XUngrabKeyboard(dpyinfo.dpy,CurrentTime);
1361 case REQUEST_OP_FORM:
1363 RequestForm *r = (RequestForm *)buf;
1368 vg_TRACE_EXECUTION("main: got REQUEST_OP_FORM ...");
1369 #endif /* VG_TRACE */
1370 siaFormInfo.num_prompts = r->num_prompts;
1371 siaFormInfo.rendition = r->rendition;
1372 siaFormInfo.title = XtMalloc(strlen(buf + r->offTitle));
1373 strcpy(siaFormInfo.title, buf + r->offTitle);
1375 prompt_ptr = buf + r->offPrompts;
1377 for (i=0; i < siaFormInfo.num_prompts; i++)
1379 siaFormInfo.visible[i] = r->visible[i];
1380 siaFormInfo.prompts[i] = XtMalloc(strlen(prompt_ptr));
1381 siaFormInfo.answers[i] = NULL;
1382 strcpy(siaFormInfo.prompts[i], prompt_ptr);
1383 prompt_ptr += strlen(prompt_ptr) + 1;
1390 * prompt labels and answer text fields for each prompt
1392 * Add callbacks as needed. If not visible don't echo.
1393 * On OK callback, collect info and send it. Destroy widgets.
1395 SiaForm(&siaFormInfo);
1406 * Send immediate response to debug.
1410 ResponseDebug *rdebug = (ResponseDebug *)outbuf;
1412 rdebug->hdr.opcode = REQUEST_OP_DEBUG;
1413 rdebug->hdr.reserved = 0;
1414 rdebug->offString = sizeof(*rdebug);
1415 p = ((char *)(rdebug)) + rdebug->offString;
1416 strcpy(p, "This is my debug string");
1417 rdebug->hdr.length = sizeof(*rdebug) + strlen(p) + 1;
1419 TellRequester(outbuf, (size_t) rdebug->hdr.length);
1424 /***************************************************************************
1428 * Respond to an exit request from client
1429 ***************************************************************************/
1437 char buf[REQUEST_LIM_MAXLEN];
1438 ResponseExit *r = (ResponseExit *)buf;
1441 vg_TRACE_EXECUTION("main: entered RespondExitCB ...");
1442 #endif /* VG_TRACE */
1444 r->hdr.opcode = REQUEST_OP_EXIT;
1445 r->hdr.reserved = 0;
1446 r->hdr.length = sizeof(*r);
1448 TellRequester(buf, (size_t) r->hdr.length);
1450 CleanupAndExit(NULL, NOTIFY_OK);
1452 /***************************************************************************
1456 * Respond to a lang item selection from user
1457 ***************************************************************************/
1463 RespondLangCB( Widget w, XtPointer client, XtPointer call)
1465 XtSetArg(argt[0], XmNset, True);
1466 XtSetValues(w, argt, 1);
1469 vg_TRACE_EXECUTION("main: entered RespondLangCB ...");
1470 #endif /* VG_TRACE */
1473 /** this is probably not the ideal way to do this **/
1474 /** but it does work ok. **/
1475 /** notice the related code in chooser.c at the **/
1476 /** beginning of main. **/
1478 if (XmToggleButtonGadgetGetState(w)) {
1479 strcpy(buff, "LANG=");
1480 strcat(buff, client);
1482 execv(orig_argv[0], orig_argv);
1485 char buf[REQUEST_LIM_MAXLEN];
1486 ResponseLang *r = (ResponseLang *)buf;
1489 r->hdr.opcode = REQUEST_OP_LANG;
1490 r->hdr.reserved = 0;
1491 r->offLang = sizeof(*r);
1492 p = ((char *)(r)) + r->offLang;
1493 strcpy(p, XmToggleButtonGadgetGetState(w) ? client : "default");
1494 r->hdr.length = sizeof(*r) + strlen(p) + 1;
1496 TellRequester(buf, (size_t) r->hdr.length);
1498 CleanupAndExit(NULL, NOTIFY_LANG_CHANGE);
1502 /***************************************************************************
1504 * RespondChallengeCB
1506 * Respond to a challenge request from client
1507 ***************************************************************************/
1515 char buf[REQUEST_LIM_MAXLEN];
1516 ResponseChallenge *r = (ResponseChallenge *)buf;
1519 LoginTextPtr textdata;
1522 vg_TRACE_EXECUTION("main: entered RespondChallengeCB ...");
1523 #endif /* VG_TRACE */
1525 XtSetSensitive(ok_button, False);
1526 XtSetSensitive(clear_button, False);
1527 XtSetSensitive(options_button, False);
1528 XtSetSensitive(help_button, False);
1530 textdata = GetLoginTextPtr(login_text);
1533 * Get username and password. Username is obtained from widget
1534 * while password is stored in global buffer.
1536 if (textdata->bEcho)
1538 value = XmTextFieldGetString(login_text);
1539 textdata->offGreetingUname = strdup(value);
1540 userName = strdup(value);
1541 if (strlen(textdata->offGreetingUname) > (size_t) 16)
1543 textdata->offGreetingUname[16] = '\0';
1544 userName[16] = '\0';
1549 value = textdata->noechobuf;
1552 r->hdr.opcode = REQUEST_OP_CHALLENGE;
1553 r->hdr.reserved = 0;
1554 r->offResponse = sizeof(*r);
1555 p = buf + r->offResponse;
1557 r->hdr.length = r->offResponse + strlen(p) + 1;
1559 if (textdata->bEcho)
1562 XmTextFieldSetString(login_text, "");
1567 * Clean password memory to foil snoopers.
1569 bzero(textdata->noechobuf, strlen(textdata->noechobuf));
1572 TellRequester(buf, (size_t) r->hdr.length);
1575 /***************************************************************************
1579 * Respond to a request that displayed a dialog
1580 ***************************************************************************/
1586 XtPointer call_data)
1588 char buf[REQUEST_LIM_MAXLEN];
1589 XmAnyCallbackStruct *reason = (XmAnyCallbackStruct *)call_data;
1592 vg_TRACE_EXECUTION("main: entered RespondDialogCB ...");
1593 #endif /* VG_TRACE */
1595 if (w == error_message)
1597 ResponseMessage *r= (ResponseMessage *)buf;
1599 r->hdr.opcode = REQUEST_OP_MESSAGE;
1600 r->hdr.reserved = 0;
1601 r->hdr.length = sizeof(*r);
1603 TellRequester(buf, (size_t) r->hdr.length);
1605 else if (w == passwd_message)
1607 if (reason->reason == XmCR_OK)
1609 CleanupAndExit(w, NOTIFY_PASSWD_EXPIRED);
1613 ResponseExpassword *r= (ResponseExpassword *)buf;
1615 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
1616 r->hdr.reserved = 0;
1617 r->hdr.length = sizeof(*r);
1619 TellRequester(buf, (size_t) r->hdr.length);
1622 else if (w == hostname_message)
1624 if (reason->reason == XmCR_OK)
1626 CleanupAndExit(w, NOTIFY_OK);
1630 CleanupAndExit(w, NOTIFY_NO_WINDOWS);
1635 /***************************************************************************
1639 * save the default dt widget.
1640 **************************************************************************/
1642 SetDefaultDt(Widget w)
1647 /***************************************************************************
1651 * label to display in the dt_label widget and
1652 * the logo to display in logo_pixmap
1653 **************************************************************************/
1657 static XmString blanks = NULL;
1664 vg_TRACE_EXECUTION("main: entered SetDtLabelAndIcon ...");
1665 #endif /* VG_TRACE */
1668 blanks = XmStringCreateLocalized(" ");
1671 * if user is logging in, set dt_label desired. No more than
1672 * one desktop can be selected at a time ...
1675 XtSetArg(argt[0], XmNset, FALSE); i++;
1677 XtSetValues(options_failsafe, argt, i);
1678 XtSetValues(options_dtlite, argt, i);
1679 XtSetValues(options_dt, argt, i);
1680 if (options_last_dt != NULL)
1681 XtSetValues(options_last_dt, argt, i);
1683 for(i = 0; i<appInfo.altDts ; ++i)
1684 if(alt_dts[i] != NULL)
1685 XtSetValues(alt_dts[i], argt, i);
1687 if (NULL != default_dt) {
1689 XtSetArg(argt[i], XmNset, True); i++;
1690 XtSetValues(default_dt, argt, i);
1692 if(default_dt == options_last_dt)
1697 XtSetArg(argt[i], XmNlabelString, &xmstr); i++;
1698 XtGetValues(default_dt, argt, i);
1702 XtSetArg(argt[i], XmNuserData, &logoFile); i++;
1703 XtGetValues(default_dt, argt, i);
1707 logoFile = logoInfo.bitmapFile;
1710 #ifdef FIX_FOR_DEFECT_CDExc19307
1712 * This code causes the Session toggle buttons to be reset
1713 * to the default setting when the user commits a typing error.
1714 * NOT very user friendly.
1716 * As for setting the defaults after the user is done entering
1717 * the we could do the same thing by passing in an argument. For
1718 * now, I'm not convinced that it is required.
1722 * to set the defaults after the user is done
1723 * entering the login ..
1725 if (strcmp(userName,"\0") != 0)
1726 strcpy(userName,"\0");
1730 XtSetArg(argt[i], XmNlabelString, xmstr); i++;
1731 XtSetValues(dt_label, argt, i);
1734 * remove trailing spaces
1736 if(strchr(logoFile,' '))
1737 temp_p = strtok(logoFile," ");
1741 logoName = _DtGetIconFileName(
1742 DefaultScreenOfDisplay(dpyinfo.dpy),
1743 temp_p, NULL, NULL, NULL);
1745 if (logoName == NULL) {
1747 ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
1753 XtSetArg(argt[i], XmNimageName, logoName); i++;
1754 XtSetValues(logo_pixmap, argt, i);
1757 /***************************************************************************
1761 * display a dialog message box
1762 ***************************************************************************/
1765 _DtShowDialog( DialogType dtype, XmString msg)
1770 vg_TRACE_EXECUTION("main: entered _DtShowDialog ...");
1771 #endif /* VG_TRACE */
1774 case copyright: w = ©right_msg; break;
1775 case error: w = &error_message; break;
1776 case expassword: w = &passwd_message; break;
1777 case help: w = &help_message; break;
1778 case hostname: w = &hostname_message; break;
1779 case help_chooser: w = &help_message; break;
1787 if ( msg != NULL ) {
1788 XtSetArg(argt[0], XmNmessageString, msg );
1789 XtSetValues(*w, argt, 1);
1794 XSetInputFocus(XtDisplay(*w), XtWindow(*w),
1795 RevertToPointerRoot, CurrentTime);
1801 /***************************************************************************
1805 * callback to display a dialog message box
1806 ***************************************************************************/
1809 ShowDialogCB( Widget w, XtPointer dialog, XtPointer call_data )
1812 _DtShowDialog( (DialogType) dialog, NULL);
1818 /***************************************************************************
1822 * set focusWidget global variable when focus changes
1823 ***************************************************************************/
1827 TextFocusCB( Widget w, XtPointer client_data, XtPointer call_data )
1829 if ( w == login_text )
1833 /***************************************************************************
1837 * Return login text widget instance data
1838 ***************************************************************************/
1841 GetLoginTextPtr( Widget w )
1843 LoginTextPtr textdata;
1847 XtSetArg(argt[i], XmNuserData, &textdata ); i++;
1848 XtGetValues(w, argt, i);
1855 /***************************************************************************
1857 * PromptSensitivityLevel
1859 * Prompt for B1 Sensitivity Level. The password widget set is reused for
1860 * this purpose rather than creating another complete widget set. It already
1861 * has most of the proper size and alignment specifications needed. Using
1862 * the password set also allows the B1 code changes to be more localized.
1864 ***************************************************************************/
1867 PromptSensitivityLevel( void)
1871 int i, width1, width2;
1874 * Use the password widget set to prompt for the B1 Sensitivity Level.
1875 * Remember to put it back to normal if the user presses [Clear].
1878 normalPasswordWidget = False;
1880 XtRemoveAllCallbacks(_text, XmNmodifyVerifyCallback);
1881 XmTextFieldSetString(_text,"");
1885 * Change the label and resize the password form...
1889 XtSetArg(argt[i], XmNresizable, True ); i++;
1890 XtSetArg(argt[i], XmNresizePolicy, XmRESIZE_ANY ); i++;
1891 XtSetValues(_form, argt, i);
1894 xmstr = ReadCatalogXms(MC_LABEL_SET, -1, "Sensitivity Level:");
1895 XtSetArg(argt[i], XmNrecomputeSize, True ); i++;
1896 XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
1897 XtSetValues(_label, argt, i);
1899 XmStringFree(xmstr);
1902 * Center the form horizontally in the login_matte...
1906 CenterForm(matte1, _form);
1908 ProcessTraversal(_text, XmTRAVERSE_CURRENT);
1916 TellRequester(char * buf, size_t nbytes)
1919 vg_TRACE_EXECUTION("main: entered TellRequester ...");
1920 #endif /* VG_TRACE */
1921 write(1, buf, nbytes);