home *** CD-ROM | disk | FTP | other *** search
- /* ====================================================================== */
-
- /* BindNames.c by Dave Haynie
-
- This is a simple utility to remove some of the drudgery of program
- installation. Instead of having to edit a Startup-Sequence for
- every logical name that must be used by a new program, this lets
- names be block-allocated. The BindNames program looks for files
- in the SYS:Names directory. Each of these files contains any number
- of lines of the form:
-
- Name: Path
-
- Where "Name" is the logical name we're assigning, "Path" is the
- path name we're making equivalent.
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <proto/all.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
-
- /* ====================================================================== */
-
- /* Macros */
-
- #define CADDR(x) ((BPTR)(((ULONG)x)>>2))
- #define NAMEDIR "SYS:Names"
- #define CopyStr(s) strcpy(malloc(strlen(s)+1),s)
- #define FreeStr(s) free(s)
-
- /* The "-rr" option doesn't like NewList, bit it's real simple. WHEN can
- we have inline functions.... */
-
- #define NewList(l) { (l)->lh_Head = (struct Node *)&(l)->lh_Tail; \
- (l)->lh_TailPred = (struct Node *)&(l)->lh_Head; \
- (l)->lh_Tail = NULL; \
- }
-
- /* ====================================================================== */
-
- /* Global variables */
-
- extern struct DosLibrary *DosBase = NULL;
- struct DosInfo *info = NULL;
- struct DeviceList *lastdev;
- BPTR namelock = NULL;
- BOOL verbose = FALSE;
- BOOL test = FALSE;
- struct FileInfoBlock *fileinfo = NULL;
-
- /* ====================================================================== */
-
- /* This function makes a BCPL string into a C style string. */
-
- char *b2cstr(char *cstr, BPTR bptr) {
- char *ptr = (char *)BADDR(bptr);
- strncpy(cstr,ptr+1,*ptr);
- cstr[*ptr] = '\0';
- return cstr;
- }
-
- /* This function allocates things in a DOS friendly way. */
-
- void *DOSAlloc(LONG size) {
- LONG *ptr = AllocMem(size+4,MEMF_PUBLIC|MEMF_CLEAR);
- *ptr = size+4;
- return ptr+1;
- }
-
- /* This function frees memory in a DOS friendly way. */
-
- void DOSFree(void *mem) {
- LONG *ptr = (LONG *)mem;
- FreeMem(ptr-1,*(ptr-1));
- }
-
- /* ====================================================================== */
-
- /* Here we manage name trees. Name nodes are built from the device list
- first. All primary nodes based on the device list have NULL paths,
- indicating that they are primary and thus, don't need to be recreated.
- Subsequent nodes are added to the node that they depend on. If a node
- is encountered that doesn't have a parent listed yet, it will be place
- on a temporary node list. */
-
- struct NameNode {
- struct Node node;
- struct NameNode *parent;
- struct List children;
- char *path;
- };
-
- struct List Names;
- struct NameNode *lostnodes;
-
- /* This function creates a name node, allocating whatever memory is
- needed. */
-
- struct NameNode *MakeNode(char *name, char *path) {
- struct NameNode *nn;
-
- if (!(nn = calloc(1,sizeof(struct NameNode)))) return NULL;
- if (name) nn->node.ln_Name = CopyStr(name);
- NewList(&nn->children);
- if (path) nn->path = CopyStr(path);
- return nn;
- }
-
- /* This function finds a particular name in the Names data base, via a
- depth-first search. If it finds the name, it returns that node,
- otherwise, it returns NULL. */
-
- struct NameNode *FindNode(struct List *lst,char *name) {
- struct Node *n;
- struct NameNode *nn;
-
- for (n = lst->lh_Head; n->ln_Succ; n = n->ln_Succ) {
- if (!(stricmp(name,n->ln_Name))) return (struct NameNode *)n;
- if (nn = FindNode(&((struct NameNode *)n)->children,name)) return nn;
- }
- return NULL;
- }
-
- /* This is the node assignment routine. It accepts a node name and a path
- for assignment. It handles all the proper node creations to add that
- information to the node data base. */
-
- void DefNode(char *name, char *path) {
- struct NameNode *nn, *parent;
- char pardev[64];
- int i;
-
- for (i = 0; path[i] != ':' && i < 63; ++i) pardev[i] = path[i];
- pardev[i] = '\0';
- if (!(parent = FindNode(&Names,pardev))) {
- AddHead(&lostnodes->children,(struct Node *)(parent=MakeNode(pardev,NULL)));
- parent->parent = lostnodes;
- }
-
- if (!(nn = FindNode(&Names,name)))
- nn = MakeNode(name,path);
- else {
- Remove((struct Node *)nn);
- if (nn->path) FreeStr(nn->path);
- nn->path = CopyStr(path);
- }
-
- AddHead(&parent->children,(struct Node *)nn);
- }
-
- /* This function reads in the individual file's data and builds entries
- in the name list based on that data. */
-
- void AddFIB(struct FileInfoBlock *fib,char *name) {
- BPTR file;
- char *buf,*com,*path;
-
- if (buf = AllocMem(fib->fib_Size+1,0L)) {
- if (file = Open(name,MODE_OLDFILE)) {
- Read(file,buf,fib->fib_Size);
- buf[fib->fib_Size] = '\0';
- com = strtok(strupr(buf)," :\t\n");
- path = strtok(NULL," \t\n");
- while (com && path) {
- DefNode(com,path);
- com = strtok(NULL," :\t\n");
- path = strtok(NULL," \t\n");
- }
- Close(file);
- }
- FreeMem(buf,fib->fib_Size+1);
- }
- }
-
- /* ====================================================================== */
-
- /* This function opens up the stuff we need. */
-
- BOOL DoInits(void) {
- if (!(DosBase = (struct DosLibrary *)OpenLibrary("dos.library",33L)))
- return FALSE;
- if (!(info = (struct DosInfo *)BADDR(((struct RootNode *)DosBase->dl_Root)->rn_Info)))
- return FALSE;
- if (!(fileinfo = AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC)))
- return FALSE;
-
- return TRUE;
- }
-
- /* This function cleans up after DoInits. */
-
- void CloseUp(int code, char *str) {
- if (str) printf("Error: %s\n",str);
- if (fileinfo) FreeMem(fileinfo,sizeof(struct FileInfoBlock));
- if (namelock) UnLock(namelock);
- if (DosBase) CloseLibrary((struct Library *)DosBase);
- exit(code);
- }
-
- /* ====================================================================== */
-
- /* This function finds a directory node. It has the side effect of
- setting "lastdev" to the last device in the global device list. */
-
- struct DeviceList *AllocDirNode(char *name) {
- struct DeviceList *dev, *newdev;
- char *str,old[64];
-
- /* Let's see if the assignment has already been made... */
- for (dev = (struct DeviceList *)BADDR(info->di_DevInfo); dev != NULL;
- dev = (struct DeviceList *)BADDR(dev->dl_Next)) {
- lastdev = dev;
- if (dev->dl_Type != DLT_DIRECTORY) continue;
- b2cstr(old,dev->dl_Name);
- if (!stricmp(old,name)) return dev;
- }
-
- /* Create the new name structure */
- if (!(newdev=DOSAlloc(sizeof(struct DeviceList))) || !(str=DOSAlloc(32L))) {
- if (newdev) DOSFree(newdev);
- return NULL;
- }
- newdev->dl_Type = DLT_DIRECTORY;
- strcpy(str+1,name);
- str[0] = strlen(name);
- newdev->dl_Name = CADDR(str);
- return newdev;
- }
-
- /* This function does the "Assign" operation. */
-
- BOOL Assign(char *name, char *path) {
- BPTR block;
- struct DeviceList *newdev;
-
- /* Let's verify that the path object is really there. If not, try to make
- the thing. */
- if (!(block = Lock(path,SHARED_LOCK))) {
- if (!(block = CreateDir(path))) return FALSE;
- UnLock(block);
- if (!(block = Lock(path,SHARED_LOCK))) return FALSE;
- }
-
- /* Get a node for this assignment. */
- Forbid();
- newdev = AllocDirNode(name);
-
- /* Make the assignment */
- if (newdev->dl_Lock) {
- Permit();
- UnLock(newdev->dl_Lock);
- newdev->dl_Lock = block;
- newdev->dl_Task = ((struct FileLock *)BADDR(block))->fl_Task;
- return TRUE;
- }
- newdev->dl_Lock = block;
- newdev->dl_Task = ((struct FileLock *)BADDR(block))->fl_Task;
-
- /* Now link it into the device list. */
- newdev->dl_Next = lastdev->dl_Next;
- lastdev->dl_Next = CADDR(newdev);
- Permit();
- return TRUE;
- }
-
- /* This list takes in a node list, and performs assignments for all non-primary
- nodes in the list, as long as "inhibit" is FALSE. */
-
- void AssignList(struct List *lst, int level, BOOL inhibit) {
- struct Node *n;
- struct NameNode *nn;
-
- for (n = lst->lh_Head; n->ln_Succ; n = n->ln_Succ) {
- nn = (struct NameNode *)n;
- if (nn->path) {
- if (!inhibit) Assign(nn->node.ln_Name,nn->path);
- if (verbose || inhibit)
- printf("%*s%-15s%*s%s\2330m\n",level+1,"\23333m",nn->node.ln_Name,
- 14-level,"\23332m",nn->path);
- }
- if (nn->children.lh_Head->ln_Succ)
- AssignList(&nn->children,level+2,inhibit);
- }
- }
-
- /* ====================================================================== */
-
- void main(int argc, char *argv[]) {
- char path[256];
- long i;
- struct NameNode *nn;
- struct DeviceList *dev;
-
- if (!DoInits()) CloseUp(5,NULL);
-
- /* Check the command line. */
- for (i = 1; i < argc; ++i)
- switch (toupper(argv[i][0])) {
- case 'S':
- Assign("SYS",argv[++i]);
- break;
- case 'V':
- verbose = TRUE;
- break;
- case 'T':
- test = TRUE;
- verbose = TRUE;
- break;
- case '?':
- printf("\2337mBindNames V1.0 by Dave Haynie\2330m\n\n");
- printf("Usage: %s [VERBOSE] [TEST] [SYSTEM drive]\n",argv[0]);
- CloseUp(0,NULL);
- }
- if (verbose) printf("\2337mBindNames V1.0 by Dave Haynie\2330m\n\n");
-
- /* Let's build the internal device list. We know this list is going to be
- a flat list; everything is primary, and thus hung from the root list. */
- NewList(&Names);
- Forbid();
- for (dev = (struct DeviceList *)BADDR(info->di_DevInfo); dev != NULL;
- dev = (struct DeviceList *)BADDR(dev->dl_Next)) {
- if (!(nn = MakeNode(strupr(b2cstr(path,dev->dl_Name)),NULL))) continue;
- AddHead(&Names,(struct Node *)nn);
- }
- Permit();
-
- /* I need to build the "lostnodes" node. In order to avoid name collisions,
- I make the name of this node '\0'. We never need to search for it by
- name... */
-
- AddTail(&Names,(struct Node *)(lostnodes = MakeNode("\0",NULL)));
-
- /* Here I build the list of required assignments by walking through the
- SYS:Names directory, and reading each file. */
-
- if ((namelock = Lock(NAMEDIR,SHARED_LOCK))) {
- Examine(namelock,fileinfo);
- while (ExNext(namelock,fileinfo) || IoErr() != ERROR_NO_MORE_ENTRIES) {
- if (fileinfo->fib_DirEntryType > 0) continue;
- strcat(strcat(strcpy(path,NAMEDIR),"/"),fileinfo->fib_FileName);
- AddFIB(fileinfo,path);
- }
- }
-
- /* Now I've got everything; let's see what's actually here. */
-
- Remove((struct Node *)lostnodes);
-
- if (verbose) printf("Assigned Names:\n");
- AssignList(&Names,1,test);
- if (lostnodes->children.lh_Head->ln_Succ) {
- if (verbose) printf("\n");
- printf("Warning: Can't Resolve Names:\n");
- AssignList(&lostnodes->children,1,TRUE);
- }
- CloseUp(0,NULL);
- }
-