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