home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / system_utils / general / movesys / movesys.c < prev    next >
C/C++ Source or Header  |  1991-01-10  |  11KB  |  385 lines

  1. /* This program will reassign all the standard assigned names to be the proper
  2.    usual directories on a new disk.  The names are:
  3.  
  4.     C:  DEVS:  FONTS:  L:  LIBS:  S:  and SYS:
  5.  
  6.    This program will assign SYS: to the given volume and each of the other
  7.    names to the directory of SYS: with that same name (C: = SYS:c etc).
  8.    
  9.    It's called MoveSys.  Hard disk users can put it in their Startup-Sequence
  10.    to ease the transition from the floppy boot disk (or RAD:) to the hard
  11.    disk.  Non-hard-disk users can use it to switch from one bootable
  12.    application disk to another without getting "please insert volume
  13.    Workbench1.3" or the like all the time.  For Aztec C.  If you want
  14.    flexibility, customize the source code.  Usage:
  15.  
  16.     MoveSys name:    ; where name is a volume name or drive name
  17.  
  18.    You can even MoveSys to a directory, if the appropriate subdirectories
  19.    are present there.  Like, MoveSys dh0:Workbench or something.  I
  20.    personally do this; it keeps my HD's root directory uncluttered.
  21.  
  22.    By Paul Kienitz, 12/10/88.  Public domain.  For Aztec C only; do not
  23.    compile with the +m flag.  The result is "pure" and can be made resident.
  24.    
  25.    1/17/89:  Ooops!  Had to add DosAllocate, because unassigning a node I
  26.    created without that could cause bad craziness.  I should put DosAllocate
  27.    into AssignDev, though it's probably not needed if I fix the bug in
  28.    detecting whether a node it's deleting is one it made, which I think
  29.    somebody already did.
  30.  
  31.    4/14/89:  Stripped down internally (no stdio, for instance) to reduce size
  32.    and make "pure".  Added IoErr code return.
  33.  
  34.    5/4/90:  Added option to make it CD to the new SYS: if the argument line
  35.    begins with the word "cd" before the pathname.  Example: movesys cd dh0:
  36.  
  37.    8/28/90:  Made a version usable from Workbench; assigns to a disk or
  38.    drawer given as a Workbench arg.  The #define flag BENCH activates this
  39.    feature.  Also made it make no change if the new SYS: has none of the
  40.    correct subdirectories.  (One out of six is enough for success.)  Added
  41.    fancier internal help message to cli version.  Made it set the cli setname
  42.    to a copy of the argument name you use CD.
  43.  
  44.    11/21/90:  Adapted for Aztec C 5.0; size reduced by 2.5% -- enough to save
  45.    one disk block under the Fast File System
  46.  
  47.    ADD LATER?  arguments after volume name to be exceptions or additions to
  48.      the built-in list of assignments?
  49.  
  50.  */
  51.  
  52.  
  53.  
  54. #include <exec/exec.h>
  55. #include <libraries/dosextens.h>
  56. #include <libraries/filehandler.h>
  57. #include <Paul.h>    /* defines null, adr, str, bool, bip, gbip, AllocXX ... */
  58.  
  59. #ifdef BENCH
  60.  
  61. #include <workbench/startup.h>
  62. #include <workbench/workbench.h>
  63.  
  64. #endif
  65.  
  66.  
  67. typedef struct DeviceNode den;
  68. typedef BPTR lock;
  69.  
  70. #define HowMany 6
  71. char *dames[HowMany] = {"C", "DEVS", "FONTS", "L", "LIBS", "S"};
  72. char *dears[HowMany] = {"SYS:c", "SYS:devs", "SYS:fonts", "SYS:l",
  73.             "SYS:libs", "SYS:s"};
  74. /* SYS: gets assigned to the volume named in the command line argument (or
  75.    workbench message argument someday), and then each name in dames gets
  76.    assigned to the corresponding directory name in dears.  You can change
  77.    dears to e.g. assign C: to RAM:C or whatever, or add more names to each,
  78.    incrementing HowMany to match. */
  79.  
  80.  
  81. /* the only global variables are unchanging, e.g. library bases */
  82.  
  83. extern struct DosLibrary *DOSBase;
  84. void *IntuitionBase, *IconBase;
  85. struct DosInfo *infoo;      /* contains the root of the dev list */
  86.  
  87.  
  88. typedef struct global {
  89.     BPTR out;
  90.     bool cd, slasher;
  91. #ifdef BENCH
  92.     bool conopen, confail, bench;
  93.     struct WBStartup *wbs;
  94. #endif
  95. } *glob;
  96.  
  97.  
  98.  
  99. #ifdef put
  100. #undef put
  101. #endif        /* shouldn't be needed but sometimes is */
  102.  
  103. void put(s, g) str s; glob g;
  104. {
  105. #ifdef BENCH
  106.     if (g->bench && !g->out && !g->confail) {
  107.     g->out = ThisProcess()->pr_COS
  108.             = NOpen("RAW:30/20/590/105/MoveSys error ");
  109.     if (g->out) {
  110.         g->conopen = true;
  111.         Write(g->out, "\007\007", 2L);        /* DisplayBeep twice */
  112.     } else g->confail = true;
  113.     }
  114. #endif
  115.     if (g->out) Write(g->out, s, (long) strlen(s));
  116. }
  117.  
  118.  
  119.  
  120. /* Allocate a block of memory the way the Dos does, with size (rounded up to
  121.    the nearest multiple of four) in the longword below the address returned */
  122.  
  123. adr DosAllocate(size) int size;
  124. {
  125.     long longlen = (size + 7) & ~3L;
  126.     long *dosalloc = AllocPZ(longlen);
  127.     if (!dosalloc) return null;
  128.     *dosalloc = longlen;
  129.     return dosalloc + 1;
  130. }
  131.  
  132.  
  133.  
  134. void DosFree(a) long *a;
  135. {
  136.     FreeMem(a - 1, a[-1]);
  137. }
  138.  
  139.  
  140.  
  141. den *MakeNewAssignNode(name) str name;   /* do this within a Forbid */
  142. {   
  143.     den *foo = DosAllocate(sizeof(den));
  144.     int len = strlen(name);
  145.     str nom;
  146.     if (!foo) return null;
  147.     if (!(nom = DosAllocate(len + 2))) {  /* room for length byte AND  */
  148.     DosFree(foo);              /*  nul, like existing nodes */
  149.     return null;
  150.     }
  151.     foo->dn_Name = (long) nom >> 2;
  152.     foo->dn_Type = 1L;
  153.     nom[0] = len;
  154.     strcpy(nom + 1, name);  /* leave the nul on the end */
  155.     foo->dn_Next = infoo->di_DevInfo;     /* put new node at top of list */
  156.     infoo->di_DevInfo = (long) foo >> 2;
  157.     return foo;
  158. }
  159.  
  160.  
  161.  
  162. bool Match(s, b) str s; BSTR b;
  163. {
  164.     str bee = bip(char, b);
  165.     short len = strlen(s);
  166.     short i;
  167.     if (bee[0] != len) return false;
  168.     for (i = 0; i < len; i++)
  169.     if (toupper(s[i]) != toupper(bee[i + 1]))
  170.         return false;
  171.     return true;
  172. }
  173.  
  174.  
  175.  
  176. den *FindDNode(name) str name;
  177. {
  178.     den *goob;
  179.     for (goob = gbip(infoo->di_DevInfo); goob; goob = gbip(goob->dn_Next))
  180.     if (goob->dn_Type == 1 && Match(name, goob->dn_Name))
  181.         return goob;
  182.     return null;
  183. }
  184.  
  185.  
  186.  
  187. lock ReAssign(name, lok, g) str name; lock lok; glob g;
  188. {
  189.     den *where;
  190.     lock old;
  191.     Forbid();
  192.     where = FindDNode(name);
  193.     if (!where) where = MakeNewAssignNode(name);
  194.     if (!where) {
  195.     Permit();
  196.     put("Couldn't find or create device node for \"", g);
  197.     put(name, g);
  198.     put("\".\nOut of memory, I guess.\n", g);
  199.     return (lock) 0;
  200.     }
  201.     old = where->dn_Lock;
  202.     where->dn_Lock = lok;
  203.     where->dn_Task = bip(struct FileLock, lok)->fl_Task;
  204.     Permit();
  205.     return old ? old : (lock) ~0;
  206. }
  207.  
  208.  
  209.  
  210. #ifdef BENCH
  211.  
  212. void BenchExit(g) glob g;
  213. {
  214.     long buf;
  215.     if (g->conopen) {
  216.     put("\n  (press any key to erase window) ", g);
  217.     Read(g->out, &buf, 1L);        /* Read(Output() ...) ?!?   yes! */
  218.     Close(g->out);
  219.     }
  220.     Forbid();
  221.     ReplyMsg(g->wbs);
  222.     Exit(0L);
  223. }
  224.  
  225. #endif
  226.  
  227.  
  228.  
  229. lock GetArg(app, alen, g) str *app; long alen; glob g;
  230. {
  231.     lock syl = (lock) 0;
  232.     long hair = 0;
  233.     struct Process *me = ThisProcess();
  234.  
  235. #ifdef BENCH
  236.     if (g->bench) {
  237.     struct MsgPort *myface = &me->pr_MsgPort;
  238.     struct DiskObject *me = null, *it = null;
  239.     struct WBArg *a0, *a1;
  240.  
  241.     *app = null;
  242.     WaitPort(myface);
  243.     g->wbs = (adr) GetMsg(myface);
  244.     a0 = g->wbs->sm_ArgList;
  245.     a1 = a0 + 1;
  246.     if (g->wbs->sm_NumArgs == 2) {
  247.         if (!*a0->wa_Name) syl = DupLock(a0->wa_Lock);
  248.         else if (!*a1->wa_Name) syl = DupLock(a1->wa_Lock);
  249.     }
  250.     if (!syl) {
  251.         put(
  252. "To use MoveSys from workbench, you must click the\n"
  253. "MoveSys icon and then shift-double-click a DISK or\n"
  254. "DRAWER icon.  Or click the disk or drawer first, and\n"
  255. "then shift-double-click the MoveSys icon.  The disk or\n"
  256. "drawer should contain subdirectories named c, s, l,\n"
  257. "libs, devs, and fonts.  MoveSys will assign SYS: to that\n"
  258. "disk or drawer and assignC:, S:, L:, LIBS:, DEVS:, and\n"
  259. "FONTS: to the subdirectories with the same names.\n", g);
  260.         BenchExit(g);
  261.     }
  262.     } else
  263. #endif
  264.     {
  265.     do
  266.         (*app)[--alen] = 0;
  267.     while (alen > 0 && (*app)[alen - 1] <= ' ');
  268.     g->slasher = alen > 0 && (*app)[alen - 1] != '/'
  269.                 && (*app)[alen - 1] != ':';
  270.     while (alen && **app <= ' ')
  271.         (*app)++, alen--;
  272.     if (tolower(**app) == 'c' && tolower((*app)[1]) == 'd' &&
  273.             (*app)[2] <= ' ' && alen >= 3) {
  274.         *app += 3;
  275.         alen -= 3;
  276.         g->cd = true;
  277.         while (alen && **app <= ' ')
  278.         (*app)++, alen--;
  279.     }
  280.     if (**app == '"') {
  281.         if ((*app)[alen - 1] == '"') (*app)[alen - 1] = 0;
  282.         (*app)++;
  283.     }
  284.     if (alen && !(alen == 1 && **app == '?')) {
  285.         syl = RLock(*app);
  286.         if (!syl) {
  287.         hair = me->pr_Result2;      /* set by Lock */
  288.         put(*app, g);
  289.         put(" not found.\n", g);
  290.         me->pr_Result2 = hair;
  291.         Exit(10L);
  292.         }
  293.     } else {
  294. #ifdef BENCH
  295.         put(
  296. "\nYou must name a drive, volume, or directory to move SYS:\n"
  297. "to.  And that disk or drawer should have subdirectories\n"
  298. "named c, s, l, libs, devs, and fonts.  MoveSys will reassign\n"
  299. "SYS: to the named disk or directory and reassign C:, S:, L:,\n"
  300. "LIBS:, DEVS:, and FONTS: to the subdirectories with the\n"
  301. "same names.  You can also cause it to CD to the new SYS: by\n"
  302. "using the word CD between the MoveSys command and the name\n"
  303. "of the new SYS:.  Example --\n\n    1> MoveSys cd dh0:\n\n", g);
  304. #else
  305.         put("You must name a disk or directory to move SYS: to.\n", g);
  306. #endif
  307.         me->pr_Result2 = ERROR_LINE_TOO_LONG;
  308.         Exit(10L);
  309.     }
  310.     }
  311.     return syl;
  312. }
  313.  
  314.  
  315.  
  316. long _main(alen, aptr) long alen; str aptr;
  317. {
  318.     lock syl, L;
  319.     short f;
  320.     long hair = 0, turn = 0;
  321.     bool oneokay = false;
  322.     struct Process *me = ThisProcess();
  323.     lock oldsys, oldsub;
  324.     struct global g;
  325.  
  326.     g.out = me->pr_COS;
  327.     g.cd = g.slasher = false;
  328. #ifdef BENCH
  329.     g.conopen = g.confail = false;
  330.     g.bench = !me->pr_CLI;
  331. #endif
  332.     infoo = bip(struct DosInfo, 
  333.         ((struct RootNode *) DOSBase->dl_Root)->rn_Info);
  334.     syl = GetArg(&aptr, alen, &g);
  335.     if (!(oldsys = ReAssign("SYS", syl, &g))) {
  336.     turn = 10;
  337.     hair = ERROR_NO_FREE_STORE;
  338.     } else {
  339.     for (f = 0; f < HowMany; f++) {
  340.         L = RLock(dears[f]);
  341.         if (!L) {
  342.         turn = 5;
  343.         hair = me->pr_Result2;    /* set by Lock */
  344.         put(aptr, &g);
  345.         if (g.slasher) put("/", &g);
  346.         put(dears[f] + 4, &g);
  347.         put(" not found.\n", &g);
  348.         } else {
  349.         if (!(oldsub = ReAssign(dames[f], L))) {
  350.             turn = 10;
  351.             hair = ERROR_NO_FREE_STORE;
  352.             break;
  353.         } else
  354.             if (~oldsub) UnLock(oldsub);
  355.         oneokay = true;
  356.         }
  357.     }
  358.     if (!oneokay) {
  359.         if (~oldsys) oldsys = ReAssign("SYS", oldsys, &g);
  360.         put("\n  None of the correct subdirectories are present!\n", &g);
  361.         hair = ERROR_OBJECT_NOT_FOUND;
  362.         turn = 10;
  363.     } else if (g.cd) {
  364.         short len = strlen(aptr);
  365.         str setname;
  366.         struct CommandLineInterface *cli = gbip(me->pr_CLI);
  367.     
  368.         L = CurrentDir(DupLock(syl));
  369.         if (L) UnLock(L);
  370.         if (len > 87) len = 87;        /* setname buffer is 88 bytes */
  371.         if (cli) {
  372.         setname = gbip(cli->cli_SetName);
  373.         *setname = len;
  374.         strncpy(setname + 1, aptr, len);
  375.         }
  376.     }
  377.     if (~oldsys) UnLock(oldsys);
  378.     }
  379. #ifdef BENCH
  380.     if (g.bench) BenchExit(&g);
  381. #endif
  382.     me->pr_Result2 = hair;
  383.     return turn;
  384. }
  385.