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