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