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: CmdProcess.c /main/8 1998/04/09 17:47:13 mgreess $ */
24 /***************************************************************************
27 * Description: Miscellaneous functions for the command execution system
30 ** (c) Copyright 1993, 1994 Hewlett-Packard Company
31 ** (c) Copyright 1993, 1994 International Business Machines Corp.
32 ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
33 ** (c) Copyright 1993, 1994 Novell, Inc.
34 ***************************************************************************/
38 #include <X11/Xproto.h>
39 #include <Dt/CommandM.h>
40 #include <Dt/DtNlUtils.h>
41 #include <Dt/ActionUtilP.h>
42 #include "myassertP.h"
49 #include <sys/getaccess.h>
52 #include <sys/socket.h>
54 #include <netinet/in.h>
61 Cmd_Resources cmd_Resources = { 0 };
62 Cmd_Globals cmd_Globals = { 0 };
64 /******** Static Function Declarations ********/
66 static char *_GetRemoteTerminalsResource (
70 static void GetRemoteTerminalsResource (
74 static void GetLocalTerminalResource (
78 static void GetWaitTimeResource (
82 static void GetDtexecPath (
86 static void GetExecutionHostLoggingResource (
90 static char *GetRemoteTerminal(
93 /******** End Static Function Declarations ********/
95 /******************************************************************************
97 * _GetRemoteTerminalsResource - gets the value of the "remoteTerminals"
102 * Display *display; The connection to the X server.
104 * char *appClass; The client's application class.
106 * char *appName; The client's application name.
108 * RETURNS: a pointer to the "remoteTerminals" resource or NULL if the
109 * resource is not defined.
111 * NOTES: The space for the returned string is "malloc'ed". The calling
112 * function should free the string.
114 *****************************************************************************/
117 *_GetRemoteTerminalsResource (
122 XrmValue resource_value;
127 char *terminals = NULL;
129 name = XtMalloc (strlen (DtREMOTE_TERMINALS_NAME) + strlen (appName) + 4);
130 sprintf (name, "%s*%s", appName, DtREMOTE_TERMINALS_NAME);
132 class = XtMalloc (strlen (DtREMOTE_TERMINALS_CLASS) + strlen (appClass) + 4);
133 sprintf (class, "%s*%s", appClass, DtREMOTE_TERMINALS_CLASS);
135 db = XtDatabase (display);
136 if (XrmGetResource (db, name, class, &rep_type, &resource_value))
137 terminals = (char *) XtNewString (resource_value.addr);
145 /******************************************************************************
147 * GetRemoteTerminalsResource - initializes the "remoteTerminals" resource.
151 * Display *display; The connection to the X server.
153 * char *appClass; The client's application class.
155 * char *appName; The client's application name.
159 * char *cmd_Resources.remoteTerminals; - Set to the list of remote
162 * char *cmd_Resources.remoteHosts; - Set to the list of remote hosts..
164 *****************************************************************************/
167 GetRemoteTerminalsResource (
176 if ((terminals = _GetRemoteTerminalsResource (display, appClass, appName))
179 * The resource was not specified, and no defaults are set.
181 cmd_Resources.remoteHosts = (char **) NULL;
182 cmd_Resources.remoteTerminals = (char **) NULL;
187 * Find out how many terminals are specified by counting the number of
190 for (pch=terminals, num=0; pch != NULL ; ) {
191 if ((pch = DtStrchr (pch, ':')) != NULL) {
202 * No "host:/terminal" pairs were found.
204 cmd_Resources.remoteHosts = (char **) NULL;
205 cmd_Resources.remoteTerminals = (char **) NULL;
210 * Create space for the pointers to the hosts and terminals and
211 * make room for a NULL terminator.
213 * Note that the host names and terminal names are "vectorized" in
214 * place by replacing the ':' and ',' characters with '\0'.
217 cmd_Resources.remoteHosts = (char **) XtMalloc (num * sizeof(char *));
218 cmd_Resources.remoteTerminals = (char **) XtMalloc (num * sizeof(char *));
220 for (pch=terminals, j=0; j < num && pch != NULL && *pch != '\0'; j++)
225 if ((pch = DtStrchr (pch, ':')) == NULL)
229 * Null terminate the host and then move past the ':'.
236 * Found a host but nothing followed it.
240 cmd_Resources.remoteHosts[j] = host;
241 cmd_Resources.remoteTerminals[j] = pch;
244 * Find the end of this entry and skip past it.
246 if ((pch = DtStrchr (pch, ',')) == NULL) {
248 * This is the last pair, advance "j" and break the loop.
255 * End the terminal name.
262 * NULL terminate the arrays.
264 cmd_Resources.remoteHosts[j] = (char *) NULL;
265 cmd_Resources.remoteTerminals[j] = (char *) NULL;
269 /******************************************************************************
271 * GetLocalTerminalResource - initializes the "localTerminal resource.
275 * Display *display; The connection to the X server.
277 * char *appClass; The client's application class.
279 * char *appName; The client's application name.
283 * char *cmd_Resources.localTerminal; - Set to the "localTerminal"
284 * or to DtDEFUALT_TERMINAL.
286 * Boolean cmd_Globals.terminal_ok; - Set to True if "localTerminal"
287 * is executable and has the correct
288 * permissions; False otherwise.
290 *****************************************************************************/
293 GetLocalTerminalResource (
298 XrmValue resource_value;
302 XrmDatabase db = XtDatabase (display);
304 name = XtMalloc (strlen (DtLOCAL_TERMINAL_NAME) + strlen (appName) + 4);
305 sprintf (name, "%s*%s", appName, DtLOCAL_TERMINAL_NAME);
307 class = XtMalloc (strlen (DtLOCAL_TERMINAL_CLASS) + strlen (appClass) + 4);
308 sprintf (class, "%s*%s", appClass, DtLOCAL_TERMINAL_CLASS);
310 if (XrmGetResource (db, name, class, &rep_type, &resource_value))
311 cmd_Resources.localTerminal = (char *) XtNewString (resource_value.addr);
313 cmd_Resources.localTerminal = XtNewString (DtTERMINAL_DEFAULT);
316 * Check to see if the execvp will potentially fail because the
317 * localTerminal is not accessable or it it is not executable. If not,
318 * log an error message.
320 cmd_Globals.terminal_ok = True;
321 if (!(_DtCmdCheckForExecutable (cmd_Resources.localTerminal))) {
322 char *errorMessage = XtMalloc(MAX_BUF_SIZE);
324 cmd_Globals.terminal_ok = False;
327 (void) sprintf (errorMessage,
328 cmd_Globals.error_terminal,
329 cmd_Resources.localTerminal);
330 _DtCmdLogErrorMessage (errorMessage);
331 XtFree(errorMessage);
339 /******************************************************************************
341 * GetWaitTimeResource - initializes the "waitTime" resource.
345 * Display *display; The connection to the X server.
347 * char *appClass; The client's application class.
349 * char *appName; The client's application name.
353 * char *cmd_Resources.waitTime; - Set to the "waitTime" resource
354 * or "True" by default.
356 *****************************************************************************/
359 GetWaitTimeResource (
364 XrmValue resource_value;
368 XrmDatabase db= XtDatabase (display);
370 cmd_Resources.waitTime = DtWAIT_TIME_DEFAULT;
372 name = XtMalloc (strlen (DtWAIT_TIME_NAME) + strlen (appName) + 4);
373 sprintf (name, "%s*%s", appName, DtWAIT_TIME_NAME);
375 class = XtMalloc (strlen (DtWAIT_TIME_CLASS) + strlen (appClass) + 4);
376 sprintf (class, "%s*%s", appClass, DtWAIT_TIME_CLASS);
378 if (XrmGetResource (db, name, class, &rep_type, &resource_value)) {
379 cmd_Resources.waitTime = atoi (resource_value.addr);
380 if (cmd_Resources.waitTime < 0)
381 cmd_Resources.waitTime = DtWAIT_TIME_DEFAULT;
388 /******************************************************************************
390 * GetDtexecPath - initializes the "dtexecPath" resource.
394 * Display *display; The connection to the X server.
396 * char *appClass; The client's application class.
398 * char *appName; The client's application name.
402 * char *cmd_Resources.dtexecPath; - Set to the "dtexecPath" resource
403 * or to DtCMD_INV_SUB_PROCESS.
405 *****************************************************************************/
413 XrmValue resource_value;
415 char errorMessage [MAX_BUF_SIZE];
418 XrmDatabase db = XtDatabase (display);
420 name = XtMalloc (strlen (DtDTEXEC_PATH_NAME) + strlen (appName) + 4);
421 sprintf (name, "%s*%s", appName, DtDTEXEC_PATH_NAME);
423 class = XtMalloc (strlen (DtDTEXEC_PATH_CLASS) + strlen (appClass) + 4);
424 sprintf (class, "%s*%s", appClass, DtDTEXEC_PATH_CLASS);
426 if (XrmGetResource (db, name, class, &rep_type, &resource_value))
427 cmd_Resources.dtexecPath = (char *) XtNewString (resource_value.addr);
429 cmd_Resources.dtexecPath = XtNewString (DtCMD_INV_SUB_PROCESS);
432 * Check to see if the execvp will potentially fail because the
433 * subprocess is not accessable or it it is not executable. If not,
434 * log an error message.
436 cmd_Globals.subprocess_ok = True;
437 if (!(_DtCmdCheckForExecutable (cmd_Resources.dtexecPath))) {
438 char *errorMessage = XtMalloc(MAX_BUF_SIZE);
440 cmd_Globals.subprocess_ok = False;
443 (void) sprintf (errorMessage,
444 cmd_Globals.error_subprocess,
445 cmd_Resources.dtexecPath);
446 _DtCmdLogErrorMessage (errorMessage);
447 XtFree(errorMessage);
455 /******************************************************************************
457 * GetExecutionHostLoggingResources - initializes the "executionHostLogging"
462 * Display *display; The connection to the X server.
464 * char *appClass; The client's application class.
466 * char *appName; The client's application name.
470 * char *cmd_Resources.executionHostLogging;
472 * - Set to the "executionHostLogging" resource or "False" by default.
474 *****************************************************************************/
477 GetExecutionHostLoggingResource (
482 XrmValue resource_value;
486 XrmDatabase db= XtDatabase (display);
488 cmd_Resources.executionHostLogging = False;
490 name = XtMalloc (strlen (DtEXECUTION_HOST_LOGGING_NAME) +
491 strlen (appName) + 4);
492 sprintf (name, "%s*%s", appName, DtEXECUTION_HOST_LOGGING_NAME);
494 class = XtMalloc (strlen (DtEXECUTION_HOST_LOGGING_CLASS) +
495 strlen (appClass) + 4);
496 sprintf (class, "%s*%s", appClass, DtEXECUTION_HOST_LOGGING_CLASS);
498 if (XrmGetResource (db, name, class, &rep_type, &resource_value)) {
499 if (((strcmp (resource_value.addr, "True")) == 0) ||
500 ((strcmp (resource_value.addr, "true")) == 0) ||
501 ((strcmp (resource_value.addr, "TRUE")) == 0))
502 cmd_Resources.executionHostLogging = True;
503 else if (((strcmp (resource_value.addr, "False")) == 0) ||
504 ((strcmp (resource_value.addr, "false")) == 0) ||
505 ((strcmp (resource_value.addr, "FALSE")) == 0))
506 cmd_Resources.executionHostLogging = False;
513 /******************************************************************************
515 * GetRemoteTerminal - takes a host name "host" and searches the list of remote
516 * host:terminal pairs for "host" and if found, returns the corresponding
521 * char *host; - Name of the host to use as the key to find
522 * the terminal emulator name.
524 * RETURNS: If "host" is found, the corresponding terminal emulator is
525 * returned, otherwise "NULL" is returned.
527 *****************************************************************************/
535 if (cmd_Resources.remoteHosts == NULL)
538 for (i=0; cmd_Resources.remoteHosts[i] != NULL; i++) {
539 if ((strcmp (host, cmd_Resources.remoteHosts[i])) == 0)
540 return (cmd_Resources.remoteTerminals[i]);
546 /******************************************************************************
548 * _DtCmdCreateTerminalCommand - takes a windowType, execString
549 * and execParms and creates an appropriate command to execute.
551 * Note that if valid execParms are found, they are simply added
552 * to the execution string, before the "-e" option.
556 * char **theCommand; - The command line to be expanded and returned.
557 * int windowType; - The request number (window number).
558 * char *execString; - The execution string to be expanded.
559 * char *execParms; - The execution parameters.
560 * char *procId - tooltalk procId for dtexec
561 * char *tmpFiles - string containing tmp file args for dtexec
565 * char ** theCommand; - Contains the completed execution string.
567 *****************************************************************************/
570 _DtCmdCreateTerminalCommand(
582 char options[MAX_BUF_SIZE];
583 char *defaultTerminal;
585 strcpy(options,execParms);
588 * Get the name of the terminal emulator to use.
590 if ((defaultTerminal = GetRemoteTerminal (execHost)) == NULL)
591 defaultTerminal = cmd_Resources.localTerminal;
594 * Create space for the expanded command line.
596 *theCommand = (char *) XtMalloc ( strlen (defaultTerminal)
598 + strlen(cmd_Resources.dtexecPath)
599 + strlen(" -open ") + 4 /* max waitTime len */
600 + strlen(" -ttprocid ") + strlen(_DtActNULL_GUARD(procId))
601 + strlen(_DtActNULL_GUARD(tmpFiles))
602 + strlen(execString) + 9 /* 2 quotes, "-e", 7 blanks, null */ );
604 if (windowType == TERMINAL) {
605 (void) sprintf (*theCommand, "%s %s -e %s -open %d -ttprocid '%s' %s %s",
606 defaultTerminal, options, cmd_Resources.dtexecPath,
607 cmd_Resources.waitTime,
608 _DtActNULL_GUARD(procId),
609 _DtActNULL_GUARD(tmpFiles),
613 (void) sprintf (*theCommand, "%s %s -e %s -open -1 -ttprocid '%s' %s %s",
614 defaultTerminal, options, cmd_Resources.dtexecPath,
615 _DtActNULL_GUARD(procId),
616 _DtActNULL_GUARD(tmpFiles),
622 /******************************************************************************
624 * _DtCmdCheckForExecutable - checks "fileName" to see if it is executable
629 * char *fileName; - The name of the file to check.
631 * RETURNS: "True" if the file is access'able && executable, "False" otherwise.
633 *****************************************************************************/
636 _DtCmdCheckForExecutable(
643 /* First check to see if the fileName contains the complete path
644 * and is access'able.
647 switch (access = _DtExecuteAccess(fileName))
649 /* execution access allowed for this process */
652 /* file found -- not executable by this process */
653 case 0: return False;
655 /* file not found -- yet */
656 case -1: /* fall through */
661 /* Append fileName to each entry in "cmd_Globals.path_list" and then see
662 * if that is accessable.
665 for (ppch = cmd_Globals.path_list; *ppch != NULL; ppch++)
667 char *longName = XtMalloc(MAXPATHLEN);
671 (void) sprintf (longName, "%s/%s", *ppch, fileName);
672 switch (access = _DtExecuteAccess(longName))
674 /* execution access allowed for this process */
677 /* file found -- not executable by this process */
678 case 0: return False;
680 /* file not found -- yet */
681 case -1: /* fall through */
692 /******************************************************************************
694 * _DtCmdValidDir - takes the client host, context directory and a context host
695 * and checks to see if the directory is valid.
699 * char *clientHost; - Host where the client is running.
701 * char *contextDir; - Directory to "chdir" to.
703 * char *contextHost; - Host where 'contextDir' resides.
707 * If the context directory is NULL, "chdir" is not run and "True" is
710 * RETURNS: "True" if "chdir" succeeds and "False" otherwise.
712 *****************************************************************************/
722 if (contextDir == NULL)
724 * Stay in the same directory.
727 if (contextHost == NULL)
729 * Change to 'contextDir'.
731 retValue = chdir (contextDir);
732 else if (_DtIsSameHost (clientHost, contextHost))
734 * Just change to 'contextDir'.
736 retValue = chdir (contextDir);
739 * Need to create a pathname for the directory.
743 char *errorMessage = XtMalloc(MAX_BUF_SIZE);
745 /* Old syntax should no longer appear in contextHost/Dir */
746 myassert( *contextHost != '*' && *contextDir != '*' );
747 netfile = (char *) tt_host_file_netfile (contextHost, contextDir);
748 if (tt_pointer_error (netfile) != TT_OK) {
749 (void) sprintf (errorMessage, cmd_Globals.error_directory_name_map,
750 contextDir, contextHost,
751 tt_status_message (tt_pointer_error(netfile)));
752 _DtCmdLogErrorMessage (errorMessage);
756 path = (char *) tt_netfile_file (netfile);
758 if (tt_pointer_error (path) != TT_OK) {
759 (void) sprintf (errorMessage, cmd_Globals.error_directory_name_map,
760 contextDir, contextHost,
761 tt_status_message (tt_pointer_error(path)));
762 _DtCmdLogErrorMessage (errorMessage);
766 retValue = chdir (path);
768 if (errorMessage) XtFree(errorMessage);
777 /******************************************************************************
779 * _DtCmdGetResources - initializes the Command Invoker's resources.
783 * Display *display; The connection to the X server.
785 * char *appClass; The client's application class.
787 *****************************************************************************/
793 char *appClass = NULL;
794 char *appName = NULL;
797 * Determine the name and class for this client.
799 XtGetApplicationNameAndClass (display, &appName, &appClass);
801 GetLocalTerminalResource (display, appClass, appName);
803 GetRemoteTerminalsResource (display, appClass, appName);
805 GetWaitTimeResource (display, appClass, appName);
807 GetDtexecPath (display, appClass, appName);
809 GetExecutionHostLoggingResource (display, appClass, appName);