File:  [Coherent Logic Development] / freem / src / init.c
Revision 1.13: download - view: text, annotated - select for diffs
Thu Apr 17 14:34:27 2025 UTC (4 months, 1 week ago) by snw
Branches: MAIN
CVS tags: HEAD
Further logging improvements

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

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