home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / lang / thinkc30.sit / onexit.c < prev    next >
Text File  |  1989-01-25  |  4KB  |  267 lines

  1.  
  2. /*
  3.  *  onexit.c - Copyright (C) 1989 by Symantec Corp.  All rights reserved.
  4.  *
  5.  *  Shutdown routines installed with "onexit" are called only on NORMAL
  6.  *  termination, i.e. calling "exit" or returning from "main".
  7.  *
  8.  *  Shutdown routines installed with "_onexit" are called on "ExitToShell"
  9.  *  as well as on normal termination.
  10.  *
  11.  *  When initiating any other form of termination (e.g. "Launch"), the
  12.  *  user can call "_exiting" to force shutdown routines to be called.
  13.  *
  14.  */
  15.  
  16. #ifndef _MacTypes_
  17. #include <MacHeaders>
  18. #endif
  19.  
  20. extern long ATrapHandler : 0x28;
  21.  
  22. typedef void (*Proc)();
  23.  
  24. Proc onexit(Proc);
  25. Proc _onexit(Proc);
  26. void _exiting(int);
  27. void exit(int);
  28. void nop(void);
  29. void abort(void);
  30.  
  31. #define NPROCS        32
  32.  
  33. static struct proc { Proc proc; int always; } procs[NPROCS];
  34. static int next = 0;
  35. static Proc oldexit, oldES;
  36. static char *ptrES;
  37.  
  38. static void normal_exit(void), newES(void);
  39.  
  40.  
  41. /*
  42.  *  exit - normal program termination
  43.  *
  44.  *  The exit status is ignored.
  45.  *
  46.  */
  47.  
  48. void
  49. exit(i)
  50. {
  51.     asm {
  52.         movea.l    0x6C(a5),a0
  53.         jsr        (a0)            ;  call onexit vector
  54.         _ExitToShell
  55.     }
  56. }
  57.  
  58.  
  59. /*
  60.  *  onexit - install user shutdown routine
  61.  *
  62.  */
  63.  
  64. Proc
  65. onexit(proc)
  66. Proc proc;
  67. {
  68.     register struct proc *p;
  69.     
  70.     if (next == NPROCS)
  71.         return(0);
  72.         
  73.             /*  install proc in table  */
  74.             
  75.     p = &procs[next++];
  76.     p->proc = proc;
  77. /*    p->always = 0;    */
  78.     if (!oldexit) {
  79.         proc = normal_exit;
  80.         
  81.             /*  install onexit vector  */
  82.             
  83.         asm {
  84.             move.l    0x6C(a5),oldexit
  85.             move.l    proc,0x6C(a5)
  86.         }
  87.     }
  88.     return(p->proc);
  89. }
  90.  
  91.  
  92. /*
  93.  *  normal_exit - onexit vector
  94.  *
  95.  */
  96.  
  97. static void
  98. normal_exit()
  99. {
  100.     _exiting(1);
  101. }
  102.  
  103.  
  104. /*
  105.  *  _onexit - install a critical shutdown routine
  106.  *
  107.  *  Routines installed with "_onexit" are called even if the program does
  108.  *  not terminate normally, provided only that "ExitToShell" is called.
  109.  *
  110.  */
  111.  
  112. Proc
  113. _onexit(proc)
  114. Proc proc;
  115. {
  116.     register struct proc *p;
  117.     
  118.     if (next == NPROCS)
  119.         return(0);
  120.         
  121.             /*  install proc in table  */
  122.             
  123.     p = &procs[next++];
  124.     p->proc = proc;
  125.     p->always = 1;
  126.     if (!oldES) {
  127.         proc = newES;
  128.         
  129.             /*  save original ExitToShell  */
  130.             
  131.         asm {
  132.             move.w    #0xA9F4,d0        ;  _ExitToShell
  133.             _GetTrapAddress
  134.             move.l    a0,oldES
  135.         }
  136.         
  137.             /*  (64K ROM only) allocate intercept in sysheap  */
  138.         
  139.         asm {
  140.             movea.l    proc,a0
  141.             tst.w    ROM85
  142.             bpl.s    @1
  143.             moveq    #6,d0
  144.             _NewPtr  SYS
  145.             move.l    a0,ptrES
  146.             move.w    #0x4EF9,(a0)    ;  JMP abs.L
  147.             move.l    proc,2(a0)
  148. @1        }
  149.  
  150.             /*  install ExitToShell intercept  */
  151.         
  152.         asm {
  153.             move.w    #0xA9F4,d0        ;  _ExitToShell
  154.             _SetTrapAddress
  155.         }
  156.     }
  157.     return(p->proc);
  158. }
  159.  
  160.  
  161. /*
  162.  *  newES - ExitToShell intercept
  163.  *
  164.  */
  165.  
  166. static void
  167. newES()
  168. {
  169.     _exiting(0);
  170.     ExitToShell();
  171. }
  172.  
  173.  
  174. /*
  175.  *  _exiting - perform shutdown activity
  176.  *
  177.  *  The argument controls which shutdown routines should be called:
  178.  *
  179.  *        _exiting(1)        call all installed shutdown routines
  180.  *        _exiting(0)        call only routines installed with "_onexit"
  181.  *
  182.  */
  183.  
  184. void
  185. _exiting(normally)
  186. {
  187.     register struct proc *p;
  188.     Proc proc;
  189.     int i;
  190.     
  191.     SetUpA5();
  192.     p = &procs[NPROCS];
  193.     for (i = NPROCS; i--; ) {
  194.         if (proc = (--p)->proc) {
  195.             p->proc = 0;
  196.             if (normally || p->always)
  197.                 (*proc)();
  198.         }
  199.     }
  200.     
  201.         /*  deallocate ExitToShell intercept  */
  202.         
  203.     asm {
  204.         move.l    ptrES,d0
  205.         beq.s    @1
  206.         movea.l    d0,a0
  207.         _DisposPtr
  208.         clr.l    ptrES
  209. @1    }
  210.  
  211.         /*  remove ExitToShell intercept  */
  212.         
  213.     asm {
  214.         move.l    oldES,d0
  215.         beq.s    @2
  216.         movea.l    d0,a0
  217.         move.w    #0xA9F4,d0
  218.         _SetTrapAddress
  219.         clr.l    oldES
  220. @2    }
  221.  
  222.         /*  call original exit proc  */
  223.  
  224.     asm {
  225.         movea.l    0x6C(a5),a0
  226.         move.l    oldexit,d0
  227.         beq.s    @3
  228.         movea.l    d0,a0
  229. @3        jsr        (a0)
  230.     }
  231.     oldexit = nop;
  232.     RestoreA5();
  233. }
  234.  
  235.  
  236. /*
  237.  *  nop - do nothing
  238.  *
  239.  */
  240.  
  241. static void
  242. nop()
  243. {
  244. }
  245.  
  246.  
  247. /*
  248.  *  abort - abort execution
  249.  *
  250.  *  A debugger trap is issued if it looks like a debugger is installed.
  251.  *
  252.  */
  253.  
  254. void
  255. abort()
  256. {
  257.     if (GetTrapAddress(0xA055) == GetTrapAddress(0xA89F)) {
  258.         if ((ATrapHandler & Lo3Bytes) < ((long) ROMBase & Lo3Bytes))
  259.             Debugger();
  260.     }
  261.     else {
  262.         if (StripAddress(ATrapHandler) < StripAddress(ROMBase))
  263.             Debugger();
  264.     }
  265.     ExitToShell();
  266. }
  267.