CmdMain.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  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)
  10. * any later version.
  11. *
  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
  16. * details.
  17. *
  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
  22. */
  23. /* $TOG: CmdMain.c /main/15 1998/04/20 12:46:37 mgreess $ */
  24. /*
  25. * (c) Copyright 1997, The Open Group
  26. */
  27. /***************************************************************************
  28. *
  29. * File: CmdMain.c
  30. * Description: Command execution system
  31. * Language: C
  32. *
  33. ** (c) Copyright 1993, 1994 Hewlett-Packard Company
  34. ** (c) Copyright 1993, 1994 International Business Machines Corp.
  35. ** (c) Copyright 1993, 1994 Sun Microsystems, Inc.
  36. ** (c) Copyright 1993, 1994 Novell, Inc.
  37. ***************************************************************************/
  38. #include "CmdInvP.h"
  39. #include <Dt/CmdInv.h>
  40. #include <fcntl.h>
  41. #include <termios.h>
  42. #include <errno.h>
  43. #include <unistd.h>
  44. #include <sys/stat.h>
  45. #ifdef _SUN_OS /* to get the define for NOFILE */
  46. #include <sys/param.h>
  47. #endif /* _SUN_OS */
  48. #define X_INCLUDE_PWD_H
  49. #define XOS_USE_XT_LOCKING
  50. #include <X11/Xos_r.h>
  51. #include <Dt/CommandM.h>
  52. #include <Dt/EnvControlP.h>
  53. #include <Dt/DtNlUtils.h>
  54. #include <Dt/Utility.h>
  55. #include <Dt/ActionDb.h>
  56. #include <Dt/ActionUtilP.h>
  57. #include "myassertP.h"
  58. #include "DtSvcLock.h"
  59. #include <SPC/spcE.h>
  60. #include <SPC/spcP.h>
  61. #include <SPC/spc-proto.h>
  62. #include <Tt/tt_c.h>
  63. #define MAX_EXEC_ARGS 1000 /* Maximum number of arguments for */
  64. /* execvp call. */
  65. /*
  66. * Dtexec return status:
  67. */
  68. #define COMMAND_CHECK_FAILURE 1
  69. #define Cmd_FreeAllocatedStringVector(sv) \
  70. _DtCmdFreeStringVector(sv);\
  71. XtFree((char *)sv);
  72. /*
  73. * Global variables for the Command Invoker.
  74. */
  75. static char _cmdClientHost[MAXHOSTNAMELEN];
  76. /*
  77. * Static variables for the Command Invoker.
  78. */
  79. static Cmd_RequestQueue *requestQueue = NULL;
  80. /*
  81. * Static function declarations:.
  82. */
  83. static void QueueRequest (
  84. SPC_Channel_Ptr channel,
  85. char *context,
  86. char *execHost,
  87. char *execString,
  88. char **argv,
  89. int windowType,
  90. unsigned long requestNum,
  91. DtSvcMsgContext replyContext,
  92. DtCmdInvExecuteProc success_proc,
  93. void *success_data,
  94. DtCmdInvExecuteProc failure_proc,
  95. void *failure_data);
  96. static void ExecuteQueuedRequest (
  97. unsigned long requestNum);
  98. static void FreeRequest (Cmd_RequestQueue *pNode);
  99. static void DtexecTerminator (
  100. SPC_Channel_Ptr cmdChannel,
  101. int pid,
  102. int type,
  103. int cause,
  104. unsigned long ind) ;
  105. static void CheckCommandTerminator (
  106. SPC_Channel_Ptr cmdChannel,
  107. int pid,
  108. int type,
  109. int cause,
  110. unsigned long ind) ;
  111. static int DtCmdGetWindowType(
  112. unsigned long windowTypeMask);
  113. static void _DtCmdInitializeErrorMessages(void);
  114. extern void _DtEnvMapForRemote (char *targetHost);
  115. extern void _DtEnvRestoreLocal (void);
  116. /*
  117. * Command invocatin error messages.
  118. */
  119. static char *errorExec,
  120. *errorSpawn,
  121. *errorFork,
  122. *errorSpcTerminator,
  123. *errorLength,
  124. *errorRequest,
  125. *errorChdir,
  126. *errorRemoteSubprocess,
  127. *errorUnknownHost,
  128. *errorBadConnect,
  129. *errorBadService,
  130. *errorRegisterHandshake,
  131. *errorRegisterUsername,
  132. *errorRegisterNetrc,
  133. *errorRegisterOpen,
  134. *errorEnvTooBig,
  135. *errorInetSecurity,
  136. *successHost;
  137. /*******************************************************************************
  138. *
  139. * _DtSPCSpawn()
  140. * This is a wrapper around DtSPCSpawn (i.e. XeSPCSPawn) that makes sure
  141. * the original environment is restored before the spawn and the DT
  142. * environment is reinstated after the spawn. It returns the value
  143. * originally returned by DtSPCSpawn.
  144. *
  145. ******************************************************************************/
  146. int
  147. _DtSPCSpawn(
  148. char *path,
  149. char *cwd,
  150. char **args,
  151. char **env,
  152. SPC_Channel_Ptr chan,
  153. char *execHost,
  154. char *contextHost,
  155. char *contextDir,
  156. char *errorMessage)
  157. {
  158. int retVal;
  159. /*
  160. * Restore the original environment
  161. */
  162. (void) _DtEnvControl (DT_ENV_RESTORE_PRE_DT);
  163. /*
  164. * Map some env var paths to execHost.
  165. */
  166. (void) _DtEnvMapForRemote(execHost);
  167. if ((retVal = XeSPCSpawn(path,
  168. cwd,
  169. args,
  170. env,
  171. chan)) == SPC_ERROR)
  172. {
  173. switch (DtSPCErrorNumber)
  174. {
  175. case SPC_cannot_Chdir:
  176. (void) sprintf (errorMessage,
  177. errorChdir,
  178. contextDir,
  179. execHost);
  180. break;
  181. case SPC_Cannot_Fork:
  182. (void) sprintf (errorMessage,
  183. errorFork,
  184. execHost);
  185. break;
  186. case SPC_Env_Too_Big:
  187. case SPC_Arg_Too_Long:
  188. (void) sprintf (errorMessage,
  189. errorLength,
  190. SPC_BUFSIZ);
  191. break;
  192. default:
  193. /*
  194. * SPC_Cannot_Exec
  195. */
  196. (void) sprintf (errorMessage,
  197. errorSpawn,
  198. execHost,
  199. path);
  200. }
  201. }
  202. /*
  203. * Restore some env var paths.
  204. */
  205. (void) _DtEnvRestoreLocal();
  206. /*
  207. * Restore the DT environment
  208. */
  209. (void) _DtEnvControl (DT_ENV_RESTORE_POST_DT);
  210. /*
  211. * Return the result of DtSPCSpawn
  212. */
  213. return retVal;
  214. }
  215. /*******************************************************************************
  216. *
  217. * _DtSPCOpen()
  218. * This is a wrapper around DtSPCOpen (i.e. XeSPCOpen) that makes sure
  219. * the original environment is restored before the spawn and the DT
  220. * environment is reinstated after the spawn. It returns the value
  221. * originally returned by DtSPCOpen.
  222. *
  223. ******************************************************************************/
  224. SPC_Channel_Ptr
  225. _DtSPCOpen(
  226. char *hostname,
  227. int iomode,
  228. char *errorMessage)
  229. {
  230. SPC_Channel_Ptr chan;
  231. _Xgetpwparams pwd_buf;
  232. struct passwd * pwd_ret;
  233. /*
  234. * Restore the original environment
  235. */
  236. (void) _DtEnvControl (DT_ENV_RESTORE_PRE_DT);
  237. /*
  238. * Map some env var paths to execHost.
  239. */
  240. (void) _DtEnvMapForRemote(hostname);
  241. if ((chan = XeSPCOpen(hostname, iomode)) == SPC_ERROR)
  242. {
  243. uid_t this_uid;
  244. char *username;
  245. switch (DtSPCErrorNumber)
  246. {
  247. case SPC_Unknown_Host:
  248. (void) sprintf (errorMessage,
  249. errorUnknownHost,
  250. hostname);
  251. break;
  252. case SPC_Bad_Connect:
  253. (void) sprintf (errorMessage,
  254. errorBadConnect,
  255. hostname,
  256. SPC_SERVICE,
  257. _cmdClientHost);
  258. break;
  259. case SPC_Bad_Service:
  260. (void) sprintf (errorMessage,
  261. errorBadService,
  262. SPC_SERVICE,
  263. _cmdClientHost);
  264. break;
  265. case SPC_Register_Handshake:
  266. this_uid = getuid();
  267. if((pwd_ret = _XGetpwuid(this_uid, pwd_buf)) ==
  268. NULL)
  269. username = NULL;
  270. else
  271. username = pwd_ret->pw_name;
  272. (void) sprintf (errorMessage,
  273. errorRegisterHandshake,
  274. hostname,
  275. username,
  276. this_uid,
  277. _cmdClientHost,
  278. hostname);
  279. break;
  280. case SPC_Register_Username:
  281. this_uid = getuid();
  282. if((pwd_ret = _XGetpwuid(this_uid, pwd_buf)) ==
  283. NULL)
  284. username = NULL;
  285. else
  286. username = pwd_ret->pw_name;
  287. (void) sprintf (errorMessage,
  288. errorRegisterUsername,
  289. hostname,
  290. username);
  291. break;
  292. case SPC_Register_Netrc:
  293. (void) sprintf (errorMessage,
  294. errorRegisterNetrc,
  295. hostname);
  296. break;
  297. case SPC_Env_Too_Big:
  298. (void) sprintf (errorMessage,
  299. errorEnvTooBig,
  300. hostname,
  301. SPC_BUFSIZ);
  302. break;
  303. case SPC_Connection_EOF:
  304. (void) sprintf (errorMessage,
  305. errorBadConnect,
  306. hostname,
  307. SPC_SERVICE,
  308. _cmdClientHost);
  309. break;
  310. default:
  311. /*
  312. * SPC_Register_Open:
  313. */
  314. (void) sprintf (errorMessage,
  315. errorRegisterOpen,
  316. hostname);
  317. }
  318. }
  319. /*
  320. * Restore some env var paths.
  321. */
  322. (void) _DtEnvRestoreLocal();
  323. /*
  324. * Restore the DT environment
  325. */
  326. (void) _DtEnvControl (DT_ENV_RESTORE_POST_DT);
  327. return chan;
  328. }
  329. /******************************************************************************
  330. *
  331. * QueueRequest - takes the "state" from a request and puts it on the
  332. * "requestQueue".
  333. *
  334. * PARAMETERS:
  335. *
  336. * SPC_Channel_Ptr channel; - Spcd channel id.
  337. * char *context; - Context for SPCSpawn.
  338. * char *execHost; - The execution host.
  339. * char *execString; - The execution string.
  340. * char **argv; - Arg vector for SPCSpawn.
  341. * (Arg vector is XtFree'd)
  342. * int windowType; - window type of queued command.
  343. * unsigned long requestNum; - Id number into the queue.
  344. * DtSvcMsgContext replyContext; - Reply info.
  345. * DtCmdInvExecuteProc success_proc; - Success callback.
  346. * void *success_data; - Success client_data.
  347. * DtCmdInvExecuteProc failure_proc; - Failure callback.
  348. * void *failure_data; - Failure client_data.
  349. *
  350. * MODIFIED:
  351. *
  352. * Cmd_RequestQueue *requestQueue; - This request to added.
  353. *
  354. *****************************************************************************/
  355. static void
  356. QueueRequest (
  357. SPC_Channel_Ptr channel,
  358. char *context,
  359. char *execHost,
  360. char *execString,
  361. char **argv,
  362. int winType,
  363. unsigned long requestNum,
  364. DtSvcMsgContext replyContext,
  365. DtCmdInvExecuteProc success_proc,
  366. void *success_data,
  367. DtCmdInvExecuteProc failure_proc,
  368. void *failure_data)
  369. {
  370. Cmd_RequestQueue *pNode;
  371. Cmd_RequestQueue *pNewNode;
  372. pNewNode = (Cmd_RequestQueue *) XtMalloc (sizeof (Cmd_RequestQueue));
  373. pNewNode->next = (Cmd_RequestQueue *) NULL;
  374. pNewNode->channel = channel;
  375. pNewNode->context = XtNewString (context);
  376. pNewNode->exec_host = XtNewString (execHost);
  377. pNewNode->exec_string = XtNewString (execString);
  378. pNewNode->argv = argv;
  379. pNewNode->winType = winType;
  380. pNewNode->request_num = requestNum;
  381. if (replyContext == NULL)
  382. pNewNode->replyContext = NULL;
  383. else
  384. pNewNode->replyContext = replyContext;
  385. pNewNode->success_proc = success_proc;
  386. pNewNode->success_data = success_data;
  387. pNewNode->failure_proc = failure_proc;
  388. pNewNode->failure_data = failure_data;
  389. if (requestQueue == NULL)
  390. {
  391. requestQueue = pNewNode;
  392. return;
  393. }
  394. /*
  395. * Find the End Of the Queue and link in the NewNode.
  396. */
  397. for (pNode = requestQueue; pNode->next != NULL; pNode = pNode->next);
  398. pNode->next = pNewNode;
  399. }
  400. /******************************************************************************
  401. *
  402. * ExecuteQueuedRequest - given a key into the requestQueue (requestNum)
  403. * find the appropriate request and execute it.
  404. *
  405. * PARAMETERS:
  406. *
  407. * unsigned long requestNum; - Key into the requestQueue.
  408. *
  409. * MODIFIED:
  410. *
  411. * Cmd_RequestQueue *requestQueue; - The executed request gets
  412. * freed.
  413. *
  414. *****************************************************************************/
  415. static void
  416. ExecuteQueuedRequest (
  417. unsigned long requestNum)
  418. {
  419. char *errorMessage;
  420. Boolean success = True;
  421. Cmd_RequestQueue *prev = NULL;
  422. Cmd_RequestQueue *pNode = requestQueue;
  423. unsigned long iomode;
  424. for (; pNode != NULL; pNode = pNode->next)
  425. {
  426. if ( pNode->request_num == requestNum )
  427. {
  428. /*
  429. * Pluck pNode out of the queue
  430. */
  431. if (prev)
  432. prev->next = pNode->next;
  433. else
  434. requestQueue = pNode->next;
  435. pNode->next = NULL;
  436. break;
  437. }
  438. /*
  439. * Move alone to the next node
  440. */
  441. prev = pNode;
  442. }
  443. if (pNode == NULL)
  444. return;
  445. errorMessage = XtMalloc (MAX_BUF_SIZE * sizeof (char));
  446. /*
  447. * Reopen SPC Channel
  448. */
  449. iomode = ( SPCIO_NOIO
  450. | SPCIO_SYNC_TERMINATOR
  451. | SPCIO_FORCE_CONTEXT );
  452. if ((pNode->channel = (_DtSPCOpen(pNode->exec_host,
  453. iomode,
  454. errorMessage))) == SPC_ERROR)
  455. {
  456. success = False;
  457. }
  458. if ( success )
  459. if ((_DtSPCSpawn(pNode->argv[0], pNode->context, pNode->argv, NULL,
  460. pNode->channel, pNode->exec_host, NULL, NULL,
  461. errorMessage)) == SPC_ERROR)
  462. {
  463. success = False;
  464. if (DtSPCErrorNumber != SPC_Arg_Too_Long)
  465. DtSPCClose(pNode->channel);
  466. }
  467. if (success && pNode->success_proc != NULL)
  468. {
  469. if (cmd_Resources.executionHostLogging && pNode->success_data != NULL)
  470. {
  471. CallbackData *data;
  472. data = (CallbackData *) pNode->success_data;
  473. (void) sprintf (errorMessage, successHost,
  474. data->actionLabel, pNode->exec_host);
  475. _DtCmdLogErrorMessage (errorMessage);
  476. }
  477. (*pNode->success_proc) (NULL, pNode->success_data);
  478. }
  479. else if (!success)
  480. {
  481. if (cmd_Resources.executionHostLogging)
  482. {
  483. if (DtSPCErrorNumber == SPC_Arg_Too_Long)
  484. {
  485. int cmdlen,i;
  486. char *cmdp; /* pointer to complete command string */
  487. char *tmp_message;
  488. /*
  489. * The message should include all of the command because
  490. * the problem may be with some on the internally generated
  491. * parts of the command (e.g. the terminal emulator and args).
  492. * This means going through all of argv to determine the
  493. * length of the string.
  494. */
  495. for (cmdlen = 0, i = 0; pNode->argv[i]; i++) {
  496. cmdlen+=strlen(pNode->argv[i]);
  497. cmdlen+=2; /* make room for a space + string terminator */
  498. }
  499. tmp_message = (char *) XtMalloc (strlen (errorSpawn) +
  500. strlen (pNode->exec_host) +
  501. cmdlen + 4);
  502. cmdp = (char *) XtMalloc(cmdlen + 1);
  503. *cmdp = '\0';
  504. for (i = 0; pNode->argv[i]; i++) {
  505. strcat(cmdp,pNode->argv[i]);
  506. strcat(cmdp, " ");
  507. }
  508. (void) sprintf (tmp_message, errorSpawn, pNode->exec_host, cmdp);
  509. _DtCmdLogErrorMessage (tmp_message);
  510. XtFree(cmdp);
  511. XtFree(tmp_message);
  512. }
  513. }
  514. if (pNode->failure_proc != NULL)
  515. (*pNode->failure_proc) (errorMessage, pNode->failure_data);
  516. }
  517. XtFree ((char *)errorMessage);
  518. FreeRequest (pNode);
  519. }
  520. Cmd_RequestQueue *
  521. _DtCmdGetQueueHead(void)
  522. {
  523. return requestQueue;
  524. }
  525. /******************************************************************************
  526. *
  527. * FreeRequest - Frees the malloced data associated with the node.
  528. * and frees the node.
  529. *
  530. * PARAMETERS:
  531. *
  532. * Cmd_RequestQueue *pNode
  533. *
  534. *
  535. *****************************************************************************/
  536. static void
  537. FreeRequest (Cmd_RequestQueue *pNode)
  538. {
  539. if (pNode == NULL)
  540. return;
  541. XtFree (pNode->context);
  542. XtFree (pNode->exec_host);
  543. XtFree (pNode->exec_string);
  544. Cmd_FreeAllocatedStringVector (pNode->argv);
  545. XtFree ((char *) pNode);
  546. }
  547. /******************************************************************************
  548. *
  549. * _DtCmdCommandInvokerExecute - executes a request on the specified host.
  550. *
  551. * RETURNS: int
  552. *
  553. * _CMD_EXECUTE_SUCCESS - successful execution
  554. * _CMD_EXECUTE_FAILURE - execution failed
  555. * _CMD_EXECUTE_QUEUED - the request was queued
  556. * _CMD_EXECUTE_FATAL - the request contains invalid information
  557. *
  558. *
  559. *****************************************************************************/
  560. int
  561. _DtCmdCommandInvokerExecute (
  562. char *errorMessage, /* MODIFIED */
  563. DtSvcMsgContext replyContext, /* OBSOLETE -- always NULL */
  564. int winMask,
  565. char *contextHost,
  566. char *contextDir,
  567. char *contextFile, /* OBSOLETE -- always NULL */
  568. char *execParms,
  569. char *execHost,
  570. char *execString,
  571. char *procId,
  572. char *tmpFiles,
  573. DtCmdInvExecuteProc success_proc,
  574. void *success_data,
  575. DtCmdInvExecuteProc failure_proc,
  576. void *failure_data)
  577. {
  578. int ioMode, i, index1;
  579. int windowType;
  580. pid_t commandPid;
  581. char context[MAXPATHLEN];
  582. char tmpDir [MAXPATHLEN];
  583. char **commandArray;
  584. SPC_Channel_Ptr cmdChannel;
  585. char *theCommand = NULL;
  586. Boolean terminalRequest = False;
  587. char *commandArray2[MAX_EXEC_ARGS];
  588. Boolean localExecution = True;
  589. Boolean xhostError;
  590. static unsigned long requestNum = 0;
  591. char *toolRequest = NULL; /* backward compatibility kludge */
  592. myassert( !(contextFile && replyContext) );
  593. /*
  594. * Check for a valid window-type.
  595. * This check is probably redundant but it converts the mask bits into
  596. * small integer values used by the rest of the command invoker code.
  597. */
  598. if ((windowType=
  599. DtCmdGetWindowType(winMask))== -1)
  600. {
  601. (void) sprintf (errorMessage, errorRequest, toolRequest,
  602. DtTERMINAL, DtPERM_TERMINAL, DtOUTPUT_ONLY,
  603. DtSHARED_OUTPUT, "" /* Obsolete shell window */,
  604. DtNO_STDIO);
  605. return (_CMD_EXECUTE_FATAL);
  606. }
  607. /*
  608. * Create the command to be exec'ed.
  609. */
  610. if (windowType == PERM_TERMINAL || windowType == TERMINAL)
  611. {
  612. _DtCmdCreateTerminalCommand (&theCommand, windowType, execString,
  613. execParms, execHost, procId, tmpFiles);
  614. terminalRequest = True;
  615. }
  616. else
  617. {
  618. /*
  619. * NO-STDIO || START-SESSION request.
  620. */
  621. theCommand = XtMalloc(
  622. + strlen (cmd_Resources.dtexecPath)
  623. + strlen(" -open ") + 4 /* waitTime len */
  624. + strlen(" -ttprocid ") + strlen(_DtActNULL_GUARD(procId))
  625. + strlen(_DtActNULL_GUARD(tmpFiles))
  626. + strlen (execString)
  627. + 5 /* for 2 quotes,2 blanks,null */);
  628. sprintf(theCommand,"%s -open %d -ttprocid '%s' %s %s",
  629. cmd_Resources.dtexecPath,
  630. 0 /* wait time zero for NO_STDIO */,
  631. _DtActNULL_GUARD(procId),
  632. _DtActNULL_GUARD(tmpFiles),
  633. execString);
  634. }
  635. /*
  636. * See if the request requires Remote Execution.
  637. */
  638. localExecution = _DtIsSameHost(execHost,NULL);
  639. /*
  640. * If this is a terminalRequest and the Command Invoker subprocess
  641. * is not executable, return now.
  642. */
  643. if (localExecution && terminalRequest && !cmd_Globals.subprocess_ok)
  644. {
  645. if (!(_DtCmdCheckForExecutable (cmd_Resources.dtexecPath)))
  646. {
  647. (void) sprintf (errorMessage, cmd_Globals.error_subprocess,
  648. cmd_Resources.dtexecPath);
  649. XtFree ((char *) theCommand);
  650. return (_CMD_EXECUTE_FAILURE);
  651. }
  652. else
  653. cmd_Globals.subprocess_ok = True;
  654. }
  655. /*
  656. * If this is a terminalRequest and the terminal emulator
  657. * is not executable, return now.
  658. */
  659. if (localExecution && terminalRequest && !cmd_Globals.terminal_ok)
  660. {
  661. if (!(_DtCmdCheckForExecutable (cmd_Resources.localTerminal)))
  662. {
  663. (void) sprintf (errorMessage, cmd_Globals.error_terminal,
  664. cmd_Resources.localTerminal);
  665. XtFree ((char *) theCommand);
  666. return (_CMD_EXECUTE_FAILURE);
  667. }
  668. else
  669. cmd_Globals.terminal_ok = True;
  670. }
  671. /*
  672. * Break the command into something execvp or SPCSpawn can handle
  673. * and then free "theCommand" if this is a termianl-based request.
  674. */
  675. commandArray = (char **) XtMalloc (MAX_EXEC_ARGS * sizeof (char *));
  676. _DtCmdStringToArrayOfStrings (theCommand, commandArray);
  677. XtFree (theCommand);
  678. if (!localExecution)
  679. {
  680. char *netfile;
  681. char *argv[4];
  682. char *tmp;
  683. /* REMOTE Execution */
  684. ioMode = SPCIO_NOIO | SPCIO_SYNC_TERMINATOR | SPCIO_FORCE_CONTEXT;
  685. if ((cmdChannel = (_DtSPCOpen(execHost,
  686. ioMode,
  687. errorMessage))) == SPC_ERROR)
  688. {
  689. Cmd_FreeAllocatedStringVector (commandArray);
  690. return (_CMD_EXECUTE_FAILURE);
  691. }
  692. /* Old syntax should no longer appear in contextHost/Dir */
  693. myassert( (contextHost?*contextHost != '*':1) &&
  694. (contextDir?*contextDir != '*':1) );
  695. /*
  696. * Create a "netfile" for the cwd to be used.
  697. */
  698. netfile = (char *) tt_host_file_netfile (
  699. ((contextHost == NULL) ? execHost : contextHost),
  700. ((contextDir == NULL) ? (char *) getenv ("HOME") : contextDir));
  701. if (tt_pointer_error (netfile) != TT_OK) {
  702. (void) sprintf (errorMessage, cmd_Globals.error_directory_name_map,
  703. ((contextDir == NULL) ? (char *) getenv ("HOME") : contextDir),
  704. ((contextHost == NULL) ? execHost : contextHost),
  705. tt_status_message (tt_pointer_error(netfile)));
  706. Cmd_FreeAllocatedStringVector (commandArray);
  707. return (_CMD_EXECUTE_FAILURE);
  708. }
  709. (void) strcpy (context, netfile);
  710. tt_free (netfile);
  711. /*
  712. * First check to see if the "dtexecPath" is executable on
  713. * the remote execution host by executing it with no
  714. * options which will cause it to immediately die.
  715. *
  716. * There is no need to set up termination handler for this
  717. * because we don't care when it dies, we only care about
  718. * whether or not it can be executed.
  719. */
  720. argv[0] = cmd_Resources.dtexecPath;
  721. argv[1] = (char *) NULL;
  722. if ((_DtSPCSpawn(argv[0], context, argv, NULL, cmdChannel,
  723. execHost, contextHost, contextDir, errorMessage))
  724. == SPC_ERROR)
  725. {
  726. if (DtSPCErrorNumber != SPC_cannot_Chdir &&
  727. DtSPCErrorNumber != SPC_Cannot_Fork &&
  728. DtSPCErrorNumber != SPC_Env_Too_Big &&
  729. DtSPCErrorNumber != SPC_Arg_Too_Long)
  730. /*
  731. * The Error message must mention that the dtexec
  732. * process is not executable so must overwrite the
  733. * error message returned by the Spawn function with
  734. * an appropriate message.
  735. */
  736. (void) sprintf (errorMessage, errorRemoteSubprocess, execHost,
  737. cmd_Resources.dtexecPath);
  738. DtSPCClose(cmdChannel);
  739. Cmd_FreeAllocatedStringVector (commandArray);
  740. return (_CMD_EXECUTE_FAILURE);
  741. }
  742. /* The dtexec process is now known to exist on the remote host */
  743. /*
  744. * Now run a test to see if the command is executable
  745. * on this exec host.
  746. */
  747. _DtCmdStringToArrayOfStrings (execString, commandArray2);
  748. tmp = (char *) XtMalloc (strlen (commandArray2[0]) +
  749. strlen ("whence ") + 2);
  750. (void) sprintf (tmp, "whence %s", commandArray2[0]);
  751. _DtCmdFreeStringVector (commandArray2);
  752. argv[0] = "ksh";
  753. argv[1] = "-c";
  754. argv[2] = tmp;
  755. argv[3] = (char *) NULL;
  756. /*
  757. * Reopen the channel
  758. */
  759. if ((cmdChannel = (_DtSPCOpen(execHost,
  760. ioMode,
  761. errorMessage))) == SPC_ERROR)
  762. {
  763. Cmd_FreeAllocatedStringVector (commandArray);
  764. return (_CMD_EXECUTE_FAILURE);
  765. }
  766. /*
  767. * Set up a callback to be invoked when the test command
  768. * terminates.
  769. */
  770. _DtSvcProcessLock();
  771. if ((DtSPCRegisterTerminator(cmdChannel,
  772. (SPC_TerminateHandlerType) CheckCommandTerminator,
  773. (void *) ++requestNum)) == SPC_ERROR)
  774. {
  775. DtSPCClose(cmdChannel);
  776. Cmd_FreeAllocatedStringVector (commandArray);
  777. (void) strcpy (errorMessage, errorSpcTerminator);
  778. XtFree ((char *) tmp);
  779. _DtSvcProcessUnlock();
  780. return (_CMD_EXECUTE_FAILURE);
  781. }
  782. if ((_DtSPCSpawn(argv[0], context, argv, NULL, cmdChannel,
  783. execHost, contextHost, contextDir, errorMessage))
  784. == SPC_ERROR)
  785. {
  786. DtSPCClose(cmdChannel);
  787. (void) sprintf (errorMessage, errorRemoteSubprocess, execHost,
  788. argv[0]);
  789. Cmd_FreeAllocatedStringVector (commandArray);
  790. XtFree ((char *) tmp);
  791. _DtSvcProcessUnlock();
  792. return (_CMD_EXECUTE_FAILURE);
  793. }
  794. /*
  795. * The command line checking process has been spawned.
  796. * There is nothing left to do but to queue the request
  797. * and return to the client's main loop. The command
  798. * line will be executed after the above spawned process
  799. * terminates.
  800. */
  801. QueueRequest (cmdChannel, context, execHost, execString,
  802. commandArray, windowType, requestNum, replyContext,
  803. success_proc, success_data, failure_proc, failure_data);
  804. _DtSvcProcessUnlock();
  805. XtFree(tmp);
  806. return (_CMD_EXECUTE_QUEUED);
  807. }
  808. else
  809. {
  810. /* LOCAL Execution */
  811. /*
  812. * Must first check to see if the execvp will potentially fail.
  813. *
  814. * Since the terminal emulator is pre-appended onto the execution
  815. * string, don't want to check it (should have been done during
  816. * startup (in _DtInitializeCommandInvoker)) but must check the
  817. * execution string that was passed in as part of the message.
  818. */
  819. /* Break the command into something execvp can handle */
  820. _DtCmdStringToArrayOfStrings (execString, commandArray2);
  821. if (!_DtCmdCheckForExecutable (commandArray2[0]))
  822. {
  823. (void) sprintf (errorMessage, errorExec, commandArray2[0]);
  824. Cmd_FreeAllocatedStringVector (commandArray);
  825. _DtCmdFreeStringVector (commandArray2);
  826. return (_CMD_EXECUTE_FAILURE);
  827. }
  828. _DtCmdFreeStringVector (commandArray2);
  829. /*
  830. * Save the current directory and then "chdir" to the directory
  831. * to do the execution. If the chdir fails, return.
  832. */
  833. if(NULL == getcwd (tmpDir, MAXPATHLEN))
  834. {
  835. perror(strerror(errno));
  836. return (_CMD_EXECUTE_FAILURE);
  837. }
  838. if (!_DtCmdValidDir (_cmdClientHost, contextDir, contextHost))
  839. {
  840. Cmd_FreeAllocatedStringVector (commandArray);
  841. (void) sprintf (errorMessage, errorChdir, contextDir, execHost);
  842. if(-1 == chdir (tmpDir)) {
  843. perror(strerror(errno));
  844. }
  845. return (_CMD_EXECUTE_FAILURE);
  846. }
  847. /*
  848. * Restore the original environment and remove any DT
  849. * specific environment variables that were added.
  850. */
  851. (void) _DtEnvControl (DT_ENV_RESTORE_PRE_DT);
  852. /* Fork and then execvp the execution string */
  853. for (index1 = 0; (index1 < 10) &&
  854. ((commandPid = fork ()) < 0); index1++)
  855. {
  856. /* Out of resources ? */
  857. if (errno != EAGAIN)
  858. break;
  859. /* If not out of resources, sleep and try again */
  860. (void) sleep ((unsigned long) 2);
  861. }
  862. if (commandPid < 0)
  863. {
  864. Cmd_FreeAllocatedStringVector (commandArray);
  865. if(-1 == chdir (tmpDir)) {
  866. perror(strerror(errno));
  867. }
  868. (void) sprintf(errorMessage, errorFork, execHost);
  869. (void) _DtEnvControl (DT_ENV_RESTORE_POST_DT);
  870. return (_CMD_EXECUTE_FAILURE);
  871. }
  872. if (commandPid == 0)
  873. {
  874. #if defined(CSRG_BASED)
  875. setsid() ;
  876. #else
  877. (void) setpgrp ();
  878. #endif
  879. if (!terminalRequest )
  880. {
  881. int fd;
  882. /*
  883. * Close stdout and redirect it to /dev/null. If this
  884. * is not done and the request writes to stdout, the
  885. * output will be queued in an "unlinked" file in
  886. * /tmp until the client using this code terminates.
  887. */
  888. if ((fd = open ("/dev/null", O_RDWR)) > 0)
  889. (void) dup2 (fd, fileno (stdout));
  890. }
  891. /*
  892. * Mark file descriptiors >=3 as "Close on Exec".
  893. */
  894. {
  895. long open_max;
  896. open_max = sysconf(_SC_OPEN_MAX);
  897. if (open_max == -1)
  898. {
  899. #ifdef _SUN_OS
  900. open_max = NOFILE;
  901. #else
  902. #if defined(_AIX)
  903. open_max = FOPEN_MAX;
  904. #else
  905. open_max = FD_SETSIZE;
  906. #endif
  907. #endif /* _SUN_OS */
  908. }
  909. for (i=3; i < open_max; i++)
  910. (void) fcntl (i, F_SETFD, 1);
  911. }
  912. (void) execvp (commandArray[0], commandArray);
  913. /* Should never get here, but if you do, must exit */
  914. /*
  915. * The following message will be written to the errorlog
  916. * file if the request is not a terminal requests or
  917. * to the terminal window if the request requires a
  918. * terminal.
  919. */
  920. (void) sprintf (errorMessage, errorExec, commandArray[0]);
  921. (void) printf ("%s\n", errorMessage);
  922. (void) _exit (1);
  923. }
  924. /*
  925. * Restore the pre-fork environment.
  926. */
  927. (void) chdir (tmpDir);
  928. (void) _DtEnvControl (DT_ENV_RESTORE_POST_DT);
  929. }
  930. Cmd_FreeAllocatedStringVector (commandArray);
  931. return (_CMD_EXECUTE_SUCCESS);
  932. }
  933. /******************************************************************************
  934. *
  935. * CheckCommandTerminator - this is the SPC termination callback
  936. * that is invoked when the command line checking process terminates.
  937. *
  938. * When this callback is invoked, the next step is to check the
  939. * exit status of the remote checking process and if the "command_
  940. * line" is executable, execute the QueuedRequest. Otherwise,
  941. * return.
  942. *
  943. * PARAMETERS: This parameters for this callback are those defined by
  944. * the type "SPC_TerminateHandlerType". Most are not used.
  945. *
  946. *****************************************************************************/
  947. static void
  948. CheckCommandTerminator(
  949. SPC_Channel_Ptr cmdChannel,
  950. int pid, /* NOT USED */
  951. int type, /* NOT USED */
  952. int cause, /* Exit value of the remote process. */
  953. unsigned long requestNum) /* Specifies the request number. */
  954. {
  955. Boolean xhostError;
  956. char errorMessage[MAX_BUF_SIZE];
  957. Cmd_RequestQueue *prev = NULL;
  958. Cmd_RequestQueue *pNode = requestQueue;
  959. DtSPCClose(cmdChannel);
  960. /*
  961. * Must find the node in the queue.
  962. */
  963. for (; pNode != NULL; pNode = pNode->next)
  964. {
  965. if ( pNode->request_num == requestNum )
  966. {
  967. /*
  968. * Pluck pNode out of the queue
  969. */
  970. if (prev)
  971. prev->next = pNode->next;
  972. else
  973. requestQueue = pNode->next;
  974. pNode->next = NULL;
  975. break;
  976. }
  977. /*
  978. * Move alone to the next node
  979. */
  980. prev = pNode;
  981. }
  982. if (pNode == NULL)
  983. return;
  984. /*
  985. * Check the exit status of the remote process.
  986. */
  987. if (cause == COMMAND_CHECK_FAILURE)
  988. {
  989. if (pNode->failure_proc != NULL)
  990. {
  991. (void) sprintf (errorMessage, errorSpawn, pNode->exec_host,
  992. pNode->exec_string);
  993. if (cmd_Resources.executionHostLogging)
  994. _DtCmdLogErrorMessage (errorMessage);
  995. (*pNode->failure_proc) (errorMessage, pNode->failure_data);
  996. }
  997. FreeRequest (pNode);
  998. return;
  999. }
  1000. /*
  1001. * Re-queue this node -- we will execute the command
  1002. */
  1003. pNode->next = requestQueue;
  1004. requestQueue = pNode;
  1005. ExecuteQueuedRequest (requestNum);
  1006. }
  1007. /******************************************************************************
  1008. *
  1009. * DtCmdGetWindowType - given a window-type mask, determine its'
  1010. * internal window type number.
  1011. *
  1012. * It should not be possible for this to be called with a bogus mask,
  1013. *
  1014. * PARAMETERS:
  1015. *
  1016. * unsigned long mask; - The request window type mask
  1017. *
  1018. * RETURNS: The window type if one if found, otherwise "-1".
  1019. *
  1020. *****************************************************************************/
  1021. static int
  1022. DtCmdGetWindowType(
  1023. unsigned long windowTypeMask)
  1024. {
  1025. int winTypeNum = -1;
  1026. /*
  1027. * Determine the winType number recognized by dtexec
  1028. * The expected wintype input here is the value of the
  1029. * wintype bits in the action mask. Convert this to the
  1030. * simple integers expected by dtexec.
  1031. */
  1032. switch ( windowTypeMask )
  1033. {
  1034. case _DtAct_NO_STDIO_BIT:
  1035. winTypeNum = 0;
  1036. break;
  1037. case _DtAct_TERMINAL_BIT:
  1038. winTypeNum = TERMINAL;
  1039. break;
  1040. case _DtAct_PERM_TERM_BIT:
  1041. winTypeNum = PERM_TERMINAL;
  1042. break;
  1043. default:
  1044. myassert(0); /* should never get here */
  1045. winTypeNum = PERM_TERMINAL;
  1046. break;
  1047. }
  1048. return winTypeNum;
  1049. }
  1050. /******************************************************************************
  1051. *
  1052. * _DtActionCommandInvoke
  1053. * ----------------------
  1054. * This is the primary entry point into the command invoker portion
  1055. * of the Dt Services library. Command Actions are routed to this
  1056. * entry point. This function is used to invoke both local and remote
  1057. * commands.
  1058. *
  1059. * If logging is turned on, the success or failure message is logged.
  1060. ******************************************************************************/
  1061. int
  1062. _DtActionCommandInvoke(
  1063. long wintype,
  1064. char * cwdHost,
  1065. char * cwdDir,
  1066. char * execString,
  1067. char * termOpts,
  1068. char * execHost,
  1069. char * procId,
  1070. char * tmpFiles,
  1071. void (*success_proc)(),
  1072. void *success_data,
  1073. void (*failure_proc)(),
  1074. void *failure_data)
  1075. {
  1076. int status;
  1077. char errorMessage[MAX_BUF_SIZE * 2];
  1078. status = _DtCmdCommandInvokerExecute (errorMessage, NULL,
  1079. wintype,
  1080. cwdHost, cwdDir, NULL,
  1081. termOpts, execHost, execString,
  1082. procId, tmpFiles,
  1083. success_proc, success_data,
  1084. failure_proc, failure_data);
  1085. switch (status)
  1086. {
  1087. case _CMD_EXECUTE_SUCCESS :
  1088. if (cmd_Resources.executionHostLogging && success_data != NULL)
  1089. {
  1090. CallbackData *data;
  1091. data = (CallbackData *) success_data;
  1092. (void) sprintf (errorMessage, successHost,
  1093. data->actionLabel, execHost);
  1094. _DtCmdLogErrorMessage (errorMessage);
  1095. }
  1096. if (success_proc != NULL)
  1097. (*success_proc) (NULL, success_data);
  1098. break;
  1099. case _CMD_EXECUTE_QUEUED :
  1100. /*
  1101. * Return for now and when the termination handler
  1102. * gets hit, the queued request will be executed.
  1103. */
  1104. break;
  1105. default :
  1106. /*
  1107. * _CMD_EXECUTE_FAILURE or _CMD_EXECUTE_FATAL
  1108. */
  1109. if (cmd_Resources.executionHostLogging)
  1110. _DtCmdLogErrorMessage (errorMessage);
  1111. if (failure_proc != NULL)
  1112. (*failure_proc) (errorMessage, failure_data);
  1113. break;
  1114. }
  1115. return (status == _CMD_EXECUTE_QUEUED) ? 1 : 0;
  1116. }
  1117. /******************************************************************************
  1118. *
  1119. * _DtCommandInvokerExecute -
  1120. *
  1121. * This function allows a client to use the DT "Command Invoker"
  1122. * Library for its' process execution. This function is intended
  1123. * for processes which do not use the Action Library.
  1124. *
  1125. * For local execution, the "fork" and "execvp" system calls are
  1126. * used. For remote execution, the "SPCD" is used.
  1127. *
  1128. * RETURNS: Nothing directly. However, if the command is successfully
  1129. * executed, the "success_proc" function is executed; otherwise,
  1130. * the "failure_proc" function is executed.
  1131. *
  1132. * NOTE: This API is NOT public it is only here for use by the Session
  1133. * manager which uses to start up remote clients at session restore
  1134. * time (see SmRestore.c).
  1135. *
  1136. *****************************************************************************/
  1137. void
  1138. _DtCommandInvokerExecute(
  1139. char *request_name,
  1140. char *context_host,
  1141. char *context_dir,
  1142. char *context_file,
  1143. char *exec_parameters,
  1144. char *exec_host,
  1145. char *exec_string,
  1146. DtCmdInvExecuteProc success_proc,
  1147. void *success_data,
  1148. DtCmdInvExecuteProc failure_proc,
  1149. void *failure_data)
  1150. {
  1151. _DtSvcAppLock(cmd_Globals.app_context);
  1152. _DtActionCommandInvoke(_DtAct_NO_STDIO_BIT,context_host,
  1153. context_dir, exec_string, exec_parameters, exec_host,
  1154. NULL, NULL,
  1155. success_proc,success_data, failure_proc,failure_data);
  1156. _DtSvcAppUnlock(cmd_Globals.app_context);
  1157. }
  1158. /******************************************************************************
  1159. *
  1160. * _DtInitializeCommandInvoker - initialize some global variables and
  1161. * and call the appropriate initialization routines.
  1162. *
  1163. * PARAMETERS:
  1164. *
  1165. * Display *display; - The X server connection.
  1166. *
  1167. * char *toolClass; - The client's tool class.
  1168. *
  1169. * char *appClass; - The client's application class.
  1170. *
  1171. * DtSvcMessageProc reloadDBHandler; - The callback function for handling
  1172. * a "RELOAD-TYPES-DB" request. (OBSOLETE)
  1173. *
  1174. * XtAppContext appContext; - The client's application context.
  1175. *
  1176. * MODIFIED:
  1177. *
  1178. * SbInputId (*SbAddInput_hookfn); - Set to _DtCmdSPCAddInputHandler
  1179. *
  1180. * SbInputId (*SbRemoveInput_hookfn); - Set to XtRemoveInput
  1181. * SbInputId (*SbAddException_hookfn); - Set to _DtCmdSPCAddExceptionHandler
  1182. * SbInputId (*SbRemoveException_hookfn); - Set to XtRemoveInput
  1183. *
  1184. *****************************************************************************/
  1185. void
  1186. _DtInitializeCommandInvoker(
  1187. Display *display,
  1188. char *toolClass, /* ignored */
  1189. char *appClass, /* ignored */
  1190. DtSvcMessageProc reloadDBHandler, /* OBSOLETE -- ignored */
  1191. XtAppContext appContext)
  1192. {
  1193. static int beenCalled = 0;
  1194. _DtSvcAppLock(appContext);
  1195. /*
  1196. * Prevent repeat calls
  1197. */
  1198. _DtSvcProcessLock();
  1199. if ( beenCalled ) {
  1200. _DtSvcProcessUnlock();
  1201. return;
  1202. }
  1203. beenCalled++;
  1204. cmd_Globals.app_context = appContext;
  1205. SbAddInput_hookfn = _DtCmdSPCAddInputHandler;
  1206. SbRemoveInput_hookfn = XtRemoveInput;
  1207. SbAddException_hookfn = _DtCmdSPCAddExceptionHandler;
  1208. SbRemoveException_hookfn = XtRemoveInput;
  1209. _DtCmdBuildPathList ();
  1210. _DtCmdInitializeErrorMessages ();
  1211. /*
  1212. * Must get the name of the invoking host, so that requests
  1213. * can be checked for remote execution.
  1214. */
  1215. if ((DtGetShortHostname(_cmdClientHost, MAXHOSTNAMELEN)) == -1) {
  1216. _DtCmdLogErrorMessage ("Cannot determine the local host name.\n");
  1217. }
  1218. _DtCmdGetResources (display);
  1219. _DtSvcProcessUnlock();
  1220. _DtSvcAppUnlock(appContext);
  1221. }
  1222. /*****************************************************************************
  1223. *
  1224. * _DtCmdInitializeErrorMessages - initializes all of the command invoker's
  1225. * error messages.
  1226. *
  1227. * PARAMETERS: None.
  1228. *
  1229. * MODIFIED: all of the Command Invoker's error messages are initialized.
  1230. *
  1231. *****************************************************************************/
  1232. static void
  1233. _DtCmdInitializeErrorMessages( void )
  1234. {
  1235. /*
  1236. * Non-Fatal -> Abort the request
  1237. */
  1238. errorChdir = strdup (((char *)Dt11GETMESSAGE(3, 2, "An attempt to change to the following directory:\n\n %s\n\nfrom host \"%s\" failed.\n\nCheck the spelling and permissions and make sure the directory exists.")));
  1239. errorSpawn = strdup (((char *)Dt11GETMESSAGE(3, 5, "An attempt to execute the following command on host\n\"%s\" failed:\n\n %s\n\nCheck that the program exists, has the correct\npermissions and is executable.")));
  1240. errorExec = strdup (((char *)Dt11GETMESSAGE(3, 6, "An attempt to execute the following command failed:\n\n %s\n\nCheck that the program exists, has the correct\npermissions and is executable.")));
  1241. cmd_Globals.error_terminal = strdup (((char *)Dt11GETMESSAGE(3, 7, "This action cannot be started because the following\nterminal emulator cannot be executed:\n\n %s\n\nCheck that the program exists, has the correct permissions\nand is executable. This problem may have occurred because the\nprogram is not in your \"PATH\".")));
  1242. errorLength = strdup (((char *)Dt11GETMESSAGE(3, 9, "The total number of characters in this action exceeds the limit of \"%d\".\n\nYou may need to break the action into more than one action.")));
  1243. errorFork = strdup (((char *)Dt11GETMESSAGE(3, 11, "An attempt to start a new process on host \"%s\" failed.\n\nTo continue, you may need to stop an unneeded process on this host.")));
  1244. errorRequest = strdup (((char *)Dt11GETMESSAGE(3, 17, "This action's WINDOW_TYPE \"%s\" is un-recognized.\n\nThe WINDOW_TYPE should be one of the following:\n\n %s, %s, %s,\n %s, %s, or %s\n")));
  1245. cmd_Globals.error_subprocess = strdup (((char *)Dt11GETMESSAGE(3, 18, "This action cannot be started because the DT subprocess program:\n\n %s\n\ncannot be executed. Check that the program has the correct\npermissions and is executable.")));
  1246. errorRemoteSubprocess = strdup (((char *)Dt11GETMESSAGE(3, 20, "This action cannot be executed on host \"%s\"\nbecause the following required program either\ndoes not exist or it is not executable:\n\n %s\n")));
  1247. /*
  1248. * The following errors may occur when a SPC
  1249. * channel is opened.
  1250. */
  1251. errorUnknownHost = XtNewString (((char *)Dt11GETMESSAGE(3, 24, "This action cannot be executed because\nhost \"%s\" cannot be reached.")));
  1252. errorBadConnect = XtNewString (((char *)Dt11GETMESSAGE(3, 25, "This action cannot be executed on host \"%s\" because the\n\"%s\" service is not properly configured on this host.")));
  1253. errorBadService = XtNewString (((char *)Dt11GETMESSAGE(3, 26, "This action cannot be executed because the \"%s\"\nservice is not configured on host \"%s\".")));
  1254. errorRegisterHandshake = XtNewString (((char *)Dt11GETMESSAGE(3, 27, "This action cannot be executed on host \"%s\" because user\n\"%s\" has a user id of \"%d\" on host \"%s\" and this does\nnot match the username and user id on the action\ninvocation host \"%s\".")));
  1255. errorRegisterUsername = XtNewString (((char *)Dt11GETMESSAGE(3, 28, "This action cannot be executed on host \"%s\" because\nuser \"%s\" does not have an account on this host.")));
  1256. errorRegisterNetrc = XtNewString (((char *)Dt11GETMESSAGE(3, 29, "This action cannot be executed on host \"%s\" because\na pathname to the authentication file cannot be created.")));
  1257. errorRegisterOpen = XtNewString (((char *)Dt11GETMESSAGE(3, 30, "This action cannot be executed on host \"%s\" because\nthe authentication file on this host cannot be opened.\n\nThis may be caused by your network home not being\nproperly configured.")));
  1258. errorEnvTooBig = XtNewString (((char *)Dt11GETMESSAGE(3, 31, "This action cannot be executed on host \"%s\" because\nthe environment exceeds \"%d\" bytes.")));
  1259. errorInetSecurity = XtNewString (((char *)Dt11GETMESSAGE(3, 32, "This action cannot be executed on host \"%s\" because\nhost \"%s\" is not authorized to use the \"%s\" service.\n\nTo fix this, add host \"%s\" to the \"%s\" service\nentry in file \"%s\" on host \"%s\".")));
  1260. /*
  1261. * Do not post a dialog, write to the error log file only.
  1262. */
  1263. errorSpcTerminator = strdup (((char *)Dt11GETMESSAGE(3, 15, "An attempt to register the output log from a remote host failed.\n\nTo continue, you may need to stop an existing process.")));
  1264. successHost = strdup (((char *)Dt11GETMESSAGE(3, 21, "The action \"%s\" was successfully executed on host \"%s\".")));
  1265. cmd_Globals.error_directory_name_map = strdup (((char *)Dt11GETMESSAGE(3, 22, "The directory \"%s\" on host \"%s\"\ncould not be converted to a network path.\n(%s)")));
  1266. }