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