Skip to content

od_exit()

The OpenDoors program termination function

Synopsis

void od_exit(INT nErrorLevel, BOOL bTermCall);

Return value

N/A

Description

Use this function whenever an initialized door is to terminate. Calling the C exit() function directly bypasses OpenDoors cleanup. od_exit() updates time accounting, invokes the application's before-exit callback, rewrites supported door-information files, closes the activity log, optionally disconnects the caller, shuts down the kernel and communications objects, restores the local display, and terminates the process with nErrorLevel.

Failure of the activity log's final entry, flush, or close does not prevent the remaining shutdown work and does not replace nErrorLevel. OpenDoors records the logging diagnosis in od_control.od_error before continuing. The same rule applies when a supported door-information file cannot be opened, written, flushed, or closed. Failure to open the file records ERR_FILEOPEN; an output or close failure records ERR_GENERALFAILURE. Because the text formats are opened in replacement mode and EXITINFO.BBS is updated in place, a failed rewrite may leave a truncated or partially updated file.

If bTermCall is TRUE, OpenDoors treats the operation as termination of the call. For a remote session it waits up to ten seconds for pending output, lowers DTR or performs the equivalent disconnect operation supplied by the active communications method, waits up to five seconds for carrier to disappear, and then raises DTR again where that operation is supported. The BBS can then perform its normal logoff processing. A value of FALSE leaves the remote connection available for the BBS which launched the door.

If your program must always perform work before exiting, such as updating or closing data files, install an od_control.od_before_exit callback. OpenDoors invokes it even when the library initiates termination, such as after the caller hangs up. The callback runs after OpenDoors has calculated the caller's remaining and used time and restored the original drop-file baud value, but before any door-information file is rewritten or communications resource is closed. A recursive call to od_exit() from that callback is ignored.

Only formats for which OpenDoors has a rewrite implementation are updated. For the extended RemoteAccess and QuickBBS EXITINFO.BBS variants, the fields available in that record are copied back. Several supported text formats are rewritten from the values retained during initialization and the current values in od_control. Fields which are written for each format are identified individually in the control-structure reference. When the system clock is unavailable or has moved backwards, OpenDoors retains the existing used-time value. A primitive EXITINFO.BBS rewrite also retains the time limit read from the BBS rather than deriving an adjustment from an invalid elapsed interval; the remaining fields are still rewritten.

Setting DIS_INFOFILE in od_control.od_disable before initialization prevents both reading and later rewriting a door-information file. Setting od_control.od_noexit causes od_exit() to perform the complete OpenDoors shutdown and then return instead of terminating the process. The application may continue doing work which does not use OpenDoors. The library is permanently terminal: it cannot initialize a second session, and a later OpenDoors function call is rejected with its normal neutral or failure value and ERR_GENERALFAILURE. The exported od_control object remains available for direct reads by the host after shutdown.

The before-exit callback runs before OpenDoors decides whether od_noexit applies, so it may set or clear that field based on application state. If a callback or nested kernel operation requests a returning shutdown, OpenDoors records the first request, causes cooperative waits to stop, and defers resource destruction until the outermost public API call unwinds. A request made during initialization is likewise retained; initialization completes before the one shutdown sequence begins.

On non-Windows text-mode targets, the local output window is reset to the full 80-by-25 display and the attribute is reset to grey on black. If od_control.od_clear_on_exit is TRUE, the local display is cleared; otherwise the cursor is moved to the upper-left corner. Platform display resources are then closed in either case.

If od_exit() is called before any other OpenDoors function, it first calls od_init() so that the resources and session information needed for an orderly shutdown exist. The function normally does not return. It can return when od_noexit is set, when a recursive exit is suppressed, when shutdown is deferred to an outer API boundary, or when it is running as part of an already active process-exit handler.

Examples

The example below demonstrates a function which a door could execute when the user chooses to exit the door. This function will ask the user whether they wish to exit the door and return to the BBS, simply logoff of the BBS, or continue using the door. The example function will then call od_exit() if the user wishes to exit the door, or return control to the function which called it, if the user does not wish to exit:

void goodbye(void)
{
   char pressed;

   od_disp_str("You have chosen to exit this door.\n\r");
   od_disp_str("Do you wish to:\n\r");
   od_disp_str("      [R]eturn to the BBS\n\r");
   od_disp_str("      [L]og off the BBS\n\r");
   od_disp_str("      [C]ontinue using the door\n\r");

   for(;;)
   {
      pressed = od_get_key(TRUE);

      if(pressed == 'R' || pressed == 'r')
         od_exit(40, FALSE);

      if(pressed == 'L' || pressed == 'l')
         od_exit(41, TRUE);

      if(pressed == 'C' || pressed == 'c')
         return;
   }
}

See also

od_init(), od_set_dtr(), Session lifecycle