[comp.sources.amiga] defdisk.c - Sets the default system disk in one command.

ahh@j.cc.purdue.edu (Brent L. Woods) (11/15/87)

#! /bin/sh
# This is a shell archive, meaning:
# 1.  Remove everything above the #! /bin/sh line.
# 2.  Save the resulting text in a file
# 3.  Execute the file with /bin/sh (not csh) to create the files:
#
#		defdisk.c
#
#
if test -f 'defdisk.c'
then
	echo shar: will not over-write existing file "'defdisk.c'"
else
	echo extracting "'defdisk.c'"
	sed 's/^X//' >defdisk.c <<'SHAR_EOF'
X/*
X * DEFDISK.C
X *
X * A program to make a specified disk/directory the default system disk.
X * It accomplishes this by resetting the DOS library structures to point
X * to the new path. To use this program you will need to compile it as
X * follows:
X *		1> cc defdisk
X *		1> ln defdisk.o -lc
X *
X * Real simple.  I used AZTEC C v3.40a, but I think that 3.30c or later would
X * also work.  It should be possible to compile & build it under LATTICE as
X * well, though I haven't tried.  Once the program is built, put it on your
X * Workbench boot disk somewhere, load up your ram: disk or hard disk and
X *
X *		1> defdisk dh0:
X *		      or
X *		1> defdisk dh0:bin
X *
X * Woila! the standard workbench assignments are now pointed at the hard
X * disk. (SYS, C, L, DEVS, LIBS, FONTS)  The advantage to me in using this
X * is that I don't have to load the Amiga DOS assign program 6 times to
X * point the system at the hard disk.
X *
X * Author: J. K. Levie
X *
X * Version 1.0 31-Mar-1987
X */
X
X#include <stdio.h>
X#include <functions.h>
X#include <exec/types.h>
X#include <exec/exec.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X
Xextern void BtoCSTR();			/* forward ... */
Xextern void CtoBSTR();			/* ... references */
X
Xstruct DevInfo
X{
X   BPTR di_Next;
X   LONG di_Type;
X   APTR di_Task;
X   BPTR di_Lock;
X   BSTR di_Handler;
X   LONG di_StackSize;
X   LONG di_Priority;
X   LONG di_Startup;
X   BPTR di_SegList;
X   BPTR di_GlobVec;
X   BSTR di_Name;
X};
Xstruct DosLibrary *dosBase;
Xstruct RootNode *root;
Xstruct DosInfo *info;
Xstruct DevInfo *dev_head, *dev_ele;
Xstruct Lock *lock;
X
X/*
X * Define the logical to physical table.
X */
Xstruct ASSIGNS
X{
X   char *log_name;			/* logical name to look for */
X   char *phy_name;			/* physical name to assign */
X   short success;			/* result 0=> failure, 1=> success */
X};
Xstruct ASSIGNS assigns[]=
X{
X   "SYS",   NULL,    0,
X   "C",     "c",     0,
X   "DEVS",  "devs",  0,
X   "LIBS",  "libs",  0,
X   "L",     "l",     0,
X   "S",     "s",     0,
X   "FONTS", "fonts", 0,
X   NULL,    NULL
X};
X
X
X
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X   char *ptr, *path;
X   register int len, n;
X
X   /*
X    * See if we can get a lock on the new C directory, if we can't
X    * we won't even attempt to do the assigns.
X    */
X   path=argv[1];
X   if(argc!=2 || *path=='?')		/* correct arg cnt?  useage? */
X   {
X      printf("Usage: defdisk dev:[dir.../dir]\n");
X      exit(20);
X   }
X   /*
X    * Now we are ready to fill in the logical name table.  Handle the 
X    * Sys logical first since it will not have anything appended.  Then
X    * see if we will need to append a path separator to the user
X    * specified path.  We stop appending when we see the "T" logical.
X    */
X   assigns[0].phy_name=path;		/* Sys is special case */
X   len=1+strlen(path);			/* find length of physical name */
X   if(path[strlen(path)-1]!=':')	/* path specify the root of volume? */
X   {
X      len++;				/* room for path separator */
X      ptr=AllocMem((long)(len+1), MEMF_PUBLIC);
X      strcpy(ptr, path);		/* put user specified path in ... */
X      strcat(ptr, "/");			/* ... and path separator */
X      path=ptr;				/* point to new path */
X   }
X   /*
X    * Now fill in the rest of the table.  Allocate memory for the
X    * complete physical name and the directory specified in the table
X    * entry.  Then concatenate the path and the directory and set up
X    * the new pointer.
X    */
X   for(n=1; assigns[n].log_name[0]!=NULL; n++)
X   {
X      ptr=AllocMem((long)(len+strlen(assigns[n].log_name)), MEMF_PUBLIC);
X      strcpy(ptr, path);
X      strcat(ptr, assigns[n].phy_name);
X      assigns[n].phy_name=ptr;
X   }
X   /*
X    * Convert the logical names to B strings.
X    */
X   for(n=0; assigns[n].log_name!=NULL; n++) CtoBSTR(assigns[n].log_name);
X
X   /*
X    * Now for a little paranoia.  I don't want to point the system
X    * somewhere that doesn't contain a C directory.
X    */
X   lock=Lock(assigns[1].phy_name, SHARED_LOCK);
X   if(lock==NULL)			/* are we sane? */
X   {
X      /*
X       * NO!  Makes no sense to set the system volume to something that
X       * doesn't contain a c directory.
X       */
X      printf("defdisk-F-%s does not contain a C directory\n",
X              assigns[1].phy_name);
X      exit(20);
X   }
X   UnLock(lock);			/* Okay unlock the c directory */
X
X   /*
X    * Now open the resources we will need.
X    */
X   dosBase=(struct DosLibrary *)OpenLibrary(DOSNAME);
X   root=(struct RootNode *)dosBase->dl_Root;
X   info=(struct DosInfo *)BADDR(root->rn_Info);
X   dev_head=(struct DevInfo *)BADDR(info->di_DevInfo);
X
X   Forbid();				/* only us & nobody else */
X   /*
X    * Walk the DevInfo list looking for the locigal names to change.  For
X    * each entry in the list we can check each of the entries in the
X    * logical name table.  As we find them reset each logical to point
X    * to the new system volume.
X    */
X   for(dev_ele=dev_head; dev_ele->di_Next;
X       dev_ele=(struct DevInfo *)BADDR(dev_ele->di_Next))
X   {
X      /*
X       * Check against each of the logical names in the table.
X       */
X      for(n=0; assigns[n].log_name!=NULL; n++)
X      {
X         /*
X          * See if this one matches.
X          */
X         if(Bstrcmp(BADDR(dev_ele->di_Name), assigns[n].log_name))
X         {
X            /*
X             * Name matches, is it the correct type?
X             */
X            if(dev_ele->di_Type!=DLT_DIRECTORY)
X            {
X               /*
X                * No put logical name back to a C string and error out.
X                */
X               BtoCSTR(assigns[n].log_name);
X               printf("defdisk-F-cannot reassign %s\n", assigns[n].log_name);
X               goto done;
X            }
X            /*
X             * Okay get a lock on the physical name for this logical.
X             */
X            lock=Lock(assigns[n].phy_name, SHARED_LOCK);
X            if(!lock)
X            {
X               /*
X                * Whoops, failed somehow, tell the world about it.
X                */
X               printf("defdisk-F-cannot get a lock on %s\n", assigns[n].phy_name);
X               goto done;
X            }
X            /*
X             * Time to clean up the old logical and point it to our
X             * physical name.
X             */
X            UnLock(dev_ele->di_Lock);
X            dev_ele->di_Lock=(BPTR)lock;
X            dev_ele->di_Task=(APTR)(DeviceProc(assigns[n].phy_name));
X            assigns[n].success=1;	/* flag that we did this one */
X         }
X      }
X   }
Xdone:
X   Permit();				/* release the system */
X   CloseLibrary(dosBase);		/* clean up */
X   
X   /*
X    * Now check to see that all of the assignments were made.
X    */
X   for(n=0; assigns[n].log_name!=NULL; n++)
X   {
X      if(assigns[n].success!=1) printf("defdisk-F-assignments failed\n");
X   }
X}
X
X
X
X/*
X * Bstrcmp(a, b)
X *
X * Compare two btrings for equality, case insensitive.
X */
XBstrcmp(a, b)
Xchar *a, *b;
X{
X   int len=(int)*a;			/* first char of B string is length */
X
X   for(len++; len!=0; len--)		/* compare at most all */
X   {
X      if((*a&~0x20)!=(*b&~0x20)) return(0); /* quit if not equal */
X      a++;				/* point both ... */
X      b++;				/* ... at next character */
X   }
X   return(1);				/* they matched */
X}
X
X
X
X/*
X * BtoCSTR(bstr)
X *
X * Convert (in place) a B string to a C string.
X */
Xvoid BtoCSTR(bstr)
Xchar *bstr;
X{
X   register int i;
X   register UBYTE *bptr, *cptr;
X
X   cptr=(UBYTE *)bstr;			/* point to input B string */
X   bptr=cptr;				/* output starts at B string len spot */
X   for(i=*bptr++; i!=0; i--) *cptr++=*bptr++; /* left shift the string */
X   *cptr='\0';				/* terminate it */
X}
X
X
X
X/*
X * CtoBSTR(cstr)
X *
X * Convert (in place) a C string to a B string.
X */
Xvoid CtoBSTR(cstr)
Xchar *cstr;
X{
X   register int i, len;
X   register UBYTE *cptr, *bptr;
X
X   cptr=(UBYTE *)cstr;			/* pointer to input */
X   for(i=0; *cptr; i++, cptr++);	/* count & push pointer to input */
X   len=i;				/* save count */
X   bptr=cptr;				/* point at end of input */
X   cptr--;				/* back up over null */
X   while(i--) *bptr--=*cptr--;		/* right the string */
X   *bptr=(UBYTE)len;			/* stuff in the string length */
X}
X
SHAR_EOF
	if test 8046 -ne "`wc -c < 'defdisk.c'`"
then
		echo shar: error transmitting "'defdisk.c'" '(should have been 8046 characters)'
	fi
fi
#
# end of shell archive
#
exit 0

=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
 Jim Levie   REMTECH Inc  Huntsville, Al 
 The opinions expressed above are just that.
 Ph.    (205) 536-8581               email: uunet!ingr!b11!jim