Notes for MagiC 3 and later versions (SHUTDOWN process)
-------------------------------------------------------

Andreas Kromke
12.11.95
English translation: Peter West, April 99.

Attention: Changes to process from 28.6.95
           Vulture support from 11.11.95


1. General
----------

With a multitasking system it is really no longer permissible to just 
switch off the computer after use. Resetting (with the Reset button)
is taboo as well. Instead one has to ensure that all programs have been 
terminated correctly and all files closed properly before one switches 
off the power to the system. Otherwise one may lose data.

For this reason other systems such as UNIX or the Macintosh have a 
so-called shutdown process. This was also introduced by Atari for MultiTOS 
and is now incorporated in MagiC 3 (and up) as well.

The shutdown is activated with the menu entry "Options/Shutdown" (in 
Magxdesk 3) or "File/Shutdown" (Magxdesk 2.5). Furthermore the shutdown 
can be activated with the key combination Ctrl-Alt-Del, or by a resolution 
change. The latter is performed in Magxdesk 3 with "Options/Change 
Resolution" or in MAGXDESK 2.5 via the dialog "Options/Change settings". 
During the shutdown one can not start any programs.

All running programs receive a message ("AP_TERM"), instructing them 
to terminate themselves. If after a given time (set by the keyword
"timeout" in the configuration file SHUTDOWN.INF, value in milliseconds)
there are still programs in memory, then SHUTDOWN will issue an error 
message. A timeout value of 0 means that SHUTDOWN.PRG will wait forever,
i.e. a program that understands AP_TERM but is stuck in an endless loop 
will bring the system to a halt. In the SHUTDOWN.INF file you can, 
moreover, specify program names (without the ".prg" or ".app") that are
"well behaved" and not critical and so should not lead to error messages
from SHUTDOWN.

After all programs in memory have been terminated, or may be ignored,
SHUTDOWN.PRG executes all programs (*.prg) in the \gemsys\magic\stop 
directory. Following this all GEMDOS device files (-1,-2,-3) are 
redirected to u:\dev\null (i.e. to -4) and all devices in u:\dev\ are 
deleted. During this the device drivers can unhook themselves from the 
system vectors.

Older versions of MagicMac are best terminated by first activating the 
shutdown in "Atari" mode. When an Atari dialog informs you that you 
may now switch off, do NOT switch off the Mac but terminate MagicMac
with [Command]-Q; directly on top of the Atari alert a similar one from 
the MacOS will appear (very plain and simple and hence nowhere near as
good looking!). Now you can close down your Mac safely by activating the
corresponding button of the Mac dialog.
Newer versions of MagicMac are terminated automatically, i.e. SHUTDOWN.PRG 
leads back directly to the Macintosh Finder.

Note: If you want to shut down the system via Ctrl-Alt-Del, you must make
      sure that the screen is not blocked at the time, say by a program 
      handling a dialog or alert box on the screen. Furthermore the shell 
      (generally MAGXDESK) must be loaded, i.e. no program may have been 
      loaded in "single mode" or in the "Shell not resident" mode (e.g. 
      with Alt+double-click).
      If the screen is blocked then only the writeback-daemon will be 
      terminated, i.e. the cache will be written back. Only after the 
      screen has been released (by closing the dialog or alert box) is it 
      possible to perform the shutdown. If the system has crashed so 
      heavily that a shutdown is no longer possible, press Ctrl-Alt-Del 
      for a second time; this performs a warm start without terminating 
      programs. If the "single mode" is active or the shell not loaded, 
      then here too just the writeback-daemon will be terminated and the 
      cache written back. For a complete shutdown the running program
      must be terminated first, so that the shell is active once more. 
      In that case the shutdown MUST be performed via the menu entry 
      "Options/Shutdown" or "File/Shutdown" respectively.


2. From the application's point of view
---------------------------------------

During shutdown or a resolution change the following message is sent to 
every program:

msg[0]         AP_TERM (50)
msg[1]         ap_id of the application that has triggered the shutdown
           -1 for Ctrl-Alt-Del (no initiator)
msg[2]      0           i.e. no message overflow
msg[3]      as msg[1]
msg[4]      0
msg[5]         AP_TERM    (50)     for a shutdown
               AP_RESCHNG (57)     for a resolution change

