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