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