home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cDos.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  14KB  |  609 lines

  1. /*
  2.  *  CELLS       An Implementation of the WireWorld cellular automata
  3.  *              as described in Scientific American, Jan 1990.
  4.  *
  5.  *              Copyright 1990 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  *  See the CELLS.HELP file for complete information on distribution conditions.
  8.  */
  9.  
  10. /*
  11.  *  File:  cDos.c               Handles AmigaDOS calls and BCPL stuff.
  12.  */
  13.  
  14.  
  15. #include "Cells.h"
  16. #include "cRequest.h"
  17. #include "cDos.h"
  18. #include "cMemory.h"
  19.  
  20. UWORD Mounted;
  21.  
  22. static FIB Fib;                     /* a common FIB structure */
  23. static INFODATA InfoData;           /* a cmmon INFO structure */
  24. static struct Process *theProc;     /* the CELLS process */
  25. static LOCK InitialDir;             /* the initial directory LOCK */
  26. static LOCK SwapLock;               /* temprary swap storage */
  27.  
  28. static char *FType[] = {"Directory","File"};
  29.  
  30.  
  31. /*
  32.  *  The DOS error messages
  33.  */
  34.  
  35. #define BASE_ERROR      201
  36. #define TOP_ERROR       226
  37. static char *DosErr[] =
  38. {
  39.    "Error 00000",
  40.    "No Default Directory",
  41.    "Object in Use",
  42.    "Object Already Exists",
  43.    "Directory Not Found",
  44.    "Object Not Found",
  45.    "Bad Stream Name",
  46.    "Object Too Large",
  47.    "Error 208",
  48.    "Action Not Known",
  49.    "Invalid Component Name",
  50.    "Invalid Lock",
  51.    "Object of Wrong Type",
  52.    "Disk Not Validated",
  53.    "Disk Write Protected",
  54.    "Rename Across Devices",
  55.    "Directory Not Empty",
  56.    "Too Many Levels",
  57.    "Device Not Mounted",
  58.    "Seek Error",
  59.    "Comment Too Big",
  60.    "Disk Full",
  61.    "Delete Protected",
  62.    "Write Protected",
  63.    "Read Protected",
  64.    "Not a DOS Disk",
  65.    "No Disk in Drive"
  66. };
  67.  
  68.  
  69. /*
  70.  *  Free the common FIB and INFO structures if they have been allocated
  71.  */
  72.  
  73. void FreeBlock()
  74. {
  75.    if (Fib)      FREESTRUCT(FileInfoBlock,Fib);
  76.    if (InfoData) FREESTRUCT(InfoData,InfoData);
  77. }
  78.  
  79.  
  80. /*
  81.  *  DosError()
  82.  *
  83.  *  If the error is outside the known error range,
  84.  *    set up the dummy error string
  85.  *  Otherwise use the known error string
  86.  *  If the active requester is a File requester (which has a message box)
  87.  *    put the message in the message box,
  88.  *  Otherwise
  89.  *    put up an error message
  90.  */
  91.  
  92. void DosError(s1,s2)
  93. char *s1,*s2;
  94. {
  95.    extern struct ExtRequest LSRequest;
  96.    int ErrNo = IoErr();
  97.    char *Error; 
  98.    
  99.    if (ErrNo < BASE_ERROR || ErrNo > TOP_ERROR)
  100.    {
  101.       sprintf(DosErr[0],"Error %d",ErrNo);
  102.       Error = DosErr[0];
  103.    } else {
  104.       Error = DosErr[ErrNo-BASE_ERROR+1];
  105.    }
  106.    if (ActiveRequest == &LSRequest)
  107.       LSMessage("Can't %s %s: %s",s1,s2,Error);
  108.      else
  109.       DoError("Can't %s %s: %s",s1,s2,Error);
  110. }
  111.  
  112.  
  113. /*
  114.  *  DosLock()
  115.  *
  116.  *  Attempt to lock the specified file.  If no good, give an error message,
  117.  *  otherwise set the lock pointer to the specified lock, and return TRUE.
  118.  */
  119.  
  120. int DosLock(LockPtr,Name,Index)
  121. LOCK *LockPtr;
  122. char *Name;
  123. int Index;
  124. {
  125.    if (!(*LockPtr = Lock(Name,ACCESS_READ)))
  126.       DosError("Lock",FType[Index]);
  127.    return((*LockPtr) != NULL);
  128. }
  129.  
  130.  
  131. /*
  132.  *  DosExamine()
  133.  *
  134.  *  If the common FIB has not been allocated, allocate it.
  135.  *  If the allocate failed, give a message
  136.  *  Otherwise try to examine the given lock.
  137.  *  If it can't be examined, give an error.
  138.  */
  139.  
  140. int DosExamine(theLock,FibPtr,Index)
  141. LOCK theLock;
  142. FIB *FibPtr;
  143. int Index;
  144. {
  145.    int status = FALSE;
  146.  
  147.    if (Fib == NULL) NEWSTRUCT(FileInfoBlock,Fib);
  148.    if ((*FibPtr = Fib) == NULL)
  149.       LSMessage("Can't Allocate FileInfoBlock");
  150.    else if (Examine(theLock,Fib)) status = TRUE;
  151.    else DosError("Examine",FType[Index]);
  152.    return(status);
  153. }
  154.  
  155.  
  156. /*
  157.  *  DosInfo()
  158.  *
  159.  *  If the common Info structure has not been allocated, allocate it.
  160.  *  If the allocation failed, give a message,
  161.  *  Otherwise attempt to the the info on the given lock
  162.  *  If the Info call failed, give an error message.
  163.  */
  164.  
  165. int DosInfo(theLock,InfoPtr,Index)
  166. LOCK theLock;
  167. INFODATA *InfoPtr;
  168. int Index;
  169. {
  170.    int status = FALSE;
  171.  
  172.    if (InfoData == NULL) NEWSTRUCT(InfoData,InfoData);
  173.    if ((*InfoPtr = InfoData) == NULL)
  174.       LSMessage("Can't Allocate Memory for Info Data");
  175.    else if (Info(theLock,InfoData)) status = TRUE;
  176.    else DosError("Get Info for",FType[Index]);
  177.    return(status);
  178. }
  179.  
  180.  
  181. /*
  182.  *  BSTRcpy()
  183.  *
  184.  *  Copy a BCPL string to a C string buffer and return the size of the string.
  185.  */
  186.  
  187. int BSTRcpy(to,BCPLfrom)
  188. char *to,*BCPLfrom;
  189. {
  190.    char *from = BCPL_TO_CHAR(BCPLfrom);
  191.    
  192.    strncpy(to,from+1,(int)(*from));
  193.    *(to+(*from)) = 0;
  194.    return((int)*from);
  195. }
  196.  
  197.  
  198. /*
  199.  *  LockCurrentDir()
  200.  *
  201.  *  Duplicate a lock on the current directory (to guarantee a non-null lock)
  202.  *  If the duplicate failed, unlock the duplicate and lock the root directory.
  203.  */
  204.  
  205. LOCK LockCurrentDir() 
  206. {
  207.    LOCK CurDir;
  208.    
  209.    CurDir = DupLock(theProc->pr_CurrentDir);
  210.    if (CurDir == NULL)
  211.    {
  212.       UnLock(CurDir);
  213.       CurDir = Lock(":",ACCESS_READ);
  214.    }
  215.    return(CurDir);
  216. }
  217.  
  218.  
  219. /*
  220.  *  GetPathFromLock()
  221.  *
  222.  *  Clear the name string
  223.  *  Start with a duplicate of the specified lock (so we can unlock it)
  224.  *  Get the device name of the device associated with the lock, and add
  225.  *  a ":" to the end of the string.
  226.  *
  227.  *  If the common FIB is not allocated, allocate it.
  228.  *  While there is a current directory lock,
  229.  *    Examine the lock
  230.  *    If it could not be examined,
  231.  *      clear the directory name and unlock the lock,
  232.  *    Otherwise
  233.  *      Keep a copy of the old lock,
  234.  *      Get a lock on the parent of the lock, and unlock the old lock
  235.  *      If there is a parent,
  236.  *        get the lenght of the parent's name,
  237.  *        move the contents of the current path to make room for the
  238.  *          new parent directory name.
  239.  *        copy the parent directory name into the string
  240.  *        add a '/' if there were other names already.
  241.  */
  242.  
  243. char *GetPathFromLock(dir,lock)
  244. char *dir;
  245. LOCK lock;
  246. {
  247.    LOCK CurDir,OldDir;
  248.    char *subdir = dir;
  249.    char *s,*s1;
  250.    char c;
  251.    int len;
  252.  
  253.    *dir = 0;
  254.    CurDir = DupLock(lock);
  255.    Forbid();
  256.    subdir += BSTRcpy(dir,DEVLIST(FILELOCK(CurDir)->fl_Volume)->dl_Name);
  257.    Permit();
  258.    *subdir++ = ':';
  259.    *subdir = 0;
  260.  
  261.    if (Fib == NULL) if (NEWSTRUCT(FileInfoBlock,Fib) == NULL)
  262.    {
  263.       LSMessage("Can't Allocate FileInfoBlock");
  264.       return(NULL);
  265.    }
  266.    while (CurDir != NULL)
  267.    {
  268.       if (!Examine(CurDir,Fib))
  269.       {
  270.          *dir = 0;
  271.          UnLock(CurDir);
  272.          CurDir = NULL;
  273.       } else {
  274.          OldDir = CurDir;
  275.          CurDir = ParentDir(OldDir);
  276.          UnLock(OldDir);
  277.          
  278.          if (CurDir)
  279.          {
  280.             len = strlen(Fib->fib_FileName);
  281.             for (s=subdir+strlen(subdir),s1=s+len+1; s>=subdir; *s1-- = *s--);
  282.             c = *subdir;
  283.             strcpy(subdir,Fib->fib_FileName);
  284.             if (c) *s1 = '/';
  285.          }
  286.       }
  287.    }
  288.    RETURN(dir);
  289. }
  290.  
  291.  
  292. /*
  293.  *  GetProcessDir()
  294.  *
  295.  *  Lock the current directory and get the path name of that lock.
  296.  *  Unlock the lock and return the name.
  297.  */
  298.  
  299. char *GetProcessDir(dir)
  300. char *dir;
  301. {
  302.    LOCK lock;
  303.    
  304.    lock = LockCurrentDir();
  305.    GetPathFromLock(dir,lock);
  306.    UnLock(lock);
  307.    RETURN(dir);
  308. }
  309.  
  310. /*
  311.  *  The names of the floppy drives
  312.  */
  313.  
  314. #define MAXDRIVE    4
  315. static char DriveName[MAXDRIVE][5] = {"DF0:","DF1:","DF2:","DF3:"};
  316.  
  317.  
  318. /*
  319.  *  MountedDrives()
  320.  *
  321.  *  Set the process WindoowPtr so that no system requests will occur
  322.  *  For each drive name in the list
  323.  *    try to lock the give drive
  324.  *    If successful
  325.  *      unlock the drive, and record that the drive is mounted
  326.  *  Put the window pointer back
  327.  *  return the mounted drives flag.
  328.  */
  329.  
  330. UWORD MountedDrives()
  331. {
  332.    APTR OldWindowPtr = theProc->pr_WindowPtr;
  333.    LOCK lock;
  334.    short i;
  335.    UWORD drive,Mounted = 0;
  336.    
  337.    theProc->pr_WindowPtr = (APTR) -1;
  338.    for (i=0,drive=1; i<MAXDRIVE; i++,drive<<=1)
  339.    {
  340.       lock = Lock(DriveName[i],ACCESS_READ);
  341.       if (lock)
  342.       {
  343.          UnLock(lock);
  344.          Mounted |= drive;
  345.       }
  346.    }
  347.    theProc->pr_WindowPtr = OldWindowPtr;
  348.    return(Mounted);
  349. }
  350.  
  351.  
  352. /*
  353.  *  DosInsertedDrive()
  354.  *
  355.  *  For each of the currently mounted drives that didn't used to be mounted
  356.  *    attempt to lock the drive
  357.  *    if successful,
  358.  *      if the the volume is not the same as the current directoty's volume,
  359.  *        get the name of the drive, and stop looking for more drives.
  360.  */
  361.  
  362. int DosInsertedDrive(OldMounted,Name)
  363. UWORD OldMounted;
  364. char *Name;
  365. {
  366.    int status = FALSE;
  367.    LOCK lock;
  368.    short i = 0;
  369.    
  370.    OldMounted = Mounted & (~OldMounted);
  371.    while (OldMounted)
  372.    {
  373.       if (OldMounted & 1)
  374.       {
  375.          lock = Lock(DriveName[i],ACCESS_READ);
  376.          if (lock)
  377.          {
  378.             if (FILELOCK(lock)->fl_Volume != 
  379.                 FILELOCK(theProc->pr_CurrentDir)->fl_Volume)
  380.             {
  381.                strcpy(Name,DriveName[i]);
  382.                OldMounted = 0;
  383.                status = TRUE;
  384.             }
  385.          }
  386.       }
  387.       OldMounted >>= 1;
  388.       i++;
  389.    }
  390.    return(status);
  391. }
  392.  
  393.  
  394. /*
  395.  *  GetDevName()
  396.  *
  397.  *  Get the device name of a specified device into a C string
  398.  */
  399.  
  400. void GetDevName(to,Dev)
  401. char *to;
  402. struct DeviceList *Dev;
  403. {
  404.    char *from = BCPL_TO_CHAR(Dev->dl_Name);
  405.    
  406.    strncpy(to,from+1,(int)(*from));
  407.    strcpy(to+(*from),":");
  408. }
  409.  
  410.  
  411. /*
  412.  *  GetNextMounted()
  413.  *
  414.  *  Skip any non-devices (i.e., ASSIGNs and volumes) and any non-mounted
  415.  *    devices in the device list.
  416.  *  If we found a device
  417.  *    get its name, and attempt to lock it
  418.  *    if successful,
  419.  *      get the volume mounted on the device
  420.  *      and record it as the first volume, if there isn't already one recorded
  421.  *      unlock the device
  422.  *    go on to the next device
  423.  */
  424.  
  425. static void GetNextMounted(Dev,DevVol,FirstVol,Name)
  426. struct DeviceList **Dev,**DevVol,**FirstVol;
  427. char *Name;
  428. {
  429.    LOCK lock;
  430.    
  431.    while (*Dev && ((*Dev)->dl_Type != DLT_DEVICE || (*Dev)->dl_Task == NULL))
  432.       *Dev = DEVLIST((*Dev)->dl_Next);
  433.    if (*Dev)
  434.    {
  435.       GetDevName(Name,*Dev);
  436.       lock = Lock(Name,ACCESS_READ);
  437.       if (lock)
  438.       {
  439.          *DevVol = DEVLIST(FILELOCK(lock)->fl_Volume);
  440.          if (FirstVol && *FirstVol == NULL) *FirstVol = *DevVol;
  441.          UnLock(lock);
  442.       }
  443.       *Dev = DEVLIST((*Dev)->dl_Next);
  444.    }
  445. }
  446.  
  447.  
  448. /*
  449.  *  DosNextDisk()
  450.  *
  451.  *  Set the window pointer so that system requests will not appear
  452.  *  Forbid() since we will be using a system list (the device list)
  453.  *  Get the pointer to the volume of the current directory
  454.  *  Starting with the first volume in the device list, look through the
  455.  *    device list until we run out of devices, or find the current device
  456.  *    (note that this will find the FirstVol - the first mounted volume)
  457.  *  Find the colume following the current one (or the end of the list).
  458.  *  If there is no following volume,
  459.  *    if there is no first mounted volume,
  460.  *      return the NO VOLUMES MOUNTED error
  461.  *    otherwise,
  462.  *      if the first volume is also the current one,
  463.  *        return the NO OTHER VOLUMES MOUNTED error
  464.  *      get the name of the first volume in the list.
  465.  *  otherwise
  466.  *    get the name of the volume found following the current one
  467.  *  Permit() again (we're done with the device list)
  468.  *  put back the window pointer so system requesters show up again.
  469.  */
  470.  
  471. int DosNextDisk(Name)
  472. char *Name;
  473. {
  474.    int status = NOERROR;
  475.    struct DeviceList *Dev = NULL;
  476.    struct DeviceList *DevVol = NULL;
  477.    struct DeviceList *FirstVol = NULL;
  478.    struct DeviceList *CurVol = NULL;
  479.    APTR OldWindowPtr = theProc->pr_WindowPtr;
  480.    
  481.    *Name = 0;
  482.    theProc->pr_WindowPtr = (APTR) -1;
  483.    
  484.    Forbid();
  485.    CurVol = DEVLIST(FILELOCK(theProc->pr_CurrentDir)->fl_Volume);
  486.    for (Dev = FIRSTDEV; Dev && DevVol != CurVol;)
  487.       GetNextMounted(&Dev,&DevVol,&FirstVol,Name);
  488.    
  489.    DevVol = NULL;
  490.    while (Dev && DevVol == NULL)
  491.       GetNextMounted(&Dev,&DevVol,NULL,Name);
  492.    
  493.    *Name = 0;
  494.    if (DevVol == NULL)
  495.    {
  496.       if (FirstVol == NULL)
  497.       {
  498.          status = NOVOLMOUNT;
  499.       } else {
  500.          if (FirstVol == CurVol) status = NOVOLOTHER;
  501.          GetDevName(Name,FirstVol);
  502.       }
  503.    } else {
  504.       GetDevName(Name,DevVol);
  505.    }
  506.    Permit();
  507.    
  508.    theProc->pr_WindowPtr = OldWindowPtr;
  509.    return(status);
  510. }
  511.  
  512.  
  513. /*
  514.  *  SaveStartingDir()
  515.  *
  516.  *  Find the current task, and set the current directory to a copy of the
  517.  *  lock on the current directory.  Save the old lock for replacement when
  518.  *  we finish.  Save a copy of the current directory in the Swap Lock for 
  519.  *  later.  Record the currently mounted floppies.
  520.  */
  521.  
  522. void SaveStartingDir()
  523. {
  524.    theProc = FindTask(NULL);
  525.    InitialDir = CurrentDir(LockCurrentDir());
  526.    SwapLock = LockCurrentDir();
  527.    Mounted = MountedDrives();
  528. }
  529.  
  530.  
  531. /*
  532.  *  RestoreStartingDir()
  533.  *
  534.  *  If saved the initial lock, put it back.
  535.  *  If there is a swap lock, unlock it.
  536.  */
  537.  
  538. void RestoreStartingDir()
  539. {
  540.    if (theProc) UnLock(CurrentDir(InitialDir));
  541.    if (SwapLock) UnLock(SwapLock);
  542. }
  543.  
  544.  
  545. /*
  546.  *  SwapLocks()
  547.  *
  548.  *  Switch current directories temporarily (save the old one so we can swap
  549.  *  back later)
  550.  */
  551.  
  552. void SwapLocks()
  553. {
  554.    SwapLock = CurrentDir(SwapLock);
  555. }
  556.  
  557.  
  558. /*
  559.  *  Days to the begining of each month, and names of the months
  560.  */
  561.  
  562. static int
  563.    DaysIn[] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
  564.  
  565. static char
  566.    *NameOf[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  567.                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  568.  
  569. #define CENTURY             (100 YEARS + 25 LEAPDAYS)
  570. #define FOURCENTURIES       (400 YEARS + 99 LEAPDAYS)
  571. #define FOURYEARS           (4 YEARS + 1 LEAPDAY)
  572. #define LEAPYEAR            (1 YEARS + 1 LEAPDAY)
  573. #define LEAPDAYS
  574. #define LEAPDAY
  575. #define YEARS               * 365
  576. #define YEAR                365
  577. #define FEBDAYS             59          /* days until the end of February */
  578.  
  579.  
  580. /*
  581.  *  GetStrTime()
  582.  *
  583.  *  Turn a date stamp into a character string
  584.  */
  585.  
  586. void GetStrTime(time,date)
  587. char time[16];             /* storage area for the return value */
  588. struct DateStamp *date;    /* the DateStamp to convert */
  589. {
  590.    int year,month,day,hour,min;
  591.  
  592.    day = date->ds_Days + 78 YEARS + 20 LEAPDAYS;
  593. /* day += (day - FEBDAYS - CENTURY + FOURCENTURIES) / FOURCENTURIES; */
  594.    year = 4 * (day/FOURYEARS) + 1900;
  595.    day %= FOURYEARS;
  596.    day += (day - FEBDAYS - 1 LEAPDAY) / YEAR;
  597.    year += day / LEAPYEAR;
  598.    day %= LEAPYEAR;
  599.  
  600.    for (month=1; day >= DaysIn[month]; month++);
  601.    day = day - DaysIn[month-1] + 1;
  602.  
  603.    hour = date->ds_Minute / 60;
  604.    min  = date->ds_Minute - hour*60;
  605.  
  606.    sprintf(time,"%02d-%3s-%02d %02d:%02d",
  607.      day,NameOf[month],(year % 100),hour,min);
  608. }
  609.