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 
11 
12 #include <dx/dx.h>
13 
14 #include <stdio.h>
15 #include <stdlib.h>
16 #if defined(HAVE_UNISTD_H)
17 #include <unistd.h>
18 #endif
19 #if defined(HAVE_SYS_WAIT_H)
20 #include <sys/wait.h>
21 #endif
22 #if defined(HAVE_SYS_PARAM_H)
23 #include <sys/param.h>
24 #endif
25 #if defined(HAVE_CTYPE_H)
26 #include <ctype.h>
27 #endif
28 #if defined(HAVE_STRING_H)
29 #include <string.h>
30 #endif
31 #if defined(HAVE_NETDB_H)
32 #include <netdb.h>
33 #endif
34 
35 #include "config.h"
36 #include "command.h"
37 #include "function.h"
38 #include "remote.h"
39 #include "compile.h"
40 #include "d.h"
41 #include "exobject.h"
42 #include "_variable.h"
43 #include "_macro.h"
44 #include "version.h"
45 #include "parse.h"
46 #include "graph.h"
47 #include "graphqueue.h"
48 #include "parsemdf.h"
49 #include "swap.h"
50 #include "loader.h"
51 #include "help.h"
52 #include "userinter.h"
53 #include "dxpfsmgr.h"
54 #include "evalgraph.h"
55 #include "dxmain.h"
56 
57 #ifdef	DXD_WIN
58 #define		strcasecmp	stricmp
59 #endif
60 
61 #ifdef DXD_LICENSED_VERSION
62 static char _dxd_LicenseKey[5];
63 #endif
64 
65 #define MAXOBJECTS 21   /* must match mdf-c generated dx.mdf file */
66 
67 /* dummy entry for master host */
68 static dpgraphstat masterentry = {NULL, NULL, NULL, -1, 0, 0, 0, 0};
69 static int *update_dptable = NULL;
70 
71 /* Defined programatically in libdx */
72 extern void _dxf_user_modules(); /* from libdx/ */
73 extern void _dxf_private_modules(); /* from libdx/ */
74 
75 /* Defined in libdx/client.c */
76 extern int _dxfHostIsLocal(char *host); /* from libdx/ */
77 
78 /* Defined by yuiif.c */
79 void _dxf_ExReadDXRCFiles ();
80 
81 typedef struct _EXTab		*EXTab;
82 
83 typedef struct _EXTab
84 {
85     char	*name;		/* string to match		*/
86     PFI		func;		/* function to call on match	*/
87     EXTab	table;		/* table to search on match	*/
88     int		size;		/* size of the table		*/
89 } _EXTab;
90 
91 
92 static Error	CmdProc		(Object *in);
93 static Error    MustRunOnMaster (Object in0);
94 
95 #if DXD_OS2_SYSCALL
96 static int _Optlink	Compare		(const void *key, const void *data);
97 #else
98 static int		Compare		(const void *key, const void *data);
99 #endif
100 
101 static Error	ProcessTable	(char *cmd, Object *in, EXTab table, int len);
102 
103 static Error	Assign		(char *c, Object *in);
104 static Error	AssignNoExec	(char *c, Object *in);
105 static Error	Describe	(char *c, Object *in);
106 static Error	FlushCache	(char *c, Object *in);
107 static Error	FlushGlobal	(char *c, Object *in);
108 static Error	FlushMacro	(char *c, Object *in);
109 static Error	Getenv		(char *c, Object *in);
110 static Error	GetKey		(char *c, Object *in);
111 static Error    GroupAttach  	(char *c, Object *in);
112 static Error    GroupDetach  	(char *c, Object *in);
113 static Error    HostDisconnect 	(char *c, Object *in);
114 static Error	KillGraph	(char *c, Object *in);
115 static Error	License		(char *c, Object *in);
116 static Error	LoadObjFile	(char *c, Object *in);
117 static Error	LoadInteractors	(char *c, Object *in);
118 static Error	MdfLoadFile	(char *c, Object *in);
119 static Error	MdfLoadString	(char *c, Object *in);
120 static Error	OutboardKill	(char *c, Object *in);
121 static Error	Pfsmgr		(char *c, Object *in);
122 static Error	PrintCache	(char *c, Object *in);
123 static Error	PrintExObjects	(char *c, Object *in);
124 static Error	PrintFunction	(char *c, Object *in);
125 static Error	PrintGlobal	(char *c, Object *in);
126 static Error	PrintGroups	(char *c, Object *in);
127 static Error	PrintHosts	(char *c, Object *in);
128 static Error	ProductVersion	(char *c, Object *in);
129 static Error	Reclaim		(char *c, Object *in);
130 static Error	Terminate	(char *c, Object *in);
131 static Error	Version		(char *c, Object *in);
132 static Error	SyncGraph	(char *c, Object *in);
133 static int 	UpdateWorkers	(char *host, char *user, char *options, int add);
134 
135 #define	FCALL(_n,_f) 		{_n, _f,   NULL, 0}
136 #define	TABLE(_n,_t)		{_n, NULL, _t,   sizeof (_t)}
137 #define	FANDT(_n,_f,_t)		{_n, _f,   _t,   sizeof (_t)}
138 
139 
140 static _EXTab AssignTable[] =
141 {
142     FCALL ("",      	  Assign),
143     FCALL ("noexecute",   AssignNoExec)
144 };
145 
146 static _EXTab FlushTable[] =
147 {
148     FCALL ("cache",      FlushCache),
149     FCALL ("dictionary", FlushGlobal),
150     FCALL ("macro",      FlushMacro),
151     FCALL ("macros",     FlushMacro)
152 };
153 
154 static _EXTab GroupTable[] =
155 {
156     FCALL ("attach",    GroupAttach),
157     FCALL ("detach", 	GroupDetach)
158 };
159 
160 static _EXTab HostTable[] =
161 {
162     FCALL ("disconnect",    HostDisconnect)
163 };
164 
165 static _EXTab MdfTable[] =
166 {
167     FCALL ("describe", 	Describe),
168     FCALL ("file",	MdfLoadFile),
169     FCALL ("print", 	Describe),
170     FCALL ("string", 	MdfLoadString)
171 };
172 
173 static _EXTab OutboardTable[] =
174 {
175     FCALL ("delete",        OutboardKill),
176 };
177 
178 static _EXTab PrintTable[] =
179 {
180     FCALL ("cache",      PrintCache),
181     FCALL ("dictionary", PrintGlobal),
182     FCALL ("env",	 Getenv),
183     FCALL ("exobjects",  PrintExObjects),
184     FCALL ("functions",  PrintFunction),
185     FCALL ("global",     PrintGlobal),
186     FCALL ("globals",    PrintGlobal),
187     FCALL ("groups",	 PrintGroups),
188     FCALL ("hosts",	 PrintHosts),
189     FCALL ("mdf", 	 Describe),
190     FCALL ("version",    Version)
191 };
192 
193 static _EXTab ProductTable[] =
194 {
195     FCALL ("version",    ProductVersion),
196 };
197 
198 
199 /*
200  * The top level command table
201  */
202 
203 static _EXTab TopLevel[] =
204 {
205     TABLE ("assign",   		AssignTable),
206     FCALL ("describe", 		Describe),
207     FCALL ("exit",     		Terminate),
208     TABLE ("flush",    		FlushTable),
209     FCALL ("getenv",   		Getenv),
210     FCALL ("getkey",   		GetKey),
211     TABLE ("group",    		GroupTable),
212     TABLE ("host",    		HostTable),
213     FCALL ("kill",     		KillGraph),
214     FCALL ("license",  		License),
215     FCALL ("load",     		LoadObjFile),
216     FCALL ("loadinteractors",   LoadInteractors),
217     TABLE ("mdf",      		MdfTable),
218     TABLE ("nop",      		NULL),
219     TABLE ("outboard", 		OutboardTable),
220     FCALL ("pfsmgr",   		Pfsmgr),
221     TABLE ("print",    		PrintTable),
222     TABLE ("product",  		ProductTable),
223     FCALL ("quit",     		Terminate),
224     FCALL ("reclaim",  		Reclaim),
225     FCALL ("sync",     		SyncGraph),
226     FCALL ("version",  		Version)
227 #if 0
228     FCALL ("unload",   UnLoadObjFile),
229 #endif
230 };
231 
232 /*
233  * The top level command interface
234  */
235 
_dxf_ExExecCommand(Object * in)236 Error _dxf_ExExecCommand (Object *in)
237 {
238     Error	ret, i;
239 
240     for (i=0; i < (MAXOBJECTS + 1) && in[i]; i++)
241         ;
242 
243     if (MustRunOnMaster (in[0]))
244 	ret = _dxf_ExRunOn (1, CmdProc, in, ((i+1) * sizeof(Object)));
245     else
246 	ret = CmdProc (in);
247 
248     return (ret);
249 }
250 
_dxf_ExExecCommandStr(char * cmd)251 Error _dxf_ExExecCommandStr (char *cmd)
252 {
253     Object in[MAXOBJECTS + 1];
254     int ret, i;
255 
256     in[0] = (Object)DXNewString(cmd);
257     if(!in[0])
258         return(ERROR);
259     for(i = 1; i < MAXOBJECTS + 1; i++)
260         in[1] = NULL;
261     ret = _dxf_ExExecCommand(in);
262     DXDelete(in[0]);
263     return(ret);
264 }
265 
266 void
_dxf_ExDeletePeer(SlavePeers * sp,int closepeer)267 _dxf_ExDeletePeer(SlavePeers *sp, int closepeer)
268 {
269     /* if name is NULL but we still have a valid file descrip then */
270     /* we are effectively marking this to be deleted when the socket */
271     /* closes. */
272     if(closepeer)
273         DXRegisterInputHandler(NULL, sp->sfd, NULL);
274     if(sp->peername) {
275         DXFree(sp->peername);
276         sp->peername = NULL;
277     }
278     sp->SlaveId = -1;
279     sp->wait_on_ack = FALSE;
280     sp->pending_req = FALSE;
281     sp->sendq.head = NULL;
282     sp->sendq.tail = NULL;
283     if(closepeer) {
284         close(sp->sfd);
285         sp->sfd = -99; /* reuse */
286     }
287 }
288 
289 void
_dxf_ExDeletePeerByName(char * host,int closepeer)290 _dxf_ExDeletePeerByName(char *host, int closepeer)
291 {
292     int i, limit;
293     SlavePeers *sp;
294 
295     for (i = 0, limit = SIZE_LIST(_dxd_slavepeers); i < limit; ++i)
296     {
297         sp = FETCH_LIST(_dxd_slavepeers, i);
298         if(sp->sfd == -99)
299            continue;
300         if (!strcmp(sp->peername,host)) {
301             _dxf_ExDeletePeer(sp, closepeer);
302             break;
303         }
304     }
305 }
306 
307 void
_dxf_ExAddPeer(SlavePeers * sp)308 _dxf_ExAddPeer(SlavePeers *sp)
309 {
310     int k, limit;
311     SlavePeers *index;
312 
313     for (k = 0, limit = SIZE_LIST(_dxd_slavepeers); k < limit; ++k) {
314         index = FETCH_LIST(_dxd_slavepeers, k);
315         if(index->sfd == -99) { /* reuse entry */
316             UPDATE_LIST(_dxd_slavepeers, *sp, k);
317             return;
318         }
319     }
320     /* we didn't find an entry to reuse */
321     APPEND_LIST(SlavePeers, _dxd_slavepeers, *sp);
322 }
323 
324 void
_dxf_ExDeleteHost(char * host,int err,int closepeer)325 _dxf_ExDeleteHost(char *host, int err, int closepeer)
326 {
327     dpgraphstat *index, *hostentry;
328     PGassign *pgindex;
329     int i, j, limit, limit2;
330     char savehost[MAXHOSTNAMELEN];
331 
332     strcpy(savehost, host);
333     _dxf_ExDeletePeerByName(savehost, closepeer);
334 
335     /* entry 0 is a dummy for the master so skip it */
336     for (i = 1, limit = SIZE_LIST(_dxd_dpgraphstat); i < limit; ++i) {
337         index = FETCH_LIST(_dxd_dpgraphstat, i);
338         /* entry not used */
339         if(index->procfd == -99)
340             continue;
341         if (!strcmp(index->prochostname,savehost)) {
342             if(err)
343                 DXUIMessage("ERROR",
344                  "PEER ABORT - Connection to peer %s has been broken.",savehost);
345             else if(index->procfd >= 0) {
346                 int peerwait = 1;
347                 _dxf_ExDistMsgfd(DM_EXIT, (Pointer)&peerwait, index->procfd);
348                 _dxf_ExDistributeMsg(DM_DELETEPEER, (Pointer)savehost, strlen(savehost)+1, TOSLAVES);
349             }
350             for (j = 0, limit2 = SIZE_LIST(_dxd_pgassign); j < limit2; ++j) {
351                 pgindex = FETCH_LIST(_dxd_pgassign, j);
352                 if(pgindex->hostindex < 0)
353                     continue; /* no host assignment */
354                 hostentry = FETCH_LIST(_dxd_dpgraphstat, pgindex->hostindex);
355                 if(!strcmp(hostentry->prochostname, savehost)) {
356                     pgindex->hostindex = -1;
357                     _dxf_ExGVariableSetStr(pgindex->pgname, NULL);
358                 }
359             }
360 
361             DXFree(index->prochostname);
362 	    DXFree(index->procusername);
363             DXFree(index->options);
364             index->prochostname = NULL;
365 	    index->procusername = NULL;
366             index->options = NULL;
367             if(index->procfd >= 0) {
368                 close(index->procfd);
369                 (*_dxd_exNSlaves)--;
370                 /* If we have to, wait for the child. */
371                 if (!_dxd_exDebugConnect)
372                     wait(0);
373             }
374             index->procfd = -99; 	/* reuse this entry */
375             index->numpgrps = 0;
376             /* set error to TRUE so we won't try to restart this entry */
377             index->error = TRUE;
378             break;
379         }
380     }
381 }
382 
383 /*
384  * update a global variable without causing a graph execution.
385  */
_dxf_ExStealthUpdate(char * name,Object obj)386 Error _dxf_ExStealthUpdate (char *name, Object obj)
387 {
388     return _dxf_ExUpdateGlobalDict (name, obj, 0);
389 }
390 
_dxf_InitDPtableflag()391 void _dxf_InitDPtableflag()
392 {
393     update_dptable = (int *)DXAllocate(sizeof(int *));
394     if(update_dptable == NULL)
395         _dxf_ExDie("Unable to allocate space for distributed flag");
396     *update_dptable = FALSE;
397     INIT_LIST(_dxd_dpgraphstat);
398     masterentry.prochostname = _dxd_exHostName;
399     masterentry.procusername = NULL;
400     APPEND_LIST(dpgraphstat, _dxd_dpgraphstat, masterentry);
401 }
402 
403 /* if a new host was added to the table return true */
_dxf_NewDPTableEntry()404 int _dxf_NewDPTableEntry()
405 {
406     if(*update_dptable) {
407         *update_dptable = FALSE;
408         return(TRUE);
409     }
410     else
411         return(FALSE);
412 }
413 
414 /* host string is in the form "hostname -options".
415  * This will update the list of slave hosts, for a delete command
416  * the entry will not be removed from the table and the sockets will
417  * not be closed.
418  */
419 
UpdateWorkers(char * host,char * user,char * options,int add)420 static int UpdateWorkers(char *host, char *user, char *options, int add)
421 {
422     int k, limit;
423     dpgraphstat *index;
424     dpgraphstat dpentry;
425     int optlen = 0;
426     int opterr = FALSE;
427 
428     if(add) {
429         if(options && *options != '-') {
430             /* print error but add to table anyway */
431             DXSetError(ERROR_BAD_PARAMETER,"bad option string %s", options);
432             opterr = TRUE;
433         }
434         if(options)
435             optlen = strlen(options) + 1;
436     }
437 
438     /* if new worker is the master don't add it to table of workers */
439     if(_dxfHostIsLocal(host)) {
440         if(add) {
441             if(options != NULL)
442                 DXWarning("%s is already connected, host arguments ignored.",
443                           _dxd_exHostName);
444             DXFree(host);
445             return(0);
446         }
447         else return(-1);
448     }
449 
450     /* entry 0 is a dummy for the master, skip it */
451     for (k = 1, limit = SIZE_LIST(_dxd_dpgraphstat); k < limit; ++k) {
452         index = FETCH_LIST(_dxd_dpgraphstat, k);
453         /* entry not used */
454         if(index->procfd == -99)
455             continue;
456 
457         if (!strcmp(index->prochostname, host)) {
458             ExDebug("*1","Current host %s  already in dpgraphstat", host);
459             /* not adding new host to table */
460             if(add) {
461                 DXFree(host);
462                 if(index->procfd >= 0) {
463                     if(options != NULL) {
464                         if(index->options != NULL &&
465                            !strcmp(index->options, options)) {
466                             index->error = opterr;
467                             if(!opterr)
468                                 index->numpgrps++;
469                             return(k);
470                         }
471                     }
472                     else {
473                         if(index->options == NULL) {
474                             index->error = FALSE;
475                             index->numpgrps++;
476                             return(k);
477                         }
478                     }
479 
480                     /* new options differ from old options */
481                     if(index->numpgrps == 0) {
482                         int peerwait = 0;
483                         _dxf_ExDistMsgfd(DM_EXIT, (Pointer)&peerwait, index->procfd);
484                         if(index->procfd >= 0) {
485                             close(index->procfd);
486                             /* If we have to, wait for the child. */
487                             if (!_dxd_exDebugConnect)
488                                 wait(0);
489                         }
490                         index->procfd = -1;
491                         index->error = opterr;
492                         if(!opterr)
493                             index->numpgrps++;
494                         if(index->options) {
495                             if(optlen > (strlen(index->options) + 1));
496                                 index->options =
497                                   DXReAllocate(index->options, optlen);
498                         }
499                         else
500                             index->options = DXAllocateLocal(optlen);
501                         if(!index->options) {
502                             index->error = TRUE;
503                             DXSetError(ERROR_NO_MEMORY,
504                                  "Cannot allocate memory for host table entry");
505                             return(k);
506                         }
507                         if(optlen > 0)
508                             strcpy(index->options, options);
509                         else {
510                             DXFree(index->options);
511                             index->options = NULL;
512                         }
513                         *update_dptable = TRUE;
514                         ExDebug("*7", "Set Flag to Update distributed table");
515                         return(k);
516                     }
517                     else {
518                         DXSetError(ERROR_BAD_PARAMETER,
519                             "Host already connected, cannot specify new options");
520                         index->error = TRUE;
521                         return(k);
522                     }
523                 }
524                 else {  /* host not connected */
525                     if(optlen > 0) {
526                         if(index->options) {
527                             if(optlen > (strlen(index->options) + 1))
528                                 index->options = DXReAllocate(index->options,
529                                                            optlen);
530                         }
531                         else
532                             index->options = DXAllocateLocal(optlen);
533                         if(!index->options) {
534                             index->error = TRUE;
535                             DXSetError(ERROR_NO_MEMORY,
536                              "Cannot allocate memory for host table entry");
537                             return(k);
538                         }
539                         strcpy(index->options, options);
540                     }
541                     else { /* no options to add, free old ones */
542                         if(index->options) {
543                             DXFree(index->options);
544                             index->options = NULL;
545                          }
546                     }
547                     index->error = opterr;
548                     if(!opterr)
549                         index->numpgrps++;
550                     *update_dptable = TRUE;
551                     ExDebug("*7", "Set Flag to Update distributed table");
552                     return(k);
553                 }
554             }
555             else { /* not adding a host */
556                 index->numpgrps--;
557                 if(index->numpgrps == 0)
558                     _dxf_ExDeleteHost(host, 0, 0);
559                 return(-1);
560             }
561         }
562     }
563     if(add) {
564         /* if we got here we did not find host name in list */
565         dpentry.error = opterr;
566         dpentry.prochostname = host;
567 	dpentry.procusername = user;
568         if(optlen > 0) {
569             dpentry.options = (char *) DXAllocateLocal (optlen);
570             if(!dpentry.options) {
571                 dpentry.error = TRUE;
572                 DXSetError(ERROR_NO_MEMORY,
573                   "Could not allocate memory for remote host table entry");
574             }
575             else
576                 strcpy(dpentry.options, options);
577         }
578         else dpentry.options = NULL;
579         dpentry.procfd = -1;
580         dpentry.SlaveId = -1;
581         dpentry.SwapMsg = -1;
582         if(!opterr)
583             dpentry.numpgrps = 1;
584         else
585             dpentry.numpgrps = 0;
586         /* entry 0 is a dummy for the master */
587         for (k = 1, limit = SIZE_LIST(_dxd_dpgraphstat); k < limit; ++k) {
588             index = FETCH_LIST(_dxd_dpgraphstat, k);
589             if(index->procfd == -99) { /* reuse entry */
590                 UPDATE_LIST(_dxd_dpgraphstat, dpentry, k);
591                 *update_dptable = TRUE;
592                 ExDebug("*7", "Set Flag to Update distributed table");
593                 return(k);
594             }
595         }
596         /* we didn't find an entry to reuse */
597         APPEND_LIST(dpgraphstat, _dxd_dpgraphstat, dpentry);
598         *update_dptable = TRUE;
599         ExDebug("*7", "Set Flag to Update distributed table");
600         limit = SIZE_LIST(_dxd_dpgraphstat);
601         return(limit-1);
602     }
603     else
604         return(-1);
605 }
606 
_dxf_ExPrintGroups()607 Error _dxf_ExPrintGroups()
608 {
609     int i, limit;
610     PGassign *index;
611     dpgraphstat *hostentry;
612 
613     DXMessage("Group Attach Table");
614     DXMessage("%-25s %s", "Groupname", "Hostname");
615     for (i = 0, limit = SIZE_LIST(_dxd_pgassign); i < limit; ++i) {
616         index = FETCH_LIST(_dxd_pgassign, i);
617         if(index->hostindex >= 0) {
618             hostentry = FETCH_LIST(_dxd_dpgraphstat, index->hostindex);
619             DXMessage("%-25s %s", index->pgname, hostentry->prochostname);
620         }
621         else
622             DXMessage("%-25s", index->pgname);
623     }
624     return OK;
625 }
626 
_dxf_ExPrintHosts()627 Error _dxf_ExPrintHosts()
628 {
629     int i, limit;
630     dpgraphstat *index;
631 
632     DXMessage("Number of Slaves %d", *_dxd_exNSlaves);
633     DXMessage("Host Connection Table");
634     DXMessage("%-25s %s", "Hostname", "Status");
635     /* entry 0 is a dummy for the master */
636     for (i = 1, limit = SIZE_LIST(_dxd_dpgraphstat); i < limit; ++i) {
637         index = FETCH_LIST(_dxd_dpgraphstat, i);
638         if(index->procfd == -99)
639             continue;
640         if(index->procfd < 0) {
641             if(index->error) {
642                 if(index->prochostname)
643                     DXMessage("%-25s %s", index->prochostname, "connect error");
644             }
645             else
646                 DXMessage("%-25s %s", index->prochostname, "not connected");
647         }
648         else {
649             if(index->numpgrps == 1)
650                 DXMessage("%-25s %s: %d group  attached",
651                  index->prochostname, "connected", index->numpgrps);
652             else
653                 DXMessage("%-25s %s: %d groups attached",
654                  index->prochostname, "connected", index->numpgrps);
655         }
656     }
657     return OK;
658 }
659 
660 /*
661  * hack for now.  the mdf commands CAN'T be started with
662  * the subroutine which is used to be sure the executive
663  * commands run on processor 0, so start implementing a layer
664  * which eventually could be used to run executive commands
665  * which are not dependent on running on proc 0 from whichever
666  * processor picked up the executive module in the first place.
667  */
MustRunOnMaster(Object in0)668 static Error MustRunOnMaster (Object in0)
669 {
670     char        *cmd;
671 
672     if (!in0 || ! DXExtractString (in0, &cmd))
673 	return ERROR;
674 
675     if (strncmp(cmd, "mdf", 3))
676 	return OK;
677 
678     return ERROR;
679 }
680 
681 
CmdProc(Object * in)682 static Error CmdProc (Object *in)
683 {
684     Error	ret;
685     char        *cmd;
686 
687     if (!in[0] || ! DXExtractString (in[0], &cmd)) {
688         DXSetError (ERROR_BAD_PARAMETER, "#10200", "command input");
689         return (ERROR);
690     }
691 
692     ret = ProcessTable (cmd, &in[1], TopLevel, sizeof (TopLevel));
693     return (ret);
694 }
695 
696 
697 #if DXD_OS2_SYSCALL
698 static int _Optlink
699 #else
700 static int
701 #endif
Compare(const void * key,const void * data)702 Compare (const void *key, const void *data)
703 {
704     EXTab a = (EXTab) key;
705     EXTab b = (EXTab) data;
706     return (strcmp (a->name, b->name));
707 }
708 
709 
ProcessTable(char * cmd,Object * in,EXTab table,int len)710 static Error ProcessTable (char *cmd, Object *in, EXTab table, int len)
711 {
712     char	*next;
713     char	buf[1024];
714     _EXTab	dummy;
715     EXTab	tab;
716     Error	fret = OK;
717     Error	tret = OK;
718 
719     for (next = cmd; next && *next && isspace (*next); next++)
720 	continue;
721 
722     buf[0] = '\0';
723     if (sscanf (next, "%1023s", buf) != 1) {
724         DXSetError(ERROR_BAD_PARAMETER, "#8310", cmd);
725         return ERROR;
726     }
727     dummy.name = buf;
728     tab = (EXTab) bsearch ((char *) &dummy, (char *) table,
729 			     len / sizeof (_EXTab), sizeof (_EXTab),
730 			     Compare);
731 
732     if (! tab) {
733 	DXSetError (ERROR_BAD_PARAMETER, "#8310", cmd);
734 	return (ERROR);
735     }
736 
737     for (next = next + strlen (buf); next && *next && isspace (*next); next++)
738 	continue;
739 
740     if (tab->func)
741 	fret = (* tab->func) (next, in);
742 
743     if (tab->table) {
744         if(strcmp(next, "") == 0) {
745             DXSetError(ERROR_BAD_PARAMETER, "#8312", cmd);
746             return (ERROR);
747         }
748 	tret = ProcessTable (next, in, tab->table, tab->size);
749     }
750 
751     return (fret == OK && tret == OK ? OK : ERROR);
752 }
753 
754 
755 /*
756  * Functions executed by the tables.
757  */
758 
Assign(char * c,Object * in)759 static int Assign(char *c, Object *in)
760 {
761     return(ERROR);
762 }
763 
AssignNoExec(char * c,Object * in)764 static int AssignNoExec(char *c, Object *in)
765 {
766     char *name;
767 
768     if (!in[0] || ! DXExtractString (in[0], &name)) {
769         DXSetError (ERROR_BAD_PARAMETER, "#10200", "variable name");
770         return (ERROR);
771     }
772     return (_dxf_ExStealthUpdate(name, in[1]));
773 
774 }
775 
Describe(char * c,Object * in)776 static int Describe (char *c, Object *in)
777 {
778     char		*str;
779     int			i, j, k, n;
780     char		*key;
781     node		*func;
782     node		*minn;
783     int			mini;
784     node		**funcs	= NULL;
785     char		help[1024];
786     char		*hp;
787 
788     if ((c == NULL || *c == '\000') && (in == NULL || in[0] == NULL))
789     {
790 	_dxf_ExDictionaryBeginIterate (_dxd_exMacroDict);
791 	for (n = 0; _dxf_ExDictionaryIterate (_dxd_exMacroDict, &key) != NULL; n++)
792 	    ;
793 	_dxf_ExDictionaryEndIterate (_dxd_exMacroDict);
794 
795 	funcs = (node **) DXAllocateLocal (n * sizeof (node *));
796 
797 	DXBeginLongMessage ();
798 	_dxf_ExDictionaryBeginIterate (_dxd_exMacroDict);
799 	for (i = 0, k = 0; i < n; i++)
800 	{
801 	    func = (node *) _dxf_ExDictionaryIterate (_dxd_exMacroDict, &key);
802             /* skip over dummy function definitions */
803             if (func->v.module.def.func == m__badfunc)
804                 continue;
805 	    if (funcs != NULL)
806 		funcs[k] = func;
807 	    else
808 		DXMessage ("%-25s %s\n", func->v.module.id->v.id.id,
809 				     func->type == NT_MACRO
810 					 ? "macro" : "module");
811             k++;
812 	}
813 	_dxf_ExDictionaryEndIterate (_dxd_exMacroDict);
814 
815 	for (i = 0; i < k; i++)
816 	{
817 	    minn = funcs[i];
818 	    mini = i;
819 	    for (j = i; j < k; j++)
820 	    {
821 		if (strcasecmp (minn->v.function.id->v.id.id,
822 				funcs[j]->v.function.id->v.id.id) > 0)
823 		{
824 		    minn = funcs[j];
825 		    mini = j;
826 		}
827 	    }
828 	    func        = funcs[i];
829 	    funcs[i]    = funcs[mini];
830 	    funcs[mini] = func;
831 	}
832 
833 	if (funcs != NULL)
834 	{
835 	    for (i = 0; i < k; i++)
836 		DXMessage ("%-25s %s\n", funcs[i]->v.module.id->v.id.id,
837 				     funcs[i]->type == NT_MACRO
838 					 ? "macro" : "module");
839 	}
840 	DXEndLongMessage ();
841 
842 	DXFree ((Pointer) funcs);
843 	return (OK);
844     }
845 
846     if (c && *c) {
847 	while (*c)
848 	{
849         int ret = 0;
850 	    help[0] = '\000';
851 	    ret = sscanf (c, "%1023s", help);
852 	    if (ret != 1 || help[0] == '\000')
853 		break;
854 	    str = _dxf_ExHelpFunction (help);
855 	    if (str)
856 	    {
857 		DXBeginLongMessage ();
858 		DXMessage (str);
859 		DXEndLongMessage ();
860 		DXFree ((Pointer) str);
861 	    }
862 	    for (c = c + strlen (help); *c && isspace (*c); c++)
863 		continue;
864 	}
865     }
866     else
867     {
868 	for (i = 0; DXExtractString (in[i], &hp); i++)
869 	{
870 	    str = _dxf_ExHelpFunction (hp);
871 	    if (str)
872 	    {
873 		DXBeginLongMessage ();
874 		DXMessage (str);
875 		DXEndLongMessage ();
876 		DXFree ((Pointer) str);
877 	    }
878 	}
879     }
880     return (OK);
881 }
882 
883 
FlushCache(char * c,Object * in)884 static int FlushCache (char *c, Object *in)
885 {
886     _dxf_ExCacheFlush (FALSE);
887     return (OK);
888 }
889 
890 
_dxf_ExFlushGlobal(void)891 void _dxf_ExFlushGlobal (void)
892 {
893     char *dummy=NULL;
894     Object *in=NULL;
895 
896     FlushGlobal(dummy, in);
897 }
898 
ExResetGroupAssign()899 void ExResetGroupAssign ()
900 {
901     int k, limit;
902     PGassign *index;
903     dpgraphstat *hostentry;
904 
905     for (k = 0, limit = SIZE_LIST(_dxd_pgassign); k < limit; ++k) {
906         index = FETCH_LIST(_dxd_pgassign, k);
907         hostentry = FETCH_LIST(_dxd_dpgraphstat, index->hostindex);
908         if(!hostentry->error)
909             _dxf_ExGVariableSetStr(index->pgname,
910                                        hostentry->prochostname);
911     }
912 }
913 
FlushGlobal(char * c,Object * in)914 static int FlushGlobal (char *c, Object *in)
915 {
916     if(!_dxd_exRemoteSlave) {
917         /* _dxf_ExCacheFlush and _dxf_ExDictionaryPurge will send msgs
918          *  to  slaves and slaves will call each of these routines
919          *  seperately
920          */
921         _dxf_ExCacheFlush (TRUE);
922         DXDebug ("1", "flushing dictionary");
923         _dxf_ExDictionaryPurge (_dxd_exGlobalDict);
924         _dxf_ExDistributeMsg(DM_FLUSHGLOBAL, NULL, 0, TOSLAVES);
925     }
926     _dxf_ExInitSystemVars ();
927     ExResetGroupAssign ();
928     return (OK);
929 }
930 
_dxf_ExFlushMacro(void)931 void _dxf_ExFlushMacro (void)
932 {
933     char *dummy=NULL;
934     Object *in=NULL;
935 
936     FlushMacro(dummy, in);
937 }
938 
FlushMacro(char * c,Object * in)939 static int FlushMacro (char *c, Object *in)
940 {
941     if(!_dxd_exRemoteSlave) {
942         /* _dxf_ExDictionaryPurge will send msg to slaves and cause
943          * the slaves to call this routine seperately
944          */
945         _dxf_ExDictionaryPurge (_dxd_exMacroDict);
946         _dxf_ExDistributeMsg(DM_FLUSHMACRO, NULL, 0, TOSLAVES);
947     }
948     _dxf_user_modules ();
949     _dxf_private_modules ();
950     _dxf_ExFunctionDone ();
951     return (OK);
952 }
953 
954 
Getenv(char * c,Object * in)955 static int Getenv (char *c, Object *in)
956 {
957     char	*env;
958     char	**envp;
959 
960     DXBeginLongMessage ();
961     if (c && *c)
962     {
963 	env = (char *) getenv (c);
964 	if (env)
965 	    DXMessage ("%s=%s", c, env);
966 	else
967 	    DXMessage ("%s is not in the environment", c);
968     }
969     else
970     {
971 	envp = (char **) _dxf_ExEnvp ();
972 	for ( ;envp && *envp; envp++)
973 	    DXMessage ("%s\n", *envp);
974     }
975     DXEndLongMessage ();
976 
977     return (OK);
978 }
979 
980 /* Insert a group to hostname assignment in table. This will not make the
981  * connection to the remote host until the current graph has finished
982  * executing. If this is updated in the middle of a graph evaluation we
983  * have a slave that is started but is not executing the current graph.
984  * The master will see the new slave and try to wait for it to execute
985  * the current graph which is doesn't have.
986  * This takes a string list with each string element being:
987  * "group1, group2, group3:hostname -options"
988  */
989 
GroupAttach(char * c,Object * in)990 static int GroupAttach(char *c, Object *in)
991 {
992     int n, k, limit, grouplen, found;
993     dpgraphstat *hostentry;
994     char *str, *delimiter;
995     char *hoststr, *userstr;
996     PGassign pgassign, *index=NULL;
997     int cerror = FALSE;
998     char *hostname;
999     char *username;
1000     char *optr;
1001     int hostlen, userlen;
1002 
1003     if(_dxd_exRemoteSlave)
1004         return(OK);
1005 
1006     if(!in[0]) {
1007         DXSetError (ERROR_BAD_PARAMETER, "#10200", "group assignment");
1008         return (ERROR);
1009     }
1010 
1011     n = 0;
1012     while(DXExtractNthString(in[0], n, &str)) {
1013         hoststr = strchr(str, ':');
1014         if(hoststr == NULL) {
1015             DXSetError(ERROR_BAD_PARAMETER, "no host assignment");
1016             return(ERROR);
1017         }
1018         hoststr++;
1019 
1020         while(*hoststr == ' ')
1021             hoststr++;
1022         if(*hoststr == '\0') {
1023             DXSetError(ERROR_BAD_PARAMETER, "no host assignment");
1024             return(ERROR);
1025         }
1026 
1027        if ( strchr(hoststr, '@') ) {
1028             userstr = hoststr;
1029             hoststr = strchr(hoststr, '@') + 1;
1030             if ( *userstr == '@' ) {
1031                DXSetError(ERROR_BAD_PARAMETER, "no user assignment");
1032                return(ERROR);
1033            }
1034             optr = userstr;
1035            while(*optr != ' ' && *optr != '@')
1036                optr++;
1037 
1038             userlen = optr - userstr;
1039        }
1040        else
1041             userstr = NULL, userlen = 0;
1042 
1043         while(*hoststr == ' ')
1044             hoststr++;
1045         if(*hoststr == '\0') {
1046             DXSetError(ERROR_BAD_PARAMETER, "no host assignment");
1047             return(ERROR);
1048         }
1049 
1050         optr = hoststr;
1051 
1052         while(*optr && *optr != ' ' && *optr != ':')
1053             optr++;
1054 
1055         if(*optr)
1056             hostlen = optr - hoststr;
1057         else
1058             hostlen = strlen(hoststr);
1059 
1060         while(*optr && *optr == ' ')
1061             optr++;
1062 
1063         if(*optr == '\0')
1064             optr = NULL;
1065 
1066         while(*str == ' ')
1067             str++;
1068         if(*str == ':' || *str == ',') {
1069             DXSetError(ERROR_BAD_PARAMETER, "no group name");
1070             return(ERROR);
1071         }
1072         while(*str) {
1073 	    hostname = (char *)DXAllocateLocal(hostlen + 1);
1074 	    if(hostname == NULL)
1075 		DXSetError(ERROR_NO_MEMORY,
1076 			   "Cannot allocate memory for host table entry");
1077 	    strncpy(hostname, hoststr, hostlen);
1078 	    hostname[hostlen] = '\0';
1079 
1080             if ( userstr ) {
1081                 username = (char *)DXAllocateLocal(userlen + 1);
1082                 if(username == NULL)
1083                     DXSetError(ERROR_NO_MEMORY,
1084                                "Cannot allocate memory for user table entry");
1085                 strncpy(username, userstr, userlen);
1086                 username[userlen] = '\0';
1087                 userstr = username;
1088             }
1089 
1090             delimiter = str;
1091             while(*delimiter && *delimiter != ',' &&
1092                   *delimiter != ' ' && *delimiter != ':')
1093                 delimiter++;
1094             grouplen = delimiter - str;
1095             pgassign.pgname = (char *)DXAllocateLocal(grouplen + 1);
1096             if(pgassign.pgname == NULL)
1097                 DXSetError(ERROR_NO_MEMORY,
1098                        "Cannot allocate memory for group table entry");
1099             strncpy(pgassign.pgname, str, grouplen);
1100             pgassign.pgname[grouplen] = '\0';
1101             found = FALSE;
1102             /* search table to see if process group is already assigned */
1103             for (k = 0, limit = SIZE_LIST(_dxd_pgassign); k < limit; ++k) {
1104                 index = FETCH_LIST(_dxd_pgassign, k);
1105                 if(!strcmp(index->pgname, pgassign.pgname)) {
1106                     found = TRUE;
1107                     break;
1108                 }
1109             }
1110             if(found) {
1111                 /* see if it is already attached */
1112                 if(index->hostindex >= 0)
1113                     hostentry = FETCH_LIST(_dxd_dpgraphstat, index->hostindex);
1114                 else hostentry = NULL;
1115                 if(hostentry && (hostentry->error == FALSE) &&
1116                   !strcmp(hostentry->prochostname, hostname)) {
1117                     if(optr != NULL) {
1118                         if(hostentry->options != NULL &&
1119                            !strcmp(hostentry->options, optr)) {
1120                             DXFree(pgassign.pgname);
1121                             goto next_string;
1122                         }
1123                     }
1124                     else {
1125                         if(hostentry->options == NULL) {
1126                             DXFree(pgassign.pgname);
1127                             goto next_string;
1128                         }
1129                     }
1130                 }
1131                 /* replace host assignment in table */
1132                 index->hostindex = UpdateWorkers(hostname, userstr, optr, 1);
1133                 hostentry = FETCH_LIST(_dxd_dpgraphstat, index->hostindex);
1134                 DXFree(pgassign.pgname);
1135                 if(!hostentry->error) {
1136                     _dxf_ExGVariableSetStr(index->pgname,
1137                                        hostentry->prochostname);
1138                     if(_dxd_exDebug)
1139                         printf("reassigning %s to %s\n",index->pgname,
1140                                 hostentry->prochostname);
1141                 }
1142                 else
1143                     cerror = hostentry->error;
1144             }
1145             else { /* adding new process group assignment */
1146                 pgassign.hostindex = UpdateWorkers(hostname, userstr, optr, 1);
1147                 hostentry = FETCH_LIST(_dxd_dpgraphstat, pgassign.hostindex);
1148                 APPEND_LIST(PGassign, _dxd_pgassign, pgassign);
1149                 if(!hostentry->error) {
1150                     _dxf_ExGVariableSetStr(pgassign.pgname,
1151                                        hostentry->prochostname);
1152                     if(_dxd_exDebug)
1153                         printf("assigning %s to %s\n",
1154                              pgassign.pgname, hostentry->prochostname);
1155                 }
1156                 else
1157                     cerror = hostentry->error;
1158             }
1159 next_string:
1160             str = delimiter;
1161             while(*str == ' ' || *str == ',')
1162                 str++;
1163             if(*str == ':')
1164                 break;
1165         }
1166         n++;
1167     }
1168     if(cerror)
1169         return(ERROR);
1170     else
1171         return(OK);
1172 }
1173 
1174 
1175 /* This routine does not close the sockets associated with a host.
1176  * This routine takes a string list of group names to be removed from the
1177  * process assignment table.
1178  */
1179 
GroupDetach(char * c,Object * in)1180 static int GroupDetach(char *c, Object *in)
1181 {
1182     char *groupname;
1183     int n, k, limit;
1184     PGassign *index;
1185     dpgraphstat *hostentry;
1186 
1187     if(_dxd_exRemoteSlave)
1188         return(OK);
1189 
1190     if(!in[0]) {
1191         DXSetError (ERROR_BAD_PARAMETER, "#10200", "group name");
1192         return (ERROR);
1193     }
1194 
1195     n = 0;
1196     while(DXExtractNthString(in[0], n, &groupname)) {
1197         for (k = 0, limit = SIZE_LIST(_dxd_pgassign); k < limit; ++k) {
1198             index = FETCH_LIST(_dxd_pgassign, k);
1199             if(!strcmp(index->pgname, groupname)) {
1200                 hostentry = FETCH_LIST(_dxd_dpgraphstat, index->hostindex);
1201                 if(hostentry) {
1202                     if(!hostentry->error)
1203                         index->hostindex = UpdateWorkers(
1204 				  hostentry->prochostname,
1205                                   hostentry->procusername, NULL, 0);
1206                 }
1207                 _dxf_ExGVariableSetStr(index->pgname, NULL);
1208                 _dxf_ExCacheFlush(FALSE);
1209                 DXFree(index->pgname);
1210                 DELETE_LIST(PGassign, _dxd_pgassign, k);
1211                 break;
1212             }
1213         }
1214         n++;
1215     }
1216     return(OK);
1217 }
1218 
HostDisconnect(char * c,Object * in)1219 static int HostDisconnect(char *c, Object *in)
1220 {
1221     int n;
1222     char *hostname;
1223 
1224     n = 0;
1225     while(DXExtractNthString(in[0], n, &hostname)) {
1226         _dxf_ExDeleteHost(hostname, 0, 0);
1227         n++;
1228     }
1229 
1230     return(OK);
1231 }
1232 
KillGraph(char * c,Object * in)1233 static int KillGraph (char *c, Object *in)
1234 {
1235     if (!_dxf_ExGQAllDone ()) {
1236 	*_dxd_exKillGraph = TRUE;
1237         _dxf_ExDistributeMsg(DM_KILLEXECGRAPH,
1238                              (Pointer)_dxd_exContext->graphId, 0, TOPEERS);
1239     }
1240     return (OK);
1241 }
1242 
LoadObjFile(char * c,Object * in)1243 static int LoadObjFile(char *c, Object *in)
1244 {
1245     char *str;
1246 
1247     if (!in[0] || ! DXExtractString (in[0], &str)) {
1248         DXSetError (ERROR_BAD_PARAMETER, "#10200", "object filename");
1249         return (ERROR);
1250     }
1251 
1252     return DXLoadObjFile(str, "DXMODULES") != NULL;
1253 }
1254 
LoadInteractors(char * c,Object * in)1255 static int LoadInteractors(char *c, Object *in)
1256 {
1257     return _dxf_ExRunOn (1, _dxfLoadUserInteractors, (Pointer)c, strlen(c)+1);
1258 }
1259 
MdfLoadFile(char * c,Object * in)1260 static int MdfLoadFile(char *c, Object *in)
1261 {
1262     char *str;
1263 
1264     if (!in[0] || ! DXExtractString (in[0], &str)) {
1265         DXSetError (ERROR_BAD_PARAMETER, "#10200", "mdf filename");
1266         return (ERROR);
1267     }
1268 
1269     return DXLoadMDFFile(str);
1270 }
1271 
MdfLoadString(char * c,Object * in)1272 static int MdfLoadString(char *c, Object *in)
1273 {
1274     char *str;
1275 
1276     if (!in[0] || ! DXExtractString (in[0], &str)) {
1277         DXSetError (ERROR_BAD_PARAMETER, "#10200", "mdf definition");
1278         return (ERROR);
1279     }
1280 
1281     return DXLoadMDFString(str);
1282 }
1283 
1284 /* disconnect the pipe between the exec and a specific outboard module.
1285  *  args are: module name, instance number (may be omitted - defaults to 0),
1286  *  and process group name (may be null - defaults to localhost).
1287  */
OutboardKill(char * c,Object * in)1288 static int OutboardKill (char *c, Object *in)
1289 {
1290     char *module;
1291     int instance;
1292     char *procgroup;
1293 
1294     if (!in[0] || ! DXExtractString (in[0], &module)) {
1295         DXSetError (ERROR_BAD_PARAMETER, "#10200", "outboard module name");
1296         return (ERROR);
1297     }
1298 
1299     if (!in[1])
1300 	instance = 0;
1301     else if (! DXExtractInteger (in[1], &instance)) {
1302         DXSetError (ERROR_BAD_PARAMETER, "#10010", "outboard instance number");
1303         return (ERROR);
1304     }
1305 
1306     if (!in[2])
1307 	procgroup = NULL;
1308     else if (! DXExtractString (in[2], &procgroup)) {
1309         DXSetError (ERROR_BAD_PARAMETER, "#10200", "outboard process group");
1310         return (ERROR);
1311     }
1312 
1313     if (procgroup) {
1314 	if (!_dxf_ExDeleteReallyRemote (procgroup, module, instance))
1315 	    return ERROR;
1316     }
1317     else if (!_dxf_ExDeleteRemote (module, instance))
1318 	return ERROR;
1319 
1320     return (OK);
1321 }
1322 
Pfsmgr(char * c,Object * in)1323 static int Pfsmgr (char *c, Object *in)
1324 {
1325     int		argc	= 0;
1326     char	*argv[1024];
1327     char	*buf	= NULL;
1328     char	*b;
1329     int		len;
1330     Error	ret	= ERROR;
1331 
1332     if (! c)
1333     {
1334 	ret = OK;
1335 	goto cleanup;
1336     }
1337 
1338     len = strlen (c) + 1;
1339     b = buf = (char *) DXAllocateLocal (len);
1340     if (buf == NULL)
1341 	goto cleanup;
1342     memcpy (buf, c, len);
1343 
1344     while (*b)
1345     {
1346 	argv[argc++] = b;
1347 	while (*b && ! isspace (*b))
1348 	    b++;
1349 	while (*b && isspace (*b))
1350 	    b++;
1351     }
1352 
1353     for (b = buf; *b; b++)
1354 	if (isspace (*b))
1355 	    *b = (char) NULL;
1356 
1357     ret = _dxf_pfsmgr (argc, argv);
1358 
1359 cleanup:
1360     DXFree ((Pointer) buf);
1361     return (ret);
1362 }
1363 
1364 
PrintCache(char * c,Object * in)1365 static int PrintCache (char *c, Object *in)
1366 {
1367     _dxf_ExDictPrint (_dxd_exCacheDict);
1368     return (OK);
1369 }
1370 
1371 
PrintExObjects(char * c,Object * in)1372 static int PrintExObjects (char *c, Object *in)
1373 {
1374 #ifdef LEAK_DEBUG
1375     PrintEXObj ();
1376 #else
1377     DXMessage ("#1280");
1378 #endif
1379     return (OK);
1380 }
1381 
1382 
PrintFunction(char * c,Object * in)1383 static int PrintFunction (char *c, Object *in)
1384 {
1385     _dxf_ExDictPrint (_dxd_exMacroDict);
1386     return (OK);
1387 }
1388 
1389 
PrintGlobal(char * c,Object * in)1390 static int PrintGlobal (char *c, Object *in)
1391 {
1392     _dxf_ExDictPrint (_dxd_exGlobalDict);
1393     return (OK);
1394 }
1395 
PrintGroups(char * c,Object * in)1396 static int PrintGroups (char *c, Object *in)
1397 {
1398     _dxf_ExPrintGroups();
1399     return (OK);
1400 }
1401 
PrintHosts(char * c,Object * in)1402 static int PrintHosts (char *c, Object *in)
1403 {
1404     _dxf_ExPrintHosts();
1405     return (OK);
1406 }
1407 
Reclaim(char * c,Object * in)1408 static int Reclaim (char *c, Object *in)
1409 {
1410     DXTraceTime (1);
1411     _dxf_ExReclaimMemory (atol (c));
1412     DXTraceTime (0);
1413     DXPrintTimes ();
1414     return (OK);
1415 }
1416 
SyncGraph(char * c,Object * in)1417 static int SyncGraph (char *c, Object *in)
1418 {
1419     _dxd_exParseAhead = FALSE;
1420     return(OK);
1421 }
1422 
Terminate(char * c,Object * in)1423 static int Terminate (char *c, Object *in)
1424 {
1425     exit (0);
1426     /* not reached */
1427     return (OK);
1428 }
1429 
License(char * c,Object * in)1430 static int License (char *c, Object *in)
1431 {
1432 
1433 #ifdef DXD_LICENSED_VERSION
1434 
1435     static int license_tried = FALSE;
1436     int i;
1437     char keybuf[14];
1438     char typebuf[5];
1439     char key[9];
1440     char salt[3];
1441 
1442     /* decode and check license string here */
1443 
1444     if (license_tried)
1445 	exit(0);		/* our UI will never call $license twice */
1446     else
1447 	license_tried = TRUE;
1448 
1449     for(i=0;i<13;i++)
1450 	keybuf[i] = c[i];
1451     keybuf[13] = '\0';
1452 
1453     for(i=0;i<4;i++)
1454 	typebuf[i] = c[i+13];
1455     typebuf[4] = '\0';
1456 
1457     for(i=0;i<4;i++)
1458 	key[i*2] = _dxd_LicenseKey[i];
1459 
1460     key[1] = 'g';
1461     key[3] = '3';
1462     key[5] = '$';
1463     key[7] = 'Q';
1464     key[8] = '\0';
1465 
1466     salt[0] = '4';
1467     salt[1] = '.';
1468     salt[2] = '\0';
1469 
1470     if(strcmp(keybuf,(const char *)crypt(key,salt))){
1471 	DXMessage("License Error: Invalid license Message\n");
1472 	DXUIMessage("LICENSE","UNAUTHORIZED");
1473 	return (OK);
1474     }
1475 
1476     sscanf(typebuf,"%04x",&i);
1477 
1478     /* This junk below is to preserve byte order, beware ! */
1479 
1480     switch(i^(*((ubyte *)&keybuf[4])<<8)+(*((ubyte *)&keybuf[5]))) {
1481 
1482       case GOT_NODELOCKED:
1483 	if (!ExGetPrimaryLicense())
1484 	    DXMessage("Exec could not get a license (UI has nodelocked)\n");
1485 	else
1486 	    DXUIMessage("LICENSE", "AUTHORIZED");
1487 	break;
1488 
1489       case GOT_CONCURRENT:
1490 	_dxd_ExHasLicense = TRUE;
1491 	DXUIMessage("LICENSE", "AUTHORIZED");
1492 	DXMessage("Running under UI's concurrent license\n");
1493 	break;
1494 
1495       default:
1496 	DXMessage("License Error: Invalid license Message\n");
1497 	break;
1498     }
1499 
1500     if (_dxd_ExHasLicense == FALSE)
1501         DXUIMessage("LICENSE","UNAUTHORIZED");
1502 
1503     if (_dxd_ExHasLicense && _dxd_exRemote)
1504 	_dxf_ExReadDXRCFiles();
1505 
1506 #else  /* DXD_LICENSED_VERSION */
1507 
1508     if (_dxd_exRemote)
1509 	_dxf_ExReadDXRCFiles();
1510 
1511     DXUIMessage("LICENSE", "AUTHORIZED");
1512 
1513 #endif /* !DXD_LICENSED_VERSION */
1514 
1515     return (OK);
1516 }
1517 
GetKey(char * c,Object * in)1518 static int GetKey  (char *c, Object *in)
1519 {
1520 #ifdef DXD_LICENSED_VERSION
1521 
1522     int i;
1523 
1524     srand(time(NULL));
1525     i = rand();
1526     i = (i<4096) ? (i+4096) : (i); /* forces to be 4 0x chars */
1527 
1528     sprintf(_dxd_LicenseKey, "%x\n", i);
1529     DXUIMessage("LICENSE", _dxd_LicenseKey);
1530 
1531 #else  /* DXD_LICENSED_VERSION */
1532 
1533     DXUIMessage("LICENSE","ffff");	/* write key ffff in case UI tries */
1534                                         /* to use license protocol  */
1535 #endif /* !DXD_LICENSED_VERSION */
1536 
1537     return (OK);
1538 }
1539 
1540 
1541 
Version(char * c,Object * in)1542 static int Version (char *c, Object *in)
1543 {
1544     int		n;
1545     int		m0, m1, m2;
1546     char	buf[256];
1547     int		err = TRUE;
1548     char	*b;
1549 
1550     if (c == NULL || *c == '\000')
1551     {
1552 	DXBeginLongMessage ();
1553         DXMessage ("Executive version:        %d %d %d\n",
1554 	            DXD_VERSION, DXD_RELEASE, DXD_MODIFICATION);
1555         DXMessage ("Executive/UI interface:   %d %d %d\n",
1556 	            UI_MAJOR, UI_MINOR, UI_MICRO);
1557         DXMessage ("Creation date:            %s\n", EX_COM_DATE);
1558         DXMessage ("Creation host:            %s\n", EX_COM_HOST);
1559 	DXEndLongMessage ();
1560 	return (OK);
1561     }
1562 
1563 #if DXD_PRINTF_RETURNS_COUNT
1564     n = sprintf (buf,
1565 		 "Executive/UI version mismatch:  %d %d %d vs ",
1566 		 UI_MAJOR, UI_MINOR, UI_MICRO);
1567 #else
1568     {
1569         sprintf (buf,
1570 		 "Executive/UI version mismatch:  %d %d %d vs ",
1571 		 UI_MAJOR, UI_MINOR, UI_MICRO);
1572         n = strlen(buf);
1573     }
1574 #endif
1575     b = buf + n;
1576 
1577     n = sscanf (c, "%d%d%d", &m0, &m1, &m2);
1578 
1579     if (n == 3 && m0 == UI_MAJOR && m1 == UI_MINOR && m2 == UI_MICRO)
1580 	err = FALSE;
1581     else
1582 	sprintf (b, "%s", *c ? c : "<no version specified>");
1583 
1584     if (err)
1585 	DXUIMessage ("ERROR", buf);
1586 
1587     return (OK);
1588 }
1589 
1590 
ProductVersion(char * c,Object * in)1591 static int ProductVersion (char *c, Object *in)
1592 {
1593     int		n;
1594     int		m0, m1, m2;
1595 
1596     if (c == NULL || *c == '\000') {
1597 	DXSetError(ERROR_BAD_PARAMETER,
1598 		   "Product Version string required for version check");
1599 	return ERROR;
1600     }
1601 
1602     n = sscanf (c, "%d%d%d", &m0, &m1, &m2);
1603 #define VERSION_ID(a,b,c)	(((a) << 16) + ((b) << 8) + (c))
1604 
1605     if (n != 3 ||
1606 	(VERSION_ID(m0,m1,m2) >
1607 	 VERSION_ID(DXD_VERSION,DXD_RELEASE,DXD_MODIFICATION))) {
1608 	DXWarning("User Interface or .net file version is newer than Executive version");
1609     }
1610 
1611     return (OK);
1612 }
1613 
1614 /* No longer used so make it undefined */
1615 #if 0
1616 static Error UnLoadObjFile(char *c, Object *in)
1617 {
1618     char *str;
1619 
1620     if (!in[0] || ! DXExtractString (in[0], &str)) {
1621         DXSetError (ERROR_BAD_PARAMETER, "#10200", "object filename");
1622         return (ERROR);
1623     }
1624 
1625     return DXUnloadObjFile(str);
1626 }
1627 #endif
1628