home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Amiga / Workbench / Archivers / ZooPPC.lha / ZooPPC / src / amiga.c < prev    next >
C/C++ Source or Header  |  1998-04-07  |  16KB  |  734 lines

  1. #ifndef LINT
  2. static char    amigaid[] = "@(#) amiga.c 1.1 91/08/03 23:21:00";
  3.  
  4. #endif                /* LINT */
  5.  
  6. /*
  7.  * machine.c for Amiga.
  8.  *
  9.  * This file is (C) Copyright 1991 by Olaf Seibert. All rights reserved. May
  10.  * be used and distributed under the same conditions as the other
  11.  * non-public-domain files that are part of Zoo.
  12.  */
  13.  
  14. #undef TEXT            /* typedef in exec/types.h */
  15. #include <assert.h>
  16. #include <exec/types.h>
  17. #include <libraries/dos.h>
  18. #include <signal.h>
  19.  
  20. #ifdef __STDC__
  21. #define __args
  22. #include <functions.h>
  23. #else
  24. BPTR        Lock(), CreateDir(), ParentDir();
  25. long        Examine(), ExNext();
  26. void           *AllocMem();
  27. struct MsgPort *DeviceProc();
  28. long        SetSignal();
  29.  
  30. #endif
  31.  
  32. int iswild    PARMS((char *));
  33. void endfile    PARMS((int));
  34. void fcbpath    PARMS((char *, char *));
  35. void ToDateStamp PARMS((struct DateStamp * datestamp, unsigned date, unsigned time));
  36. void ToMSDate    PARMS((unsigned *date, unsigned *time, struct DateStamp * datestamp));
  37. void _abort    PARMS((void));
  38. long Chk_Abort    PARMS((void));
  39.  
  40. /*
  41.  * WARNING:  This file assumes that ZOOFILE is a standard buffered file.
  42.  * It will have to be modified if ZOOFILE is changed to be an unbuffered
  43.  * file descriptor or to any other kind of file.
  44.  */
  45.  
  46. #ifdef UNBUF_IO
  47. /*
  48.  * Function tell() returns the current seek position for a file
  49.  * descriptor. 4.3BSD on VAX-11/785 has an undocumented tell() function
  50.  * but it may not exist on all implementations, so we code one here to be
  51.  * on the safe side.  It is needed for unbuffered I/O only.
  52.  */
  53. long lseek    PARMS((int, long, int));
  54. long
  55. tell(fd)
  56. int        fd;
  57. {
  58.     return lseek(fd, 0L, 1);
  59. }
  60.  
  61. #endif
  62.  
  63.  
  64. /*
  65.  * Function zootrunc() truncates a file.
  66.  */
  67.  
  68. int
  69. zootrunc(f)
  70. ZOOFILE     f;
  71. {
  72.     fflush(f);                  /* just in case it matters */
  73.     /* Cannot truncate on AmigaOS < 2.0 */
  74. }
  75.  
  76. /*
  77.  * Function fixfname() converts the supplied filename to a syntax legal
  78.  * for the host system.  It is used during extraction.
  79.  */
  80.  
  81. char           *
  82. fixfname(fname)
  83. char           *fname;
  84. {
  85.     return fname;        /* default is no-op */
  86. }
  87.  
  88. /*
  89.  * Function isuadir() returns 1 if the supplied name is a directory, else
  90.  * it returns 0.
  91.  */
  92.  
  93. int
  94. isuadir(path)
  95. char           *path;
  96. {
  97.     struct FileInfoBlock *fib;
  98.     int         its_a_dir;
  99.  
  100.     its_a_dir = 0;
  101.     if (fib = malloc(sizeof (*fib))) {
  102.     BPTR        lock;
  103.  
  104.     if (lock = Lock(path, ACCESS_READ)) {
  105.         Examine(lock, fib);
  106.         its_a_dir = (fib->fib_DirEntryType > 0);
  107.         UnLock(lock);
  108.     }
  109.     free(fib);
  110.     }
  111.     return its_a_dir;
  112. }
  113.  
  114. /* No standard UNIX-compatible time routines */
  115.  
  116. /*
  117.  * Function getutime() gets the date and time of the file name supplied.
  118.  * Date and time is in MSDOS format.
  119.  */
  120. int
  121. getutime(path, date, time)
  122. char           *path;
  123. unsigned       *date,
  124.            *time;
  125. {
  126.     struct FileInfoBlock *fib;
  127.  
  128.     *date = 0;
  129.     *time = 0;
  130.  
  131.     if (fib = malloc(sizeof (*fib))) {
  132.     BPTR        lock;
  133.  
  134.     if (lock = Lock(path, ACCESS_READ)) {
  135.         Examine(lock, fib);
  136.  
  137.         ToMSDate(date, time, &fib->fib_Date);
  138.         UnLock(lock);
  139.     }
  140.     free(fib);
  141.     }
  142.     return 0;
  143. }
  144.  
  145. /*
  146.  * Function setutime() sets the date and time of the filename supplied.
  147.  * Date and time is in MSDOS format.
  148.  */
  149.  
  150. int
  151. setutime(path, date, time)
  152. char           *path;
  153. unsigned int    date,
  154.         time;
  155. {
  156.     struct DateStamp DateStamp;
  157. #ifndef __PPC__
  158.     extern int SetFileDate PARMS((char *file, struct DateStamp * date));
  159. #endif
  160.  
  161.     ToDateStamp(&DateStamp, date, time);
  162.  
  163.     return !SetFileDate(path, &DateStamp);
  164. }
  165.  
  166. #ifdef AZTEC_C
  167. # ifndef  EXEC_MEMORY_H
  168. #    include <exec/memory.h>
  169. # endif
  170. # ifndef ACTION_SET_DATE
  171. #    define ACTION_SET_DATE        34L
  172. # endif
  173.  
  174. int
  175. SetFileDate(path, date)
  176. char           *path;
  177. struct DateStamp *date;
  178. {
  179.     struct MsgPort *task;
  180.     BPTR        lock,
  181.             plock;
  182.     UBYTE       *bcplstring;
  183.     int         result;
  184.  
  185.     if (!(bcplstring = (UBYTE *) AllocMem(64L, (long) MEMF_PUBLIC)))
  186.     return 0;
  187.     result = 0;
  188.     if (!(task = DeviceProc(path))) {
  189.     goto abort;
  190.     }
  191.     if (!(lock = Lock(path, SHARED_LOCK))) {
  192.     goto abort;
  193.     }
  194.     plock = ParentDir(lock);
  195.     UnLock(lock);
  196.  
  197.     /* Strip pathnames first */
  198.     strcpy((char *) (bcplstring + 1), nameptr(path));
  199.     *bcplstring = strlen((char *) (bcplstring + 1));
  200.  
  201.     result = dos_packet(task, ACTION_SET_DATE, NULL, plock,
  202.               (ULONG) bcplstring >> 2, (ULONG) date, 0L, 0L, 0L);
  203.  
  204.     UnLock(plock);
  205. abort:
  206.     FreeMem((void *) bcplstring, 64L);
  207.     return result;
  208. }
  209.  
  210. #endif
  211.  
  212.  
  213. /* No standard UNIX-specific file attribute routines */
  214.  
  215. /*
  216.  * Get file attributes.  Currently only the lowest nine of the *IX mode
  217.  * bits are used.  Also we return bit 23=0 and bit 22=1, which means use
  218.  * portable attribute format, and use attribute value instead of using
  219.  * default at extraction time.
  220.  */
  221.  
  222. unsigned long
  223. getfattr(f)
  224. ZOOFILE     f;
  225. {
  226.     return NO_FATTR;        /* inaccessible -- no attributes */
  227. }
  228.  
  229. /*
  230.  * Set file attributes.  Only the lowest nine bits are used.
  231.  */
  232.  
  233. int
  234. setfattr(f, a)
  235. char           *f;        /* filename */
  236. unsigned long    a;        /* atributes to set */
  237. {
  238.     return 0;            /* cannot do */
  239. }
  240.  
  241. int
  242. iswild(name)
  243. char           *name;
  244. {
  245.     return (strchr(name, '*') != NULL) || (strchr(name, '?') != NULL);
  246. }
  247.  
  248. #define FMAX    3        /* Number of different filename patterns */
  249.  
  250.  
  251. /* #include "various.h" */
  252. /* #include "zoo.h" *//* solely to define PATHSIZE */
  253.  
  254. #ifdef SPECNEXT
  255. /*-
  256.  
  257. nextfile() returns the name of the next source file matching a filespec.
  258.  
  259. INPUT
  260.    what: A flag specifying what to do. If "what" is 0, nextfile()
  261.       initializes itself.     If "what" is 1, nextfile() returns the next
  262.       matching filename.
  263.    filespec:  The filespec, usually containing wildcard characters, that
  264.       specifies which files are needed.  If "what" is 0, filespec must be
  265.       the filespec for which matching filenames are needed.  If "what" is 1,
  266.       nextfile() does not use "filespec" and "filespec" should be NULL to
  267.       avoid an assertion error during debugging.
  268.    fileset:  nextfile() can keep track of more than one set of filespecs.
  269.       The fileset specifies which filespec is being matched and therefore
  270.       which set of files is being considered.  "fileset" can be in the
  271.       range 0:FMAX.   Initialization of one fileset does not affect the
  272.       other filesets.
  273.  
  274. OUTPUT
  275.    IF what == 0 THEN
  276.       return value is NULL
  277.    ELSE IF what == 1 THEN
  278.       IF a matching filename is found THEN
  279.      return value is pointer to matching filename including supplied path
  280.       ELSE
  281.      IF at least one file matched previously but no more match THEN
  282.         return value is NULL
  283.      ELSE IF supplied filespec never matched any filename THEN
  284.         IF this is the first call with what == 1 THEN
  285.            return value is pointer to original filespec
  286.         ELSE
  287.         return value is NULL
  288.         END IF
  289.      END IF
  290.        END IF
  291.    END IF
  292.  
  293. NOTE
  294.  
  295.    Initialization done when "what"=0 is not dependent on the correctness
  296.    of the supplied filespec but simply initializes internal variables
  297.    and makes a local copy of the supplied filespec.  If the supplied
  298.    filespec was illegal, the only effect is that the first time that
  299.    nextfile() is called with "what"=1, it will return the original
  300.    filespec instead of a matching filename.       That the filespec was
  301.    illegal will become obvious when the caller attempts to open the
  302.    returned filename for input/output and the open attempt fails.
  303.  
  304. USAGE HINTS
  305.  
  306. nextfile() can be used in the following manner:
  307.  
  308.       char *filespec;              -- will point to filespec
  309.       char *this_file;              -- will point to matching filename
  310.       filespec = parse_command_line();    -- may contain wildcards
  311.       FILE *stream;
  312.  
  313.       nextfile (0, filespec, 0);          -- initialize fileset 0
  314.       while ((this_file = nextfile(1, (char *) NULL, 0)) != NULL) {
  315.      stream = fopen (this_file, "whatever");
  316.      if (stream == NULL)
  317.         printf ("could not open %s\n", this_file);
  318.      else
  319.          perform_operations (stream);
  320.       }
  321. */
  322.  
  323. static int    first_time[FMAX + 1];
  324. static BPTR    filelock[FMAX + 1];
  325. static struct FileInfoBlock *fib[FMAX + 1];
  326.  
  327. char           *
  328. nextfile(what, filespec, fileset)
  329. int        what;        /* whether to initialize or match     */
  330. register char  *filespec;    /* filespec to match if initializing     */
  331. register int    fileset;    /* which set of files             */
  332. {
  333.     static char     pathholder[FMAX + 1][PATHSIZE];    /* holds a pathname to
  334.                              * return */
  335.     static char     saved_fspec[FMAX + 1][PATHSIZE];    /* our own copy of
  336.                              * filespec   */
  337.  
  338.     long        success;
  339.     char       *ph_fs;
  340.     BPTR        fl_fs;
  341.     struct FileInfoBlock *fib_fs;
  342.  
  343.     assert(fileset >= 0 && fileset <= FMAX);
  344.     ph_fs = pathholder[fileset];
  345.     fl_fs = filelock[fileset];
  346.     fib_fs = fib[fileset];
  347.     if (what == 0) {
  348.     assert(filespec != NULL);
  349.     strcpy(saved_fspec[fileset], nameptr(filespec));        /* save the filespec */
  350.     strcpy(ph_fs, filespec);/* save the path */
  351.     first_time[fileset] = 1;
  352.     return NULL;
  353.     }
  354.     assert(what == 1);
  355.     assert(filespec == NULL);
  356.     assert(first_time[fileset] == 0 || first_time[fileset] == 1);
  357.  
  358.     success = DOSFALSE;
  359.     if (first_time[fileset]) {  /* first time -- initialize etc. */
  360.     filelock[fileset] = fl_fs = 0;
  361.     if (!iswild(saved_fspec[fileset])) {
  362.         goto notwild;
  363.     }
  364.     if (fib[fileset] = fib_fs = malloc(sizeof (struct FileInfoBlock))) {
  365.         char       *np,
  366.                 n;
  367.  
  368.         np = nameptr(ph_fs);
  369.         n = *np;
  370.         *np = '\0';
  371.         if (filelock[fileset] = fl_fs = Lock(ph_fs, ACCESS_READ)) {
  372.         Examine(fl_fs, fib_fs);
  373.         assert(fib_fs->fib_DirEntryType > 0); /* ARK: fixed, using fib_fs instead of fib (7/Apr/98) */
  374.         }
  375.         *np = n;
  376.     }
  377.     }
  378.     /* find first or next matching file; skip directories (type > 0) */
  379.     if (fib_fs) {
  380.     for (;;) {
  381.         success = ExNext(fl_fs, fib_fs);
  382.         if (success == DOSFALSE)
  383.         break;
  384.         if (fib_fs->fib_DirEntryType > 0)
  385.         continue;
  386.         if (match_half(fib_fs->fib_FileName, saved_fspec[fileset]))
  387.         break;
  388.     }
  389.     }
  390.     if (success == DOSFALSE) {  /* if error status */
  391. notwild:
  392.     if (first_time[fileset]) {      /* if file never matched then */
  393.         first_time[fileset] = 0;
  394.         return ph_fs;    /* return original filespec */
  395.     } else {        /* else */
  396.         endfile(fileset);
  397.         return NULL;    /* return NULL for no more   */
  398.     }
  399.     } else {            /* a file matched */
  400.     first_time[fileset] = 0;
  401.     /* add path info     */
  402.     strcpy(nameptr(ph_fs), fib_fs->fib_FileName);
  403.     return ph_fs;        /* matching path  */
  404.     }
  405.     /* NOTREACHED */
  406. }                /* nextfile */
  407.  
  408. void
  409. endfile(fileset)
  410. int        fileset;
  411. {
  412.     assert(fileset >= 0 && fileset <= FMAX);
  413.     first_time[fileset] = 0;
  414.     if (fib[fileset]) {
  415.     free(fib[fileset]);
  416.     fib[fileset] = NULL;
  417.     }
  418.     if (filelock[fileset]) {
  419.     UnLock(filelock[fileset]);
  420.     filelock[fileset] = 0;
  421.     }
  422. }
  423.  
  424. #endif
  425.  
  426. char           *
  427. mktemp(name)
  428. char           *name;
  429. {
  430.     char       *x;
  431.  
  432.     if (x = strchr(name, 'X')) {
  433.     struct DateStamp ds;
  434.     long        rnd;
  435.     BPTR        lock;
  436.  
  437.     DateStamp(&ds);
  438.     rnd = (ds.ds_Days << 17) + (ds.ds_Minute << 6) + ds.ds_Tick;
  439.  
  440. retry:
  441.     rnd += (rnd >> 24);
  442.     sprintf(x, "%06lx", rnd & 0x00ffffff);
  443.     if (lock = Lock(name, ACCESS_READ)) {
  444.         UnLock(lock);
  445.         rnd--;
  446.         goto retry;
  447.     }
  448.     }
  449.     return name;
  450. }
  451.  
  452. #ifdef AZTEC_C
  453. # ifndef __STDC__
  454. /*
  455.  * A bit of a rough (and rude) implementation of realloc
  456.  */
  457. void           *
  458. realloc(oldptr, size)
  459. char           *oldptr;
  460. unsigned int    size;
  461. {
  462.     char       *newptr;
  463.  
  464.     newptr = malloc(size);
  465.     if (newptr) {
  466.     CopyMem(oldptr, newptr, (long) size);
  467.     free(oldptr);
  468.     }
  469.     return newptr;
  470. }
  471.  
  472. # endif
  473. #endif
  474.  
  475. void
  476. makedir(name)
  477. char           *name;
  478. {
  479.     BPTR        lock;
  480.  
  481.     if (lock = CreateDir(name)) {
  482.     UnLock(lock);
  483.     }
  484. }
  485.  
  486. #define BASEYEAR         1978
  487. #define DAYS_PER_YEAR         365
  488. #define HOURS_PER_DAY         24
  489. #define MINUTES_PER_HOUR     60
  490. #define SECONDS_PER_MINUTE  60
  491.  
  492. #define DAYS_PER_WEEK         7
  493. #define MONTHS_PER_YEAR      12
  494.  
  495. #define MINUTES_PER_DAY      (MINUTES_PER_HOUR * HOURS_PER_DAY)
  496. #define SECONDS_PER_DAY      ((long) SECONDS_PER_MINUTE * \
  497.                   MINUTES_PER_HOUR * HOURS_PER_DAY)
  498.  
  499. #define DATE_MIN         0x21    /* 1-jan-80 */
  500.  
  501. #define LeapYear(year)  ((year & 3) == 0)       /* From 1-Mar-1901 to
  502.                          * 28-Feb-2100 */
  503.  
  504. int        daycount[MONTHS_PER_YEAR] = {
  505.     31, 28, 31, 30, 31, 30,
  506.     31, 31, 30, 31, 30, 31
  507. };
  508.  
  509. void
  510. ToDateStamp(datestamp, date, time)
  511. struct DateStamp *datestamp;
  512. unsigned    date;
  513. unsigned    time;
  514. {
  515.     {
  516.     int        hours,
  517.             minutes,
  518.             seconds;
  519.  
  520.     seconds = (time & 31) * 2;
  521.     time >>= 5;
  522.     minutes = time & 63;
  523.     time >>= 6;
  524.     hours = time;
  525.  
  526.     datestamp->ds_Minute = MINUTES_PER_HOUR * hours + minutes;
  527.     datestamp->ds_Tick = TICKS_PER_SECOND * seconds;
  528.     }
  529.  
  530.     {
  531.     unsigned    i,
  532.             j,
  533.             t;
  534.     int        year,
  535.             month,
  536.             day;
  537.  
  538.     if (date < DATE_MIN)
  539.         date = DATE_MIN;
  540.  
  541.     day = date & 31;
  542.     date >>= 5;
  543.     month = (date & 15) - 1;
  544.     date >>= 4;
  545.     year = date + 1980;
  546.  
  547.     if ((unsigned) month > 11 ||
  548.         (unsigned) day > (unsigned) daycount[month]) {
  549.         day = 31;
  550.         month = 11;
  551.         year = 1979;
  552.     }
  553.     j = year - BASEYEAR;
  554.  
  555.     /*
  556.      * Get the next lower full leap period (4 years and a day) since
  557.      * ...
  558.      */
  559.     t = (year - BASEYEAR) & ~3;
  560.     i = t;
  561.     t = (t / 4) * (4 * DAYS_PER_YEAR + 1);
  562.  
  563.     /* t now is the number of days in 4 whole years since ... */
  564.  
  565.     while (i < j) {
  566.         t += DAYS_PER_YEAR;
  567.         if (LeapYear(i + BASEYEAR)) {
  568.         t++;
  569.         }
  570.         i++;
  571.     }
  572.  
  573.     /* t now is the number of days in whole years since ... */
  574.  
  575.     for (i = 0; i < month; i++) {
  576.         t += daycount[i];
  577.         if (i == 1 && LeapYear(year)) {
  578.         t++;
  579.         }
  580.     }
  581.  
  582.     /* t now is the number of days in whole months since ... */
  583.  
  584.     t += day - 1;
  585.  
  586.     /* t now is the number of days in whole days since ... */
  587.  
  588.     datestamp->ds_Days = t;
  589.     }
  590. }
  591.  
  592. void
  593. ToMSDate(date, time, datestamp)
  594. unsigned       *date;
  595. unsigned       *time;
  596. register struct DateStamp *datestamp;
  597. {
  598.     {
  599.     unsigned short    hours,
  600.             minutes,
  601.             seconds;
  602.  
  603.     hours = datestamp->ds_Minute / MINUTES_PER_HOUR;
  604.     minutes = datestamp->ds_Minute % MINUTES_PER_HOUR;
  605.     seconds = datestamp->ds_Tick / TICKS_PER_SECOND;
  606.  
  607.     *time = (hours << 11) | (minutes << 5) | (seconds / 2);
  608.     }
  609.     {
  610.     register long    days,
  611.             i,
  612.             t;
  613.     int        year,
  614.             month,
  615.             day;
  616.  
  617.     days = datestamp->ds_Days;
  618.  
  619.     year = BASEYEAR + (days / (4 * DAYS_PER_YEAR + 1)) * 4;
  620.     days %= 4 * DAYS_PER_YEAR + 1;
  621.     while (days) {
  622.         t = DAYS_PER_YEAR;
  623.         if (LeapYear(year))
  624.         t++;
  625.         if (days < t)
  626.         break;
  627.         days -= t;
  628.         year++;
  629.     }
  630.     days++;
  631.     for (i = 0; i < MONTHS_PER_YEAR; i++) {
  632.         t = daycount[i];
  633.         if (i == 1 && LeapYear(year))
  634.         t++;
  635.         if (days <= t)
  636.         break;
  637.         days -= t;
  638.     }
  639.     month = i + 1;
  640.     day = days;
  641.  
  642.     *date = ((year - 1980) << 9) | (month << 5) | day;
  643.     }
  644. }
  645.  
  646. void spec_init    PARMS((void));
  647. void
  648. spec_init()
  649. {
  650. #ifndef NOSIGNAL
  651.     signal(SIGINT, _abort);
  652. #endif
  653. }
  654.  
  655. void
  656. zooexit(code)
  657. int        code;
  658. {
  659.     int         i;
  660.  
  661. #ifdef SPECNEXT
  662.     for (i = 0; i <= FMAX; i++)
  663.     endfile(i);
  664. #endif
  665.  
  666.     exit(code);
  667. }
  668.  
  669. /*
  670.  * called by DB debugger and on CTRL-C.
  671.  */
  672. void
  673. _abort()
  674. {
  675.     zooexit(20);
  676. }
  677.  
  678. #ifdef NEED_SIGNAL
  679.  
  680. /*
  681.  * A minimalistic signal implementation, that ignores the signal number,
  682.  * which is assumed to be SIGINT.
  683.  */
  684.  
  685. static void    (*Handler) PARMS((int));
  686.  
  687. void
  688. (*signal(sig, handler)) PARMS((int))
  689. int        sig;
  690. void        (*handler) PARMS((int));
  691. {
  692.     void        (*oldhandler) PARMS((int));
  693.  
  694.     assert(sig == SIGINT);
  695.  
  696.     oldhandler = Handler;
  697.     Handler = handler;
  698.     Chk_Abort();
  699.  
  700.     return oldhandler;
  701. }
  702.  
  703. /*
  704.  * This function should have the name that is used by your C library to
  705.  * poll CTRL-C.
  706.  */
  707.  
  708. long
  709. Chk_Abort PARMS((void))
  710. {
  711.     if (Handler == SIG_IGN) {
  712.     /*
  713.      * Don't clear the signal; if the user wants to abort we'll do
  714.      * that when it is allowed again.
  715.      */
  716.     return 0;
  717.     }
  718.     if ((SetSignal(0L, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C)) {
  719.     void        (*oldhandler) PARMS((int));
  720.  
  721.     oldhandler = Handler;
  722.     Handler = SIG_DFL;
  723.     if (oldhandler == SIG_DFL) {
  724.         _abort();           /* must call zooexit() */
  725.         zooexit(20);        /* just in case */
  726.     }
  727.     (*oldhandler) (SIGINT);
  728.     return 1;
  729.     }
  730.     return 0;
  731. }
  732.  
  733. #endif
  734.