1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8
9 #include <dxconfig.h>
10 #include "../base/defines.h"
11
12 #include "DXStrings.h"
13 #include "DXChild.h"
14
15 #ifdef OS2
16 #define INCL_DOSPROCESS
17 #define INCL_DOSDATETIME
18 #define INCL_DOSFILEMGR
19 #define INCL_DOSQUEUES
20 #include <os2.h>
21 #endif
22
23 #include "DXApplication.h"
24 #include "ErrorDialogManager.h"
25 #include "MsgWin.h"
26
27 #include <stdlib.h>
28 #include <stdio.h>
29 #if defined(HAVE_FCNTL_H)
30
31 #include <fcntl.h>
32 #endif
33
34 #if defined(HAVE_IO_H)
35 #include <io.h>
36 #endif
37
38 #if defined(HAVE_PROCESS_H)
39 #include <process.h>
40 #endif
41
42 #ifdef DXD_WIN
43 #define close _close
44 int LocalRead( int handle, void *buffer, unsigned int count );
45 int SetSocketMode(int s, int iMode);
46 int UxRecv(int s, char *ExternalBuffer, int BuffSize, int Flags);
47 #define read LocalRead
48 #endif
49
50 #include <errno.h>
51 #include <ctype.h>
52
53 #if defined(HAVE_FCNTL_H)
54 #include <fcntl.h>
55 #endif
56
57 #if defined(HAVE_NETDB_H)
58 #ifdef alphax
59 extern "C"
60 {
61 #endif
62 #include <netdb.h>
63 #ifdef alphax
64 }
65 #endif
66 #endif
67
68 #if defined(HAVE_STRINGS_H)
69 #include <strings.h>
70 #endif
71
72 #include <signal.h>
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76
77 #if defined(HAVE_UNISTD_H)
78 #include <unistd.h>
79 #endif
80 #if defined(HAVE_NETINET_IN_H)
81 #include <netinet/in.h>
82 #endif
83
84 #if defined(HAVE_SYS_SELECT_H)
85 #include <sys/select.h>
86 #endif
87
88 #if defined(HAVE_SYS_WAIT_H)
89 #include <sys/wait.h>
90 #endif
91
92 #if defined(HAVE_SYSENT_H)
93 #include <sysent.h>
94 #endif
95
96
97 #if HAVE_CC_OSFCN_H
98 #include <CC/osfcn.h>
99 #endif
100 #if HAVE_CC_LIBC_H
101 #include <CC/libc.h>
102 #endif
103
104 #if defined(HAVE_TIME_H)
105 #include <time.h>
106 #endif
107
108 #if defined(HAVE_SYS_TIMEB_H)
109 #include <sys/timeb.h>
110 #endif
111
112 #if defined(HAVE_SYS_TIME_H)
113 #include <sys/time.h>
114 #endif
115
116 #if defined(HAVE_SYS_TYPES_H)
117 #include <sys/types.h>
118 #endif
119
120 #if defined(HAVE_SYS_STAT_H)
121 #include <sys/stat.h>
122 #endif
123
124 #if defined(HAVE_SYS_UN_H)
125 #include <sys/un.h>
126 #endif
127
128 #if defined(HAVE_SYS_UTSNAME_H)
129 #include <sys/utsname.h>
130 #endif
131
132 #ifdef ibm6000
133 extern "C"
134 {
135 void herror(const char *);
136 }
137 #endif
138
139 #if 0
140 #if (REQUIRES_BZERO_DECLARATION == 1)
141 extern "C" void bzero(char *, int);
142 #endif
143 #endif
144
145
146 #define verbose 0
147
148 #ifdef DXD_WIN
149 #if defined(XtInputReadMask)
150 #undef XtInputReadMask
151 #endif
152
153 #define XtInputReadMask XtInputReadWinsock
154
155 void ClearExecMessages(void *arg);
156
157 #endif
158
159 int
HostIsLocal(const char * host)160 DXChild::HostIsLocal(const char *host)
161 {
162 char localHostname[BUFSIZ];
163 char localhostHostname[BUFSIZ];
164 char remoteHostname[BUFSIZ];
165 struct hostent *he;
166 int hostnameFound;
167 #if defined(HAVE_SYS_UTSNAME_H)
168
169 struct utsname Uts_Name;
170
171 if (strcmp ("unix", host) == 0)
172 return TRUE;
173
174 he = gethostbyname ((char*)host);
175 if (he == NULL) {
176 // If here, assume that the hostname is not in the dns; therefore,
177 // the only machine we can connect to would be the localhost,
178 // thus return true.
179 return TRUE;
180 }
181 strcpy(remoteHostname, he->h_name);
182
183 if (uname(&Uts_Name) >= 0 && (he=gethostbyname(Uts_Name.nodename)) != NULL) {
184 strcpy(localHostname, he->h_name);
185 hostnameFound = 1;
186 } else {
187 hostnameFound = 0;
188 }
189
190 he = gethostbyname ("localhost");
191 if (he == NULL) {
192 // herror ("localhost");
193 ErrorMessage("%s: Invalid host", "localhost");
194 return (0);
195 }
196 strcpy(localhostHostname, he->h_name);
197
198 return ((hostnameFound && strcmp (localHostname, remoteHostname) == 0) ||
199 strcmp (localhostHostname, remoteHostname) == 0);
200 #endif
201
202 #ifdef DXD_WIN
203
204 int i;
205
206 if(_stricmp(host, "localhost") == 0
207 ||
208 _stricmp(host, "localPC") == 0)
209 return TRUE;
210
211
212 i = gethostname(localHostname, BUFSIZ - 1);
213 if(strcmp(localHostname, host) == 0)
214 return TRUE;
215
216 he = gethostbyname(host);
217 if(he == NULL || he->h_name == NULL)
218 return TRUE; /* Host is Local */
219
220
221 strcpy(remoteHostname, he->h_name);
222 he = gethostbyname(localHostname);
223 if(he == NULL || he->h_name == NULL)
224 return TRUE; /* Host is Local */
225
226 strcpy(localhostHostname, he->h_name);
227 if(strcmp(remoteHostname, localhostHostname) != 0)
228 i = FALSE;
229 else
230 i = TRUE;
231
232 return i;
233
234
235 #endif
236
237 return TRUE;
238
239 }
240 /* This routine returns the pid of the forked child to communicate with (or
241 * 0 if no waiting is required),
242 * or, if failure, -1. It (for now) also does a perror. It also returns
243 * remin, remout, and remerr, stdin,out,err for the created task.
244 */
245 int
ConnectTo(const char * host,const char * user,const char * cwd,int ac,char * av[],char * ep[],int * remin,int * remout,int * remerr,char * errstr)246 DXChild::ConnectTo(const char *host,
247 const char *user,
248 const char *cwd,
249 int ac,
250 char *av[],
251 char *ep[],
252 int *remin,
253 int *remout,
254 int *remerr,
255 char *errstr)
256 {
257 char s[BUFSIZ];
258 char script_name[500],cmd[1000];
259 FILE *fp;
260 int i;
261 #if defined(DXD_WIN) || defined(OS2)
262
263 int *in[2], *out[2], *err[2];
264 #else
265
266 int in[2], out[2], err[2];
267 #endif
268
269 char **rep;
270 char **fargv = NULL;
271 int child;
272 struct hostent *he;
273 int findx;
274 char *pathEnv;
275 int j;
276 char *dnum;
277 #if defined(HAVE_SYS_UTSNAME_H)
278
279 struct utsname Uts_Name;
280 char *local_rsh_cmd;
281
282 local_rsh_cmd = getenv( "DXRSH" );
283 if ( !local_rsh_cmd )
284 local_rsh_cmd = RSH;
285
286 /*
287 * Initialize return values (to default negative results).
288 */
289 *remin = -1;
290 *remout = -1;
291 *remerr = -1;
292 *errstr = '\0';
293
294 /*
295 * Check to see if "host" is a valid hostname.
296 */
297 if (strcmp("unix", host) != 0) {
298 he = gethostbyname ((char*)host);
299 if (he == NULL) {
300 ErrorMessage("Unable to resolve %s, connecting locally.", host);
301
302 // herror (host);
303 // ErrorMessage("%s: Invalid host", host);
304 // return (-1);
305 }
306 }
307
308 for (pathEnv = NULL, i = 0; ep[i] && pathEnv == NULL; ++i)
309 if ( strncmp (ep[i], "PATH=", STRLEN("PATH=")) == 0 ||
310 strncmp (ep[i], "PATH =", STRLEN("PATH =")) == 0)
311 pathEnv = ep[i];
312
313 if (DXChild::HostIsLocal(host)) {
314 char *path;
315 char *opath;
316 struct STATSTRUCT sbuffer;
317
318 if (verbose)
319 fprintf(stderr, "local\n");
320
321 if (user != NULL)
322 fprintf (stdout, "Different user on local machine ignored\n");
323
324 fargv = (char**)CALLOC((ac + 1), sizeof (char*));
325 if (fargv == NULL) {
326 ErrorMessage("calloc() error: %s", strerror(errno));
327 goto error_return;
328 }
329 for (i = 0; i < ac; ++i) {
330 fargv[i] = av[i];
331 }
332 fargv[i] = 0;
333 rep = ep;
334 /* Scan through ep looking for "PATH". If "PATH" is found, then
335 * look through path for the specified command, and if it's
336 * found and executable, replace it in fargv with the expanded
337 * path name.
338 */
339 if (*fargv[0] != '.' && *fargv[0] != '/') {
340 path = strchr (pathEnv, '=') + 1;
341 opath = path = strdup(path);
342 if (path == NULL) {
343 ErrorMessage("strdup() error: %s", strerror(errno));
344 goto error_return;
345 }
346 while (*path) {
347 for (i = 0;
348 *path != '\0' && *path != ':';
349 ++i, ++path) {
350 s[i] = *path;
351 }
352 if (*path == ':') {
353 ++path;
354 }
355 s[i] = '\0';
356 strcat (s, "/");
357 strcat (s, av[0]);
358 if (STATFUNC(s, &sbuffer) < 0) {
359 /* if the file doesn't exist, go on */
360 if (errno == ENOENT) {
361 /* We have no more paths to search */
362 if (*path == '\0') {
363 FREE(opath);
364 goto error_return;
365 }
366 }
367 /* Ignore bad stats, we just can't find it */
368 continue;
369 }
370 /* If it's executable, and a regular file, we're done. */
371 if ((sbuffer.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH)) != 0 &&
372 (sbuffer.st_mode & S_IFREG) != 0) {
373 break; /* out of while(*path) */
374 }
375 }
376 fargv[0] = s;
377 FREE (opath);
378 }
379 } else { /* Host is NOT local */
380 /* The general thread here is to first create a script on the
381 * remote host using popen(). The script contains shell code to
382 * 1) set up a similar environment to the current one (PATH,...)
383 * 2) exec 'dx -...'
384 * 3) remove the script from the remote file system.
385 * Then we set up fargv to contain the following:
386 * rsh host [ -l user ] /bin/sh /tmp/dx-$host:$pid
387 */
388
389 if (verbose)
390 fprintf(stderr, "remote\n");
391
392 fargv = (char**)CALLOC(12, sizeof(char*));
393
394 if (fargv == NULL) {
395 ErrorMessage("calloc() error: %s", strerror(errno));
396 goto error_return;
397 }
398
399
400 if (uname(&Uts_Name) < 0) {
401 ErrorMessage("uname() error: %s", strerror(errno));
402 goto error_return;
403 }
404 sprintf(script_name,"/tmp/dx-%s:%d",Uts_Name.nodename,getpid());
405 findx=0;
406 fargv[findx++] = local_rsh_cmd;
407 fargv[findx++] = (char *)host;
408
409 if (user != NULL) {
410 fargv[findx++] = "-l";
411 fargv[findx++] = (char *)user;
412 sprintf(cmd, "%s -c \"%s %s -l %s 'cat > %s' > /dev/null 2>&1\"",
413 BSH, local_rsh_cmd, host, user, script_name);
414 } else
415 sprintf(cmd, "%s -c \"%s %s 'cat > %s' > /dev/null 2>&1\"",
416 BSH, local_rsh_cmd, host, script_name);
417
418 fargv[findx++] = BSH;
419 fargv[findx++] = script_name;
420 fargv[findx++] = NULL ;
421
422 fp = popen(cmd,"w");
423 if (!fp) {
424 ErrorMessage("popen() error: %s", strerror(errno));
425 goto error_return;
426 }
427 setbuf(fp,NULL); /* Unbuffered so file is 'immediately' updated */
428
429 for (i = 0; ep[i]; ++i) {
430 /* Environment variables which are NOT passed to remote process */
431 static char *eignore[] = {"HOST=","HOSTNAME=","TZ=","SHELL=", 0};
432 int ignore;
433
434 /* Look for and skip certain environment variables */
435 /* We could do this more quickly elsewhere, but ... */
436 for (ignore=j=0 ; !ignore && eignore[j] ; j++)
437 if (!strncmp(ep[i], eignore[j], STRLEN(eignore[j])))
438 ignore = 1;
439 if (ignore)
440 continue;
441
442 /*
443 * Write the environment variable to the remote script file
444 */
445 if ((strncmp(ep[i],"DISPLAY=unix:",STRLEN("DISPLAY=unix:"))==0 ||
446 strncmp(ep[i],"DISPLAY=localhost:",
447 STRLEN("DISPLAY=localhost:"))==0 ||
448 strncmp(ep[i],"DISPLAY=:", STRLEN("DISPLAY=:")) == 0) &&
449 (dnum = strchr(ep[i], ':')) != NULL) {
450 fprintf(fp,"DISPLAY='%s%s';export DISPLAY\n",
451 Uts_Name.nodename,dnum);
452 } else {
453 int k;
454 char evar[256], c;
455 char eval[1024];
456
457 for (j=0 ; ep[i][j] && (ep[i][j] != '=') ; j++)
458 evar[j] = ep[i][j];
459 evar[j] = '\0';
460 k = j + 1; /* Skip the '=' sign */
461 for (j=0 ; (c = ep[i][k]) ; k++, j++) {
462 if (c == '\'') { /* ' -> '\'' */
463 /* Value contains a double quote */
464 eval[j++] = '\'';
465 eval[j++] = '\\';
466 eval[j++] = '\'';
467 }
468 eval[j] = c;
469 }
470 eval[j] = '\0';
471 fprintf(fp,"%s='%s'; export %s\n", evar, eval, evar);
472 }
473 }
474
475 if (cwd != NULL)
476 fprintf(fp,"cd %s\n",cwd);
477
478 fprintf(fp,"\n(sleep 15; rm -f %s) &\nexec ",script_name);
479 for (i = 0; i < ac; ++i)
480 fprintf(fp, "%s ",av[i]);
481 fprintf(fp,"\n");
482 pclose(fp);
483
484 rep = ep;
485 }
486
487 /* Set up three pipes */
488 if (pipe(in) < 0) {
489 ErrorMessage("pipe(in) error: %s", strerror(errno));
490 goto error_return;
491 }
492 if (pipe(out) < 0) {
493 ErrorMessage("pipe(out) error: %s", strerror(errno));
494 goto error_return;
495 }
496 if (pipe(err) < 0) {
497 ErrorMessage("pipe(err) error: %s", strerror(errno));
498 goto error_return;
499 }
500
501 child = fork();
502 if (child == 0) {
503 if (verbose && cwd != NULL)
504 fprintf(stderr, "cd %s\n", cwd);
505 fflush (stdout);
506 if (verbose)
507 fprintf(stderr, "exec %s\n", fargv[0]);
508 fflush (stdout);
509 if (verbose)
510 for (i = 0; rep[i]; ++i)
511 fprintf(stderr, "envp[%d] = `%s'\n", i, rep[i]);
512 if (verbose)
513 for (i = 0; fargv[i]; ++i)
514 fprintf(stderr, "argv[%d] = `%s'\n", i, fargv[i]);
515 close (in[1]);
516 close (out[0]);
517 close (err[0]);
518 if (dup2(in[0], 0) < 0) {
519 ErrorMessage("dup2() error: %s", strerror(errno));
520 exit(1);
521 }
522 if (dup2(out[1], 1) < 0) {
523 ErrorMessage("dup2() error: %s", strerror(errno));
524 exit(1);
525 }
526 if (dup2(err[1], 2) < 0) {
527 ErrorMessage("dup2() error: %s", strerror(errno));
528 exit(1);
529 }
530
531 if (cwd != NULL && chdir (cwd) < 0) {
532 ErrorMessage("chdir() error: %s", strerror(errno));
533 exit(1);
534 }
535 if (execve(fargv[0], fargv, rep) < 0) {
536 ErrorMessage("execve() error: %s", strerror(errno));
537 exit(1);
538 }
539 } else if (child > 0) {
540 close (in[0]);
541 close (out[1]);
542 close (err[1]);
543 *remin = in[1];
544 *remout = out[0];
545 *remerr = err[0];
546 } else {
547 goto error_return;
548 }
549
550
551 if (fargv != NULL)
552 FREE ((char*)fargv);
553 return (child);
554
555 #endif // HAVE_SYS_UTSNAME_H
556
557
558 #ifdef OS2
559
560 #define BuffSize 1000
561 #define HF_STDOUT 1
562
563 if (DXChild::HostIsLocal(host)) {
564 CHAR LoadError[100];
565 PSZ Envs;
566 RESULTCODES ReturnCodes;
567 APIRET rc;
568 PSZ ptr;
569 HFILE hpR, hpW;
570 int PipeSize=4096;
571 int NRead, TotRead;
572 char Buff[BuffSize];
573 HFILE hfSave = -1;
574 HFILE hfNew = HF_STDOUT;
575
576
577 rc=DosDupHandle(HF_STDOUT, &hfSave);
578 rc=DosCreatePipe(&hpR, &hpW, PipeSize);
579 rc=DosDupHandle(hpW, &hfNew);
580 *remout = hpR;
581
582 if (verbose)
583 fprintf(stderr, "local\n");
584
585 if (user != NULL)
586 fprintf (stdout, "Different user on local machine ignored\n");
587
588 Envs = 0;
589
590 strcpy(cmd,"CMD.EXE");
591 ptr = &cmd[strlen(cmd)+1];
592 strcpy(ptr,"");
593 for (i=0;i<ac;i++) {
594 if (i==0)
595 strcpy(ptr,"/C");
596 strcat(ptr," ");
597 strcat(ptr,av[i]);
598 }
599 ptr[strlen(ptr)+1]='\0';
600
601 rc = DosExecPgm(LoadError, sizeof(LoadError), EXEC_ASYNC, cmd, Envs,
602 (PRESULTCODES)&ReturnCodes, "CMD.EXE");
603
604 DosClose(hpW);
605 rc=DosDupHandle(hfSave, &hfNew);
606
607 child = -1;
608 if (rc==0)
609 child = ReturnCodes.codeTerminate;
610 else
611 ErrorMessage("Failure to spawn dx.cmd", "XXXX");
612 return child;
613 } else {
614 return (-1);
615 }
616
617 #endif // OS2
618
619 #ifdef DXD_WIN
620
621 char args[1000];
622 char exename[255];
623
624 char *Envs;
625 int ReturnCodes, rc, iHostIsLocal, pid;
626
627 HFILE hpR0, hpW0;
628 HFILE hpR1, hpW1;
629 HFILE hpR2, hpW2;
630
631 int NRead, TotRead, bTest;
632 HFILE hfSave0 = -1;
633 HFILE hfSave1 = -1;
634 HFILE hfSave2 = -1;
635
636 HFILE hin = _fileno(stdin);
637 HFILE hout = _fileno(stdout);
638 HFILE herr = _fileno(stderr);
639 DWORD dwordTmp;
640
641 unsigned long ThrdTID;
642 STARTUPINFO sInfo;
643 SECURITY_ATTRIBUTES sa;
644 PROCESS_INFORMATION pInfo;
645
646 iHostIsLocal = DXChild::HostIsLocal(host);
647 if (verbose)
648 fprintf(stderr, "local\n");
649
650 if (user != NULL)
651 fprintf (stdout, "Different user on local machine ignored\n");
652
653 strcpy(exename,av[0]);
654 for (i=0;i<strlen(exename);i++)
655 if (exename[i]=='/')
656 exename[i]='\\';
657
658 if ((strstr(exename,".bat") || strstr(exename,".BAT")) && iHostIsLocal) {
659 strcpy(cmd,"command.com /C "); // FIXME Different on NT and 95?
660
661 strcat(cmd,exename);
662 } else {
663 strcpy(cmd, "");
664
665 if(! iHostIsLocal) {
666 strcat(cmd, "rsh ");
667 strcat(cmd, host);
668 strcat(cmd, " ");
669 }
670
671 strcat(cmd,exename);
672 }
673
674 for (i=1;i<ac;i++) {
675 if (av[i] && *av[i]) {
676 strcat(cmd, " ");
677 strcat(cmd, av[i]);
678 }
679 }
680
681 Envs = NULL;
682
683 memset(&pInfo, 0, sizeof(pInfo));
684 memset(&sInfo, 0, sizeof(sInfo));
685 memset(&sa, 0, sizeof(sa));
686
687 sa.nLength = sizeof(SECURITY_ATTRIBUTES); // structure size
688 sa.lpSecurityDescriptor = NULL; // default descriptor
689 sa.bInheritHandle = TRUE; // inheritable
690
691 bTest = CreatePipe( &this->hpipeRead, // reading handle
692 &this->hpipeWrite, // writing handle
693 &sa, // lets handles be inherited
694 0 ); // default buffer size
695
696 bTest = DuplicateHandle( GetCurrentProcess( ),
697 this->hpipeRead, // original handle
698 GetCurrentProcess( ),
699 NULL, // don't create new handle
700 0,
701 FALSE, // not inheritable
702 DUPLICATE_SAME_ACCESS );
703
704 sInfo.cb = sizeof(sInfo);
705 sInfo.dwFlags = STARTF_USESTDHANDLES;
706 sInfo.hStdInput = GetStdHandle( STD_INPUT_HANDLE );
707 sInfo.hStdOutput = this->hpipeWrite;
708 sInfo.hStdError = GetStdHandle( STD_ERROR_HANDLE );
709
710 pid = rc = CreateProcess(NULL,
711 cmd,
712 NULL,
713 NULL,
714 TRUE,
715 0,
716 Envs,
717 NULL, // CurDir
718 &sInfo, // Startup Info
719 &pInfo // address of PROCESS_INFORMATION
720 );
721 if(rc == TRUE) {
722 CloseHandle(pInfo.hThread); // discard new thread handle
723 pid = pInfo.dwProcessId;
724 rc = 0;
725 bTest = (int) CreateThread(NULL, 0,
726 (LPTHREAD_START_ROUTINE) ClearExecMessages,
727 (LPVOID) this->hpipeRead, 0, &ThrdTID);
728 SetThreadPriority((LPVOID) &ThrdTID, THREAD_PRIORITY_BELOW_NORMAL);
729 } else {
730 rc = 1;
731 pid = -1;
732 }
733
734 *remout = -1;
735 child = -1;
736
737 if (rc == 0)
738 child = pid;
739 else
740 ErrorMessage("Failure to spawn dx child process");
741
742 return child;
743
744 #endif // DXD_WIN
745
746 error_return:
747 sprintf(errstr,"Could not connect using '%s'\n",fargv[0]);
748 if (fargv != NULL)
749 FREE ((char*)fargv);
750 return (-1);
751 }
752
753 void
setServer(char * s)754 DXChild::setServer(char *s)
755 {
756 if (this->server)
757 delete this->server;
758 this->server = DuplicateString(s);
759 fprintf(stderr, "child: server set to %s\n", s);
760 }
761
762 #define RSIZE 512
763 void
MakeLine(char * string,char * newString)764 DXChild::MakeLine(char *string, char *newString)
765 {
766 int p = STRLEN(string);
767 int i = 0;
768 int newlen = STRLEN(newString);
769 for (i = 0; i < newlen; ++i) {
770 if (p > 0 && (p == RSIZE-1)) // || string[p-1] == '\n'))
771 {
772 p = 0;
773 }
774 string[p++] = newString[i];
775 }
776 string[p] = '\0';
777 }
778
779 /* uipStartExecutive starts the dx script and returns information about the
780 * resulting child.
781 * Return Values if block is TRUE:
782 * 0 -- Success
783 * -1 -- Failure
784 * 1 -- Retry OK (The server was busy).
785 * Return Values if block is FALSE:
786 * 0 -- Success
787 * Else -- Failure
788 */
789 int
StartExecutive(const char * host,const char * user,const char * cwd,const char * cmd,int * in,int * out,int * err,int * port,int * child,int block,char ** rstringParam)790 DXChild::StartExecutive(const char* host,
791 const char* user,
792 const char* cwd,
793 const char* cmd,
794 int* in,
795 int* out,
796 int* err,
797 int* port,
798 int* child,
799 int block,
800 char **rstringParam)
801 {
802 extern char **environ;
803 char **av = NULL;
804 char **t;
805 int ac = 0;
806 int i, j, k;
807 int result;
808 static char rstring[RSIZE];
809
810 rstring[0] = '\0';
811 result = -1;
812 *child = -1;
813
814 if (verbose) {
815 fprintf(stderr, "Connect to `%s'\n", host);
816 if (user)
817 fprintf(stderr, "tas `%s'\n", user);
818 if (cwd)
819 fprintf(stderr, "tin `%s'\n", cwd);
820 fprintf(stderr, "trunning `%s'\n", cmd);
821 }
822
823 /* Turn the optional cmd into an ac/av pair */
824 av = (char **)CALLOC(1, sizeof (char*));
825 if (av == NULL) {
826 ErrorMessage("calloc() error: %s", strerror(errno));
827 goto error_return;
828 }
829 for (ac = 0; *cmd; ++ac) {
830 t = (char**)REALLOC ((char*)av, (ac + 1) * sizeof (char*));
831 if (t == NULL) {
832 ErrorMessage("realloc() error: %s", strerror(errno));
833 goto error_return;
834 } else
835 av = t;
836 /* Skip leading whitespace */
837 cmd += strspn(cmd, " \t");
838
839 i = 0;
840 while(cmd[i] != ' ' && cmd[i] != '\0') {
841 if(cmd[i] == '"') {
842 i++;
843 while(cmd[i] != '"' && cmd[i] != '\0') {
844 i++;
845 }
846 }
847 if(cmd[i] != '\0')
848 i++;
849 }
850
851 ;
852 av[ac] = (char *)CALLOC((i + 1), sizeof (char));
853 if (av[ac] == NULL)
854 goto error_return;
855
856 /* Now copy the string into the argv without quotes */
857 for (j = 0, k = 0; j<i; ++j, ++cmd)
858 if(*cmd != '"')
859 av[ac][k++] = *cmd;
860 av[ac][k] = '\0';
861 }
862
863 *child =DXChild::ConnectTo(host, user, cwd, ac, av, environ, in, out, err,
864 rstring);
865
866
867 if (!block) {
868 #ifndef DXD_WIN
869 result = (*child < 0);
870 #else
871
872 result = (*child == -1);
873 #endif
874
875 goto error_return;
876 }
877
878
879 error_return:
880 if (av) {
881 for (i = 0; i < ac; ++i)
882 if (av[i] != NULL)
883 FREE (av[i]);
884 FREE ((char*)av);
885 }
886 /* remove the \n at the end of the string */
887 char *p = strrchr(rstring,'\n');
888 if (p)
889 *p = '\0';
890 *rstringParam = rstring;
891
892 return (result);
893 }
894
DXChild_OutQueuedInputHandler(XtPointer clientData,int * socket,XtInputId * id)895 extern "C" void DXChild_OutQueuedInputHandler(XtPointer clientData,
896 int *socket,
897 XtInputId *id)
898 {
899 char buffer[1000];
900 DXChild *obj = (DXChild *)clientData;
901 if (obj->input_handlers_stalled)
902 return ;
903 int sts = 0;
904
905 if ((sts = read(*socket, buffer, 1000)) < 0) {
906 ErrorMessage("Unable to read from executive, read() error: %s",
907 strerror(errno));
908 } else if (sts == 0)
909 obj->closeOutput();
910 else {
911 int i = 0;
912 int j = STRLEN(obj->outLine);
913 for (i = 0; i < sts; ++i, ++j) {
914 if (buffer[i] == '\n' || j == obj->lineSize) {
915 char *s = obj->outLine;
916 int port;
917 obj->outLine[j] = '\n';
918 obj->outLine[j+1] = '\0';
919 theDXApplication->getMessageWindow()->addInformation(
920 obj->outLine);
921 if ((s = strstr(obj->outLine, "host = ")) != NULL) {
922 char buf[256];
923 sscanf(s, "host = %s", buf);
924 theDXApplication->setServer(buf);
925 obj->setServer(buf);
926 }
927 if ((s = strstr(obj->outLine, "port = ")) != NULL) {
928 sscanf(obj->outLine, "port = %d\n", &port);
929 theDXApplication->connectToServer(port, obj);
930 }
931 obj->outLine[0] = '\0';
932 j = -1;
933 } else {
934 obj->outLine[j] = buffer[i];
935 obj->outLine[j+1] = '\0';
936 }
937 }
938 }
939 }
DXChild_ErrQueuedInputHandler(XtPointer clientData,int * socket,XtInputId * id)940 extern "C" void DXChild_ErrQueuedInputHandler(XtPointer clientData,
941 int *socket,
942 XtInputId *id)
943 {
944 char buffer[1000];
945 DXChild *obj = (DXChild *)clientData;
946 if (obj->input_handlers_stalled)
947 return ;
948 int sts = 0;
949
950 if ((sts = read(*socket, buffer, 1000)) < 0) {
951 ErrorMessage("Unable to read from executive, read() error: %s",
952 strerror(errno));
953 } else if (sts == 0)
954 obj->closeError();
955 else {
956 int i = 0;
957 int j = STRLEN(obj->errLine);
958 for (i = 0; i < sts; ++i, ++j) {
959 if (buffer[i] == '\n' || j == obj->lineSize) {
960 obj->errLine[j] = '\0';
961 // write(2, obj->errLine, j + 1);
962 theDXApplication->getMessageWindow()->addError(obj->errLine);
963 obj->errLine[0] = '\0';
964 j = -1;
965 } else {
966 obj->errLine[j] = buffer[i];
967 obj->errLine[j+1] = '\0';
968 }
969 }
970 }
971 }
DXChild_OutInputHandler(XtPointer clientData,int * socket,XtInputId * id)972 extern "C" void DXChild_OutInputHandler(XtPointer clientData,
973 int *socket,
974 XtInputId *id)
975 {
976 char buffer[1000];
977 DXChild *obj = (DXChild *)clientData;
978 if (obj->input_handlers_stalled)
979 return ;
980 int sts = 0;
981
982 if ((sts = read(*socket, buffer, 1000)) < 0) {
983 ErrorMessage("Unable to read from executive, read() error: %s",
984 strerror(errno));
985 } else if (sts == 0)
986 obj->closeOutput();
987 else {
988 int i = 0;
989 int j = STRLEN(obj->outLine);
990 for (i = 0; i < sts; ++i, ++j) {
991 if (buffer[i] == '\n' || j == obj->lineSize) {
992 obj->outLine[j] = '\n';
993 obj->outLine[j+1] = '\0';
994 theDXApplication->getMessageWindow()->addInformation(
995 obj->outLine);
996 // write(1, obj->outLine, j + 1);
997 obj->outLine[0] = '\0';
998 j = -1;
999 } else {
1000 obj->outLine[j] = buffer[i];
1001 obj->outLine[j+1] = '\0';
1002 }
1003 }
1004 }
1005 }
DXChild_ErrInputHandler(XtPointer clientData,int * socket,XtInputId * id)1006 extern "C" void DXChild_ErrInputHandler(XtPointer clientData,
1007 int *socket,
1008 XtInputId *id)
1009 {
1010 char buffer[1000];
1011 DXChild *obj = (DXChild *)clientData;
1012 if (obj->input_handlers_stalled)
1013 return ;
1014 int sts = 0;
1015
1016 if ((sts = read(*socket, buffer, 1000)) < 0) {
1017 ErrorMessage("Unable to read from executive, read() error: %s",
1018 strerror(errno));
1019 } else if (sts == 0)
1020 obj->closeError();
1021 else {
1022 int i = 0;
1023 int j = STRLEN(obj->errLine);
1024 for (i = 0; i < sts; ++i, ++j) {
1025 if (buffer[i] == '\n' || j == obj->lineSize) {
1026 obj->errLine[j] = '\0';
1027 theDXApplication->getMessageWindow()->addError(
1028 obj->errLine);
1029 // write(2, obj->errLine, j+1);
1030 obj->errLine[0] = '\0';
1031 j = -1;
1032 } else {
1033 obj->errLine[j] = buffer[i];
1034 obj->errLine[j+1] = '\0';
1035 }
1036 }
1037 }
1038 }
1039
DXChild(char * host,char * cmd,int block,char * user,char * cwd)1040 DXChild::DXChild(char *host,
1041 char *cmd,
1042 int block,
1043 char *user,
1044 char *cwd)
1045 {
1046 int port = 0;
1047 char *s = NULL;
1048
1049 this->lineSize = 1000;
1050 this->outLine = new char[this->lineSize + 2];
1051 this->errLine = new char[this->lineSize + 2];
1052 *this->outLine = '\0';
1053 *this->errLine = '\0';
1054 this->deletion_wpid = NUL(XtWorkProcId);
1055 this->input_handlers_stalled = FALSE;
1056
1057 this->server = DuplicateString(host);
1058
1059 int result = StartExecutive(this->server,
1060 user,
1061 cwd,
1062 cmd,
1063 &this->in,
1064 &this->out,
1065 &this->err,
1066 &port,
1067 &this->child,
1068 block,
1069 &s);
1070 if (!block && result < 0) {
1071 this->queued = 1;
1072 #if !defined(DXD_WIN) && !defined(OS2)
1073
1074 this->outId = XtAppAddInput(theApplication->getApplicationContext(),
1075 this->out,
1076 (XtPointer)XtInputReadMask,
1077 DXChild_OutQueuedInputHandler,
1078 (XtPointer)this);
1079 this->errId = XtAppAddInput(theApplication->getApplicationContext(),
1080 this->err,
1081 (XtPointer)XtInputReadMask,
1082 DXChild_ErrQueuedInputHandler,
1083 (XtPointer)this);
1084 #endif //SMH
1085
1086 } else if (result == 0) {
1087 this->queued = 0;
1088 #if !defined(DXD_WIN) && !defined(OS2)
1089
1090 this->outId = XtAppAddInput(theApplication->getApplicationContext(),
1091 this->out,
1092 (XtPointer)XtInputReadMask,
1093 DXChild_OutInputHandler,
1094 (XtPointer)this);
1095 this->errId = XtAppAddInput(theApplication->getApplicationContext(),
1096 this->err,
1097 (XtPointer)XtInputReadMask,
1098 DXChild_ErrInputHandler,
1099 (XtPointer)this);
1100 #endif //SMH
1101 // if (block)
1102 // {
1103 // theDXApplication->connectToServer(port, this);
1104 // }
1105 } else {
1106 this->queued = 0;
1107 }
1108
1109 if (!IsBlankString(s)) {
1110 this->errorString = DuplicateString(s);
1111 } else {
1112 this->errorString = NULL;
1113 }
1114 }
1115
1116
~DXChild()1117 DXChild::~DXChild()
1118 {
1119 if (this->out >= 0) {
1120 close(this->out);
1121 #if !defined(DXD_WIN) && !defined(OS2)
1122
1123 XtRemoveInput(this->outId);
1124 #endif
1125
1126 }
1127 if (this->err >= 0) {
1128 close(this->err);
1129 #if !defined(DXD_WIN) && !defined(OS2)
1130
1131 XtRemoveInput(this->errId);
1132 #endif
1133
1134 }
1135 if (this->in >= 0) {
1136 close(this->in);
1137 }
1138
1139 if (this->child > 1) {
1140 #if defined(DXD_WIN)
1141 TerminateProcess((HANDLE)this->child,-1);
1142 #else
1143
1144 kill(this->child, SIGTERM);
1145 wait(0);
1146 #endif
1147
1148 }
1149
1150 delete this->server;
1151 if (this->errorString != NULL)
1152 delete this->errorString;
1153 delete this->outLine;
1154 delete this->errLine;
1155
1156 }
1157
1158
1159 void
closeOutput(boolean closeConnection)1160 DXChild::closeOutput(boolean closeConnection)
1161 {
1162 if (this->out >= 0) {
1163 close (this->out);
1164 XtRemoveInput(this->outId);
1165 }
1166 this->out = -1;
1167 if (closeConnection && this->err == -1) {
1168 theDXApplication->closeConnection(this);
1169 if (this->deletion_wpid == NUL(XtWorkProcId))
1170 this->deletion_wpid =
1171 XtAppAddWorkProc (theDXApplication->getApplicationContext(),
1172 (XtWorkProc) DXChild_DeleteObjectWP, (XtPointer)this);
1173 }
1174 }
1175
1176 void
closeError(boolean closeConnection)1177 DXChild::closeError(boolean closeConnection)
1178 {
1179 if (this->err >= 0) {
1180 close (this->err);
1181 #if !defined(DXD_WIN) && !defined(OS2)
1182
1183 XtRemoveInput(this->errId);
1184 #endif
1185
1186 }
1187 this->err = -1;
1188 if (closeConnection && this->out == -1) {
1189 theDXApplication->closeConnection(this);
1190 if (this->deletion_wpid == NUL(XtWorkProcId))
1191 this->deletion_wpid =
1192 XtAppAddWorkProc (theDXApplication->getApplicationContext(),
1193 (XtWorkProc) DXChild_DeleteObjectWP, (XtPointer)this);
1194 }
1195 }
1196
DXChild_DeleteObjectWP(XtPointer clientData)1197 extern "C" Boolean DXChild_DeleteObjectWP (XtPointer clientData)
1198 {
1199 DXChild* c = (DXChild*)clientData;
1200 ASSERT(c);
1201 delete c;
1202 return TRUE;
1203 }
1204
1205 void
unQueue()1206 DXChild::unQueue()
1207 {
1208 if (this->out >= 0) {
1209 XtRemoveInput(this->outId);
1210 this->outId = XtAppAddInput(theApplication->getApplicationContext(),
1211 this->out,
1212 (XtPointer)XtInputReadMask,
1213 DXChild_OutInputHandler,
1214 (XtPointer)this);
1215 }
1216 if (this->err >= 0) {
1217 #ifndef DXD_WIN
1218 XtRemoveInput(this->errId);
1219 this->errId = XtAppAddInput(theApplication->getApplicationContext(),
1220 this->err,
1221 (XtPointer)XtInputReadMask,
1222 DXChild_ErrInputHandler,
1223 (XtPointer)this);
1224 #endif
1225
1226 }
1227 this->queued = FALSE;
1228 }
1229
1230 //
1231 // Wait for a connection, and if it succedes, return 0, if it gets queued,
1232 // return 1, and if it fails, return -1.
1233 //
1234 int
waitForConnection()1235 DXChild::waitForConnection()
1236 {
1237 char *s, rdbuffer[BUFSIZ+1];
1238 int sts;
1239 int result = 0;
1240 int port;
1241 static char rstring[RSIZE];
1242 rstring[0] = '\0';
1243 #if defined(HAVE_SYS_UTSNAME_H)
1244
1245 fd_set fds;
1246 #endif
1247
1248 /* Until we get port = ..., read from stdout and error. Close the
1249 * port down and fail if we get an eof on either.
1250 */
1251
1252 #if !defined(HAVE_SYS_UTSNAME_H)
1253
1254 result = 0;
1255 /* Need to loop here because dx.cmd first sends "Starting DX Exec", followed by
1256 * "[E:\usr1\....\dxexec -r -B"
1257 * A few seconds later, "port = 1900" comes across. Thus need to loop over the read
1258 * strings until port = appears, or one of the other options...
1259 * Maybe should put timeout here...
1260 */
1261 #ifdef DXD_WIN
1262
1263 DWORD dwordTmp;
1264 int iRet, iLoop = 0;
1265 while (result==0) {
1266
1267 iLoop = 0;
1268 while(1) {
1269 iRet = PeekNamedPipe(this->hpipeRead, rdbuffer,
1270 sizeof(rdbuffer), &dwordTmp,
1271 NULL, NULL);
1272 if(iRet && dwordTmp > 0)
1273 break;
1274 Sleep(10);
1275 iLoop++;
1276 if(iLoop > 1000) {
1277 ErrorMessage("read() error: %s", strerror(errno));
1278 return -1;
1279 }
1280 }
1281
1282
1283 sts = ReadFile(this->hpipeRead, // handle of file to read
1284 rdbuffer, // address of buffer that receives data
1285 sizeof(rdbuffer), // number of bytes to read
1286 &dwordTmp, // address of number of bytes read
1287 NULL // address of structure for data
1288 );
1289 sts = dwordTmp; // strlen(rdbuffer);
1290 rdbuffer[sts] = '\0';
1291 theDXApplication->getMessageWindow()->addInformation(rdbuffer);
1292 fprintf(stderr, "========= %s\n", rdbuffer);
1293 if (sts >= 0) {
1294 DXChild::MakeLine(rstring, rdbuffer);
1295 if ((s = strstr(rdbuffer, "host = ")) != NULL) {
1296 char buf[256];
1297 sscanf(s, "host = %s", buf);
1298 theDXApplication->setServer(buf);
1299 this->setServer(buf);
1300 }
1301 if ((s = strstr(rdbuffer, "port = ")) != NULL) {
1302 sscanf (s, "port = %d", &port);
1303 if (this->isQueued())
1304 this->unQueue();
1305 theDXApplication->connectToServer(port, this);
1306 return 0;
1307 } else if (strstr(rdbuffer, "Execution has been queued") ||
1308 strstr(rdbuffer, "Server appears to be in use") ||
1309 strstr(rdbuffer, "rror")) // suits added
1310 {
1311 return 1;
1312 }
1313 }
1314 } // while
1315
1316 #endif // if DXD_WIN
1317
1318 #ifdef OS2
1319 while (result==0)
1320 {
1321 result = DosRead(this->out, rdbuffer, BUFSIZ,(PULONG) &sts); // This will block until something to read...
1322 if (result != 0) {
1323 ErrorMessage("read() error: %s", strerror(errno));
1324 this->closeOutput(FALSE);
1325 result = -1;
1326 }
1327 // #endif // if OS2
1328 else {
1329 rdbuffer[sts] = '\0';
1330 theDXApplication->getMessageWindow()->addInformation(
1331 rdbuffer);
1332 if (result >= 0) {
1333 DXChild::MakeLine(rstring, rdbuffer);
1334 if ((s = strstr(rdbuffer, "host = ")) != NULL) {
1335 char buf[256];
1336 sscanf(s, "host = %s", buf);
1337 theDXApplication->setServer(buf);
1338 this->setServer(buf);
1339 }
1340 if ((s = strstr(rdbuffer, "port = ")) != NULL) {
1341 sscanf (s, "port = %d", &port);
1342 if (this->isQueued())
1343 this->unQueue();
1344 theDXApplication->connectToServer(port, this);
1345 return 0;
1346 }
1347 if (strstr(rdbuffer, "Execution has been queued") ||
1348 strstr(rdbuffer, "Server appears to be in use") ||
1349 strstr(rdbuffer, "rror")) // suits added
1350 {
1351 return 1;
1352 }
1353 }
1354 }
1355 } // while
1356 #endif // OS2
1357 return result;
1358 #endif // HAVE_SYS_UTSNAME_H
1359
1360
1361 #if defined(HAVE_SYS_UTSNAME_H)
1362
1363 //
1364 // Stop using the subevent loop. The call to XtAppNextEvent has the side effect
1365 // of checking sockets identified to XtAppAddInput and possibly going into the
1366 // associated event handler. So select() might say that there is no input ready
1367 // at this->out but by the time the call to XtAppNextEvent is made, something
1368 // may have arrived.
1369 // The event handler for this->out does not know
1370 // anything about "port =". The result is that that handler swallows that string
1371 // and the code below never sees it, so the port # is lost and we can't connect
1372 // to the server. The correct fix would be to erase the while loop below and
1373 // to build the smarts into the event handlers. Doing that would also accomplish
1374 // what I originally intended to do which was to process X events during the
1375 // 2 to 5 seconds we sit here idly waiting for input from the fresh server.
1376 //
1377 #define USE_SUB_EVENT_LOOP 0
1378 #if USE_SUB_EVENT_LOOP
1379
1380 this->input_handlers_stalled = TRUE;
1381 Display *d = theApplication->getDisplay();
1382 XtAppContext app = theApplication->getApplicationContext();
1383 struct timeval to;
1384 int counts = 0;
1385 #define MAX_COUNTS 1000000
1386 #endif // USE_SUB_EVENT_LOOP
1387
1388 int status;
1389
1390 while (this->child >= 0 && (this->out >= 0 || this->err >= 0)) {
1391 int width = (this->out > this->err ? this->out : this->err) + 1;
1392 FD_ZERO(&fds);
1393 if (this->out >= 0)
1394 FD_SET(this->out, &fds);
1395 if (this->err >= 0)
1396 FD_SET(this->err, &fds);
1397 #if USE_SUB_EVENT_LOOP
1398 //
1399 // Do coarse polling because there are important timers created during
1400 // program startup and they're being ignored by calling select().
1401 // The "counts" var says that we'll poll at most 1 million times
1402 // which at 2/10 second each poll is a long time, but the loop will
1403 // still terminate as soon as there is an error on a socket.
1404 // I testing this by killing the exec from csh while dxui was waiting for
1405 // it to start. The results are OK but not great. The ui doesnt' report
1406 // the failure to connect until several seconds later.
1407 //
1408 // This AppPending stuff isn't living down below with the other X stuff
1409 // because that other X stuff is only executed if the socket from the
1410 // server has input which is not the case if a timer goes off.
1411 if (XtAppPending (app) & XtIMTimer)
1412 XtAppProcessEvent (app, XtIMTimer);
1413 FD_SET(ConnectionNumber(d), &fds);
1414 to.tv_sec = 0;
1415 to.tv_usec = 200000; // 2/10 of a second
1416 if (counts++ >= MAX_COUNTS)
1417 status = -1;
1418 else
1419 status = select(width, (SELECT_ARG_TYPE *)&fds, NULL, NULL, &to);
1420 #else // USE_SUB_EVENT_LOOP
1421
1422 status = select(width, (SELECT_ARG_TYPE *)&fds, NULL, NULL, NULL);
1423 #endif // USE_SUB_EVENT_LOOP
1424
1425 if (status < 0) {
1426 this->input_handlers_stalled = FALSE;
1427 return result;
1428 }
1429 if (this->err >= 0 && FD_ISSET(this->err, &fds)) {
1430 sts = read(this->err, rdbuffer, BUFSIZ);
1431 if (sts < 0) {
1432 ErrorMessage("read() error: %s", strerror(errno));
1433 this->closeError(FALSE);
1434 result = -1;
1435 } else if (sts == 0) {
1436 this->closeError(FALSE);
1437 result = -1;
1438 } else {
1439 rdbuffer[sts] = '\0';
1440 DXChild::MakeLine(rstring, rdbuffer);
1441 if ((s = strstr(rdbuffer, "host = ")) != NULL) {
1442 char buf[256];
1443 sscanf(s, "host = %s", buf);
1444 theDXApplication->setServer(buf);
1445 this->setServer(buf);
1446 }
1447 if (strstr (rdbuffer, "Server appears to be in use")) {
1448 result = 1;
1449 this->input_handlers_stalled = FALSE;
1450 return result;
1451 }
1452 }
1453 }
1454 #if USE_SUB_EVENT_LOOP
1455 else if (FD_ISSET(ConnectionNumber(d), &fds)) {
1456 XEvent event;
1457 // XmUpdateDisplay() is a higher level way of doing the same
1458 // thing, but it's a very expensive function - uses XSync().
1459 boolean server_ready = FALSE;
1460 while ((!server_ready) && (XtAppPending(app) & XtIMXEvent)) {
1461 XtAppNextEvent (app, &event);
1462 switch (event.type) {
1463 case ButtonPress:
1464 case ButtonRelease:
1465 case KeyPress:
1466 case KeyRelease:
1467 break;
1468 default:
1469 printf ("%s[%d] XEvent\n", __FILE__,__LINE__);
1470 theDXApplication->passEventToHandler (&event);
1471 break;
1472 }
1473 //
1474 // Check server readiness each time thru this loop because
1475 // the -program option can keep us here for a long time and
1476 // we only want to process events while the real work isn't ready.
1477 //
1478 FD_ZERO(&fds);
1479 if (this->out >= 0)
1480 FD_SET(this->out, &fds);
1481 if (this->err >= 0)
1482 FD_SET(this->err, &fds);
1483 to.tv_sec = 0;
1484 to.tv_usec = 0;
1485 status = select(width, (SELECT_ARG_TYPE *)&fds, NULL, NULL, &to);
1486 if (status > 0) {
1487 if (this->err >= 0 && FD_ISSET(this->err, &fds)) {
1488 server_ready = TRUE;
1489 } else if (this->out >= 0 && FD_ISSET(this->out, &fds)) {
1490 server_ready = TRUE;
1491 }
1492 } else {
1493 server_ready = TRUE;
1494 }
1495 }
1496 }
1497 #endif // USE_SUB_EVENT_LOOP
1498
1499 else if (this->out >= 0 && FD_ISSET(this->out, &fds)) {
1500 sts = read(this->out, rdbuffer, BUFSIZ);
1501 if (sts < 0) {
1502 ErrorMessage("read() error: %s", strerror(errno));
1503 this->closeOutput(FALSE);
1504 result = -1;
1505 } else if (sts == 0) {
1506 this->closeOutput(FALSE);
1507 result = -1;
1508 } else {
1509 char *s;
1510 rdbuffer[sts] = '\0';
1511 theDXApplication->getMessageWindow()->addInformation(
1512 rdbuffer);
1513 // write (1, rdbuffer, sts);
1514
1515 if (result >= 0) {
1516 DXChild::MakeLine(rstring, rdbuffer);
1517
1518 if ((s = strstr(rdbuffer, "host = ")) != NULL) {
1519 char buf[256];
1520 sscanf(s, "host = %s", buf);
1521 theDXApplication->setServer(buf);
1522 this->setServer(buf);
1523 }
1524 if ((s = strstr(rdbuffer, "port = ")) != NULL) {
1525 sscanf (s, "port = %d", &port);
1526 if (this->isQueued())
1527 this->unQueue();
1528 theDXApplication->connectToServer(port, this);
1529 this->input_handlers_stalled = FALSE;
1530 return 0;
1531 }
1532 if (strstr(rdbuffer, "Execution has been queued") ||
1533 strstr(rdbuffer, "Server appears to be in use")) {
1534 return 1;
1535 } else if (strstr(rdbuffer, "rror")) {
1536 this->errorString = DuplicateString(rdbuffer);
1537 return -1;
1538 }
1539 }
1540 }
1541 }
1542 }
1543
1544 /* If we ever get here, there was an error in the read,
1545 * then wait for any children to quit, and fail.
1546 * Sigterm the child, just for good measure.
1547 */
1548 while (this->err >= 0 && (sts = read (this->err, rdbuffer, BUFSIZ)) > 0) {
1549 // write (2, rdbuffer, sts);
1550 rdbuffer[sts] = '\0';
1551 theDXApplication->getMessageWindow()->addError(rdbuffer);
1552 }
1553 if (this->child > 0) {
1554 result = -1;
1555 }
1556
1557 this->errorString = DuplicateString(rstring);
1558
1559
1560 this->input_handlers_stalled = FALSE;
1561 return (result);
1562 #endif // !defined(DXD_LACKS_UTD)
1563 }
1564
1565
1566
1567 #ifdef DXD_WIN
LocalRead(int handle,void * buffer,unsigned int count)1568 int LocalRead( int handle, void *buffer, unsigned int count )
1569 {
1570 int i;
1571
1572 SetSocketMode(handle, 0);
1573 // i = _read(handle, buffer, count);
1574
1575 i = UxRecv(handle, (char *)buffer, count, 0);
1576
1577 return i;
1578 }
1579
ClearExecMessages(void * arg)1580 void ClearExecMessages(void *arg)
1581 {
1582 #define READ_BUFFER_SIZE 2048
1583
1584 int bTest, iPrint;
1585 DWORD dwordTmp;
1586 char achStr[READ_BUFFER_SIZE];
1587
1588 if(getenv("DEBUG_EXEC_MESSAGES"))
1589 iPrint = 1;
1590 else
1591 iPrint = 0;
1592
1593 Sleep(30*1000);
1594 if(1) {
1595 do {
1596 if(!arg)
1597 break;
1598 bTest = ReadFile(arg, // handle of file to read
1599 achStr, // address of buffer that receives data
1600 READ_BUFFER_SIZE, // number of bytes to read
1601 &dwordTmp, // address of number of bytes read
1602 NULL // address of structure for data
1603 );
1604 if(bTest && iPrint)
1605 printf("FROM DX %s \n ", achStr);
1606 } while(0);
1607 }
1608 if(iPrint)
1609 printf("UI:Terminating ClearExecMessages \n");
1610
1611 return;
1612 }
1613
1614
1615 #endif // DXD_WIN
1616
1617