File:  [Coherent Logic Development] / freem / src / init.c
Revision 1.18: download - view: text, annotated - select for diffs
Thu Mar 19 19:03:58 2026 UTC (12 days, 10 hours ago) by snw
Branches: MAIN
CVS tags: HEAD
Attempt to rectify terminal corruption problem when the user performs a gracious exit

    1: /*
    2:  *   $Id: init.c,v 1.18 2026/03/19 19:03:58 snw Exp $
    3:  *    FreeM initialization 
    4:  *
    5:  *  
    6:  *   Author: Serena Willis <snw@coherent-logic.com>
    7:  *    Copyright (C) 1998 MUG Deutschland
    8:  *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
    9:  *
   10:  *
   11:  *   This file is part of FreeM.
   12:  *
   13:  *   FreeM is free software: you can redistribute it and/or modify
   14:  *   it under the terms of the GNU Affero Public License as published by
   15:  *   the Free Software Foundation, either version 3 of the License, or
   16:  *   (at your option) any later version.
   17:  *
   18:  *   FreeM is distributed in the hope that it will be useful,
   19:  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   20:  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21:  *   GNU Affero Public License for more details.
   22:  *
   23:  *   You should have received a copy of the GNU Affero Public License
   24:  *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
   25:  *
   26:  *   $Log: init.c,v $
   27:  *   Revision 1.18  2026/03/19 19:03:58  snw
   28:  *   Attempt to rectify terminal corruption problem when the user performs a gracious exit
   29:  *
   30:  *   Revision 1.17  2026/03/14 21:04:51  snw
   31:  *   Fix segfault in OPEN command with I/O channel specified but no file
   32:  *
   33:  *   Revision 1.16  2026/01/07 19:51:33  snw
   34:  *   Fix segfault in reverse $QUERY
   35:  *
   36:  *   Revision 1.15  2025/05/16 04:02:14  snw
   37:  *   Make FreeM build on macOS on Apple Silicon
   38:  *
   39:  *   Revision 1.14  2025/04/20 03:13:17  snw
   40:  *   Updates to init_execution_context
   41:  *
   42:  *   Revision 1.13  2025/04/17 14:34:27  snw
   43:  *   Further logging improvements
   44:  *
   45:  *   Revision 1.12  2025/04/15 14:39:06  snw
   46:  *   Further improvements to logging
   47:  *
   48:  *   Revision 1.11  2025/04/13 04:22:43  snw
   49:  *   Fix snprintf calls
   50:  *
   51:  *   Revision 1.10  2025/04/10 01:24:38  snw
   52:  *   Remove C++ style comments
   53:  *
   54:  *   Revision 1.9  2025/04/03 16:58:34  snw
   55:  *   Make error message for shm_init error during initialization more friendly
   56:  *
   57:  *   Revision 1.8  2025/03/24 04:44:55  snw
   58:  *   Don't call ttyname on OS/2
   59:  *
   60:  *   Revision 1.7  2025/03/24 04:05:36  snw
   61:  *   Replace crlf with frm_crlf to avoid symbol conflict with readline on OS/2
   62:  *
   63:  *   Revision 1.6  2025/03/09 19:14:25  snw
   64:  *   First phase of REUSE compliance and header reformat
   65:  *
   66:  *
   67:  * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
   68:  * SPDX-License-Identifier: AGPL-3.0-or-later
   69:  **/
   70: 
   71: #include <stdio.h>
   72: #include <stdlib.h>
   73: #include <string.h>
   74: #include <unistd.h>
   75: #include <limits.h>
   76: #include <sys/types.h>
   77: #include <sys/stat.h>
   78: #include <pwd.h>
   79: #include <time.h>
   80: #include <errno.h>
   81: #include <sys/ioctl.h>
   82: 
   83: #if !defined(__APPLE__) && !defined(__gnu_hurd__) && !defined(EMSCRIPTEN)
   84: # if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__AMIGA)
   85: #  include <termios.h>
   86: #  if !defined(__AMIGA)
   87: #   define TCGETA TIOCGETA
   88: #   define TCSETA TIOCSETA
   89: #  endif
   90: #  define termio termios
   91: # else
   92: #  if !defined(MSDOS) && !defined(__linux__)
   93: #    include <termio.h>
   94: #  else
   95: #    include <termios.h>
   96: #    define termio termios
   97: #  endif
   98: # endif
   99: #else
  100: # include <termios.h>
  101: #endif
  102: 
  103: 
  104: #if defined(__APPLE__)
  105: # define termio termios
  106: # define TCGETA TIOCGETA
  107: # define TCSETA TIOCSETA
  108: #endif
  109: 
  110: #include "config.h"
  111: 
  112: #if defined(HAVE_MWAPI_MOTIF)
  113: # include <Xm/Xm.h>
  114: #endif
  115: 
  116: #include "mpsdef.h"
  117: #include "transact.h"
  118: #include "namespace.h"
  119: #include "events.h"
  120: #include "mdebug.h"
  121: #include "shmmgr.h"
  122: #include "locktab.h"
  123: #include "jobtab.h"
  124: #include "datatypes.h"
  125: #include "objects.h"
  126: #include "log.h"
  127: 
  128: #ifdef HAVE_LIBREADLINE
  129: #  if defined(HAVE_READLINE_READLINE_H)
  130: #    include <readline/readline.h>
  131: #  elif defined(HAVE_READLINE_H)
  132: #    include <readline.h>
  133: #  else /* !defined(HAVE_READLINE_H) */
  134: extern char *readline ();
  135: #  endif /* !defined(HAVE_READLINE_H) */
  136: char *cmdline = NULL;
  137: #else /* !defined(HAVE_READLINE_READLINE_H) */
  138:   /* no readline */
  139: #endif /* HAVE_LIBREADLINE */
  140: 
  141: #ifdef HAVE_READLINE_HISTORY
  142: #  if defined(HAVE_READLINE_HISTORY_H)
  143: #    include <readline/history.h>
  144: #  elif defined(HAVE_HISTORY_H)
  145: #    include <history.h>
  146: #  else /* !defined(HAVE_HISTORY_H) */
  147: extern void add_history ();
  148: extern int write_history ();
  149: extern int read_history ();
  150: #  endif /* defined(HAVE_READLINE_HISTORY_H) */
  151:   /* no history */
  152: #endif /* HAVE_READLINE_HISTORY */
  153: 
  154: #if defined(HAVE_WIRINGPI_H)
  155: # include <wiringPi.h>
  156: #endif
  157: 
  158: #if !defined(PATH_MAX) && defined(_SCO_DS)
  159: # define PATH_MAX 4096
  160: #endif
  161: 
  162: #if !defined(PATH_MAX) && defined(__gnu_hurd__)
  163: # define PATH_MAX 1024
  164: #endif
  165: 
  166: #if !defined(PATH_MAX) && defined(__sun__)
  167: # include <limits.h>
  168: #endif
  169: 
  170: #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)
  171: # include <sys/syslimits.h>
  172: #endif
  173: 
  174: #define SHMKEY 0x990120
  175: #define SHMSIZ 1048576
  176: 
  177: void init_process(void);
  178: void init_devtable(void);
  179: void init_signals(void);
  180: void init_timezone(void);
  181: void init_freem_path(void);
  182: 
  183: #if defined(HAVE_LIBREADLINE)
  184: void init_readline(void);
  185: #endif
  186: 
  187: void init_execution_context(void);
  188: void init_io(void);
  189: void init_random_number(void);
  190: void init_ztrap(void);
  191: void init_ssvn(void);
  192: void init_terminal(void);
  193: void init_estack(void);
  194: 
  195: void init_mwapi(void);
  196: 
  197: short init (char *namespace_name) 
  198: {
  199:     short retval;
  200:     int log_level;
  201:     
  202:     init_log ();
  203:     init_process ();
  204:     init_devtable ();
  205:     init_signals ();
  206:     init_freem_path ();
  207:     init_timezone ();
  208: 
  209: #if defined(HAVE_LIBREADLINE)
  210:     init_readline ();
  211: #endif    
  212: 
  213:     init_execution_context ();
  214: 
  215:     if (run_daemon == FALSE) {
  216:         init_io ();
  217:     }
  218:     
  219:     init_random_number ();
  220:     init_ztrap ();
  221: 
  222:     retval = shm_init (shm_init_size);
  223: 
  224:     if (retval == SHMS_GET_ERR) {
  225:         if (errno != 13) {
  226:             logprintf (FM_LOG_FATAL, "init:  error initializing shared memory (error code %d [%s])", errno, strerror (errno));
  227:         }
  228:         else {
  229:             logprintf (FM_LOG_FATAL, "init:  error attaching to environment -- does your user belong to the group that owns environment '%s'?", shm_env);
  230:         }
  231:     }
  232: 
  233:     symtab_init ();
  234:     tp_init ();
  235:     
  236:     set_namespace (namespace_name, FALSE);
  237: 
  238:     if (first_process) {
  239:         log_level = FM_LOG_INFO;
  240:     }
  241:     else {
  242:         log_level = FM_LOG_DEBUG;
  243:     }
  244:     
  245:     if (first_process) {
  246:         logprintf (log_level, "init:  we are the first process in the environment (pid %d)", pid);
  247:     }
  248: 
  249:     logprintf (log_level, "init:  initializing job table");
  250:     jobtab_init ();
  251: 
  252:     logprintf (log_level, "init:  adding job to job table");
  253:     job_init (FALSE);
  254: 
  255:     logprintf (log_level, "init:  initializing structured system variables");
  256:     init_ssvn ();
  257: 
  258:     logprintf (log_level, "init:  initializing terminal");
  259:     init_terminal ();
  260: 
  261:     logprintf (log_level, "init:  initializing asynchronous events");
  262:     evt_init ();
  263: 
  264:     logprintf (log_level, "init:  initializing debugger");
  265:     dbg_init ();    
  266: 
  267:     logprintf (log_level, "init:  initializing error stack");
  268:     init_estack();
  269:     
  270:     etrap[0] = EOL;
  271:     ecode[0] = EOL;
  272:     estack = 0;
  273: 
  274:     init_mwapi();
  275:     
  276:     if (merr () == OK) {
  277:         return TRUE;
  278:     }
  279: 
  280:     return FALSE;
  281: }
  282: 
  283: void init_process (void)
  284: {
  285:     pid = getpid ();            /* get $J = process ID */
  286:     umask (0);              /* protection bits mask to full rights */
  287:     snprintf (fp_conversion, sizeof (fp_conversion) - 1, "%%.%df\201", DBL_DIG);
  288: 
  289:     if (fp_mode) {
  290:         zprecise = DBL_DIG;
  291:     }
  292:     else {
  293:         zprecise = 100;
  294:     }
  295: }
  296: 
  297: void init_devtable (void)
  298: {
  299:     register int i;
  300:     register int j;
  301: 
  302:     for (j = 0; j <= MAXDEV; j++) { /* init. translation tables */
  303:         
  304:         for (i = 0; i < 256; i++) {
  305:             G0I[j][i] = (char) i;
  306:             G0O[j][i] = (char) i;
  307:             G1I[j][i] = (char) i;
  308:             G1O[j][i] = (char) i;
  309:         }
  310:         
  311:         G0I[j][UNSIGN (EOL)] = NUL;
  312:         G0O[j][UNSIGN (EOL)] = NUL;
  313:         G1I[j][UNSIGN (EOL)] = NUL;
  314:         G1O[j][UNSIGN (EOL)] = NUL;
  315:         G0I[j][UNSIGN (DELIM)] = NUL;
  316:         G0O[j][UNSIGN (DELIM)] = NUL;
  317:         G1I[j][UNSIGN (DELIM)] = NUL;
  318:         G1O[j][UNSIGN (DELIM)] = NUL;
  319:         G0I[j][256] = EOL;
  320:         G0O[j][256] = EOL;
  321:         G1I[j][256] = EOL;
  322:         G1O[j][256] = EOL;
  323:     
  324:     }
  325: 
  326:     #ifdef SCO
  327:         #ifndef HACK_NOXLATE
  328:             G0I[HOME][245] = 64;
  329:             G0O[HOME][64] = 245;        /* Paragraph */
  330:             G0I[HOME][142] = 91;
  331:             G0O[HOME][91] = 142;        /* A umlaut */
  332:             G0I[HOME][153] = 92;
  333:             G0O[HOME][92] = 153;        /* O umlaut */
  334:             G0I[HOME][154] = 93;
  335:             G0O[HOME][93] = 154;        /* U umlaut */
  336:             G0I[HOME][132] = 123;
  337:             G0O[HOME][123] = 132;       /* a umlaut */
  338:             G0I[HOME][148] = 124;
  339:             G0O[HOME][124] = 148;       /* o umlaut */
  340:             G0I[HOME][129] = 125;
  341:             G0O[HOME][125] = 129;       /* u umlaut */
  342:             G0I[HOME][225] = 126;
  343:             G0O[HOME][126] = 225;       /* sharp s  */
  344:         #endif/*HACK_NOXLATE*/
  345: 
  346:         /* DEC Special graphics                             */
  347:         G1I[HOME][254] = 96;
  348:         G1O[HOME][96] = 254;        /* diamond  */
  349:         G1I[HOME][176] = 97;
  350:         G1O[HOME][97] = 176;        /* checker board */
  351:         G1I[HOME][241] = 99;
  352:         G1O[HOME][99] = 241;        /* FF */
  353:         G1I[HOME][242] = 100;
  354:         G1O[HOME][100] = 242;       /* CR */
  355:         G1I[HOME][243] = 101;
  356:         G1O[HOME][101] = 243;       /* LF */
  357:         G1I[HOME][248] = 102;
  358:         G1O[HOME][102] = 248;       /* degree sign */
  359:         G1I[HOME][241] = 103;
  360:         G1O[HOME][103] = 241;       /* plus minus */
  361:         G1I[HOME][244] = 104;
  362:         G1O[HOME][104] = 244;       /* NL */
  363:         G1I[HOME][251] = 105;
  364:         G1O[HOME][105] = 251;       /* VT */
  365:         G1I[HOME][217] = 106;
  366:         G1O[HOME][106] = 217;       /* lower right corner */
  367:         G1I[HOME][191] = 107;
  368:         G1O[HOME][107] = 191;       /* upper right corner */
  369:         G1I[HOME][218] = 108;
  370:         G1O[HOME][108] = 218;       /* upper left corner */
  371:         G1I[HOME][192] = 109;
  372:         G1O[HOME][109] = 192;       /* lower left corner */
  373:         G1I[HOME][197] = 110;
  374:         G1O[HOME][110] = 197;       /* cross */
  375:         G1I[HOME][200] = 111;
  376:         G1O[HOME][111] = 200;       /* linescan 5 */
  377:         G1I[HOME][201] = 112;
  378:         G1O[HOME][112] = 201;       /* linescan 4 */
  379:         G1I[HOME][196] = 113;
  380:         G1O[HOME][113] = 196;       /* linescan 3 */
  381:         G1I[HOME][202] = 114;
  382:         G1O[HOME][114] = 202;       /* linescan 2 */
  383:         G1I[HOME][203] = 115;
  384:         G1O[HOME][115] = 203;       /* linescan 1 */
  385:         G1I[HOME][195] = 116;
  386:         G1O[HOME][116] = 195;       /* left  junction */
  387:         G1I[HOME][180] = 117;
  388:         G1O[HOME][117] = 180;       /* right junction */
  389:         G1I[HOME][193] = 118;
  390:         G1O[HOME][118] = 193;       /* lower junction */
  391:         G1I[HOME][194] = 119;
  392:         G1O[HOME][119] = 194;       /* upper junction */
  393:         G1I[HOME][179] = 120;
  394:         G1O[HOME][120] = 179;       /* vertival bar */
  395:         G1I[HOME][243] = 121;
  396:         G1O[HOME][121] = 243;       /* lower equals */
  397:         G1I[HOME][242] = 122;
  398:         G1O[HOME][122] = 242;       /* greater equals */
  399:         G1I[HOME][227] = 123;
  400:         G1O[HOME][123] = 227;       /* pi */
  401:         G1I[HOME][246] = 124;
  402:         G1O[HOME][124] = 246;       /* not equals */
  403:         G1I[HOME][128] = 125;
  404:         G1O[HOME][125] = 128;       /* euro sign */
  405:         G1I[HOME][250] = 126;
  406:         G1O[HOME][126] = 250;       /* centered dot */
  407:     #endif /* SCO */
  408: }
  409: 
  410: void init_signals (void)
  411: {
  412:     sig_init ();
  413: }
  414: 
  415: void init_timezone (void)
  416: {
  417:    
  418:     struct tm lt;
  419:     struct tm gt;
  420: 
  421:     unsigned long gmt;
  422:     unsigned long lmt;
  423: 
  424:     long clock;
  425: 
  426: #if defined(__CYGWIN__)
  427:     tzset ();                        /* may be required in order   */
  428:                                      /* to guarantee _timezone set */
  429: #else
  430: 
  431:     clock = time (0L);
  432:     lt = *localtime (&clock);
  433:     gt = *gmtime (&clock);
  434: 
  435:     /* This is awkward but I think it is portable: steve_morris */
  436:     gmt = gt.tm_year * 365;
  437:     gmt = (gmt + gt.tm_yday) * 24;
  438:     gmt = (gmt + gt.tm_hour) * 60;
  439:     gmt = (gmt + gt.tm_min);
  440: 
  441:     lmt = lt.tm_year * 365;
  442:     lmt = (lmt + lt.tm_yday) * 24;
  443:     lmt = (lmt + lt.tm_hour) * 60;
  444:     lmt = (lmt + lt.tm_min);
  445: 
  446:     FreeM_timezone = (gmt - lmt) * 60;
  447:     tzoffset = -FreeM_timezone;
  448:     
  449: #endif /* __CYGWIN__ */
  450:     
  451: 
  452: }
  453: 
  454: void init_freem_path (void)
  455: {
  456: 
  457:     if((freem_path = malloc(PATH_MAX + 1)) == NULL) {
  458:         fprintf(stderr, "Can't allocate freem_path. Exiting.");
  459: 
  460:         exit(1);
  461:     }
  462: 
  463:     freem_path[0] = NUL;
  464: 
  465:     /* check where I'm being executed from */
  466: #ifdef __linux__
  467:     readlink ("/proc/self/exe", freem_path, PATH_MAX);
  468: #endif
  469: #ifdef __FreeBSD__
  470:     readlink ("/proc/curproc/file", freem_path, PATH_MAX);
  471: #endif
  472: #ifdef __sun
  473:     readlink ("/proc/self/path/a.out", freem_path, PATH_MAX);
  474: #endif
  475: 
  476:     if(freem_path[0] == NUL) {
  477:         /* we don't know where we came from */
  478:     }
  479: 
  480:     getcwd (curdir, PATHLEN);
  481:     stcnv_c2m (curdir);
  482:     
  483: }
  484: 
  485: #if defined(HAVE_LIBREADLINE)
  486: void init_readline (void)
  487: {
  488:     uid_t uid = geteuid ();
  489:     struct passwd *pw = getpwuid (uid);
  490:     char *pw_buf;
  491: 
  492:     pw_buf = (char *) calloc (strlen(pw->pw_dir) + 1, sizeof(char));
  493:     strcpy (pw_buf, pw->pw_dir);
  494: 
  495:     snprintf (history_file, sizeof (history_file) - 1, "%s/.freem_history", pw_buf);
  496: 
  497:     free (pw_buf);
  498: 
  499:     using_history ();
  500:     read_history (history_file);
  501: }
  502: #endif    
  503: 
  504: void init_execution_context (void)
  505: {
  506:     register int i;
  507: 
  508:     obj_init ();
  509:     
  510:     merr_clear ();
  511:     
  512:     codptr = code;
  513:     code[0] = EOL;          /* init code_pointer */
  514: 
  515:     if ((partition = calloc ((unsigned) (PSIZE + 2), 1)) == NULL) {
  516:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate symbol table (error code %d [%s])", errno, strerror (errno));
  517:     }
  518: 
  519:     for (i = 0; i < MAXNO_OF_RBUF; i++) {
  520:         rbuf_flags[i].standard = standard;
  521:     }
  522: 
  523:     for (i = 0; i < NESTLEVLS; i++) {
  524:         extr_types[i] = DT_STRING;
  525:     }
  526:     
  527:     symlen = PSIZE;
  528:     s = &partition[PSIZE] - 256;    /* pointer to symlen_offset        */
  529:     argptr = partition;         /* pointer to beg of tmp-storage   */
  530: 
  531:     if ((svntable = calloc ((unsigned) (UDFSVSIZ + 1), 1)) == NULL) {
  532:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate user-defined ISV table (error code %d [%s])", errno, strerror (errno));
  533:     }    
  534:     svnlen = UDFSVSIZ;          /* begin of udf_svn_table         */
  535: 
  536:     if ((buff = calloc ((unsigned) NO_OF_RBUF * (unsigned) PSIZE0, 1)) == NULL) {
  537:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate routine buffers (error code %d [%s])", errno, strerror (errno));
  538:     }
  539:     
  540:     if ((newstack = calloc ((unsigned) NSIZE, 1)) == NULL) {
  541:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate NEW stack (error code %d [%s])", errno, strerror (errno));
  542:     }
  543: 
  544:     logprintf (FM_LOG_DEBUG, "allocating newptr stack...");
  545: 
  546:     newptr = newstack;
  547:     newlimit = newstack + NSIZE - 1024;
  548:     
  549: 
  550:     if ((namstck = calloc ((unsigned) NESTLEVLS * 13, 1)) == NULL) {
  551:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate newptr stack (error code %d [%s])", errno, strerror (errno));
  552:     }
  553:     
  554:     *namstck = EOL;
  555:     *(namstck + 1) = EOL;
  556:     namptr = namstck;           /* routine name stack pointer       */
  557:     
  558:     if ((framstck = calloc ((unsigned) NESTLEVLS * 256, 1)) == NULL) {
  559:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate DO frame stack stack (error code %d [%s])", errno, strerror (errno));
  560:     }
  561: 
  562:     *framstck = EOL;
  563:     *(framstck + 1) = EOL;
  564:     dofrmptr = framstck;        /* DO_frame stack pointer           */
  565: 
  566:     if ((cmdstack = calloc ((unsigned) NESTLEVLS * 256, 1)) == NULL) {
  567:         logprintf (FM_LOG_FATAL, "init_execution_context:  could not allocate command stack (error code %d [%s])", errno, strerror (errno));
  568:     }
  569: 
  570:     cmdptr = cmdstack;          /* command stack */
  571: 
  572:     rouend = rouins = rouptr = buff;
  573:     roucur = buff + (NO_OF_RBUF * PSIZE0 + 1);
  574:     *rouptr = EOL;
  575:     *(rouptr + 1) = EOL;
  576:     *(rouptr + 2) = EOL;
  577: 
  578:     err_suppl[0] = EOL; /* empty out supplemental error info */
  579: }
  580: 
  581: void init_estack (void)
  582: {
  583:     stcpy (merr_stack[0].PLACE, "xecline()\201");
  584: }
  585: 
  586: #if defined(HAVE_MWAPI_MOTIF)
  587: void init_mwapi (void)
  588: {
  589:     /*
  590:     if (getenv("DISPLAY") != NULL) {
  591:         gtk_init (0, NULL);
  592:     }
  593:     */
  594:     /* TODO: init Motif/libXt */
  595: }
  596: #else
  597: void init_mwapi (void)
  598: {
  599:     return;
  600: }
  601: #endif
  602: 
  603: void init_io (void)
  604: {
  605:     register int i;
  606: 
  607:     /* initialize screen */
  608:     setbuf (stdin, NULL);      /* no input buffering */
  609:     glvnflag.all = 0L;
  610:     stcpy (buff, "\201");
  611:     writeHOME (buff);
  612:     sq_modes[0] = '+';
  613:     for (i = 0; i <= MAXDEV; ug_buf[i++][0] = EOL); /* init read-buffers */
  614: 
  615:     frm_crlf[HOME] = frm_filter;
  616: 
  617:     if (hardcopy) zbreakon = ENABLE;        /* enable CTRL/B */
  618: 
  619:     set_io (MUMPS);         /* set i/o parameters */
  620: 
  621: #if !defined(__AMIGA) && !defined(__OS2__)
  622:     if (ttyname (HOME)) {       /* for $IO of HOME */
  623:         strcpy (dev[HOME], ttyname (HOME));
  624:         dev[HOME][strlen (dev[HOME])] = EOL;
  625:     } 
  626:     else {
  627:         dev[HOME][0] = EOL;     /* ...we are in a pipe */
  628:     }
  629:     for (i = 5; i <= MAXDEV; i++) dev[i][0] = EOL;
  630: #else
  631: #if defined(__AMIGA)
  632:     strcpy (dev[HOME], "CONSOLE:");
  633: #else
  634: #if defined(__OS2__)
  635:     strcpy (dev[HOME], "CON:");
  636: #endif
  637: #endif
  638: #endif    
  639: 
  640:     /* init function keys */
  641:     for (i = 0; i < 44; zfunkey[i++][0] = EOL);
  642: }
  643: 
  644: void init_random_number (void)
  645: {
  646: 
  647:     srand (time (NULL));
  648: 
  649:     if ((nrandom = time (0L) * getpid ()) < 0) {
  650:         nrandom = (-nrandom);
  651:     }
  652: 
  653: }
  654: 
  655: void init_ztrap (void)
  656: {
  657: 
  658:     if (frm_filter) { 
  659:         ztrap[0][0] = EOL;      /* no default ztrap for filters */
  660:     }
  661:     else if (startuprou[0] == '^') {
  662:         stcpy (ztrap[0], startuprou);
  663:     }
  664:     else {
  665:         stcpy (ztrap[0], "^%SYSINIT\201");
  666:     }
  667: 
  668:     /* $ZT to be xecuted on startup */
  669:     
  670:     stcpy (ztrap[NESTLEVLS + 1], ztrap[0]); /* DSM V.2 error trapping */
  671: 
  672: }
  673: 
  674: void init_ssvn(void)
  675: {
  676:     ssvn_job_update ();
  677:     ssvn_display_update ();
  678:     ssvn_routine_update ();
  679:     ssvn_library_update ();
  680:     if (first_process) ssvn_system_update ();
  681: }
  682: 
  683: void init_terminal(void)
  684: {
  685:     xpos[HOME] = 80;
  686:     ypos[HOME] = 24;
  687: }
  688: 
  689: void reset_terminal(void)
  690: {
  691:     struct termio tpara;
  692: 
  693:     ioctl (0, TCGETA, &tpara);
  694: 
  695:     tpara.c_lflag |= (ECHO | ICANON);	/* enable echo/no cbreak mode */
  696:     tpara.c_iflag |= ICRNL;		/* cr-lf mapping */
  697:     tpara.c_oflag |= ONLCR;		/* cr-lf mapping */
  698:     tpara.c_cc[VMIN] = EOT;
  699:     tpara.c_cc[VTIME] = -1;
  700: 
  701:     ioctl (0, TCSETA, &tpara);
  702: }
  703: 
  704: void cleanup (void)
  705: {
  706:     char k_buf[256];
  707:     int ch;
  708: 
  709:     /* remove this job's entry from ^$JOB SSVN */
  710:     snprintf (k_buf, sizeof (k_buf) - 1, "^$JOB\202%d\201", pid);
  711:     symtab_shm (kill_sym, k_buf, " \201");
  712:     
  713:     reset_terminal ();
  714: 
  715:     if (tp_level > 0) {
  716: 
  717:         if (direct_mode == TRUE) {
  718:             fprintf (stderr, "UNCOMMITTED TRANSACTIONS EXIST:\n\n");
  719:             tp_tdump ();
  720:             set_io (UNIX);
  721:             fprintf (stderr, "\nWould you like to c)ommit or r)ollback the above transactions and their operations? ($TLEVEL = %d) ", tp_level);
  722: 
  723:             for (;;) {
  724:                 ch = fgetc (stdin);
  725: 
  726:                 if (ch == 'c' || ch == 'C') {
  727:                     while (tp_level > 0) tp_tcommit ();
  728: 
  729:                     fprintf (stderr, "\n\nTransactions have been committed.\n");
  730: 
  731:                     break;
  732:                 }
  733:                 else if (ch == 'r' || ch == 'R') {
  734:                     tp_trollback (tp_level);
  735: 
  736:                     fprintf (stderr, "\n\nTransactions have been rolled back.\n");
  737: 
  738:                     break;
  739:                 }
  740:                 else {
  741:                     fprintf (stderr, "\n\nInvalid input '%c'. Must choose c)ommit or r)ollback.\n", ch);
  742:                 }
  743:             }
  744:         }
  745:         else {
  746:             fprintf (stderr, "Uncommitted transactions exist. Rolling back.\n");
  747:             tp_trollback (tp_level);
  748:         }
  749:     }
  750: 
  751: #if defined(HAVE_LIBREADLINE)
  752:     write_history (history_file);
  753: #endif
  754: 
  755:     locktab_unlock_all ();    
  756:     job_remove (pid);
  757: 
  758:     shm_exit ();
  759: 
  760:     if (run_daemon == TRUE) {
  761: 
  762:         if (pid_fd != -1) {
  763:             lockf (pid_fd, F_ULOCK, 0);
  764:             close (pid_fd);
  765:         }
  766: 
  767:         if (pid_file_path != NULL) {
  768:             unlink (pid_file_path);
  769:         }
  770: 
  771:     }  
  772:     
  773:     free (buff);            /* free previously allocated space */
  774:     free (svntable);
  775:     if (partition) free (partition);
  776:     if (apartition) free (apartition);
  777: 
  778:    
  779:     free (newstack);
  780:     
  781:     
  782:     if (v22size) free (v22ali);    
  783:     
  784:     return;
  785: }                   /* end of cleanup */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>