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: Main.c /main/18 1998/07/23 17:56:36 mgreess $ */
24 /*****************************************************************************
25 *****************************************************************************
31 ** Description: This file contains the main program for dtaction.
34 **(c) Copyright 1993, 1994 Hewlett-Packard Company
35 **(c) Copyright 1993, 1994 International Business Machines Corp.
36 **(c) Copyright 1993, 1994 Sun Microsystems, Inc.
37 **(c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
40 ****************************************************************************
41 ************************************<+>*************************************/
50 #include <sys/param.h> /* for MAXPATHLEN and MAXHOSTNAMELEN */
52 #if defined(sun) || defined(__linux__)
61 #include <X11/Intrinsic.h>
65 #include <Xm/SelectioB.h>
66 #include <Xm/MessageB.h>
67 #include <Xm/Protocols.h>
68 #include <Xm/MwmUtil.h>
71 #include <Dt/DbUtil.h>
72 #include <Dt/CmdInv.h>
73 #include <Dt/Action.h>
74 #include <Dt/EnvControlP.h>
77 /******************************************************************************/
82 /* Command line options */
83 XrmOptionDescRec option_list[] =
85 { "-user", "user", XrmoptionSepArg, NULL},
86 { "-contextDir", "contextDir", XrmoptionSepArg, NULL},
87 { "-execHost", "execHost", XrmoptionSepArg, NULL},
88 { "-termOpts", "termOpts", XrmoptionSepArg, NULL},
96 } ApplArgs, *ApplArgsPtr;
98 #define LOGIN_STR_LEN 15
104 int passwordLength = 0;
106 Boolean finished = False;
107 Boolean rootRequest = False;
108 char * toPword = NULL;
109 char * rootPword = NULL;
110 char * origName = "Unknown";
114 /* Dtaction resources */
115 XtResource resources[] =
118 "user", "User", XmRString, sizeof(char *),
119 XtOffsetOf(ApplArgs, user), XmRImmediate, (XtPointer) NULL,
122 "contextDir", "ContextDir", XmRString, sizeof(char *),
123 XtOffsetOf(ApplArgs, contextDir), XmRImmediate, (XtPointer) NULL,
126 "execHost", "ExecHost", XmRString, sizeof(char *),
127 XtOffsetOf(ApplArgs, execHost), XmRImmediate, (XtPointer) NULL,
130 "termOpts", "TermParms", XmRString, sizeof(char *),
131 XtOffsetOf(ApplArgs, termOpts), XmRImmediate, (XtPointer) NULL,
136 * macro to get message catalog strings
139 #ifndef NO_MESSAGE_CATALOG
140 # define _CLIENT_CAT_NAME "dtact"
141 extern char *_DtGetMessage(char *filename, int set, int n, char *s);
142 # define GETMESSAGE(set, number, string)\
143 (_DtGetMessage(_CLIENT_CAT_NAME, set, number, string))
145 # define GETMESSAGE(set, number, string)\
149 Boolean _DtWmStringsAreEqual(
153 XtPointer clientData,
155 void CheckUserRequest( void ) ;
156 void CheckPasswd( void ) ;
165 XtPointer clientData,
166 XtPointer callData) ;
169 XtPointer clientData,
170 XtPointer callData) ;
173 XtPointer clientData,
174 XtPointer callData) ;
177 XtPointer clientData,
178 XtPointer callData) ;
180 void actionStatusCallback (
181 DtActionInvocationID id,
182 XtPointer client_data,
185 DtActionStatus status );
187 void GetUserPrompt( void ) ;
188 void LogSuccess( void ) ;
189 void LogFailure( void ) ;
194 Cardinal *num_params) ;
199 Cardinal *num_params) ;
204 void UnknownUser( void ) ;
205 void UnknownUserCallback(
207 XtPointer clientData,
208 XtPointer callData) ;
211 /******** End Forward Function Declarations ********/
214 /***************************************************************************
216 * Text widget actions and translations
218 ***************************************************************************/
220 XtActionsRec textActions[] = {
221 {"my-insert", (XtActionProc)MyInsert},
222 {"my-cancel", (XtActionProc)MyCancel},
225 char textEventBindings[] = {
226 "Shift <Key>Tab: prev-tab-group() \n\
227 Ctrl <Key>Tab: next-tab-group() \n\
228 <Key>Tab: next-tab-group() \n\
229 <Key>osfEndLine: end-of-line() \n\
230 <Key>osfBeginLine: beginning-of-line() \n\
231 ~Shift <Key>osfRight: forward-character()\n\
232 ~Shift <Key>osfLeft: backward-character()\n\
233 Ctrl <Key>osfDelete: delete-to-end-of-line()\n\
234 <Key>osfDelete: delete-next-character()\n\
235 <Key>osfBackSpace: delete-previous-character()\n\
236 <Key>osfActivate: activate()\n\
237 Ctrl <Key>Return: activate()\n\
238 <Key>Return: activate()\n\
239 <Key>osfCancel: my-cancel()\n\
240 <Key>: my-insert()\n\
241 ~Ctrl ~Shift ~Meta ~Alt<Btn1Down>: grab-focus() \n\
242 <EnterWindow>: enter()\n\
243 <LeaveWindow>: leave()\n\
244 <FocusIn>: focusIn()\n\
245 <FocusOut>: focusOut()\n\
250 /****************************************************************************/
251 /****************************************************************************/
253 static Widget toplevel;
254 static ApplArgs appArgs;
255 static XtAppContext appContext;
256 static DtActionInvocationID actionId;
257 static Boolean exitAfterInvoked = False;
258 static int exitStatus = 0;
263 XtPointer clientData,
266 if ( toplevel->core.num_popups == 0 )
269 XtAppAddTimeOut(appContext,
270 10, (XtTimerCallbackProc)CheckForDone,
285 DtActionArg *ap = NULL;
287 XtSetLanguageProc(NULL, NULL, NULL);
288 _DtEnvControl(DT_ENV_SET);
289 (void) signal(SIGCHLD, (void (*)())SIG_IGN);
291 /* Initialize the toolkit and open the display */
292 XtToolkitInitialize() ;
293 appContext = XtCreateApplicationContext() ;
294 if ( !(display = XtOpenDisplay( appContext, NULL, argv[0], "Dtaction",
296 sizeof(option_list)/sizeof(XrmOptionDescRec),
299 setlocale(LC_ALL, "");
300 fprintf(stderr, "%s", GETMESSAGE(1,11,"Can't open display.\n"));
304 XtSetArg(args[n], XmNallowShellResize, True); n++;
305 XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
306 XtSetArg(args[n], XmNheight, 1); n++;
307 XtSetArg(args[n], XmNwidth, 1); n++;
308 toplevel = XtAppCreateShell( argv[0], "Dtaction",
309 topLevelShellWidgetClass, display, args, n) ;
311 XtRealizeWidget(toplevel);
313 display = XtDisplay (toplevel);
314 XtGetApplicationResources(toplevel, &appArgs,
315 resources, XtNumber(resources), NULL, 0);
317 password = XtMalloc(1);
322 /* Get Dt initialized */
323 if (DtInitialize (display, toplevel, argv[0], "Dtaction") == False)
325 /* Fatal Error: could not connect to the messaging system. */
326 /* DtInitialize() has already logged an appropriate error msg */
331 * If the request specified that it wanted to run as a different
332 * user, then take care of prompting for a password, and doing any
333 * necessary verification and logging.
337 /* Load the filetype/action dbs; DtInvokeAction() requires this */
341 * Get the requested action name
343 if ( (actionName = argv[1]) == NULL)
345 fprintf(stderr, "%s", GETMESSAGE(1,10,"No action name specified.\n"));
352 * create an action arg array for the file objects for
353 * this action. This number of objects should be one
354 * less than the argument count. The returned vector will
355 * be terminated by a null pointer.
358 ap = (DtActionArg *) XtCalloc(numArgs,sizeof(DtActionArg));
362 * This client is restricted to FILE arguments.
363 * for the time being.
365 for ( n = 0; n < numArgs; n++) {
366 ap[n].argClass = DtACTION_FILE;
367 ap[n].u.file.name = argv[n+2];
370 actionId = DtActionInvoke(toplevel, actionName, ap, numArgs,
374 True, /* use indicator */
375 (DtActionCallbackProc) actionStatusCallback,
379 * Set up a timer if we didn't get a valid procId -- since there will
380 * be no invocation update in that case.
381 * We must invoke XtMainLoop() at least once, to force any prompt or
382 * error dialogs to get posted.
385 XtAppAddTimeOut(appContext,
386 10, (XtTimerCallbackProc)CheckForDone,
389 XtAppMainLoop(appContext);
396 SetGidUid ( unsigned short rgid, unsigned short ruid )
399 /* fix process gid */
400 #if defined(SVR4) || defined(_AIX)
402 #elif defined(__linux__) || defined(CSRG_BASED)
403 if(-1 == setregid(rgid, rgid)) {
404 fprintf(stderr, "SetGidUid: setregid failed on %d\n", rgid);
406 #elif defined(__hpux)
407 setresgid(rgid, rgid, rgid);
409 setregid(rgid, rgid, rgid);
412 /* fix process uid */
413 #if defined (SVR4) || defined (_AIX)
415 #elif defined(__linux__) || defined(CSRG_BASED)
416 if(-1 == setreuid(ruid, ruid)) {
417 fprintf(stderr, "SetGidUid: setreuid failed on %d\n", ruid);
419 #elif defined(__hpux)
420 setresuid(ruid, ruid, ruid);
422 setreuid(ruid, ruid, ruid);
429 * This function checks to see if the user has requested that the action
430 * be invoked under a different user Id. If a different user Id has been
431 * requested, then the user will be prompted to enter either the password
432 * for that user, or the root password. Once a valid password has been
433 * entered, this function will return.
437 CheckUserRequest( void )
442 struct passwd * passwd;
446 Boolean notExist = False;
447 Boolean alreadySetToRoot = False;
451 /* get current group id */
453 /* get current user id */
456 /* See if the user wants to run as himself */
457 if (appArgs.user == NULL)
459 SetGidUid(rgid,ruid);
463 /* Get password for the requested user */
464 passwd = getpwnam(appArgs.user);
467 spwd = getspnam(appArgs.user);
471 if (passwd->pw_uid == ruid)
474 * We are already running as the
475 * requested user. So return now.
477 SetGidUid(rgid,ruid);
483 toPword = XtNewString(spwd->sp_pwdp);
486 if (passwd->pw_passwd)
487 toPword = XtNewString(passwd->pw_passwd);
489 basegid = passwd->pw_gid;
490 newuid = passwd->pw_uid;
495 /* Root requests require some extra work later */
496 if (strcmp(appArgs.user, "root") == 0)
499 /* Get name for the current user */
500 passwd = getpwuid(ruid);
501 if (passwd && passwd->pw_name)
502 origName = XtNewString(passwd->pw_name);
504 /* Get password for the root user */
505 passwd = getpwnam("root");
506 if (passwd && passwd->pw_passwd)
509 spwd = getspnam("root");
510 if (spwd && spwd->sp_pwdp)
512 rootPword = XtNewString(spwd->sp_pwdp);
515 rootPword = XtNewString(passwd->pw_passwd);
518 if (passwd->pw_uid == ruid)
519 alreadySetToRoot = True;
523 * If 'alreadySetToRoot' is set to True, then that means that the
524 * user is currently running as root.
529 /* Requested user does not exist; this function will exit() */
532 else if ((alreadySetToRoot) || /* requested users passwd is null */
533 ((toPword && (toPword[0] == '\0')) || (toPword == NULL)))
535 /* Already there -- no need to check a passwd */
544 * void CheckPasswd ()
546 * get a password from the user and check it against an encrypted passwd
561 * get this users password
568 * void AddSuLog (FromName, ToName, ChangeType)
570 * add switch from user "FromName" to user "ToName" to sulog.
571 * ChangeType is "+" for success, "-" for failure.
574 * char *FromName -- from name (for logging).
575 * char *ToName -- to name (for logging).
576 * char *ChangeType -- +/- (for logging).
587 struct tm *localtime ();
594 #ifdef hpV4 /* 10.* versions */
595 char * SULog = "/var/adm/sulog";
596 #elif defined( hpux ) /* 9.* versions */
597 char * SULog = "/usr/adm/sulog";
599 char * SULog = "/var/adm/sulog";
602 if ((f = fopen (SULog, "a")) == NULL)
605 (void) time (&timenow);
606 now = localtime (&timenow);
608 /* build toString... */
609 if (ToName && *ToName)
614 fprintf(f, (GETMESSAGE(1,1,
615 "dtaction %1$.2d/%2$.2d %3$.2d:%4$.2d %5$1.1s %6$s %7$s-%8$s\n")),
616 now -> tm_mon + 1, now -> tm_mday, now -> tm_hour,
617 now -> tm_min, ChangeType, "?", FromName, toString);
622 * take away write access from SULog
625 if(chmod (SULog, (int) (st.st_mode & 07777) & ~0222) == -1) {
626 fprintf(stderr, "Error on chmod of '%s', %s\n", SULog, strerror(errno));
634 * void CleanPath (Path);
636 * remove any directories from the path that are
637 * - null (leading/trailing colon or double colon)
638 * - not anchored to root (no leading /)
640 * the returned path is the original path with any such
641 * directories stripped
644 * char *Path -- $PATH to clean
650 * Unanchored paths will be stripped off of Path.
661 StrippedPath = PathHead = Path;
666 * remove multiple ':'s
669 while (*Path && (*Path == ':')) {
674 * is the first character of this
675 * directory a '/'????
681 * copy directory intact;
684 while (*Path && (*Path != ':')) {
685 *StrippedPath++ = *Path++;
689 *StrippedPath++ = *Path++;
698 while (*Path && (*Path != ':')) {
710 * remove all trailing ':'s
713 while ((StrippedPath > PathHead) && (StrippedPath[-1] == ':')) {
718 * null terminate the path
721 *StrippedPath = '\0';
727 * This is the Ok callback for the password dialog. It will attempt to
728 * validate the password. If invalid, then an error dialog is posted,
729 * and the user is prompted to try again. If valid, then the process
730 * will change to run as the requested user, and dtaction will continue
731 * on its way, attempting to invoke the requested action.
738 XtPointer clientData,
742 Boolean valid = False;
744 /* Do any verification here */
746 /* check for primary passwd... */
747 if (!strcmp (crypt (password, toPword), toPword))
750 /* check for secondary passwd ... */
751 if (rootPword && *rootPword &&
752 !strcmp (crypt (password, rootPword), rootPword))
756 else if (((rootPword == NULL) || (*rootPword == '\0')) &&
759 /* No root password, and the user entered no password */
764 /* If valid password, then unpost */
767 XtUnmanageChild(dlog);
768 XFlush(XtDisplay(dlog));
774 /* Invalid password */
784 okLabel = XmStringCreateLocalized(GETMESSAGE(1, 2, "OK"));
785 template = (GETMESSAGE(1,3, "The password you entered does not match\nthe password for user %s.\n\nPlease reenter the password, or select the\nCancel button to terminate the operation."));
786 master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
787 sprintf(master, template, appArgs.user);
788 message = XmStringCreateLocalized(master);
789 title = (GETMESSAGE(1,4, "Action Invoker - Password Error"));
791 /* Post an error dialog */
793 XtSetArg(args[n], XmNtitle, title); n++;
794 XtSetArg(args[n], XmNmessageString, message); n++;
795 XtSetArg(args[n], XmNokLabelString, okLabel); n++;
796 err = XmCreateErrorDialog(dlog, "err", args, n);
797 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
798 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
800 XtAddCallback(err, XmNokCallback, ErrOkCallback, err);
802 XFlush(XtDisplay(dlog));
803 XmUpdateDisplay(dlog);
805 XmStringFree(okLabel);
806 XmStringFree(message);
813 * This is the Cancel callback for the password dialog. It will unpost
814 * the dialog, and exit.
821 XtPointer clientData,
825 XtUnmanageChild(dlog);
826 XFlush(XtDisplay(dlog));
832 * This is the 'Ok' callback for the invalid password error dialog.
833 * It will simply unpost and destroy the error dialog.
840 XtPointer clientData,
844 Widget err = (Widget)clientData;
846 XtUnmanageChild(err);
847 XFlush(XtDisplay(err));
848 XmUpdateDisplay(err);
849 XtDestroyWidget(err);
854 * This callback is invoked when the password dialog is posted; it forces
855 * the focus to the text input field.
862 XtPointer clientData,
867 Widget dlog = (Widget)clientData;
869 /* Force focus initially to the text field */
870 text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
871 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
876 * This function creates the prompt dialog for collecting the password
877 * from the user. It will not give up control until a valid password
878 * has been entered. If the user cancels the request, then the cancel
879 * callback will exit.
883 GetUserPrompt( void )
894 XtTranslations textTable;
895 XmString cancelLabel;
898 snprintf(prompt, sizeof prompt, (GETMESSAGE(1,5, "Enter password for user %s:")),
900 xmString = XmStringCreateLocalized(prompt);
901 xmString2 =XmStringCreateLocalized(GETMESSAGE(1,6, "Action Invoker - Password"));
902 cancelLabel = XmStringCreateLocalized(GETMESSAGE(1,7, "Cancel"));
903 okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
905 XtAppAddActions(appContext,textActions, 2);
906 textTable = XtParseTranslationTable(textEventBindings);
908 /* Create the prompt dialog */
910 XtSetArg(args[n], XmNselectionLabelString, xmString); n++;
911 XtSetArg(args[n], XmNdialogTitle, xmString2); n++;
912 XtSetArg(args[n], XmNautoUnmanage, False); n++;
913 XtSetArg(args[n], XmNokLabelString, okLabel); n++;
914 XtSetArg(args[n], XmNcancelLabelString, cancelLabel); n++;
915 XtSetArg(args[n], XmNdefaultPosition, False); n++;
916 dlog = XmCreatePromptDialog(toplevel, "prompt", args, n);
917 XmStringFree(xmString);
918 XmStringFree(xmString2);
919 XmStringFree(okLabel);
920 XmStringFree(cancelLabel);
921 XtAddCallback(dlog, XmNokCallback, OkCallback, NULL);
922 XtAddCallback(dlog, XmNcancelCallback, CancelCallback, NULL);
924 text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
926 XtSetArg(args[n], XmNtranslations, textTable); n++;
927 XtSetArg(args[n], XmNverifyBell, False); n++;
928 XtSetValues(text, args, n);
929 XtAddCallback(text, XmNmodifyVerifyCallback, EditPasswdCB, NULL);
931 /* Add callback for forcing traversal to the text field */
932 XtAddCallback (XtParent(dlog), XmNpopupCallback, MapCallback, dlog);
934 /* Unmanage the help button */
935 help = XmSelectionBoxGetChild(dlog, XmDIALOG_HELP_BUTTON);
936 XtUnmanageChild(help);
938 /* Center the dialog */
939 XtRealizeWidget(dlog);
940 XtSetArg (args[0], XmNx,
941 (Position)(WidthOfScreen(XtScreen(dlog)) -
942 dlog->core.width) / 2);
943 XtSetArg (args[1], XmNy,
944 (Position)(HeightOfScreen(XtScreen(dlog)) -
945 dlog->core.height) / 2);
946 XtSetValues (dlog, args, 2);
948 /* Set the transient property */
949 XSetTransientForHint (XtDisplay (toplevel),
950 XtWindow (XtParent (dlog)),
951 XtWindow (toplevel));
953 /* Adjust the decorations for the dialog shell of the dialog */
955 XtSetArg(args[n], XmNmwmFunctions, 0); n++;
956 XtSetArg(args[n], XmNmwmDecorations,
957 MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
958 XtSetValues(XtParent(dlog), args, n);
960 /* Post the dialog */
963 /* Wait for the user to finish with the dialog */
966 XtAppNextEvent(appContext,&event);
967 XtDispatchEvent(&event);
970 /* Destroy the widget, and return any data back to the appl */
971 XtDestroyWidget(dlog);
976 * When a user has successfully logged in as another user, we need to set
977 * the uid and gid to the requested user. In addition, if the user is
978 * changing to 'root', then we need to log this in /usr/adm/sulog, and
979 * we need to do some housekeeping of the $PATH environment variable.
989 AddSuLog(origName, appArgs.user, "+");
993 /* Special stuff for the root user */
994 /* Cleanse the $PATH setting */
995 tmpPath = getenv("PATH");
996 path = XtNewString(tmpPath);
998 tmpPath = XtMalloc(strlen(path) + 10);
999 strcpy(tmpPath, "PATH=");
1000 strcat(tmpPath, path);
1004 /* Set up the user's new id's */
1005 SetGidUid(basegid,newuid);
1006 initgroups(appArgs.user, basegid);
1012 * Each time the user enters an invalid password, we need to log this in
1013 * /usr/adm/sulog, if the user is attempting to switch to the 'root' user.
1020 /* Unable to change to specified user; post error, then exit */
1021 AddSuLog(origName, appArgs.user, "-");
1025 /***************************************************************************
1029 * Local self-insert action for the text widget. The default action
1030 * discards control characters, which are allowed in password.
1031 ***************************************************************************/
1039 Cardinal *num_params )
1042 XComposeStatus compstatus;
1045 n = XLookupString((XKeyEvent *)event, str, sizeof(str),
1046 (KeySym *)NULL, &compstatus);
1050 XmTextFieldInsert(w, XmTextFieldGetInsertionPosition(w), str);
1055 /***************************************************************************
1059 * This action catches the 'Escape' key, and following Motif standards,
1060 * unposts the dialog, as if the 'Cancel' button had been pressed.
1061 ***************************************************************************/
1069 Cardinal *num_params )
1071 CancelCallback(w, NULL, NULL);
1076 /***************************************************************************
1080 * implement no-echo of the password
1081 ***************************************************************************/
1092 static Boolean allow_flag = False;
1093 int replaced_length, i;
1095 XmTextVerifyPtr cbData = (XmTextVerifyPtr) call;
1100 * we need to keep track of the password ourselves in order to
1101 * disable echoing of the password...
1104 replaced_length = cbData->endPos - cbData->startPos;
1105 if (replaced_length > cbData->text->length)
1107 /* shift the text at and after endPos to the left... */
1108 for (src = password + cbData->endPos,
1109 dst = src + (cbData->text->length - replaced_length),
1110 i = passwordLength - cbData->endPos;
1117 else if (replaced_length < cbData->text->length)
1119 /* Buffer must grow */
1120 password = XtRealloc(password,
1121 passwordLength + cbData->text->length - replaced_length + 5);
1123 /* shift the text at and after endPos to the right... */
1124 for (src = password + passwordLength - 1,
1125 dst = src + (cbData->text->length - replaced_length),
1126 i = passwordLength - cbData->endPos;
1135 * update the password...
1138 for (src = cbData->text->ptr,
1139 dst = password + cbData->startPos,
1140 i = cbData->text->length;
1147 passwordLength += cbData->text->length - replaced_length;
1148 password[passwordLength] = '\0';
1149 stars = XtRealloc(stars, cbData->text->length + 10);
1150 for (i = 0; i < cbData->text->length; i++)
1152 stars[cbData->text->length] = '\0';
1155 * put the appropriate number of stars in the passwd Widget..
1159 XmTextFieldReplace(w, cbData->startPos, cbData->endPos, stars);
1163 cbData->doit = allow_flag;
1168 * This function posts an error dialog informing the user that they have
1169 * specified an invalid user name. No further processing will be done; we
1170 * will simply wait for the user to acknowledge the error, and then exit.
1186 okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
1187 template = (GETMESSAGE(1,8, "The user '%s' is an unknown user name.\n\nThe requested action will not be executed."));
1188 master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
1189 sprintf(master, template, appArgs.user);
1190 message = XmStringCreateLocalized(master);
1191 title = (GETMESSAGE(1,9, "Action Invoker - Unknown User"));
1193 /* Post an error dialog */
1195 XtSetArg(args[n], XmNtitle, title); n++;
1196 XtSetArg(args[n], XmNmessageString, message); n++;
1197 XtSetArg(args[n], XmNokLabelString, okLabel); n++;
1198 XtSetArg(args[n], XmNdefaultPosition, False); n++;
1199 err = XmCreateErrorDialog(toplevel, "err", args, n);
1200 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
1201 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
1203 /* Center the dialog */
1204 XtRealizeWidget(err);
1205 XtSetArg (args[0], XmNx,
1206 (Position)(WidthOfScreen(XtScreen(err)) -
1207 err->core.width) / 2);
1208 XtSetArg (args[1], XmNy,
1209 (Position)(HeightOfScreen(XtScreen(err)) -
1210 err->core.height) / 2);
1211 XtSetValues (err, args, 2);
1214 XtAddCallback(err, XmNokCallback, UnknownUserCallback, err);
1215 XtAddCallback(err, XmNcancelCallback, UnknownUserCallback, err);
1217 XFlush(XtDisplay(toplevel));
1218 XmUpdateDisplay(toplevel);
1220 XmStringFree(okLabel);
1221 XmStringFree(message);
1223 XtAppMainLoop(appContext);
1228 * This is the 'Cancel' callback for the 'Invalid User' error dialog.
1229 * It removes the dialog, and then exits.
1234 UnknownUserCallback(
1236 XtPointer clientData,
1237 XtPointer callData )
1240 Widget err = (Widget)clientData;
1242 XtUnmanageChild(err);
1243 XFlush(XtDisplay(err));
1244 XmUpdateDisplay(err);
1248 void actionStatusCallback(
1249 DtActionInvocationID id,
1250 XtPointer client_data,
1253 DtActionStatus status )
1257 case DtACTION_INVOKED:
1259 * There may still be error dialogs to post so we must return
1260 * to mainLoop before exiting.
1262 if ( exitAfterInvoked )
1263 XtAppAddTimeOut(appContext,
1264 10 , (XtTimerCallbackProc)CheckForDone,
1269 XtAppAddTimeOut(appContext,
1270 10 , (XtTimerCallbackProc)CheckForDone,
1274 case DtACTION_FAILED:
1275 case DtACTION_CANCELED:
1277 XtAppAddTimeOut(appContext,
1278 10 , (XtTimerCallbackProc)CheckForDone,