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 libraries 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];
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 snprintf(s, sizeof(buffer) - (s - buffer), "%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 int dpwidth, dpheight; /* JET - display w/h set according to */
561 int xorg, yorg; /* xinerama usage */
563 struct { /* position, size of widgets (pixels) */
567 } mw, pw; /* matte, logo, drop shadow, login matte
568 and greeting widgets */
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 */
578 Widget buttons[4]; /* pushbutton widgets */
580 XtWidgetGeometry geometry; /* geometry of a widget */
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 */
588 vg_TRACE_EXECUTION("main: entered LayoutCB ...");
589 #endif /* VG_TRACE */
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;
601 #else /* no Xinerama */
602 dpwidth = dpyinfo.width;
603 dpheight = dpyinfo.height;
608 * - squeeze dialog to fit onto screen (if necessary)
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)
617 int delta = mw.width + HMARGIN - dpwidth;
619 * Matte width greater than screen so shrink matteFrame
620 * and matte1 width to compensate.
623 XtSetArg(argt[i], XmNwidth, &width ); i++;
624 XtGetValues(matteFrame, argt, i);
626 width1 = ToPixel(matteFrame, XmHORIZONTAL, (int)width );
628 width1 = FromPixel(matteFrame, XmHORIZONTAL, width1 );
631 XtSetArg(argt[i], XmNwidth, width1 ); i++;
632 XtSetValues(matteFrame, argt, i);
634 width1 = dpwidth - HMARGIN;
635 mw.width = FromPixel(matte, XmHORIZONTAL, width1 );
638 XtSetArg(argt[i], XmNwidth, mw.width ); i++;
639 XtSetValues(matte, argt, i);
643 * - Make sure the login widgets don't overlap.
647 XtSetArg(argt[i], XmNy, &y ); i++;
648 XtSetArg(argt[i], XmNheight, &height ); i++;
649 XtGetValues(greeting, argt, i);
652 XtSetArg(argt[i], XmNy, &y1 ); i++;
653 XtGetValues(login_form, argt, i);
655 overlap = y + height - y1;
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);
668 * - center the main matte horizontally and vertically...
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);
679 mw.width = ToPixel(matte, XmHORIZONTAL, (int)width );
680 mw.height = ToPixel(matte, XmVERTICAL, (int)height );
682 mw.x = ( x > 0 ? ToPixel(matte, XmHORIZONTAL, (int) x)
683 : (dpwidth - mw.width)/2 );
685 mw.y = ( y > 0 ? ToPixel(matte, XmVERTICAL, (int) y)
686 : (dpheight - mw.height)/2 );
688 if ( mw.x < 0 ) mw.x = 0;
689 if ( mw.y < 0 ) mw.y = 0;
691 x1 = FromPixel(matte, XmHORIZONTAL, mw.x );
692 y1 = FromPixel(matte, XmVERTICAL, mw.y );
694 x1 += xorg; /* JET - adjust for xinerama */
699 XtSetArg(argt[i], XmNx, x1 ); i++;
700 XtSetArg(argt[i], XmNy, y1 ); i++;
701 XtSetValues(matte, argt, i);
705 * space the buttons horizontally. Start at the center of the matte
706 * and allow them to grow towards the edges...
710 XtSetArg(argt[i], XmNwidth, &width ); i++;
711 XtGetValues(matte1, argt, i);
716 XtSetArg(argt[i], XmNwidth, &width ); i++;
717 XtGetValues(clear_button, argt, i);
719 space = max_width - 4*width;
722 if (spacing < 12) spacing = 12;
725 XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM); i++;
726 XtSetArg(argt[i], XmNleftOffset, spacing/2); i++;
727 XtSetValues(ok_button, argt, i);
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);
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);
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);
748 * - adjust the copyright vertically to align top with login_matte...
752 XtQueryGeometry(copyright_msg, NULL, &geometry);
755 XtSetArg(argt[i], XmNshadowThickness, &width ); i++;
756 XtGetValues(copyright_msg, argt, i);
758 width1 = ToPixel(copyright_msg, XmHORIZONTAL, width);
759 width1 = (dpwidth - (int) geometry.width - 2 * width1)/2;
761 x1 = FromPixel(copyright_msg, XmHORIZONTAL, width1);
762 y1 = FromPixel(copyright_msg, XmVERTICAL, mw.y);
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);
775 /***************************************************************************
779 * callback for options menu items
780 ***************************************************************************/
783 MenuItemCB( Widget w, XtPointer client_data, XtPointer call_data )
789 char temp[MAXPATHLEN];
792 vg_TRACE_EXECUTION("main: entered MenuItemCB ...");
793 #endif /* VG_TRACE */
795 session_selected = True;
797 switch ( (long) client_data) {
799 case OB_RESTART_SERVER:
800 CleanupAndExit(NULL, NOTIFY_RESTART);
804 CleanupAndExit(NULL, NOTIFY_NO_WINDOWS);
808 _DtShowDialog(copyright, NULL);
817 * set the label on the dt_label widget..
820 if(w != options_last_dt) {
821 XtSetArg(argt[0], XmNlabelString, &xmstr);
822 XtGetValues(w, argt, 1);
824 XtSetArg(argt[0], XmNlabelString, xmstr);
825 XtSetValues(dt_label, argt, 1);
831 XtSetArg(argt[i], XmNuserData, &logoFile ); i++;
832 XtGetValues(w, argt, i);
835 * remove trailing spaces
837 if(strchr(logoFile,' '))
838 temp_p = strtok(logoFile," ");
842 logoName = _DtGetIconFileName(DefaultScreenOfDisplay(dpyinfo.dpy),
843 temp_p, NULL, NULL, 0);
845 if (logoName == NULL) {
847 ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
852 XtSetArg(argt[i], XmNimageName, logoName); i++;
853 XtSetValues(logo_pixmap, argt, i);
856 * Clear Dt toggles...
861 * set the selected toggle button...
863 XtSetArg(argt[0], XmNset, True);
864 XtSetValues(w, argt, 1);
869 * return focus to name/password widgets...
872 if ( focusWidget != NULL)
873 ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT);
883 /***************************************************************************
887 * callback when options menu unmaps
888 ***************************************************************************/
891 OptionsUnmapCB( Widget wd, XtPointer client_data, XtPointer call_data )
895 Dimension width, height;
901 vg_TRACE_EXECUTION("main: entered OptionsUnmapCB ...");
902 #endif /* VG_TRACE */
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)...
913 XtSetArg(argt[i], XmNwidth, &width ); i++;
914 XtSetArg(argt[i], XmNheight, &height ); i++;
915 XtGetValues(w, argt, i);
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);
924 event.xexpose.width = 1; /* one pixel seems to be good enough, */
925 event.xexpose.height = 1; /* but time will tell... */
927 event.xexpose.width = ToPixel(matte, XmHORIZONTAL, (int)width );
928 event.xexpose.height = ToPixel(matte, XmVERTICAL, (int)height );
930 event.xexpose.count = 0;
932 XtDispatchEvent (&event);
937 /***************************************************************************
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
945 ***************************************************************************/
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.) */
956 longjmp (pingTime, 1);
961 PingBlocked( int arg )
965 longjmp (pingTime, 1);
976 oldError = XSetIOErrorHandler ((XIOErrorHandler)PingLost);
977 oldAlarm = alarm (0);
978 oldSig = signal (SIGALRM, PingBlocked);
979 alarm (pingTimeout * 60);
980 if (!setjmp (pingTime))
982 XSync (dpyinfo.dpy, 0);
987 LogError(ReadCatalog(
988 MC_LOG_SET,MC_LOG_DEADSRV,MC_DEF_LOG_DEADSRV),
991 signal (SIGALRM, SIG_DFL);
992 XSetIOErrorHandler (oldError);
997 signal (SIGALRM, oldSig);
999 XSetIOErrorHandler (oldError);
1005 PingServerCB( XtPointer call_data, XtIntervalId *id )
1012 * get ping values from the environment...
1015 if ( pingInterval == 0 ) {
1016 pingInterval = ((t = (char *)getenv(PINGINTERVAL)) == NULL ? 0 : atoi(t));
1017 pingTimeout = ((t = (char *)getenv(PINGTIMEOUT)) == NULL ? 0 : atoi(t));
1022 * ping the server. If successful, set a timer for the next ping,
1023 * otherwise cleanup and exit...
1026 if ( pingInterval != 0 ) {
1028 XtAddTimeOut((unsigned long) pingInterval * 60 * 1000,
1029 PingServerCB, NULL);
1031 exit(NOTIFY_RESTART);
1037 /***************************************************************************
1041 * post the option_button pop-up menu
1042 ***************************************************************************/
1045 PostMenuCB( Widget w, XtPointer client_data, XtPointer call_data )
1048 XmAnyCallbackStruct *p;
1050 p = (XmAnyCallbackStruct *) call_data;
1053 vg_TRACE_EXECUTION("main: entered PostMenuCB ...");
1054 #endif /* VG_TRACE */
1057 * make options menus if they don't yet exist...
1060 if (options_menu == NULL)
1068 if (p->reason == XmCR_ARM &&
1069 p->event->type == ButtonPress) {
1071 XmMenuPosition(options_menu, p->event);
1072 XtManageChild(options_menu);
1079 /***************************************************************************
1083 * move the input focus
1084 ***************************************************************************/
1087 ProcessTraversal( Widget w, int direction )
1092 vg_TRACE_EXECUTION("main: entered ProcessTraversal ...");
1093 #endif /* VG_TRACE */
1095 i = XmProcessTraversal(w, direction);
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...
1104 TextFocusCB(w, NULL, NULL);
1111 /***************************************************************************
1115 * cause the entire screen to refresh via exposure events
1116 ***************************************************************************/
1119 RefreshEH( Widget w, XtPointer client_data, XEvent *event,
1120 Boolean *continue_to_dispatch )
1126 vg_TRACE_EXECUTION("main: entered RefreshEH ...");
1127 #endif /* VG_TRACE */
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.
1135 cover = XCreateWindow ( dpyinfo.dpy, /* display */
1136 dpyinfo.root, /* root window ID */
1139 dpyinfo.width, /* width */
1140 dpyinfo.height, /* height */
1141 0, /* border width */
1143 InputOutput, /* class */
1144 CopyFromParent, /* visual */
1146 (XSetWindowAttributes *)NULL); /* attributes */
1148 XMapWindow(dpyinfo.dpy, cover);
1149 XDestroyWindow(dpyinfo.dpy, cover);
1150 XFlush(dpyinfo.dpy);
1154 /***************************************************************************
1158 * Accept a request from client
1159 ***************************************************************************/
1163 XtPointer client_data,
1170 RequestHeader *phdr = (RequestHeader *)buf;
1173 vg_TRACE_EXECUTION("main: entered RequestCB ...");
1174 #endif /* VG_TRACE */
1177 * There's a request in the pipe. Read the header.
1179 count = read(0, buf, sizeof(*phdr));
1180 if (count != sizeof(*phdr))
1186 * Calculate amount of data after header.
1188 remainder = phdr->length - sizeof(*phdr);
1192 * Read remainder of request.
1194 count = read(0, buf+sizeof(*phdr), remainder);
1198 * Initiate response to request.
1200 switch(phdr->opcode)
1202 case REQUEST_OP_EXIT:
1204 vg_TRACE_EXECUTION("main: got REQUEST_OP_EXIT ...");
1205 #endif /* VG_TRACE */
1206 RespondExitCB(NULL, NULL, NULL);
1209 case REQUEST_OP_MESSAGE:
1211 RequestMessage *r = (RequestMessage *)phdr;
1215 vg_TRACE_EXECUTION("main: got REQUEST_OP_MESSAGE ...");
1216 #endif /* VG_TRACE */
1222 * Caller passed in MC_* message id.
1224 if (r->idMC == MC_NO_LOGIN &&
1225 (fp = fopen(NO_LOGIN_FILE,"r")) != NULL)
1228 * For MC_NO_LOGIN read message from file.
1235 while (fgets(buffer, 256, fp) != NULL)
1238 if ( buffer[j-1] == '\n' ) buffer[j-1] = '\0';
1240 string = XmStringConcat(xmstr,
1241 XmStringCreate(buffer,
1242 XmFONTLIST_DEFAULT_TAG));
1243 string = XmStringConcat(xmstr, XmStringSeparatorCreate());
1251 * Read message from message catalog.
1253 string = ReadCatalogXms(MC_ERROR_SET, r->idMC, buf+r->offMessage);
1259 * Generate message from provided string.
1262 string = multiline_xmstring(buf+r->offMessage);
1264 string = XmStringCreate(buf+r->offMessage,XmFONTLIST_DEFAULT_TAG);
1268 _DtShowDialog(error, string);
1270 XmStringFree(string);
1274 case REQUEST_OP_HOSTNAME:
1276 vg_TRACE_EXECUTION("main: got REQUEST_OP_HOSTNAME ...");
1277 #endif /* VG_TRACE */
1278 _DtShowDialog(hostname, NULL);
1281 case REQUEST_OP_EXPASSWORD:
1283 vg_TRACE_EXECUTION("main: got REQUEST_OP_EXPASSWORD ...");
1284 #endif /* VG_TRACE */
1285 _DtShowDialog(expassword, NULL);
1288 case REQUEST_OP_CHPASS:
1290 vg_TRACE_EXECUTION("main: got REQUEST_OP_CHPASS ...");
1291 #endif /* VG_TRACE */
1294 case REQUEST_OP_CHALLENGE:
1296 RequestChallenge *r = (RequestChallenge *)phdr;
1299 LoginTextPtr textdata;
1303 vg_TRACE_EXECUTION("main: got REQUEST_OP_CHALLENGE ...");
1304 #endif /* VG_TRACE */
1305 textdata = GetLoginTextPtr(login_text);
1307 change = (textdata->bEcho != r->bEcho);
1309 XtUnmapWidget(textdata->text[textdata->bEcho]);
1311 textdata->bEcho = r->bEcho;
1312 textdata->noechobuf[0] = '\0';
1314 XtAddEventHandler(textdata->text[textdata->bEcho], ExposureMask, False,
1317 XtMapWidget(textdata->text[textdata->bEcho]);
1319 XtPopup(login_shell, XtGrabNone);
1321 XGrabKeyboard (dpyinfo.dpy, XtWindow (textdata->text[textdata->bEcho]),
1322 False, GrabModeAsync, GrabModeAsync, CurrentTime);
1324 XmTextFieldSetString(
1325 textdata->text[textdata->bEcho],
1326 r->offUserNameSeed ? buf+r->offUserNameSeed : "");
1328 XmTextFieldSetSelection (
1330 0, XmTextFieldGetLastPosition(textdata->text[1]),
1336 * Read message from message catalog.
1338 string = ReadCatalogXms(MC_LABEL_SET, r->idMC, buf+r->offChallenge);
1343 * Generate message from provided string.
1345 string = XmStringCreate(buf+r->offChallenge,XmFONTLIST_DEFAULT_TAG);
1349 XtSetArg(argt[i], XmNlabelString, string ); i++;
1350 XtSetValues(login_label, argt, i);
1352 XmStringFree(string);
1359 if (textdata->bEcho)
1361 XtSetArg(argt[i], XmNlabelString, textdata->onGreeting ); i++;
1365 sprintf(buf, textdata->offGreetingFormat,
1366 textdata->offGreetingUname);
1367 string = XmStringCreate(buf, XmFONTLIST_DEFAULT_TAG);
1368 XtSetArg(argt[i], XmNlabelString, string ); i++;
1369 free(textdata->offGreetingUname);
1371 XtSetValues(greeting, argt, i);
1372 /* set the dt_label with the session that is enabled */
1373 SetDtLabelAndIcon();
1377 XtSetSensitive(ok_button, True);
1378 XtSetSensitive(clear_button, True);
1379 XtSetSensitive(options_button, True);
1380 XtSetSensitive(help_button, True);
1382 XUngrabKeyboard(dpyinfo.dpy,CurrentTime);
1386 case REQUEST_OP_FORM:
1388 RequestForm *r = (RequestForm *)buf;
1393 vg_TRACE_EXECUTION("main: got REQUEST_OP_FORM ...");
1394 #endif /* VG_TRACE */
1395 siaFormInfo.num_prompts = r->num_prompts;
1396 siaFormInfo.rendition = r->rendition;
1397 siaFormInfo.title = XtMalloc(strlen(buf + r->offTitle));
1398 strcpy(siaFormInfo.title, buf + r->offTitle);
1400 prompt_ptr = buf + r->offPrompts;
1402 for (i=0; i < siaFormInfo.num_prompts; i++)
1404 siaFormInfo.visible[i] = r->visible[i];
1405 siaFormInfo.prompts[i] = XtMalloc(strlen(prompt_ptr));
1406 siaFormInfo.answers[i] = NULL;
1407 strcpy(siaFormInfo.prompts[i], prompt_ptr);
1408 prompt_ptr += strlen(prompt_ptr) + 1;
1415 * prompt labels and answer text fields for each prompt
1417 * Add callbacks as needed. If not visible don't echo.
1418 * On OK callback, collect info and send it. Destroy widgets.
1420 SiaForm(&siaFormInfo);
1431 * Send immediate response to debug.
1435 ResponseDebug *rdebug = (ResponseDebug *)outbuf;
1437 rdebug->hdr.opcode = REQUEST_OP_DEBUG;
1438 rdebug->hdr.reserved = 0;
1439 rdebug->offString = sizeof(*rdebug);
1440 p = ((char *)(rdebug)) + rdebug->offString;
1441 strcpy(p, "This is my debug string");
1442 rdebug->hdr.length = sizeof(*rdebug) + strlen(p) + 1;
1444 TellRequester(outbuf, (size_t) rdebug->hdr.length);
1449 /***************************************************************************
1453 * Respond to an exit request from client
1454 ***************************************************************************/
1462 char buf[REQUEST_LIM_MAXLEN];
1463 ResponseExit *r = (ResponseExit *)buf;
1466 vg_TRACE_EXECUTION("main: entered RespondExitCB ...");
1467 #endif /* VG_TRACE */
1469 r->hdr.opcode = REQUEST_OP_EXIT;
1470 r->hdr.reserved = 0;
1471 r->hdr.length = sizeof(*r);
1473 TellRequester(buf, (size_t) r->hdr.length);
1475 CleanupAndExit(NULL, NOTIFY_OK);
1477 /***************************************************************************
1481 * Respond to a lang item selection from user
1482 ***************************************************************************/
1488 RespondLangCB( Widget w, XtPointer client, XtPointer call)
1490 XtSetArg(argt[0], XmNset, True);
1491 XtSetValues(w, argt, 1);
1494 vg_TRACE_EXECUTION("main: entered RespondLangCB ...");
1495 #endif /* VG_TRACE */
1498 /** this is probably not the ideal way to do this **/
1499 /** but it does work ok. **/
1500 /** notice the related code in chooser.c at the **/
1501 /** beginning of main. **/
1503 if (XmToggleButtonGadgetGetState(w)) {
1504 snprintf(buff, sizeof(buff), "LANG=%s", (char *) client);
1506 execv(orig_argv[0], orig_argv);
1509 char buf[REQUEST_LIM_MAXLEN];
1510 ResponseLang *r = (ResponseLang *)buf;
1513 r->hdr.opcode = REQUEST_OP_LANG;
1514 r->hdr.reserved = 0;
1515 r->offLang = sizeof(*r);
1516 p = ((char *)(r)) + r->offLang;
1517 strcpy(p, XmToggleButtonGadgetGetState(w) ? client : "default");
1518 r->hdr.length = sizeof(*r) + strlen(p) + 1;
1520 TellRequester(buf, (size_t) r->hdr.length);
1522 CleanupAndExit(NULL, NOTIFY_LANG_CHANGE);
1526 /***************************************************************************
1528 * RespondChallengeCB
1530 * Respond to a challenge request from client
1531 ***************************************************************************/
1539 char buf[REQUEST_LIM_MAXLEN];
1540 ResponseChallenge *r = (ResponseChallenge *)buf;
1543 LoginTextPtr textdata;
1546 vg_TRACE_EXECUTION("main: entered RespondChallengeCB ...");
1547 #endif /* VG_TRACE */
1549 XtSetSensitive(ok_button, False);
1550 XtSetSensitive(clear_button, False);
1551 XtSetSensitive(options_button, False);
1552 XtSetSensitive(help_button, False);
1554 textdata = GetLoginTextPtr(login_text);
1557 * Get username and password. Username is obtained from widget
1558 * while password is stored in global buffer.
1560 if (textdata->bEcho)
1562 value = XmTextFieldGetString(login_text);
1563 textdata->offGreetingUname = strdup(value);
1564 userName = strdup(value);
1565 if (strlen(textdata->offGreetingUname) > (size_t) 16)
1567 textdata->offGreetingUname[16] = '\0';
1568 userName[16] = '\0';
1573 value = textdata->noechobuf;
1576 r->hdr.opcode = REQUEST_OP_CHALLENGE;
1577 r->hdr.reserved = 0;
1578 r->offResponse = sizeof(*r);
1579 p = buf + r->offResponse;
1581 r->hdr.length = r->offResponse + strlen(p) + 1;
1583 if (textdata->bEcho)
1586 XmTextFieldSetString(login_text, "");
1591 * Clean password memory to foil snoopers.
1593 bzero(textdata->noechobuf, strlen(textdata->noechobuf));
1596 TellRequester(buf, (size_t) r->hdr.length);
1599 /***************************************************************************
1603 * Respond to a request that displayed a dialog
1604 ***************************************************************************/
1610 XtPointer call_data)
1612 char buf[REQUEST_LIM_MAXLEN];
1613 XmAnyCallbackStruct *reason = (XmAnyCallbackStruct *)call_data;
1616 vg_TRACE_EXECUTION("main: entered RespondDialogCB ...");
1617 #endif /* VG_TRACE */
1619 if (w == error_message)
1621 ResponseMessage *r= (ResponseMessage *)buf;
1623 r->hdr.opcode = REQUEST_OP_MESSAGE;
1624 r->hdr.reserved = 0;
1625 r->hdr.length = sizeof(*r);
1627 TellRequester(buf, (size_t) r->hdr.length);
1629 else if (w == passwd_message)
1631 if (reason->reason == XmCR_OK)
1633 CleanupAndExit(w, NOTIFY_PASSWD_EXPIRED);
1637 ResponseExpassword *r= (ResponseExpassword *)buf;
1639 r->hdr.opcode = REQUEST_OP_EXPASSWORD;
1640 r->hdr.reserved = 0;
1641 r->hdr.length = sizeof(*r);
1643 TellRequester(buf, (size_t) r->hdr.length);
1646 else if (w == hostname_message)
1648 if (reason->reason == XmCR_OK)
1650 CleanupAndExit(w, NOTIFY_OK);
1654 CleanupAndExit(w, NOTIFY_NO_WINDOWS);
1659 /***************************************************************************
1663 * save the default dt widget.
1664 **************************************************************************/
1666 SetDefaultDt(Widget w)
1671 /***************************************************************************
1675 * label to display in the dt_label widget and
1676 * the logo to display in logo_pixmap
1677 **************************************************************************/
1679 SetDtLabelAndIcon(void)
1681 static XmString blanks = NULL;
1688 vg_TRACE_EXECUTION("main: entered SetDtLabelAndIcon ...");
1689 #endif /* VG_TRACE */
1692 blanks = XmStringCreateLocalized(" ");
1695 * if user is logging in, set dt_label desired. No more than
1696 * one desktop can be selected at a time ...
1699 XtSetArg(argt[0], XmNset, FALSE); i++;
1701 XtSetValues(options_failsafe, argt, i);
1702 XtSetValues(options_dtlite, argt, i);
1703 XtSetValues(options_dt, argt, i);
1704 if (options_last_dt != NULL)
1705 XtSetValues(options_last_dt, argt, i);
1707 for(i = 0; i<appInfo.altDts ; ++i)
1708 if(alt_dts[i] != NULL)
1709 XtSetValues(alt_dts[i], argt, i);
1711 if (NULL != default_dt) {
1713 XtSetArg(argt[i], XmNset, True); i++;
1714 XtSetValues(default_dt, argt, i);
1716 if(default_dt == options_last_dt)
1721 XtSetArg(argt[i], XmNlabelString, &xmstr); i++;
1722 XtGetValues(default_dt, argt, i);
1726 XtSetArg(argt[i], XmNuserData, &logoFile); i++;
1727 XtGetValues(default_dt, argt, i);
1731 logoFile = logoInfo.bitmapFile;
1734 #ifdef FIX_FOR_DEFECT_CDExc19307
1736 * This code causes the Session toggle buttons to be reset
1737 * to the default setting when the user commits a typing error.
1738 * NOT very user friendly.
1740 * As for setting the defaults after the user is done entering
1741 * the we could do the same thing by passing in an argument. For
1742 * now, I'm not convinced that it is required.
1746 * to set the defaults after the user is done
1747 * entering the login ..
1749 if (strcmp(userName,"\0") != 0)
1750 strcpy(userName,"\0");
1754 XtSetArg(argt[i], XmNlabelString, xmstr); i++;
1755 XtSetValues(dt_label, argt, i);
1758 * remove trailing spaces
1760 if(strchr(logoFile,' '))
1761 temp_p = strtok(logoFile," ");
1765 logoName = _DtGetIconFileName(
1766 DefaultScreenOfDisplay(dpyinfo.dpy),
1767 temp_p, NULL, NULL, 0);
1769 if (logoName == NULL) {
1771 ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT),
1777 XtSetArg(argt[i], XmNimageName, logoName); i++;
1778 XtSetValues(logo_pixmap, argt, i);
1781 /***************************************************************************
1785 * display a dialog message box
1786 ***************************************************************************/
1789 _DtShowDialog( DialogType dtype, XmString msg)
1794 vg_TRACE_EXECUTION("main: entered _DtShowDialog ...");
1795 #endif /* VG_TRACE */
1798 case copyright: w = ©right_msg; break;
1799 case error: w = &error_message; break;
1800 case expassword: w = &passwd_message; break;
1801 case help: w = &help_message; break;
1802 case hostname: w = &hostname_message; break;
1803 case help_chooser: w = &help_message; break;
1811 if ( msg != NULL ) {
1812 XtSetArg(argt[0], XmNmessageString, msg );
1813 XtSetValues(*w, argt, 1);
1818 XSetInputFocus(XtDisplay(*w), XtWindow(*w),
1819 RevertToPointerRoot, CurrentTime);
1825 /***************************************************************************
1829 * callback to display a dialog message box
1830 ***************************************************************************/
1833 ShowDialogCB( Widget w, XtPointer dialog, XtPointer call_data )
1836 _DtShowDialog( (DialogType) dialog, NULL);
1842 /***************************************************************************
1846 * set focusWidget global variable when focus changes
1847 ***************************************************************************/
1851 TextFocusCB( Widget w, XtPointer client_data, XtPointer call_data )
1853 if ( w == login_text )
1857 /***************************************************************************
1861 * Return login text widget instance data
1862 ***************************************************************************/
1865 GetLoginTextPtr( Widget w )
1867 LoginTextPtr textdata;
1871 XtSetArg(argt[i], XmNuserData, &textdata ); i++;
1872 XtGetValues(w, argt, i);
1879 /***************************************************************************
1881 * PromptSensitivityLevel
1883 * Prompt for B1 Sensitivity Level. The password widget set is reused for
1884 * this purpose rather than creating another complete widget set. It already
1885 * has most of the proper size and alignment specifications needed. Using
1886 * the password set also allows the B1 code changes to be more localized.
1888 ***************************************************************************/
1891 PromptSensitivityLevel( void)
1895 int i, width1, width2;
1898 * Use the password widget set to prompt for the B1 Sensitivity Level.
1899 * Remember to put it back to normal if the user presses [Clear].
1902 normalPasswordWidget = False;
1904 XtRemoveAllCallbacks(_text, XmNmodifyVerifyCallback);
1905 XmTextFieldSetString(_text,"");
1909 * Change the label and resize the password form...
1913 XtSetArg(argt[i], XmNresizable, True ); i++;
1914 XtSetArg(argt[i], XmNresizePolicy, XmRESIZE_ANY ); i++;
1915 XtSetValues(_form, argt, i);
1918 xmstr = ReadCatalogXms(MC_LABEL_SET, -1, "Sensitivity Level:");
1919 XtSetArg(argt[i], XmNrecomputeSize, True ); i++;
1920 XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
1921 XtSetValues(_label, argt, i);
1923 XmStringFree(xmstr);
1926 * Center the form horizontally in the login_matte...
1930 CenterForm(matte1, _form);
1932 ProcessTraversal(_text, XmTRAVERSE_CURRENT);
1940 TellRequester(char * buf, size_t nbytes)
1943 vg_TRACE_EXECUTION("main: entered TellRequester ...");
1944 #endif /* VG_TRACE */
1945 if(-1 == write(1, buf, nbytes)) {
1946 perror(strerror(errno));