2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $TOG: 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 */
61 #include <X11/Intrinsic.h>
64 #include <Xm/SelectioB.h>
65 #include <Xm/MessageB.h>
66 #include <Xm/Protocols.h>
67 #include <Xm/MwmUtil.h>
70 #include <Dt/DbUtil.h>
71 #include <Dt/CmdInv.h>
72 #include <Dt/Action.h>
73 #include <Dt/EnvControlP.h>
76 /******************************************************************************/
81 /* Command line options */
82 XrmOptionDescRec option_list[] =
84 { "-user", "user", XrmoptionSepArg, NULL},
85 { "-contextDir", "contextDir", XrmoptionSepArg, NULL},
86 { "-execHost", "execHost", XrmoptionSepArg, NULL},
87 { "-termOpts", "termOpts", XrmoptionSepArg, NULL},
90 /* Fallback Resources */
91 static char *fallback_resources[] = {
101 } ApplArgs, *ApplArgsPtr;
103 #define LOGIN_STR_LEN 15
109 int passwordLength = 0;
111 Boolean finished = False;
112 Boolean rootRequest = False;
113 char * toPword = NULL;
114 char * rootPword = NULL;
115 char * origName = "Unknown";
119 /* Dtaction resources */
120 XtResource resources[] =
123 "user", "User", XmRString, sizeof(char *),
124 XtOffsetOf(ApplArgs, user), XmRImmediate, (XtPointer) NULL,
127 "contextDir", "ContextDir", XmRString, sizeof(char *),
128 XtOffsetOf(ApplArgs, contextDir), XmRImmediate, (XtPointer) NULL,
131 "execHost", "ExecHost", XmRString, sizeof(char *),
132 XtOffsetOf(ApplArgs, execHost), XmRImmediate, (XtPointer) NULL,
135 "termOpts", "TermParms", XmRString, sizeof(char *),
136 XtOffsetOf(ApplArgs, termOpts), XmRImmediate, (XtPointer) NULL,
141 * macro to get message catalog strings
144 #ifndef NO_MESSAGE_CATALOG
146 # define _CLIENT_CAT_NAME "dtact.cat"
147 # else /* __ultrix */
148 # define _CLIENT_CAT_NAME "dtact"
149 # endif /* __ultrix */
150 extern char *_DtGetMessage(char *filename, int set, int n, char *s);
151 # define GETMESSAGE(set, number, string)\
152 (_DtGetMessage(_CLIENT_CAT_NAME, set, number, string))
154 # define GETMESSAGE(set, number, string)\
158 Boolean _DtWmStringsAreEqual(
159 register char *in_str,
160 register char *test_str) ;
162 XtPointer clientData,
164 void CheckUserRequest( void ) ;
165 void CheckPasswd( void ) ;
174 XtPointer clientData,
175 XtPointer callData) ;
178 XtPointer clientData,
179 XtPointer callData) ;
182 XtPointer clientData,
183 XtPointer callData) ;
186 XtPointer clientData,
187 XtPointer callData) ;
189 void actionStatusCallback (
190 DtActionInvocationID id,
191 XtPointer client_data,
194 DtActionStatus status );
196 void GetUserPrompt( void ) ;
197 void LogSuccess( void ) ;
198 void LogFailure( void ) ;
203 Cardinal *num_params) ;
208 Cardinal *num_params) ;
213 void UnknownUser( void ) ;
214 void UnknownUserCallback(
216 XtPointer clientData,
217 XtPointer callData) ;
220 /******** End Forward Function Declarations ********/
223 /***************************************************************************
225 * Text widget actions and translations
227 ***************************************************************************/
229 XtActionsRec textActions[] = {
230 {"my-insert", (XtActionProc)MyInsert},
231 {"my-cancel", (XtActionProc)MyCancel},
234 char textEventBindings[] = {
235 "Shift <Key>Tab: prev-tab-group() \n\
236 Ctrl <Key>Tab: next-tab-group() \n\
237 <Key>Tab: next-tab-group() \n\
238 <Key>osfEndLine: end-of-line() \n\
239 <Key>osfBeginLine: beginning-of-line() \n\
240 ~Shift <Key>osfRight: forward-character()\n\
241 ~Shift <Key>osfLeft: backward-character()\n\
242 Ctrl <Key>osfDelete: delete-to-end-of-line()\n\
243 <Key>osfDelete: delete-next-character()\n\
244 <Key>osfBackSpace: delete-previous-character()\n\
245 <Key>osfActivate: activate()\n\
246 Ctrl <Key>Return: activate()\n\
247 <Key>Return: activate()\n\
248 <Key>osfCancel: my-cancel()\n\
249 <Key>: my-insert()\n\
250 ~Ctrl ~Shift ~Meta ~Alt<Btn1Down>: grab-focus() \n\
251 <EnterWindow>: enter()\n\
252 <LeaveWindow>: leave()\n\
253 <FocusIn>: focusIn()\n\
254 <FocusOut>: focusOut()\n\
259 /****************************************************************************/
260 /****************************************************************************/
262 static Widget toplevel;
263 static ApplArgs appArgs;
264 static XtAppContext appContext;
265 static DtActionInvocationID actionId;
266 static Boolean exitAfterInvoked = False;
267 static int exitStatus = 0;
272 XtPointer clientData,
275 if ( toplevel->core.num_popups == 0 )
278 XtAppAddTimeOut(appContext,
279 10, (XtTimerCallbackProc)CheckForDone,
294 char contextDir[MAXPATHLEN+1];
295 DtActionArg *ap = NULL;
297 XtSetLanguageProc(NULL, NULL, NULL);
298 _DtEnvControl(DT_ENV_SET);
299 (void) signal(SIGCHLD, (void (*)())SIG_IGN);
301 /* Initialize the toolkit and open the display */
302 XtToolkitInitialize() ;
303 appContext = XtCreateApplicationContext() ;
304 if ( !(display = XtOpenDisplay( appContext, NULL, argv[0], "Dtaction",
306 sizeof(option_list)/sizeof(XrmOptionDescRec),
309 setlocale(LC_ALL, "");
310 fprintf(stderr, "%s", GETMESSAGE(1,11,"Can't open display.\n"));
314 XtSetArg(args[n], XmNallowShellResize, True); n++;
315 XtSetArg(args[n], XmNmappedWhenManaged, False); n++;
316 XtSetArg(args[n], XmNheight, 1); n++;
317 XtSetArg(args[n], XmNwidth, 1); n++;
318 toplevel = XtAppCreateShell( argv[0], "Dtaction",
319 topLevelShellWidgetClass, display, args, n) ;
321 XtRealizeWidget(toplevel);
323 display = XtDisplay (toplevel);
324 XtGetApplicationResources(toplevel, &appArgs,
325 resources, XtNumber(resources), NULL, 0);
327 password = XtMalloc(1);
332 /* Get Dt initialized */
333 if (DtInitialize (display, toplevel, argv[0], "Dtaction") == False)
335 /* Fatal Error: could not connect to the messaging system. */
336 /* DtInitialize() has already logged an appropriate error msg */
341 * If the request specified that it wanted to run as a different
342 * user, then take care of prompting for a password, and doing any
343 * necessary verification and logging.
347 /* Load the filetype/action dbs; DtInvokeAction() requires this */
351 * Get the requested action name
353 if ( (actionName = argv[1]) == NULL)
355 fprintf(stderr, "%s", GETMESSAGE(1,10,"No action name specified.\n"));
362 * create an action arg array for the file objects for
363 * this action. This number of objects should be one
364 * less than the argument count. The returned vector will
365 * be terminated by a null pointer.
368 ap = (DtActionArg *) XtCalloc(numArgs,sizeof(DtActionArg));
372 * This client is restricted to FILE arguments.
373 * for the time being.
375 for ( n = 0; n < numArgs; n++) {
376 ap[n].argClass = DtACTION_FILE;
377 ap[n].u.file.name = argv[n+2];
380 actionId = DtActionInvoke(toplevel, actionName, ap, numArgs,
384 True, /* use indicator */
385 (DtActionCallbackProc) actionStatusCallback,
389 * Set up a timer if we didn't get a valid procId -- since there will
390 * be no invocation update in that case.
391 * We must invoke XtMainLoop() at least once, to force any prompt or
392 * error dialogs to get posted.
395 XtAppAddTimeOut(appContext,
396 10, (XtTimerCallbackProc)CheckForDone,
399 XtAppMainLoop(appContext);
406 SetGidUid ( unsigned short rgid, unsigned short ruid )
409 /* fix process gid */
410 #if defined(SVR4) || defined(_AIX)
412 #elif defined(__osf__) || defined(linux) || defined(CSRG_BASED)
413 setregid(rgid, rgid);
414 #elif defined(__hpux)
415 setresgid(rgid, rgid, rgid);
417 setregid(rgid, rgid, rgid);
420 /* fix process uid */
421 #if defined (SVR4) || defined (_AIX)
423 #elif defined(__osf__) || defined(linux) || defined(CSRG_BASED)
424 setreuid(ruid, ruid);
425 #elif defined(__hpux)
426 setresuid(ruid, ruid, ruid);
428 setreuid(ruid, ruid, ruid);
435 * This function checks to see if the user has requested that the action
436 * be invoked under a different user Id. If a different user Id has been
437 * requested, then the user will be prompted to enter either the password
438 * for that user, or the root password. Once a valid password has been
439 * entered, this function will return.
443 CheckUserRequest( void )
448 struct passwd * passwd;
452 Boolean notExist = False;
453 Boolean alreadySetToRoot = False;
457 /* get current group id */
459 /* get current user id */
462 /* See if the user wants to run as himself */
463 if (appArgs.user == NULL)
465 SetGidUid(rgid,ruid);
469 /* Get password for the requested user */
470 passwd = getpwnam(appArgs.user);
473 spwd = getspnam(appArgs.user);
477 if (passwd->pw_uid == ruid)
480 * We are already running as the
481 * requested user. So return now.
483 SetGidUid(rgid,ruid);
489 toPword = XtNewString(spwd->sp_pwdp);
492 if (passwd->pw_passwd)
493 toPword = XtNewString(passwd->pw_passwd);
495 basegid = passwd->pw_gid;
496 newuid = passwd->pw_uid;
501 /* Root requests require some extra work later */
502 if (strcmp(appArgs.user, "root") == 0)
505 /* Get name for the current user */
506 passwd = getpwuid(ruid);
507 if (passwd && passwd->pw_name)
508 origName = XtNewString(passwd->pw_name);
510 /* Get password for the root user */
511 passwd = getpwnam("root");
512 if (passwd && passwd->pw_passwd)
515 spwd = getspnam("root");
516 if (spwd && spwd->sp_pwdp)
518 rootPword = XtNewString(spwd->sp_pwdp);
521 rootPword = XtNewString(passwd->pw_passwd);
524 if (passwd->pw_uid == ruid)
525 alreadySetToRoot = True;
529 * If 'alreadySetToRoot' is set to True, then that means that the
530 * user is currently running as root.
535 /* Requested user does not exist; this function will exit() */
538 else if ((alreadySetToRoot) || /* requested users passwd is null */
539 ((toPword && (toPword[0] == '\0')) || (toPword == NULL)))
541 /* Already there -- no need to check a passwd */
550 * void CheckPasswd ()
552 * get a password from the user and check it against an encrypted passwd
567 * get this users password
574 * void AddSuLog (FromName, ToName, ChangeType)
576 * add switch from user "FromName" to user "ToName" to sulog.
577 * ChangeType is "+" for success, "-" for failure.
580 * char *FromName -- from name (for logging).
581 * char *ToName -- to name (for logging).
582 * char *ChangeType -- +/- (for logging).
593 struct tm *localtime ();
600 #ifdef hpV4 /* 10.* versions */
601 char * SULog = "/var/adm/sulog";
602 #elif defined( hpux ) /* 9.* versions */
603 char * SULog = "/usr/adm/sulog";
605 char * SULog = "/var/adm/sulog";
608 if ((f = fopen (SULog, "a")) == NULL)
611 (void) time (&timenow);
612 now = localtime (&timenow);
614 /* build toString... */
615 if (ToName && *ToName)
620 fprintf(f, (GETMESSAGE(1,1,
621 "dtaction %1$.2d/%2$.2d %3$.2d:%4$.2d %5$1.1s %6$s %7$s-%8$s\n")),
622 now -> tm_mon + 1, now -> tm_mday, now -> tm_hour,
623 now -> tm_min, ChangeType, "?", FromName, toString);
628 * take away write access from SULog
631 if (stat (SULog, &st) == 0)
632 chmod (SULog, (int) (st.st_mode & 07777) & ~0222);
639 * void CleanPath (Path);
641 * remove any directories from the path that are
642 * - null (leading/trailing colon or double colon)
643 * - not anchored to root (no leading /)
645 * the returned path is the original path with any such
646 * directories stripped
649 * char *Path -- $PATH to clean
655 * Unanchored paths will be stripped off of Path.
663 register char *StrippedPath;
664 register char *PathHead;
666 StrippedPath = PathHead = Path;
671 * remove multiple ':'s
674 while (*Path && (*Path == ':')) {
679 * is the first character of this
680 * directory a '/'????
686 * copy directory intact;
689 while (*Path && (*Path != ':')) {
690 *StrippedPath++ = *Path++;
694 *StrippedPath++ = *Path++;
703 while (*Path && (*Path != ':')) {
715 * remove all trailing ':'s
718 while ((StrippedPath > PathHead) && (StrippedPath[-1] == ':')) {
723 * null terminate the path
726 *StrippedPath = '\0';
732 * This is the Ok callback for the password dialog. It will attempt to
733 * validate the password. If invalid, then an error dialog is posted,
734 * and the user is prompted to try again. If valid, then the process
735 * will change to run as the requested user, and dtaction will continue
736 * on its way, attempting to invoke the requested action.
743 XtPointer clientData,
747 Boolean valid = False;
749 /* Do any verification here */
751 /* check for primary passwd... */
752 if (!strcmp (crypt (password, toPword), toPword))
755 /* check for secondary passwd ... */
756 if (rootPword && *rootPword &&
757 !strcmp (crypt (password, rootPword), rootPword))
761 else if (((rootPword == NULL) || (*rootPword == '\0')) &&
764 /* No root password, and the user entered no password */
769 /* If valid password, then unpost */
772 XtUnmanageChild(dlog);
773 XFlush(XtDisplay(dlog));
779 /* Invalid password */
789 okLabel = XmStringCreateLocalized(GETMESSAGE(1, 2, "OK"));
790 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."));
791 master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
792 sprintf(master, template, appArgs.user);
793 message = XmStringCreateLocalized(master);
794 title = (GETMESSAGE(1,4, "Action Invoker - Password Error"));
796 /* Post an error dialog */
798 XtSetArg(args[n], XmNtitle, title); n++;
799 XtSetArg(args[n], XmNmessageString, message); n++;
800 XtSetArg(args[n], XmNokLabelString, okLabel); n++;
801 err = XmCreateErrorDialog(dlog, "err", args, n);
802 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
803 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
805 XtAddCallback(err, XmNokCallback, ErrOkCallback, err);
807 XFlush(XtDisplay(dlog));
808 XmUpdateDisplay(dlog);
810 XmStringFree(okLabel);
811 XmStringFree(message);
818 * This is the Cancel callback for the password dialog. It will unpost
819 * the dialog, and exit.
826 XtPointer clientData,
830 XtUnmanageChild(dlog);
831 XFlush(XtDisplay(dlog));
837 * This is the 'Ok' callback for the invalid password error dialog.
838 * It will simply unpost and destroy the error dialog.
845 XtPointer clientData,
849 Widget err = (Widget)clientData;
851 XtUnmanageChild(err);
852 XFlush(XtDisplay(err));
853 XmUpdateDisplay(err);
854 XtDestroyWidget(err);
859 * This callback is invoked when the password dialog is posted; it forces
860 * the focus to the text input field.
867 XtPointer clientData,
872 Widget dlog = (Widget)clientData;
874 /* Force focus initially to the text field */
875 text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
876 XmProcessTraversal(text, XmTRAVERSE_CURRENT);
881 * This function creates the prompt dialog for collecting the password
882 * from the user. It will not give up control until a valid password
883 * has been entered. If the user cancels the request, then the cancel
884 * callback will exit.
888 GetUserPrompt( void )
899 XtTranslations textTable;
900 XmString cancelLabel;
903 snprintf(prompt, sizeof prompt, (GETMESSAGE(1,5, "Enter password for user %s:")),
905 xmString = XmStringCreateLocalized(prompt);
906 xmString2 =XmStringCreateLocalized(GETMESSAGE(1,6, "Action Invoker - Password"));
907 cancelLabel = XmStringCreateLocalized(GETMESSAGE(1,7, "Cancel"));
908 okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
910 XtAppAddActions(appContext,textActions, 2);
911 textTable = XtParseTranslationTable(textEventBindings);
913 /* Create the prompt dialog */
915 XtSetArg(args[n], XmNselectionLabelString, xmString); n++;
916 XtSetArg(args[n], XmNdialogTitle, xmString2); n++;
917 XtSetArg(args[n], XmNautoUnmanage, False); n++;
918 XtSetArg(args[n], XmNokLabelString, okLabel); n++;
919 XtSetArg(args[n], XmNcancelLabelString, cancelLabel); n++;
920 XtSetArg(args[n], XmNdefaultPosition, False); n++;
921 dlog = XmCreatePromptDialog(toplevel, "prompt", args, n);
922 XmStringFree(xmString);
923 XmStringFree(xmString2);
924 XmStringFree(okLabel);
925 XmStringFree(cancelLabel);
926 XtAddCallback(dlog, XmNokCallback, OkCallback, NULL);
927 XtAddCallback(dlog, XmNcancelCallback, CancelCallback, NULL);
929 text = XmSelectionBoxGetChild(dlog, XmDIALOG_TEXT);
931 XtSetArg(args[n], XmNtranslations, textTable); n++;
932 XtSetArg(args[n], XmNverifyBell, False); n++;
933 XtSetValues(text, args, n);
934 XtAddCallback(text, XmNmodifyVerifyCallback, EditPasswdCB, NULL);
936 /* Add callback for forcing traversal to the text field */
937 XtAddCallback (XtParent(dlog), XmNpopupCallback, MapCallback, dlog);
939 /* Unmanage the help button */
940 help = XmSelectionBoxGetChild(dlog, XmDIALOG_HELP_BUTTON);
941 XtUnmanageChild(help);
943 /* Center the dialog */
944 XtRealizeWidget(dlog);
945 XtSetArg (args[0], XmNx,
946 (Position)(WidthOfScreen(XtScreen(dlog)) -
947 dlog->core.width) / 2);
948 XtSetArg (args[1], XmNy,
949 (Position)(HeightOfScreen(XtScreen(dlog)) -
950 dlog->core.height) / 2);
951 XtSetValues (dlog, args, 2);
953 /* Set the transient property */
954 XSetTransientForHint (XtDisplay (toplevel),
955 XtWindow (XtParent (dlog)),
956 XtWindow (toplevel));
958 /* Adjust the decorations for the dialog shell of the dialog */
960 XtSetArg(args[n], XmNmwmFunctions, 0); n++;
961 XtSetArg(args[n], XmNmwmDecorations,
962 MWM_DECOR_BORDER | MWM_DECOR_TITLE); n++;
963 XtSetValues(XtParent(dlog), args, n);
965 /* Post the dialog */
968 /* Wait for the user to finish with the dialog */
971 XtAppNextEvent(appContext,&event);
972 XtDispatchEvent(&event);
975 /* Destroy the widget, and return any data back to the appl */
976 XtDestroyWidget(dlog);
981 * When a user has successfully logged in as another user, we need to set
982 * the uid and gid to the requested user. In addition, if the user is
983 * changing to 'root', then we need to log this in /usr/adm/sulog, and
984 * we need to do some housekeeping of the $PATH environment variable.
994 AddSuLog(origName, appArgs.user, "+");
998 /* Special stuff for the root user */
999 /* Cleanse the $PATH setting */
1000 tmpPath = getenv("PATH");
1001 path = XtNewString(tmpPath);
1003 tmpPath = XtMalloc(strlen(path) + 10);
1004 strcpy(tmpPath, "PATH=");
1005 strcat(tmpPath, path);
1009 /* Set up the user's new id's */
1010 SetGidUid(basegid,newuid);
1012 initgroups(appArgs.user, basegid);
1019 * Each time the user enters an invalid password, we need to log this in
1020 * /usr/adm/sulog, if the user is attempting to switch to the 'root' user.
1027 /* Unable to change to specified user; post error, then exit */
1028 AddSuLog(origName, appArgs.user, "-");
1032 /***************************************************************************
1036 * Local self-insert action for the text widget. The default action
1037 * discards control characters, which are allowed in password.
1038 ***************************************************************************/
1046 Cardinal *num_params )
1049 XComposeStatus compstatus;
1052 n = XLookupString((XKeyEvent *)event, str, sizeof(str),
1053 (KeySym *)NULL, &compstatus);
1057 XmTextFieldInsert(w, XmTextFieldGetInsertionPosition(w), str);
1062 /***************************************************************************
1066 * This action catches the 'Escape' key, and following Motif standards,
1067 * unposts the dialog, as if the 'Cancel' button had been pressed.
1068 ***************************************************************************/
1076 Cardinal *num_params )
1078 CancelCallback(w, NULL, NULL);
1083 /***************************************************************************
1087 * implement no-echo of the password
1088 ***************************************************************************/
1099 static Boolean allow_flag = False;
1100 int replaced_length, i;
1102 XmTextVerifyPtr cbData = (XmTextVerifyPtr) call;
1107 * we need to keep track of the password ourselves in order to
1108 * disable echoing of the password...
1111 replaced_length = cbData->endPos - cbData->startPos;
1112 if (replaced_length > cbData->text->length)
1114 /* shift the text at and after endPos to the left... */
1115 for (src = password + cbData->endPos,
1116 dst = src + (cbData->text->length - replaced_length),
1117 i = passwordLength - cbData->endPos;
1124 else if (replaced_length < cbData->text->length)
1126 /* Buffer must grow */
1127 password = XtRealloc(password,
1128 passwordLength + cbData->text->length - replaced_length + 5);
1130 /* shift the text at and after endPos to the right... */
1131 for (src = password + passwordLength - 1,
1132 dst = src + (cbData->text->length - replaced_length),
1133 i = passwordLength - cbData->endPos;
1142 * update the password...
1145 for (src = cbData->text->ptr,
1146 dst = password + cbData->startPos,
1147 i = cbData->text->length;
1154 passwordLength += cbData->text->length - replaced_length;
1155 password[passwordLength] = '\0';
1156 stars = XtRealloc(stars, cbData->text->length + 10);
1157 for (i = 0; i < cbData->text->length; i++)
1159 stars[cbData->text->length] = '\0';
1162 * put the appropriate number of stars in the passwd Widget..
1166 XmTextFieldReplace(w, cbData->startPos, cbData->endPos, stars);
1170 cbData->doit = allow_flag;
1175 * This function posts an error dialog informing the user that they have
1176 * specified an invalid user name. No further processing will be done; we
1177 * will simply wait for the user to acknowledge the error, and then exit.
1193 okLabel = XmStringCreateLocalized(GETMESSAGE(1,2, "OK"));
1194 template = (GETMESSAGE(1,8, "The user '%s' is an unknown user name.\n\nThe requested action will not be executed."));
1195 master = XtMalloc(strlen(template) + strlen(appArgs.user) + 10);
1196 sprintf(master, template, appArgs.user);
1197 message = XmStringCreateLocalized(master);
1198 title = (GETMESSAGE(1,9, "Action Invoker - Unknown User"));
1200 /* Post an error dialog */
1202 XtSetArg(args[n], XmNtitle, title); n++;
1203 XtSetArg(args[n], XmNmessageString, message); n++;
1204 XtSetArg(args[n], XmNokLabelString, okLabel); n++;
1205 XtSetArg(args[n], XmNdefaultPosition, False); n++;
1206 err = XmCreateErrorDialog(toplevel, "err", args, n);
1207 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_CANCEL_BUTTON));
1208 XtUnmanageChild(XmMessageBoxGetChild(err, XmDIALOG_HELP_BUTTON));
1210 /* Center the dialog */
1211 XtRealizeWidget(err);
1212 XtSetArg (args[0], XmNx,
1213 (Position)(WidthOfScreen(XtScreen(err)) -
1214 err->core.width) / 2);
1215 XtSetArg (args[1], XmNy,
1216 (Position)(HeightOfScreen(XtScreen(err)) -
1217 err->core.height) / 2);
1218 XtSetValues (err, args, 2);
1221 XtAddCallback(err, XmNokCallback, UnknownUserCallback, err);
1222 XtAddCallback(err, XmNcancelCallback, UnknownUserCallback, err);
1224 XFlush(XtDisplay(toplevel));
1225 XmUpdateDisplay(toplevel);
1227 XmStringFree(okLabel);
1228 XmStringFree(message);
1230 XtAppMainLoop(appContext);
1235 * This is the 'Cancel' callback for the 'Invalid User' error dialog.
1236 * It removes the dialog, and then exits.
1241 UnknownUserCallback(
1243 XtPointer clientData,
1244 XtPointer callData )
1247 Widget err = (Widget)clientData;
1249 XtUnmanageChild(err);
1250 XFlush(XtDisplay(err));
1251 XmUpdateDisplay(err);
1255 void actionStatusCallback(
1256 DtActionInvocationID id,
1257 XtPointer client_data,
1260 DtActionStatus status )
1264 case DtACTION_INVOKED:
1266 * There may still be error dialogs to post so we must return
1267 * to mainLoop before exiting.
1269 if ( exitAfterInvoked )
1270 XtAppAddTimeOut(appContext,
1271 10 , (XtTimerCallbackProc)CheckForDone,
1276 XtAppAddTimeOut(appContext,
1277 10 , (XtTimerCallbackProc)CheckForDone,
1281 case DtACTION_FAILED:
1282 case DtACTION_CANCELED:
1284 XtAppAddTimeOut(appContext,
1285 10 , (XtTimerCallbackProc)CheckForDone,