File:  [Coherent Logic Development] / freem / src / init.c
Revision 1.5: download - view: text, annotated - select for diffs
Sun Mar 9 15:20:18 2025 UTC (6 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Begin formatting overhaul and REUSE compliance

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

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