/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* $TOG: vgcallback.c /main/16 1998/11/02 18:34:55 mgreess $ */ /* * * (c) Copyright 1993, 1994 Hewlett-Packard Company * * (c) Copyright 1993, 1994 International Business Machines Corp. * * (c) Copyright 1993, 1994 Sun Microsystems, Inc. * * (c) Copyright 1993, 1994 Novell, Inc. * */ /************************************<+>************************************* **************************************************************************** ** ** File: vgcallback.c ** ** Project: HP Visual User Environment (DT) ** ** Description: Callback routines Dtgreet application. ** ** These routines handle the callbacks from the widgets. ** ** ** (c) Copyright 1987, 1988, 1989 by Hewlett-Packard Company ** ** ** **************************************************************************** ************************************<+>*************************************/ /*************************************************************************** * * Includes * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #undef USE_XFT #include #include #include #include #include #include
#include
#include #ifdef AUDIT # include #endif /* necessary for bzero */ #ifdef SVR4 #include #endif #include "vg.h" #include "vgmsg.h" /*************************************************************************** * * External declarations * ***************************************************************************/ extern LogoInfo logoInfo; /* information about the logo */ /*************************************************************************** * * Procedure declarations * ***************************************************************************/ static void CenterForm( Widget w1, Widget w2); static void PingLost( void ) ; static SIGVAL PingBlocked( int arg ) ; static void ProcessTraversal( Widget w, int direction) ; static void _DtShowDialog(DialogType dtype, XmString msg); static void TellRequester(char * buf, size_t nbytes); # ifdef BLS static void PromptSensitivityLevel(void); /* prompt for B1 Sen. Level */ int VerifySensitivityLevel(void); /* verify B1 Sensitivity Level */ # endif static int session_selected = False; static Widget default_dt = NULL; /*************************************************************************** * * Global variables * ***************************************************************************/ Widget focusWidget = NULL; char *userName = "\0"; struct passwd *user_p; #ifdef BLS static int normalPasswordWidget = True; char *sensitivityLevel = NULL; #endif #ifndef SVR4 long groups[NGROUPS]; #endif #ifdef SIA #include SiaFormInfo siaFormInfo; XmString multiline_xmstring(char *text) { char *start, *end; Boolean done; XmString string = NULL; XmString tmp_string; XmString separator = NULL; char *buffer; if (!text) return (NULL); buffer = alloca(strlen((const char *)text) + 1); start = text; done = FALSE; while ( ! done) /* loop thu local copy */ { /* looking for \n */ end = start; while ((*end != '\0') && (*end != '\n')) end++; if (*end == '\0') done = TRUE; /* we are at the end */ /* Don't convert empty string unless it's an initial newline. */ if ((start != end) || (start == text)) { strncpy(buffer, start, end - start); buffer[end - start] = '\0'; if (!string) string = XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG); else { tmp_string = XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG); string = XmStringConcat(string, tmp_string); XmStringFree(tmp_string); } } /* Make a separator if this isn't the last segment. */ if (!done) { if (!separator) separator = XmStringSeparatorCreate(); string = XmStringConcat(string, separator); start = ++end; /* start at next char */ } } if (separator) XmStringFree(separator); return (string); } #endif /* SIA */ /*************************************************************************** * * CenterForm * * Utility function to center one form horizontally within another. ***************************************************************************/ static void CenterForm( Widget w1, Widget w2 ) { Dimension width; int i, width1, width2; XtSetArg(argt[0], XmNwidth, &width); XtGetValues(w1, argt, 1); width1 = (int)width; XtSetArg(argt[0], XmNwidth, &width); XtGetValues(w2, argt, 1); width2 = (int)width; i = 0; XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM ); i++; XtSetArg(argt[i], XmNleftOffset, (width1 - width2) / 2 ); i++; XtSetValues(w2, argt, i); } /*************************************************************************** * * CleanupAndExit * * close things down gracefully and exit ***************************************************************************/ void CleanupAndExit( Widget w, int exit_code ) { int i; Boolean toggleon; /* status of session toggle buttons */ #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered CleanupAndExit ..."); #endif /* VG_TRACE */ if (w != NULL) XtDestroyWidget(w); /* * if user is logging in, set type of session desired. No more than * one session type can be selected at a time (if any) ... */ if ( exit_code == NOTIFY_OK ) { XtSetArg(argt[0], XmNset, &toggleon ); XtGetValues(options_failsafe, argt, 1); if ( toggleon ) exit_code = NOTIFY_FAILSAFE; XtGetValues(options_dtlite, argt, 1); if ( toggleon ) exit_code = NOTIFY_DTLITE; XtGetValues(options_dt, argt, 1); if ( toggleon ) exit_code = NOTIFY_DT; if(options_last_dt != NULL) { XtGetValues(options_last_dt, argt, 1); if ( toggleon ) exit_code = NOTIFY_LAST_DT; } for(i = 0; i < appInfo.altDts ; ++i) { if(alt_dts[i] != NULL) { XtGetValues(alt_dts[i], argt, 1); if ( toggleon ) exit_code = NOTIFY_ALT_DTS + i + 1; /* alt desktops start at 1 */ } } } if (!session_selected) exit_code = NOTIFY_OK; CloseCatalog(); ChangeBell("on"); UnsecureDisplay(); XSync (dpyinfo.dpy, 0); XtCloseDisplay(dpyinfo.dpy); exit (exit_code); } /*************************************************************************** * * ClearDtlabel * ***************************************************************************/ static void ClearDtlabel(void) { int i; XmString xms; #ifdef VG_TRACE vg_TRACE_EXECUTION("ClearDtlabel: entered ..."); #endif /* VG_TRACE */ i = 0; xms = XmStringCreateLocalized(" "); XtSetArg(argt[i], XmNlabelString, xms); i++; XtSetValues(dt_label, argt, i); XmStringFree(xms); } /*************************************************************************** * * ClearDtlabel * ***************************************************************************/ static void ClearDtButtons(void) { int i; /* * Clear Dt toggles... */ XtSetArg(argt[0], XmNset, False); for (i=0; ihdr.opcode = REQUEST_OP_CLEAR; r->hdr.reserved = 0; r->hdr.length = sizeof(*r); TellRequester(buf, (size_t) r->hdr.length); } /*************************************************************************** * * CopyrightCB * * move the highlight back to login or password fields AFTER the copyright * dialog is unposted. * ***************************************************************************/ void CopyrightCB( Widget w, XtPointer client_data, XtPointer call_data ) { #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered CopyrightCB ..."); #endif /* VG_TRACE */ if ( focusWidget != NULL) ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT); } /*************************************************************************** * * EditPasswdCB * * implement no-echo and no-cursor motion of the password ***************************************************************************/ void EditPasswdCB(Widget w, XtPointer client, XtPointer call_data) { LoginTextPtr textdata; XmTextVerifyPtr cbs = (XmTextVerifyPtr) call_data; int i; static char buffer[MAXPATHLEN]; char *s, *t; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered EditPasswdCB ..."); vg_TRACE_EXECUTION( "currInsert=%d newInsert=%d startPos=%d endPos=%d\n", cbs->currInsert,cbs->newInsert,cbs->startPos, cbs->endPos); if (cbs->text->ptr) vg_TRACE_EXECUTION("text->ptr=%s\n", cbs->text->ptr); vg_TRACE_EXECUTION("noechobuf=%s\n", textdata->noechobuf); #endif /* VG_TRACE */ textdata = GetLoginTextPtr(w); if (NULL == textdata || textdata->bEcho) return; if (cbs->reason == XmCR_MOVING_INSERT_CURSOR) return; for (i=0, s=buffer, t=textdata->noechobuf; (*t && istartPos); i++, s++, t++) *s = *t; if (cbs->text->ptr) { snprintf(s, sizeof(buffer) - (s - buffer), "%s", cbs->text->ptr); s += cbs->text->length; } else *s = '\0'; if (strlen(textdata->noechobuf) >= cbs->endPos) { t = textdata->noechobuf+cbs->endPos; if (strlen(t)) strcpy(s, t); } strcpy(textdata->noechobuf, buffer); if (cbs->text->ptr) for (i=0, s=cbs->text->ptr; itext->length; i++, s++) *s = '*'; #ifdef VG_TRACE vg_TRACE_EXECUTION("textdata->noechobuf=%s\n", textdata->noechobuf); #endif } /*************************************************************************** * * FakeFocusIn * * simulate a FocusIn event to the login_shell in order to turn on * traversal. There is a bug in the Toolkit that is normally masked by * the window manager. Since we have no window manager, we need to simulate * the FocusIn event it sends to the application. * * Also force the initial focus to the login_text widget. ***************************************************************************/ void FakeFocusIn( Widget focus_widget, XtPointer client_data, XEvent *eventprm, Boolean *continue_to_dispatch ) { XEvent event; XEvent * eventPtr = &event; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered FakeFocusIn ..."); #endif /* VG_TRACE */ /* * set the input focus to the login text widget... */ XSetInputFocus( XtDisplay(focus_widget), XtWindow(focus_widget), RevertToNone, CurrentTime); /* * create a synthetic focus-in event. * * Note: The above call to XSetInputFocus() was not originally included * in this routine. A bug fix to Motif made it necessary to add * the call. The synthetic focus-in event is probably now * unnecessary but is left in for caution's sake. (12/08/92) */ /* focus_widget = login_shell; */ eventPtr->type = FocusIn; eventPtr->xfocus.serial = LastKnownRequestProcessed(XtDisplay(focus_widget)); eventPtr->xfocus.send_event = True; eventPtr->xfocus.display = XtDisplay(focus_widget); eventPtr->xfocus.window = XtWindow(focus_widget); eventPtr->xfocus.mode = NotifyNormal; eventPtr->xfocus.detail = NotifyAncestor; XtDispatchEvent (eventPtr); ProcessTraversal(focus_widget, XmTRAVERSE_CURRENT); XtRemoveEventHandler(focus_widget, ExposureMask, FALSE, FakeFocusIn, NULL); } /*************************************************************************** * * LayoutCB * * do final layout adjustments right before windows are mapped. This is * necessary because the size of managers (Forms, etc) is not known until * their window has been created (XtRealize). We want to make adjustments * before the windows become visible * * 1. squeeze dialog width to fit on screen. * 2. increase dialog height if widgets overlap. * 3. center the main matte horizontally and vertically * 4. position the pushbuttons * 5. position the copyright * ***************************************************************************/ void LayoutCB( Widget w, XtPointer client_data, XtPointer call_data ) { int i, j; Dimension width, height; /* size values returned by XtGetValues */ Dimension shadowThickness;/* size values returned by XtGetValues */ Position x, y; /* position values returned by XtGetValues */ int dpwidth, dpheight; /* JET - display w/h set according to */ int xorg, yorg; /* xinerama usage */ struct { /* position, size of widgets (pixels) */ int x, y; int width; int height; } mw, pw; /* matte, logo, drop shadow, login matte and greeting widgets */ int width1, width2; /* general width variable */ int height1; /* general height variable */ Position x1, y1; /* general position variables */ int offsety; /* general offset variable */ int shadow_offsetx; /* offset for drop shadow (pixels) */ int shadow_offsety; /* offset for drop shadow (pixels) */ int spacing; /* spacing between login & matte bottoms */ Widget buttons[4]; /* pushbutton widgets */ XtWidgetGeometry geometry; /* geometry of a widget */ int max_width; /* maximum width of a set of widgets */ int origin; /* horizontal origin for button placement */ int space; /* total available space left between buttons */ int overlap; /* possible widget overlap */ #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered LayoutCB ..."); #endif /* VG_TRACE */ #ifdef USE_XINERAMA /* get info on the prefered screen */ if (!_DtXineramaGetScreen(dpyinfo.DtXineramaInfo, appInfo.xineramaPreferredScreen, &dpwidth, &dpheight, &xorg, &yorg)) { /* no joy here either - setup for normal */ dpwidth = dpyinfo.width; dpheight = dpyinfo.height; xorg = yorg = 0; } #else /* no Xinerama */ dpwidth = dpyinfo.width; dpheight = dpyinfo.height; xorg = yorg = 0; #endif /* * - squeeze dialog to fit onto screen (if necessary) */ i = 0; XtSetArg(argt[i], XmNwidth, &width ); i++; XtGetValues(matte, argt, i); mw.width = ToPixel(matte, XmHORIZONTAL, (int)width ); #define HMARGIN 4 /* min sum horizontal margin of matte */ if (mw.width+HMARGIN > dpwidth) { int delta = mw.width + HMARGIN - dpwidth; /* * Matte width greater than screen so shrink matteFrame * and matte1 width to compensate. */ i=0; XtSetArg(argt[i], XmNwidth, &width ); i++; XtGetValues(matteFrame, argt, i); width1 = ToPixel(matteFrame, XmHORIZONTAL, (int)width ); width1 -= delta; width1 = FromPixel(matteFrame, XmHORIZONTAL, width1 ); i=0; XtSetArg(argt[i], XmNwidth, width1 ); i++; XtSetValues(matteFrame, argt, i); width1 = dpwidth - HMARGIN; mw.width = FromPixel(matte, XmHORIZONTAL, width1 ); i=0; XtSetArg(argt[i], XmNwidth, mw.width ); i++; XtSetValues(matte, argt, i); } /* * - Make sure the login widgets don't overlap. */ if (login_form) { i = 0; XtSetArg(argt[i], XmNy, &y ); i++; XtSetArg(argt[i], XmNheight, &height ); i++; XtGetValues(greeting, argt, i); i = 0; XtSetArg(argt[i], XmNy, &y1 ); i++; XtGetValues(login_form, argt, i); overlap = y + height - y1; if (overlap > -10) { i = 0; XtSetArg(argt[i], XmNbottomAttachment, XmATTACH_WIDGET); i++; XtSetArg(argt[i], XmNbottomWidget, login_form); i++; XtSetArg(argt[i], XmNbottomOffset, 10); i++; XtSetValues(greeting, argt, i); } } /* * - center the main matte horizontally and vertically... */ i = 0; XtSetArg(argt[i], XmNx, &x ); i++; XtSetArg(argt[i], XmNy, &y ); i++; XtSetArg(argt[i], XmNwidth, &width ); i++; XtSetArg(argt[i], XmNheight, &height ); i++; XtSetArg(argt[i], XmNshadowThickness, &shadowThickness ); i++; XtGetValues(matte, argt, i); mw.width = ToPixel(matte, XmHORIZONTAL, (int)width ); mw.height = ToPixel(matte, XmVERTICAL, (int)height ); mw.x = ( x > 0 ? ToPixel(matte, XmHORIZONTAL, (int) x) : (dpwidth - mw.width)/2 ); mw.y = ( y > 0 ? ToPixel(matte, XmVERTICAL, (int) y) : (dpheight - mw.height)/2 ); if ( mw.x < 0 ) mw.x = 0; if ( mw.y < 0 ) mw.y = 0; x1 = FromPixel(matte, XmHORIZONTAL, mw.x ); y1 = FromPixel(matte, XmVERTICAL, mw.y ); x1 += xorg; /* JET - adjust for xinerama */ y1 += yorg; i = 0; XtSetArg(argt[i], XmNx, x1 ); i++; XtSetArg(argt[i], XmNy, y1 ); i++; XtSetValues(matte, argt, i); /* * space the buttons horizontally. Start at the center of the matte * and allow them to grow towards the edges... */ i = 0; XtSetArg(argt[i], XmNwidth, &width ); i++; XtGetValues(matte1, argt, i); max_width = width; i = 0; XtSetArg(argt[i], XmNwidth, &width ); i++; XtGetValues(clear_button, argt, i); space = max_width - 4*width; spacing = space/4; if (spacing < 12) spacing = 12; i = 0; XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM); i++; XtSetArg(argt[i], XmNleftOffset, spacing/2); i++; XtSetValues(ok_button, argt, i); i = 0; XtSetArg(argt[i], XmNleftAttachment, XmATTACH_WIDGET ); i++; XtSetArg(argt[i], XmNleftWidget, ok_button); i++; XtSetArg(argt[i], XmNleftOffset, spacing); i++; XtSetValues(clear_button, argt, i); i = 0; XtSetArg(argt[i], XmNleftAttachment, XmATTACH_WIDGET ); i++; XtSetArg(argt[i], XmNleftWidget, clear_button); i++; XtSetArg(argt[i], XmNleftOffset, spacing); i++; XtSetValues(options_button, argt, i); i = 0; XtSetArg(argt[i], XmNleftAttachment, XmATTACH_WIDGET ); i++; XtSetArg(argt[i], XmNleftWidget, options_button); i++; XtSetArg(argt[i], XmNleftOffset, spacing); i++; XtSetValues(help_button, argt, i); /* * - adjust the copyright vertically to align top with login_matte... */ if (copyright_msg) { XtQueryGeometry(copyright_msg, NULL, &geometry); i = 0; XtSetArg(argt[i], XmNshadowThickness, &width ); i++; XtGetValues(copyright_msg, argt, i); width1 = ToPixel(copyright_msg, XmHORIZONTAL, width); width1 = (dpwidth - (int) geometry.width - 2 * width1)/2; x1 = FromPixel(copyright_msg, XmHORIZONTAL, width1); y1 = FromPixel(copyright_msg, XmVERTICAL, mw.y); i = 0; XtSetArg(argt[i], XmNdefaultPosition, False ); i++; XtSetArg(argt[i], XmNx, x1 ); i++; XtSetArg(argt[i], XmNy, y1 ); i++; XtSetValues(copyright_msg, argt, i); } } /*************************************************************************** * * MenuItemCB * * callback for options menu items ***************************************************************************/ void MenuItemCB( Widget w, XtPointer client_data, XtPointer call_data ) { int i; char *logoFile; char *logoName; char *temp_p; char temp[MAXPATHLEN]; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered MenuItemCB ..."); #endif /* VG_TRACE */ session_selected = True; switch ( (long) client_data) { case OB_RESTART_SERVER: CleanupAndExit(NULL, NOTIFY_RESTART); break; case OB_NO_WINDOWS: CleanupAndExit(NULL, NOTIFY_NO_WINDOWS); break; case OB_COPYRIGHT: _DtShowDialog(copyright, NULL); break; case OB_ALT_DTS: case OB_FAILSAFE: case OB_DTLITE: case OB_DT: case OB_LAST_DT: /* * set the label on the dt_label widget.. */ if(w != options_last_dt) { XtSetArg(argt[0], XmNlabelString, &xmstr); XtGetValues(w, argt, 1); XtSetArg(argt[0], XmNlabelString, xmstr); XtSetValues(dt_label, argt, 1); } else ClearDtlabel(); i = 0; XtSetArg(argt[i], XmNuserData, &logoFile ); i++; XtGetValues(w, argt, i); /* * remove trailing spaces */ if(strchr(logoFile,' ')) temp_p = strtok(logoFile," "); else temp_p = logoFile; logoName = _DtGetIconFileName(DefaultScreenOfDisplay(dpyinfo.dpy), temp_p, NULL, NULL, 0); if (logoName == NULL) { LogError( ReadCatalog(MC_LOG_SET,MC_LOG_NO_LOGOBIT,MC_DEF_LOG_NO_LOGOBIT), logoFile); logoFile = NULL; } i = 0; XtSetArg(argt[i], XmNimageName, logoName); i++; XtSetValues(logo_pixmap, argt, i); /* * Clear Dt toggles... */ ClearDtButtons(); /* * set the selected toggle button... */ XtSetArg(argt[0], XmNset, True); XtSetValues(w, argt, 1); SetDefaultDt(w); /* * return focus to name/password widgets... */ if ( focusWidget != NULL) ProcessTraversal(focusWidget, XmTRAVERSE_CURRENT); break; } } /*************************************************************************** * * OptionsUnmapCB * * callback when options menu unmaps ***************************************************************************/ void OptionsUnmapCB( Widget wd, XtPointer client_data, XtPointer call_data ) { int i; Dimension width, height; Widget w; XEvent event; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered OptionsUnmapCB ..."); #endif /* VG_TRACE */ /* * simulate an exposure event over the Options pushbutton to make sure * the pushbutton elevates. (there is a bug in the toolkit where this * doesn't always happen on some servers)... */ w = options_button; i = 0; XtSetArg(argt[i], XmNwidth, &width ); i++; XtSetArg(argt[i], XmNheight, &height ); i++; XtGetValues(w, argt, i); event.type = Expose; event.xexpose.serial = LastKnownRequestProcessed(XtDisplay(w)); event.xexpose.send_event = True; event.xexpose.display = XtDisplay(w); event.xexpose.window = XtWindow(w); event.xexpose.x = 0; event.xexpose.y = 0; event.xexpose.width = 1; /* one pixel seems to be good enough, */ event.xexpose.height = 1; /* but time will tell... */ #if 0 event.xexpose.width = ToPixel(matte, XmHORIZONTAL, (int)width ); event.xexpose.height = ToPixel(matte, XmVERTICAL, (int)height ); #endif event.xexpose.count = 0; XtDispatchEvent (&event); } /*************************************************************************** * * PingServerCB * * Ping the server occasionally with an Xsync to see if it is still there. * We do this here rather than in dtlogin since dtgreet has the server * grabbed. * ***************************************************************************/ static jmp_buf pingTime; static int serverDead = FALSE; static int pingInterval = 0; /* ping interval (sec.) */ static int pingTimeout; /* ping timeout (sec.) */ static void PingLost( void ) { serverDead = TRUE; longjmp (pingTime, 1); } static SIGVAL PingBlocked( int arg ) { serverDead = TRUE; longjmp (pingTime, 1); } int PingServer( void ) { int (*oldError)(); SIGVAL (*oldSig)(); int oldAlarm; oldError = XSetIOErrorHandler ((XIOErrorHandler)PingLost); oldAlarm = alarm (0); oldSig = signal (SIGALRM, PingBlocked); alarm (pingTimeout * 60); if (!setjmp (pingTime)) { XSync (dpyinfo.dpy, 0); } else { if ( serverDead ) { LogError(ReadCatalog( MC_LOG_SET,MC_LOG_DEADSRV,MC_DEF_LOG_DEADSRV), dpyinfo.name); alarm (0); signal (SIGALRM, SIG_DFL); XSetIOErrorHandler (oldError); return 0; } } alarm (0); signal (SIGALRM, oldSig); alarm (oldAlarm); XSetIOErrorHandler (oldError); return 1; } void PingServerCB( XtPointer call_data, XtIntervalId *id ) { char *t; /* * get ping values from the environment... */ if ( pingInterval == 0 ) { pingInterval = ((t = (char *)getenv(PINGINTERVAL)) == NULL ? 0 : atoi(t)); pingTimeout = ((t = (char *)getenv(PINGTIMEOUT)) == NULL ? 0 : atoi(t)); } /* * ping the server. If successful, set a timer for the next ping, * otherwise cleanup and exit... */ if ( pingInterval != 0 ) { if (PingServer()) XtAddTimeOut((unsigned long) pingInterval * 60 * 1000, PingServerCB, NULL); else exit(NOTIFY_RESTART); } } /*************************************************************************** * * PostMenuCB * * post the option_button pop-up menu ***************************************************************************/ void PostMenuCB( Widget w, XtPointer client_data, XtPointer call_data ) { XmAnyCallbackStruct *p; p = (XmAnyCallbackStruct *) call_data; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered PostMenuCB ..."); #endif /* VG_TRACE */ /* * make options menus if they don't yet exist... */ if (options_menu == NULL) MakeOptionsMenu(); /* * post menu... */ if (p->reason == XmCR_ARM && p->event->type == ButtonPress) { XmMenuPosition(options_menu, (XButtonPressedEvent *)p->event); XtManageChild(options_menu); } } /*************************************************************************** * * ProcessTraversal * * move the input focus ***************************************************************************/ static void ProcessTraversal( Widget w, int direction ) { int i; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered ProcessTraversal ..."); #endif /* VG_TRACE */ i = XmProcessTraversal(w, direction); #ifndef __hpux /* * Versions of Motif other than HP do not support the XmfocusCallback * on the TextField widget. We simulate it here by manually invoking the * callback routine... */ TextFocusCB(w, NULL, NULL); #endif } /*************************************************************************** * * RefreshEH * * cause the entire screen to refresh via exposure events ***************************************************************************/ void RefreshEH( Widget w, XtPointer client_data, XEvent *event, Boolean *continue_to_dispatch ) { Window cover; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered RefreshEH ..."); #endif /* VG_TRACE */ /* * map/unmap a window that covers the entire screen. The resultant * exposure events will refresh the screen. Note, the default * background pixmap is NONE. */ cover = XCreateWindow ( dpyinfo.dpy, /* display */ dpyinfo.root, /* root window ID */ 0, /* x origin */ 0, /* y origin */ dpyinfo.width, /* width */ dpyinfo.height, /* height */ 0, /* border width */ 0, /* depth */ InputOutput, /* class */ CopyFromParent, /* visual */ 0, /* value mask */ (XSetWindowAttributes *)NULL); /* attributes */ XMapWindow(dpyinfo.dpy, cover); XDestroyWindow(dpyinfo.dpy, cover); XFlush(dpyinfo.dpy); } /*************************************************************************** * * RequestCB * * Accept a request from client ***************************************************************************/ void RequestCB( XtPointer client_data, int *source, XtInputId *id) { char buf[512]; int count; int remainder; RequestHeader *phdr = (RequestHeader *)buf; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered RequestCB ..."); #endif /* VG_TRACE */ /* * There's a request in the pipe. Read the header. */ count = read(0, buf, sizeof(*phdr)); if (count != sizeof(*phdr)) { return; } /* * Calculate amount of data after header. */ remainder = phdr->length - sizeof(*phdr); if (remainder > 0) { /* * Read remainder of request. */ count = read(0, buf+sizeof(*phdr), remainder); } /* * Initiate response to request. */ switch(phdr->opcode) { case REQUEST_OP_EXIT: #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_EXIT ..."); #endif /* VG_TRACE */ RespondExitCB(NULL, NULL, NULL); break; case REQUEST_OP_MESSAGE: { RequestMessage *r = (RequestMessage *)phdr; XmString string; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_MESSAGE ..."); #endif /* VG_TRACE */ if (r->idMC) { FILE *fp; /* * Caller passed in MC_* message id. */ if (r->idMC == MC_NO_LOGIN && (fp = fopen(NO_LOGIN_FILE,"r")) != NULL) { /* * For MC_NO_LOGIN read message from file. */ char buffer[256]; int j; string = NULL; while (fgets(buffer, 256, fp) != NULL) { j = strlen(buffer); if ( buffer[j-1] == '\n' ) buffer[j-1] = '\0'; string = XmStringConcat(xmstr, XmStringCreate(buffer, XmFONTLIST_DEFAULT_TAG)); string = XmStringConcat(xmstr, XmStringSeparatorCreate()); } fclose(fp); } else { /* * Read message from message catalog. */ string = ReadCatalogXms(MC_ERROR_SET, r->idMC, buf+r->offMessage); } } else { /* * Generate message from provided string. */ #ifdef SIA string = multiline_xmstring(buf+r->offMessage); #else string = XmStringCreate(buf+r->offMessage,XmFONTLIST_DEFAULT_TAG); #endif } _DtShowDialog(error, string); XmStringFree(string); } break; case REQUEST_OP_HOSTNAME: #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_HOSTNAME ..."); #endif /* VG_TRACE */ _DtShowDialog(hostname, NULL); break; case REQUEST_OP_EXPASSWORD: #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_EXPASSWORD ..."); #endif /* VG_TRACE */ _DtShowDialog(expassword, NULL); break; case REQUEST_OP_CHPASS: #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_CHPASS ..."); #endif /* VG_TRACE */ break; case REQUEST_OP_CHALLENGE: { RequestChallenge *r = (RequestChallenge *)phdr; XmString string; int i; LoginTextPtr textdata; Boolean change; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_CHALLENGE ..."); #endif /* VG_TRACE */ textdata = GetLoginTextPtr(login_text); change = (textdata->bEcho != r->bEcho); XtUnmapWidget(textdata->text[textdata->bEcho]); textdata->bEcho = r->bEcho; textdata->noechobuf[0] = '\0'; XtAddEventHandler(textdata->text[textdata->bEcho], ExposureMask, False, FakeFocusIn, NULL); XtMapWidget(textdata->text[textdata->bEcho]); XtPopup(login_shell, XtGrabNone); XGrabKeyboard (dpyinfo.dpy, XtWindow (textdata->text[textdata->bEcho]), False, GrabModeAsync, GrabModeAsync, CurrentTime); XmTextFieldSetString( textdata->text[textdata->bEcho], r->offUserNameSeed ? buf+r->offUserNameSeed : ""); XmTextFieldSetSelection ( textdata->text[1], 0, XmTextFieldGetLastPosition(textdata->text[1]), CurrentTime ); if (r->idMC) { /* * Read message from message catalog. */ string = ReadCatalogXms(MC_LABEL_SET, r->idMC, buf+r->offChallenge); } else { /* * Generate message from provided string. */ string = XmStringCreate(buf+r->offChallenge,XmFONTLIST_DEFAULT_TAG); } i = 0; XtSetArg(argt[i], XmNlabelString, string ); i++; XtSetValues(login_label, argt, i); XmStringFree(string); if (change) { char buf[256]; i = 0; if (textdata->bEcho) { XtSetArg(argt[i], XmNlabelString, textdata->onGreeting ); i++; } else { sprintf(buf, textdata->offGreetingFormat, textdata->offGreetingUname); string = XmStringCreate(buf, XmFONTLIST_DEFAULT_TAG); XtSetArg(argt[i], XmNlabelString, string ); i++; free(textdata->offGreetingUname); } XtSetValues(greeting, argt, i); /* set the dt_label with the session that is enabled */ SetDtLabelAndIcon(); } XtSetSensitive(ok_button, True); XtSetSensitive(clear_button, True); XtSetSensitive(options_button, True); XtSetSensitive(help_button, True); XUngrabKeyboard(dpyinfo.dpy,CurrentTime); } break; #ifdef SIA case REQUEST_OP_FORM: { RequestForm *r = (RequestForm *)buf; int i; char *prompt_ptr; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: got REQUEST_OP_FORM ..."); #endif /* VG_TRACE */ siaFormInfo.num_prompts = r->num_prompts; siaFormInfo.rendition = r->rendition; siaFormInfo.title = XtMalloc(strlen(buf + r->offTitle)); strcpy(siaFormInfo.title, buf + r->offTitle); prompt_ptr = buf + r->offPrompts; for (i=0; i < siaFormInfo.num_prompts; i++) { siaFormInfo.visible[i] = r->visible[i]; siaFormInfo.prompts[i] = XtMalloc(strlen(prompt_ptr)); siaFormInfo.answers[i] = NULL; strcpy(siaFormInfo.prompts[i], prompt_ptr); prompt_ptr += strlen(prompt_ptr) + 1; } /* * Create Widgets: * Form * Title * prompt labels and answer text fields for each prompt * OK button * Add callbacks as needed. If not visible don't echo. * On OK callback, collect info and send it. Destroy widgets. */ SiaForm(&siaFormInfo); } break; #endif /* SIA */ } #if 0 { /* * Send immediate response to debug. */ char outbuf[512]; char *p; ResponseDebug *rdebug = (ResponseDebug *)outbuf; rdebug->hdr.opcode = REQUEST_OP_DEBUG; rdebug->hdr.reserved = 0; rdebug->offString = sizeof(*rdebug); p = ((char *)(rdebug)) + rdebug->offString; strcpy(p, "This is my debug string"); rdebug->hdr.length = sizeof(*rdebug) + strlen(p) + 1; TellRequester(outbuf, (size_t) rdebug->hdr.length); } #endif } /*************************************************************************** * * RespondExitCB * * Respond to an exit request from client ***************************************************************************/ void RespondExitCB( Widget w, XtPointer client, XtPointer call) { char buf[REQUEST_LIM_MAXLEN]; ResponseExit *r = (ResponseExit *)buf; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered RespondExitCB ..."); #endif /* VG_TRACE */ r->hdr.opcode = REQUEST_OP_EXIT; r->hdr.reserved = 0; r->hdr.length = sizeof(*r); TellRequester(buf, (size_t) r->hdr.length); CleanupAndExit(NULL, NOTIFY_OK); } /*************************************************************************** * * RespondLangCB * * Respond to a lang item selection from user ***************************************************************************/ int amChooser = 0; int orig_argc; char **orig_argv; void RespondLangCB( Widget w, XtPointer client, XtPointer call) { XtSetArg(argt[0], XmNset, True); XtSetValues(w, argt, 1); #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered RespondLangCB ..."); #endif /* VG_TRACE */ if (amChooser) { /** this is probably not the ideal way to do this **/ /** but it does work ok. **/ /** notice the related code in chooser.c at the **/ /** beginning of main. **/ char buff[128]; if (XmToggleButtonGadgetGetState(w)) { snprintf(buff, sizeof(buff), "LANG=%s", (char *) client); putenv(buff); execv(orig_argv[0], orig_argv); } } else { char buf[REQUEST_LIM_MAXLEN]; ResponseLang *r = (ResponseLang *)buf; char *p; r->hdr.opcode = REQUEST_OP_LANG; r->hdr.reserved = 0; r->offLang = sizeof(*r); p = ((char *)(r)) + r->offLang; strcpy(p, XmToggleButtonGadgetGetState(w) ? client : "default"); r->hdr.length = sizeof(*r) + strlen(p) + 1; TellRequester(buf, (size_t) r->hdr.length); CleanupAndExit(NULL, NOTIFY_LANG_CHANGE); } } /*************************************************************************** * * RespondChallengeCB * * Respond to a challenge request from client ***************************************************************************/ void RespondChallengeCB( Widget w, XtPointer client, XtPointer call) { char buf[REQUEST_LIM_MAXLEN]; ResponseChallenge *r = (ResponseChallenge *)buf; char *value; char *p; LoginTextPtr textdata; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered RespondChallengeCB ..."); #endif /* VG_TRACE */ XtSetSensitive(ok_button, False); XtSetSensitive(clear_button, False); XtSetSensitive(options_button, False); XtSetSensitive(help_button, False); textdata = GetLoginTextPtr(login_text); /* * Get username and password. Username is obtained from widget * while password is stored in global buffer. */ if (textdata->bEcho) { value = XmTextFieldGetString(login_text); textdata->offGreetingUname = strdup(value); userName = strdup(value); if (strlen(textdata->offGreetingUname) > (size_t) 16) { textdata->offGreetingUname[16] = '\0'; userName[16] = '\0'; } } else { value = textdata->noechobuf; } r->hdr.opcode = REQUEST_OP_CHALLENGE; r->hdr.reserved = 0; r->offResponse = sizeof(*r); p = buf + r->offResponse; strcpy(p, value); r->hdr.length = r->offResponse + strlen(p) + 1; if (textdata->bEcho) { XtFree(value); XmTextFieldSetString(login_text, ""); } else { /* * Clean password memory to foil snoopers. */ bzero(textdata->noechobuf, strlen(textdata->noechobuf)); } TellRequester(buf, (size_t) r->hdr.length); } /*************************************************************************** * * RespondDialogCB * * Respond to a request that displayed a dialog ***************************************************************************/ void RespondDialogCB( Widget w, XtPointer client, XtPointer call_data) { char buf[REQUEST_LIM_MAXLEN]; XmAnyCallbackStruct *reason = (XmAnyCallbackStruct *)call_data; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered RespondDialogCB ..."); #endif /* VG_TRACE */ if (w == error_message) { ResponseMessage *r= (ResponseMessage *)buf; r->hdr.opcode = REQUEST_OP_MESSAGE; r->hdr.reserved = 0; r->hdr.length = sizeof(*r); TellRequester(buf, (size_t) r->hdr.length); } else if (w == passwd_message) { if (reason->reason == XmCR_OK) { CleanupAndExit(w, NOTIFY_PASSWD_EXPIRED); } else { ResponseExpassword *r= (ResponseExpassword *)buf; r->hdr.opcode = REQUEST_OP_EXPASSWORD; r->hdr.reserved = 0; r->hdr.length = sizeof(*r); TellRequester(buf, (size_t) r->hdr.length); } } else if (w == hostname_message) { if (reason->reason == XmCR_OK) { CleanupAndExit(w, NOTIFY_OK); } else { CleanupAndExit(w, NOTIFY_NO_WINDOWS); } } } /*************************************************************************** * * SetDefaultDt * * save the default dt widget. **************************************************************************/ void SetDefaultDt(Widget w) { default_dt = w; } /*************************************************************************** * * SetDtLabelAndIcon * * label to display in the dt_label widget and * the logo to display in logo_pixmap **************************************************************************/ void SetDtLabelAndIcon(void) { static XmString blanks = NULL; int i; char *logoFile; char *logoName; char *temp_p; #ifdef VG_TRACE vg_TRACE_EXECUTION("main: entered SetDtLabelAndIcon ..."); #endif /* VG_TRACE */ if (NULL == blanks) blanks = XmStringCreateLocalized(" "); /* * if user is logging in, set dt_label desired. No more than * one desktop can be selected at a time ... */ i = 0; XtSetArg(argt[0], XmNset, FALSE); i++; XtSetValues(options_failsafe, argt, i); XtSetValues(options_dtlite, argt, i); XtSetValues(options_dt, argt, i); if (options_last_dt != NULL) XtSetValues(options_last_dt, argt, i); for(i = 0; i