Note: If Ctrl-Alt-Del was pressed, only the writeback-daemon and the 
      application 0 will receive a AP_TERM-message at first.
      As initiator -1 will be entered here in buf[1] and buf[3].
      buf[5] is AP_TERM.
      The application #0 (generally the shell MAGXDESK) then terminates 
      itself and starts the shutdown program SHUTDOWN.PRG. This property 
      can be exploited by simulating a Ctrl-Alt-Del and sending a 
      corresponding message to application #0, rather than undertaking 
      one's own shutdown handling. Note that MAGXDESK can not receive 
      the message if another program is currently being handled (in 
      "single" or "non-resident" modes). However this may be tested
      with appl_find().

The manner in which MagiC handles applications during shutdown depends 
on whether these have informed the AES that they understand the AP_TERM 
message. With shel_write and doex = SHW_INFRECGN (9) an application 
signals via the parameter <isgr> which messages it understands. A set 
bit 0 of <isgr> here means that AP_TERM is understood.

While MultiTOS only sends AP_TERM to those applications that explicitly 
understand AP_TERM, MagiC sends this message to all applications. The 
shutdown will be regarded as "successful" by the AES if all applications
that explicitly understand AP_TERM have terminated themselves. A special
case occurs if all these applications terminate but further programs 
remain within the system;  here the AES returns a special message (see 
below). The AES will only abort the shutdown if an application informs the 
AES that it cannot terminate itself. Thus an application that has received 
AP_TERM has only two permitted options in principle:

a) The application terminates immediately
b) The application makes the following call:

     int msg[8];
     msg[0] = AP_TFAIL /*51*/;
     msg[1] = err;
     shel_write(SHW_AESSEND /*10*/, 0, 0, (char *) msg, NULL);

   and with that informs the AES that the process was interrupted with the 
   error message <err>. The application that originated the shutdown has 
   returned to it the ap_id and the error code of the interrupting 
   application.

If the application reacts a different way, i.e. if it ignores the AP_TERM
message, then the behaviour of the system depends on whether the system 
was notified that the application understands AP_TERM:

a) If the applications explicitly understands AP_TERM, the system assumes 
   that the application can not receive messages at the present time.
   This means that the shutdown process will not be aborted, but will 
   continue until the caller (i.e. in general the SHUTDOWN program) breaks 
   off the shutdown. For this SHUTDOWN uses a timeout, which is set in 
   SHUTDOWN.INF to 10s as a default; this means that if 10 seconds after 
   starting the shutdown there are still programs active that understand 
   the AP_TERM message, SHUTDOWN will abort the shutdown process. One can 
   also set the timeout to 0, in which case SHUTDOWN will abort. If 
   however an application "sticks", one has to terminate it, or SHUTDOWN 
   itself, via the program manager (Ctrl-Alt-Esc).

b) If the application does not explicitly understand AP_TERM, the system 
   informs the initiator of the shutdown (i.e. generally SHUTDOWN.PRG) of 
   an unsuccessful (!) termination of the shutdown processs; this means 
   that the shutdown mode is automatically deactivated by the system. As 
   the SHUTDOWN.PRG is very patient with old programs, it tests whether 
   any applications are still active, and if so issues a message. For this 
   one can specify in SHUTDOWN.INF programs that should not produce an 
   error message, i.e. that do not need to be terminated.


3. From the initiator's point of view
-------------------------------------

The shutdown process and resolution changes in MagiC 3 (and up) are 
undertaken by the SHUTDOWN program. In principle there is no need to 
develop one's own program for this, i.e. to perform the shutdown oneself.
SHUTDOWN.PRG is called with the following parameters:

     SHUTDOWN.PRG <dev> <txt>

or, from MagiC 4 onwards:

     SHUTDOWN.PRG <dev> <txt> <xdv>

Here <dev> = -1 if a shutdown is to be performed without a resolution 
change, otherwise the device number of the VDI screen-driver.
<txt> is the text height for the AES, which generally should be zero 
(i.e. default height).
If a Falcon resolution is to be et, one can additionally specify the 
Falcon-mode word <xdv>.

If one nevertheless decides to produce one's own "low level" solution,
the following applies:

A shutdown is performed with the following system call:

     ret = shel_write(SHW_SHUTDOWN /*4*/, TRUE, 0, NULL, NULL));

