/*--------------------------------------------------------------------------- initializer.c initializer routines Markus Zolliker, March 2005 ---------------------------------------------------------------------------- */ #include "sics.h" #include "initializer.h" #include "splitter.h" typedef struct Item { struct Item *next; char *type; /* "Object" for all commands created by makeobject, else something more general */ char *name; /* the name for identifying an initializer */ char *desc; /* a description of the initializer. not the same as pObjectDescriptor->name */ Initializer maker; int startupOnly; } Item; static Item *list = NULL; static int startup = 1; void MakeInitializer(const char *type, const char *name, Initializer maker, int startupOnly, const char *desc) { Item *item; item = calloc(1, sizeof *item); assert(item); item->maker = maker; item->next = list; item->type = strdup(type); item->name = strdup(name); item->desc = strdup(desc); item->startupOnly = startupOnly; list = item; } Initializer GetInitializer(const char *type, const char *name) { Item *p, **last; if (startup && !ServerIsStarting(pServ)) { /* pServ->pReader exists: startup finished */ startup = 0; /* remove startup initializers */ p = list; last = &list; while (p != NULL) { if (p->startupOnly) { *last = p->next; free(p); p = *last; } else { last = &p->next; p = p->next; } } } for (p = list; p != NULL; p = p->next) { if (strcasecmp(p->name, name) == 0 && strcasecmp(p->type, type) == 0) { return p->maker; } } return NULL; } static int MakeObject(SConnection * con, SicsInterp * sics, void *data, int argc, char *argv[]) { CmdInitializer cmdin; if (argc < 3) { SCPrintf(con, eError, "ERROR: should be: %s ...", argv[0]); return 0; } /* missing check for user (manager?) privilege */ cmdin = (CmdInitializer) GetInitializer("Object", argv[2]); if (cmdin) { return cmdin(con, argc, argv, strcasecmp(argv[0], "makeobject") == 0); } else { SCPrintf(con, eError, "do not know how to make a %s object", argv[2]); return 0; } } static int DriverList(SConnection * con, SicsInterp * sics, void *data, int argc, char *argv[]) { Item *p; char *name, *type; if (argc < 2 || strcasecmp(argv[1], "list") == 0) { for (p = list; p != NULL; p = p->next) { if (argc < 3) { SCPrintf(con, eValue, "%s %s %s", p->type, p->name, p->desc); } else if (strcasecmp(argv[2], p->type) == 0) { SCPrintf(con, eValue, "%s %s", p->name, p->desc); } } } else { if (argc == 2) { name = argv[1]; type = "Object"; } else { name = argv[2]; type = argv[1]; } p = list; while (p != NULL && (strcasecmp(p->type, type) != 0 || strcasecmp(p->name, name) != 0)) { p = p->next; } if (p) { SCPrintf(con, eValue, "%s", p->desc); } else { SCPrintf(con, eValue, "notfound"); } } return 1; } static int RemoveObject(SConnection * con, SicsInterp * sics, void *data, int argc, char *argv[]) { CmdInitializer cmdin; ObjectDescriptor *desc; char *className; char shortClassName[32]; char *p; int removeAllowed; char *creationCommand; if (argc != 2) { SCPrintf(con, eError, "ERROR: should be: %s ", argv[0]); return 0; } /* missing check for user (manager?) privilege */ desc = FindCommandDescriptor(sics, argv[1]); if (!desc) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); return 0; } creationCommand = GetDescriptorKey(desc, "creationCommand"); if (creationCommand != NULL) { /* if there is a creationCommand, we are allowed to remove */ removeAllowed = 1; } else { /* if we have an initializer: we are also allowed to remove */ className = desc->name; cmdin = (CmdInitializer) GetInitializer("Object", className); if (cmdin == 0) { /* allow also a longer descriptor starting with the initializer name and a blank */ p = strchr(className, ' '); if (p) { snprintf(shortClassName, sizeof shortClassName, "%.*s", (int)(p - className), className); cmdin = (CmdInitializer) GetInitializer("Object", shortClassName); } } removeAllowed = (cmdin != NULL); } if (removeAllowed) { if (pServ->pExecutor && isInRunMode(pServ->pExecutor)) { SCPrintf(con, eError, "ERROR: cannot remove %s while running", argv[1]); return 0; } SCPrintf(con, eValue, "remove %s", argv[1]); SCparChange(con); return RemoveCommand(sics, argv[1]); } else { SCPrintf(con, eError, "ERROR: %s is not removable", argv[1]); return 0; } } typedef struct { int printHeader; FILE *fil; } SaveData; static int SaveCreationCommand(char *name, pDummy object, void *userData) { SaveData *saveData = userData; char *creationCommand; creationCommand = GetDescriptorKey(object->pDescriptor, "creationCommand"); if (creationCommand && strcmp(creationCommand, "0") != 0) { if (saveData->printHeader == 0) { saveData->printHeader = 1; fprintf(saveData->fil, "\n#--- BEGIN creation commands\n"); } fprintf(saveData->fil, "%s\n", creationCommand); } return 1; } static int SaveCreationCommands(void *object, char *name, FILE * fil) { SaveData saveData; saveData.fil = fil; saveData.printHeader = 0; ForEachCommand(SaveCreationCommand, &saveData); if (saveData.printHeader == 1) { fprintf(fil, "#--- END creation commands\n\n"); } return 1; } static int CreationCommand(SConnection * con, SicsInterp * sics, void *data, int argc, char *argv[]) { CmdInitializer cmdin; char *className; char shortClassName[32]; char *p; int removeAllowed; ObjectDescriptor *desc; char *creationCommand; char buf[256]; if (argc < 2) { SCPrintf(con, eError, "ERROR: should be: %s []", argv[0]); return 0; } desc = FindCommandDescriptor(sics, argv[1]); if (!desc) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); return 0; } creationCommand = GetDescriptorKey(desc, "creationCommand"); if (argc < 3) { if (creationCommand != NULL) { SCPrintf(con, eValue, "%s", creationCommand); } else { SCPrintf(con, eValue, ""); } } else { if (!creationCommand) { SCPrintf(con, eValue, "ERROR: %s is a static object", argv[1]); return 0; } creationCommand = Arg2Tcl(argc - 2, argv + 2, buf, sizeof buf); if (creationCommand) { SetDescriptorKey(desc, "creationCommand", creationCommand); if (creationCommand != buf) free(creationCommand); } else { SetDescriptorKey(desc, "creationCommand", "0"); } } return 1; } static void KillInitializers(void *data) { KillDummy(data); Item *item, *next; item = list; while (item) { next = item->next; if (item->name) free(item->name); if (item->type) free(item->type); if (item->desc) free(item->desc); free(item); item = next; } list = NULL; } void MakeDriver(const char *driver, CmdInitializer maker, int startupOnly, const char *desc) { MakeInitializer("Object", driver, (Initializer) maker, startupOnly, desc); } void InitializerInit(void) { pDummy cc = NULL; AddCommandWithFlag(pServ->pSics, "MakeObject", MakeObject, KillInitializers, NULL, 0); AddCommandWithFlag(pServ->pSics, "MakeStaticObject", MakeObject, NULL, NULL, 0); AddCommandWithFlag(pServ->pSics, "RemoveObject", RemoveObject, NULL, NULL, 0); AddCommandWithFlag(pServ->pSics, "DriverList", DriverList, NULL, NULL, 0); cc = CreateDummy("creation commands"); cc->pDescriptor->SaveStatus = SaveCreationCommands; AddCommandWithFlag(pServ->pSics, "CreationCommand", CreationCommand, KillDummy, cc, 0); }