A return value of 0 means that a shutdown is not possible because, for 
instance, a shutdown application is already running. Additionally a 
shutdown may not be performed if the caller has blocked the screen with
wind_update(BEG_UDPATE) or wind_update(BEG_MCTRL), as in that case the 
other programs cannot terminate. However, for reasons of compatibility 
with MultiTOS this is not checked by the system (starting from the version 
dated 17.5.95).
If successful, ret = 1.

A resolution change is performed with the following system call:

     ret = shel_write(SHW_RESCHNG /*5*/, dev, 0, NULL, NULL));

Here <dev> is the VDI device driver. Alternatively one can use:

     ret = shel_write(SHW_RESCHNG /*5*/, xdv, 1, NULL, NULL));

where <xdv> specifies a Falcon resolution-mode.

These calls all conform to the MultiTOS convention. In addition the 
following call also exists in MagiC 3:

     ret = shel_write(SHW_RESCHNG /*5*/, dev, 100+txt, NULL, NULL));

With this one can specify the text height for the AES. One can not pass a 
Falcon resolution in this mode, so <dev> is the device number of the VDI 
screen-driver.

This call was replaced (!) in MagiC 4 by:

     ret = shel_write(SHW_RESCHNG /*5*/, dev, (txt<<8), NULL, NULL));
or:
     ret = shel_write(SHW_RESCHNG /*5*/, xdv, (txt<<8)+(dev<<1)+1, NULL, NULL));

Here one can specify the text height for the AES in the high byte of the 
third parameter, both for Falcon resolutions as well as for normal VDI
device numbers. In addition one can specify a VDI device also for the 
Falcon in bits 1..4 of the same parameter, where 0 corresponds to device 5
(Falcon standard).

The device number depends on the operating system and the VDI (or NVDI or
Nova-VDI etc.). With a "plain" ST, TT or Falcon without a graphics card
the following assignments apply:

     1    Default resolution
     2    ST low      (320*200*16)
     3    ST medium   (640*200*4)
     4    ST high     (640*400*2)
     5    Falcon modes with additional mode-codes
     6    TT medium   (640*480*16)
     8    TT high     (1280*960*2)
     9    TT low      (320*480*256)

When using a graphics card or on a Mac the device numbers are included in 
the file ASSIGN.SYS in the root directory of the booting partition.

After a successful shel_write call the system will be in the shutdown mode 
and no further programs can be started. After a successful conclusion of 
a shutdown or resolution change the initiator will receive the following 
message:

     msg[0] = SHUT_COMPLETED  (60)
     msg[3] = 1 - Shutdown successful

or, for a resolution change:

     msg[0] = RESCH_COMPLETED  (61)
     msg[3] = 1 - Resolution change successful

"Successful" for the system means that all programs that explicitly 
understand AP_TERM have terminated themselves, and that no further 
programs remain active (other than perhaps desk accessories). 
If the sutdown should nevertheless be aborted, one can break off the 
shutdown mode or the resolution change with:

     ret = shel_write(SHW_SHUTDOWN /*4*/, FALSE, 0, NULL, NULL));

Otherwise the resolution change will be performed finally when the 
initiator has terminated itself. In contrast the shutdown will be aborted 
when the initiator terminates.

If a program has refused a shutdown with AP_TFAIL (see above), the 
initiator will receive the following message:

     msg[0] = SHUT_COMPLETED  (60)
     msg[3] = 0 - Shutdown aborted
     msg[4] = ap_id of the application that has refused, or -1
     msg[5] = Error code of this application (see above)

or, for a resolution change:

     msg[0] = RESCH_COMPLETED  (61)
     msg[3] = 0 - Resolution change aborted
     msg[4] = ap_id of the application that has refused, or -1
     msg[5] = Error code of this application (see above)

In this case the system has already aborted the shutdown or resolution 
change, i.e the initiator cannot do any more.
If msg[4] == -1, then all programs that explicitly understand AP_TERM 
have been terminated; however there are still further programs running on 
the system (ACCs do not count here).

As it may happen (for instance with XCONTROL) that the system never 
reports that the shutdown process has been completed or aborted (i.e. 
the message RESCH_COMPLETED or SHUT_COMPLETED is never sent), there should 
be provision for a timeout in the initiator's wait for the message. If 
this occurs then the shutdown must be aborted explicitly (see above).

With appl_search() the initiator can test whether programs are still 
active that do not explicitly understand AP_TERM. That is the way that 
SHUTDOWN.PRG works.
