Annotation of freem/src/fmadm.c, revision 1.34
1.1 snw 1: /*
1.34 ! snw 2: * $Id: fmadm.c,v 1.33 2025/04/10 01:24:38 snw Exp $
1.1 snw 3: * FreeM Administration Tool
4: *
5: *
1.6 snw 6: * Author: Serena Willis <snw@coherent-logic.com>
1.1 snw 7: * Copyright (C) 1998 MUG Deutschland
1.7 snw 8: * Copyright (C) 2020, 2023, 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.8 snw 26: * $Log: fmadm.c,v $
1.34 ! snw 27: * Revision 1.33 2025/04/10 01:24:38 snw
! 28: * Remove C++ style comments
! 29: *
1.33 snw 30: * Revision 1.32 2025/04/09 19:52:02 snw
31: * Eliminate as many warnings as possible while building with -Wall
32: *
1.32 snw 33: * Revision 1.31 2025/04/04 19:43:18 snw
34: * Switch to using environment catalog to determine user and group for environment, and remove -u and -g flags from freem
35: *
1.31 snw 36: * Revision 1.30 2025/04/03 20:48:14 snw
37: * Improve daemon error diagnostics and bump to 0.63.0-rc3
38: *
1.30 snw 39: * Revision 1.29 2025/04/03 01:41:02 snw
40: * New features frozen; prepare 0.63.0-rc1
41: *
1.29 snw 42: * Revision 1.28 2025/04/02 19:59:38 snw
43: * Automatically modify env.conf from fmadm reconfigure
44: *
1.28 snw 45: * Revision 1.27 2025/04/02 15:36:25 snw
46: * Do extensive result checking for environment stop/start/restart in fmadm
47: *
1.27 snw 48: * Revision 1.26 2025/04/02 14:37:57 snw
49: * Improve environment control parts of fmadm
50: *
1.26 snw 51: * Revision 1.25 2025/04/02 04:50:49 snw
52: * Allow vendor routines to be upgraded
53: *
1.25 snw 54: * Revision 1.24 2025/04/02 03:02:42 snw
55: * Stop requiring users to pass -e to fmadm when -u or -g are passed
56: *
1.24 snw 57: * Revision 1.23 2025/04/02 02:16:27 snw
58: * Add fmadm status environment command and move journals to a better location
59: *
1.23 snw 60: * Revision 1.22 2025/04/01 23:21:45 snw
61: * fmadm commands for stopping, starting, and restarting environments now functional
62: *
1.22 snw 63: * Revision 1.21 2025/04/01 20:11:46 snw
64: * Further work on fmadm
65: *
1.21 snw 66: * Revision 1.20 2025/04/01 16:37:12 snw
67: * Configure DEFAULT environment the same as others, and set permissions/ownership directly in fmadm configure. Add env.conf file as a centralized configuration listing all environments.
68: *
1.20 snw 69: * Revision 1.19 2025/04/01 14:32:11 snw
70: * Begin work on environment and namespace reorg
71: *
1.19 snw 72: * Revision 1.18 2025/03/31 16:33:56 snw
73: * Work on fmadm edit global
74: *
1.18 snw 75: * Revision 1.17 2025/03/30 01:36:58 snw
76: * Make it easier to bring back fma_gedit, fix double-free in global handler, limit $CHAR to 7-bit ASCII
77: *
1.17 snw 78: * Revision 1.16 2025/03/24 20:59:58 snw
79: * Try using DosCopy API instead of built-in cp function on OS/2
80: *
1.16 snw 81: * Revision 1.15 2025/03/24 20:58:05 snw
82: * Try using DosCopy API instead of built-in cp function on OS/2
83: *
1.15 snw 84: * Revision 1.14 2025/03/24 20:57:06 snw
85: * Try using DosCopy API instead of built-in cp function on OS/2
86: *
1.14 snw 87: * Revision 1.13 2025/03/24 20:15:09 snw
88: * Set file permissions on freemd.exe on OS/2 in fmadm configure
89: *
1.13 snw 90: * Revision 1.12 2025/03/24 20:13:34 snw
91: * Set file permissions on freemd.exe on OS/2 in fmadm configure
92: *
1.12 snw 93: * Revision 1.11 2025/03/24 19:25:48 snw
94: * Make fmadm configure copy freem.exe to freemd.exe for daemon operation on OS/2 systems
95: *
1.11 snw 96: * Revision 1.10 2025/03/24 19:22:16 snw
97: * Make fmadm configure copy freem.exe to freemd.exe for daemon operation on OS/2 systems
98: *
1.10 snw 99: * Revision 1.9 2025/03/24 19:19:42 snw
100: * Make fmadm configure copy freem.exe to freemd.exe for daemon operation on OS/2 systems
101: *
1.9 snw 102: * Revision 1.8 2025/03/22 18:43:54 snw
103: * Make STRLEN 255 chars and add BIGSTR macro for larger buffers
104: *
1.8 snw 105: * Revision 1.7 2025/03/09 19:14:25 snw
106: * First phase of REUSE compliance and header reformat
107: *
1.7 snw 108: *
109: * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC
110: * SPDX-License-Identifier: AGPL-3.0-or-later
1.1 snw 111: **/
112:
113: #include <sys/types.h>
114: #include <sys/stat.h>
1.19 snw 115: #include <pwd.h>
116: #include <grp.h>
1.1 snw 117: #include <stddef.h>
118: #include <stdio.h>
119: #include <string.h>
120: #include <dirent.h>
121: #include <stdlib.h>
122: #include <unistd.h>
123: #include <errno.h>
1.4 snw 124: #include <ctype.h>
1.1 snw 125: #include "config.h"
126: #include "transact.h"
127: #include "namespace.h"
128: #include "fs.h"
129:
1.14 snw 130: #if defined(__OS2__)
131: # include <os2.h>
132: #endif
133:
1.1 snw 134: #ifdef HAVE_LIBREADLINE
135: # if defined(HAVE_READLINE_READLINE_H)
136: # include <readline/readline.h>
137: # elif defined(HAVE_READLINE_H)
138: # include <readline.h>
139: # else /* !defined(HAVE_READLINE_H) */
140: extern char *readline ();
141: # endif /* !defined(HAVE_READLINE_H) */
142: /*char *cmdline = NULL;*/
143: #else /* !defined(HAVE_READLINE_READLINE_H) */
144: /* no readline */
145: #endif /* HAVE_LIBREADLINE */
146:
147: #ifdef HAVE_READLINE_HISTORY
148: # if defined(HAVE_READLINE_HISTORY_H)
149: # include <readline/history.h>
150: # elif defined(HAVE_HISTORY_H)
151: # include <history.h>
152: # else /* !defined(HAVE_HISTORY_H) */
153: extern void add_history ();
154: extern int write_history ();
155: extern int read_history ();
156: # endif /* defined(HAVE_READLINE_HISTORY_H) */
157: /* no history */
158: #endif /* HAVE_READLINE_HISTORY */
159:
160:
161: #include "fmadm.h"
162: #include "errmsg.h"
163: #include "iniconf.h"
164: #include "init.h"
165: #include "version.h"
166: #include "shmmgr.h"
167: #include "jobtab.h"
168: #include "locktab.h"
169:
170: /* namespace configuration */
171: char fma_environment[STRLEN];
172: char fma_namespace[STRLEN];
1.8 snw 173: char fma_routine_path[PATHLEN];
174: char fma_global_path[PATHLEN];
175: char fma_journal_path[PATHLEN];
176: char fma_pct_global_path[PATHLEN];
177: char fma_pct_routine_path[PATHLEN];
1.1 snw 178: char fma_journal_cut_threshold[STRLEN];
1.8 snw 179: char fma_locktab[PATHLEN];
1.1 snw 180: short fma_base_opt = 1;
181: short fma_min_args = 2;
182: short fma_explicit_namespace = FALSE;
183: short fma_explicit_environment = FALSE;
184:
185: /* miscellaneous global state */
186: char obj_str[STRLEN];
187:
188: extern char config_file[4096];
1.20 snw 189: extern char env_config_file[4096];
190: extern char env_user[255];
191: extern char env_group[255];
1.29 snw 192: extern char env_enabled[10];
1.1 snw 193:
194: int fm_shell(void);
195: void fm_checkperms(void);
196: void fm_reconfigure(void);
197: void fm_configure(void);
1.21 snw 198: int fm_daemonctl (short action, short object, int optc, char **options);
1.1 snw 199: void fm_write (FILE *file, char *buf);
200: int fma_jobs_remove (int optc, char **opts);
1.20 snw 201: void set_permissions(char *path, char *user, char *grp, int mode);
1.27 snw 202: int fm_environment_running (char *env);
1.21 snw 203: extern int read_profile_string(char *file, char *section, char *key, char *value);
1.1 snw 204:
205: int main (int argc, char **argv)
206: {
207: char action[STRLEN];
208:
209: short act = -1;
210: short obj = -1;
211:
212: char **opts;
213: int optc = argc - 3;
214:
215: int i = 0;
216: int j = 1;
217: int base_arg = 4;
218: int k = 0;
219:
220: short got_action = FALSE;
221: short got_object = FALSE;
222:
1.29 snw 223: strcpy (env_enabled, "true");
1.1 snw 224:
225: /* snprintf (config_file, 4096, "%s/freem.conf", SYSCONFDIR); */
226:
227: base_arg = 1;
228:
229: /* enforce action in argv[1] */
230: if (argc > 1) {
231: if (argv[1][0] == '-') {
232: fprintf (stderr, "fmadm: first argument, if given, must be an action, not a flag\n");
233: fmadm_usage ();
234: exit (1);
235: }
236: }
237:
238: for (i = base_arg; i < argc; i++) {
239: if (i == 1 && isalpha (argv[i][0])) {
240: got_action = TRUE;
241: strncpy (action, argv[i], STRLEN - 1);
242: base_arg++;
243: }
244: if (i == 2 && isalpha (argv[i][0])) {
245: got_object = TRUE;
246: strncpy (obj_str, argv[i], STRLEN - 1);
247: base_arg++;
248: }
249: if (argv[i][0] == '-') {
250:
251: switch (argv[i][1]) {
1.20 snw 252:
253: case 'u':
254: if (argv[i][2] != '=') {
255: fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]);
256: fmadm_usage ();
257: exit (1);
258: }
259:
260: k = 0;
261:
262: for (j = 3; j < strlen (argv[i]); j++) {
263: env_user[k++] = argv[i][j];
264: }
265:
266: base_arg++;
267:
268: break;
269:
270: case 'g':
271: if (argv[i][2] != '=') {
272: fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]);
273: fmadm_usage ();
274: exit (1);
275: }
276:
277: k = 0;
278:
279: for (j = 3; j < strlen (argv[i]); j++) {
280: env_group[k++] = argv[i][j];
281: }
282:
283: base_arg++;
284:
285: break;
286:
1.1 snw 287:
288: case 'e':
289: if (argv[i][2] != '=') {
290: fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]);
291: fmadm_usage ();
292: exit (1);
293: }
294:
295: k = 0;
296:
297: for (j = 3; j < strlen (argv[i]); j++) {
298: fma_environment[k++] = argv[i][j];
299: }
1.21 snw 300:
301: if (strcmp (fma_environment, "all") == 0 ) {
302: fprintf (stderr, "fmadm: 'all' is an invalid environment name\n");
303: exit (1);
304: }
1.1 snw 305:
306: fma_explicit_environment = TRUE;
307: base_arg++;
308:
309: break;
1.29 snw 310:
311: case 'E':
312: if (argv[i][2] != '=') {
313: fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]);
314: fmadm_usage ();
315: exit (1);
316: }
317:
318: k = 0;
319:
320: for (j = 3; j < strlen (argv[i]); j++) {
321: env_enabled[k++] = argv[i][j];
322: }
323: env_enabled[k] = '\0';
324:
325: if ((strcmp (env_enabled, "true") != 0) && (strcmp (env_enabled, "false") != 0)) {
326: fprintf (stderr, "fmadm: -E (environment enabled) option must be either 'true' or 'false'\n");
327: fmadm_usage ();
328: exit (1);
329: }
330:
331: base_arg++;
332:
333: break;
334:
1.1 snw 335:
336: case 'n':
337: if (argv[i][2] != '=') {
338: fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]);
339: fmadm_usage ();
340: exit (1);
341: }
342:
343: k = 0;
344:
345: for (j = 3; j < strlen (argv[i]); j++) {
346: fma_namespace[k++] = argv[i][j];
347: }
348:
349: fma_explicit_namespace = TRUE;
350: base_arg++;
351:
352: break;
353:
354: }
355: }
356: }
1.24 snw 357:
1.21 snw 358: if (obj != OBJ_DAEMON) {
359: if (strlen (env_user) == 0) {
360: snprintf (env_user, 6, "freem");
361: }
362:
363: if (strlen (env_group) == 0) {
364: snprintf (env_group, 6, "freem");
365: }
1.20 snw 366:
1.1 snw 367:
1.21 snw 368: if (!fma_explicit_environment) snprintf (fma_environment, 4096, "DEFAULT");
369: if (!fma_explicit_namespace) snprintf (fma_namespace, 4096, "SYSTEM");
370:
371: snprintf (config_file, 4096, "%s/freem/%s/freem.conf", SYSCONFDIR, fma_environment);
372: }
1.1 snw 373:
1.20 snw 374: snprintf (env_config_file, 4096, "%s/freem/env.conf", SYSCONFDIR);
375:
1.26 snw 376: /*
1.1 snw 377: printf ("action = '%s' object = '%s' environment = '%s' namespace = '%s' config_file = '%s' base_arg = '%d' next argument = '%s'\n", action, obj_str, fma_environment, fma_namespace, config_file, base_arg, argv[base_arg]);
378: exit(1);
1.26 snw 379: */
1.1 snw 380:
1.21 snw 381: /* override for fmadm configure and daemon stuff */
1.1 snw 382: if (got_action) {
383: if (strcmp (argv[1], "configure") == 0) {
384: fm_configure ();
385: exit (0);
386: }
387: else if (strcmp (argv[1], "reconfigure") == 0) {
388: fm_reconfigure ();
389: exit (0);
390: }
1.21 snw 391: else if (strcmp (argv[1], "start") == 0 && strcmp (argv[2], "environment") == 0) {
392: act = ACT_START;
393: obj = OBJ_DAEMON;
1.26 snw 394: goto process_args;
1.21 snw 395: }
396: else if (strcmp (argv[1], "stop") == 0 && strcmp (argv[2], "environment") == 0) {
397: act = ACT_STOP;
398: obj = OBJ_DAEMON;
1.26 snw 399: goto process_args;
1.21 snw 400: }
401: else if (strcmp (argv[1], "restart") == 0 && strcmp (argv[2], "environment") == 0) {
402: act = ACT_RESTART;
403: obj = OBJ_DAEMON;
1.26 snw 404: goto process_args;
1.23 snw 405: }
406: else if (strcmp (argv[1], "status") == 0 && strcmp (argv[2], "environment") == 0) {
407: act = ACT_STATUS;
408: obj = OBJ_DAEMON;
1.26 snw 409: goto process_args;
1.21 snw 410: }
1.23 snw 411:
1.1 snw 412: }
413:
414: pid = getpid ();
415:
416: shm_init (16777216);
417: tp_init ();
418: jobtab_init ();
419: job_init (TRUE);
420:
421: fm_sig_init ();
1.21 snw 422:
1.1 snw 423: /* go to fmadm shell if no arguments passed */
424: if (!got_action && !got_object) return fm_shell ();
425:
426: if (argc > 1 && strcmp (argv[1], "checkperms") == 0) {
427: fm_checkperms ();
428: exit (0);
429: }
430:
431: set_namespace (fma_namespace, FALSE);
1.26 snw 432:
433: process_args:
1.1 snw 434: /* allocate opts array */
435:
436: /* first dimension */
437: if ((opts = (char **) malloc (FMA_MAXARGS * sizeof (char *))) == NULL) {
438: fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n");
439: return 1;
440: }
441:
442: /* second dimension */
443: for (i = 0; i < FMA_MAXARGS; i++) {
444: if ((opts[i] = (char *) malloc (STRLEN * sizeof (char *))) == NULL) {
445: fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n");
446: return 1;
447: }
448: }
449:
450: /* copy argv[base_arg] through argv[argc - 1] to opts[1] through opts[argc - 3] */
451:
452: strncpy (opts[0], argv[0], STRLEN - 1); /* preserve argv[0] */
453:
454: j = 1;
455: for (i = base_arg; i < argc; i++) {
1.26 snw 456: if (i > FMA_MAXARGS) return fmadm_usage();
457: /* bail if we're going to overrun the array */
1.1 snw 458: strncpy (opts[j++], argv[i], STRLEN - 1);
459: }
460:
461: if (strncmp (action, "list", STRLEN - 1) == 0) act = ACT_LIST;
462: else if (strncmp (action, "examine", STRLEN - 1) == 0) act = ACT_EXAMINE;
463: else if (strncmp (action, "verify", STRLEN - 1) == 0) act = ACT_VERIFY;
464: else if (strncmp (action, "compact", STRLEN - 1) == 0) act = ACT_COMPACT;
465: else if (strncmp (action, "repair", STRLEN - 1) == 0) act = ACT_REPAIR;
466: else if (strncmp (action, "create", STRLEN - 1) == 0) act = ACT_CREATE;
467: else if (strncmp (action, "remove", STRLEN - 1) == 0) act = ACT_REMOVE;
468: else if (strncmp (action, "import", STRLEN - 1) == 0) act = ACT_IMPORT;
469: else if (strncmp (action, "export", STRLEN - 1) == 0) act = ACT_EXPORT;
470: else if (strncmp (action, "backup", STRLEN - 1) == 0) act = ACT_BACKUP;
471: else if (strncmp (action, "restore", STRLEN - 1) == 0) act = ACT_RESTORE;
472: else if (strncmp (action, "migrate", STRLEN - 1) == 0) act = ACT_MIGRATE;
1.21 snw 473: else if (strncmp (action, "edit", STRLEN - 1) == 0) act = ACT_EDIT;
474: else if (strncmp (action, "start", STRLEN - 1) == 0) act = ACT_START;
475: else if (strncmp (action, "stop", STRLEN - 1) == 0) act = ACT_STOP;
476: else if (strncmp (action, "restart", STRLEN - 1) == 0) act = ACT_RESTART;
1.26 snw 477: else if (strncmp (action, "status", STRLEN - 1) == 0) act = ACT_STATUS;
1.1 snw 478: else return fmadm_usage();
479:
480: if (strncmp (obj_str, "lock", STRLEN - 1) == 0) obj = OBJ_LOCK;
481: else if (strncmp (obj_str, "journal", STRLEN - 1) == 0) obj = OBJ_JOURNAL;
482: else if (strncmp (obj_str, "namespace", STRLEN - 1) == 0) obj = OBJ_NAMESPACE;
483: else if (strncmp (obj_str, "global", STRLEN - 1) == 0) obj = OBJ_GLOBAL;
484: else if (strncmp (obj_str, "routine", STRLEN - 1) == 0) obj = OBJ_ROUTINE;
485: else if (strncmp (obj_str, "job", STRLEN - 1) == 0) obj = OBJ_JOB;
1.21 snw 486: else if (strncmp (obj_str, "environment", STRLEN - 1) == 0) obj = OBJ_DAEMON;
1.1 snw 487: else return fmadm_usage();
488:
1.21 snw 489: if (act > ACT_EDIT) goto act_switch;
490:
1.1 snw 491: if (get_conf (fma_namespace, "routines_path", fma_routine_path) == FALSE) {
492: fprintf (stderr, "fmadm: cannot determine routine path for namespace %s\n", fma_namespace);
493: return 1;
494: }
495:
496: if (get_conf (fma_namespace, "globals_path", fma_global_path) == FALSE) {
497: fprintf (stderr, "fmadm: cannot determine global path for namespace %s\n", fma_namespace);
498: return 1;
499: }
500:
501: if (get_conf ("SYSTEM", "globals_path", fma_pct_global_path) == FALSE) {
502: fprintf (stderr, "fmadm: cannot determine %% global path for namespace %s\n", "SYSTEM");
503: return 1;
504: }
505:
506: if (get_conf ("SYSTEM", "routines_path", fma_pct_routine_path) == FALSE) {
507: fprintf (stderr, "fmadm: cannot determine %% routine path for namespace %s\n", "SYSTEM");
508: return 1;
509: }
510:
511: if (get_conf ("SYSTEM", "journal_file", fma_journal_path) == FALSE) {
512: strcpy (fma_journal_path, "");
513: }
514:
515: if (get_conf ("SYSTEM", "journal_cut_threshold", fma_journal_cut_threshold) == FALSE) {
516: strcpy (fma_journal_cut_threshold, "1073741824");
517: }
518:
519: strcpy (gloplib, fma_pct_global_path);
520: stcnv_c2m (gloplib);
521:
522: strcpy (glopath, fma_global_path);
523: stcnv_c2m (glopath);
524:
525:
1.21 snw 526: act_switch:
1.1 snw 527: switch (act) {
528:
529:
530: case ACT_LIST:
531: fmadm_exit (fm_list (obj, optc, opts));
532:
533:
534: case ACT_EXAMINE:
535: fmadm_exit (fm_examine (obj, optc, opts));
536:
537:
538: case ACT_VERIFY:
539: fmadm_exit (fm_verify (obj, optc, opts));
540:
541:
542: case ACT_COMPACT:
543: fmadm_exit (fm_compact (obj, optc, opts));
544:
545:
546: case ACT_REPAIR:
547: fmadm_exit (fm_repair (obj, optc, opts));
548:
549:
550: case ACT_CREATE:
551: fmadm_exit (fm_create (obj, optc, opts));
552:
553:
554: case ACT_REMOVE:
555: fmadm_exit (fm_remove (obj, optc, opts));
556:
557:
558: case ACT_IMPORT:
559: fmadm_exit (fm_import (obj, optc, opts));
560:
561:
562: case ACT_EXPORT:
563: fmadm_exit (fm_export (obj, optc, opts));
564:
565:
566: case ACT_BACKUP:
567: fmadm_exit (fm_backup (obj, optc, opts));
568:
569:
570: case ACT_RESTORE:
571: fmadm_exit (fm_restore (obj, optc, opts));
572:
573:
574: case ACT_MIGRATE:
575: fmadm_exit (fm_migrate (obj, optc, opts));
576:
577:
578: case ACT_EDIT:
579: fmadm_exit (fm_edit (obj, optc, opts));
580:
1.21 snw 581: case ACT_START:
582: case ACT_STOP:
583: case ACT_RESTART:
1.23 snw 584: case ACT_STATUS:
1.21 snw 585: fmadm_exit (fm_daemonctl (act, obj, optc, opts));
1.1 snw 586:
587: default:
588: return fmadm_usage();
589: }
590:
591: return 0; /* should never be reached */
592:
593: } /* main() */
594:
595: int fm_shell (void)
596: {
597:
598: #if defined(HAVE_LIBREADLINE) && !defined(_AIX)
599: int cmd;
600: int i;
601: int j;
602: int obj;
603: int optc;
604: int argc;
605: char **args;
606: char **opts;
607: char *fmarl_buf;
608: char *fma_prompt = (char *) malloc (STRLEN * sizeof (char));
609: char *cmdt = (char *) malloc (65535 * sizeof (char));
610: char *result = (char *) malloc (65535 * sizeof (char));
611:
1.33 snw 612: obj = 0;
1.1 snw 613:
614: snprintf (fma_prompt, STRLEN - 1, "fmadm [%s]> ", fma_namespace);
615:
616: if (get_conf (fma_namespace, "routines_path", fma_routine_path) == FALSE) {
617: fprintf (stderr, "fmadm: cannot determine routine path for namespace %s\n", fma_namespace);
618: return 1;
619: }
620:
621: if (get_conf (fma_namespace, "globals_path", fma_global_path) == FALSE) {
622: fprintf (stderr, "fmadm: cannot determine global path for namespace %s\n", fma_namespace);
623: return 1;
624: }
625:
626: if (get_conf ("SYSTEM", "globals_path", fma_pct_global_path) == FALSE) {
627: fprintf (stderr, "fmadm: cannot determine %% global path for namespace %s\n", "SYSTEM");
628: return 1;
629: }
630:
631: if (get_conf ("SYSTEM", "routines_path", fma_pct_routine_path) == FALSE) {
632: fprintf (stderr, "fmadm: cannot determine %% routine path for namespace %s\n", "SYSTEM");
633: return 1;
634: }
635:
636: if (get_conf ("SYSTEM", "journal_file", fma_journal_path) == FALSE) {
637: strcpy (fma_journal_path, "");
638: }
639:
640: if (get_conf ("SYSTEM", "journal_cut_threshold", fma_journal_cut_threshold) == FALSE) {
641: strcpy (fma_journal_cut_threshold, "1073741824");
642: }
643:
644: strcpy (gloplib, fma_pct_global_path);
645: stcnv_c2m (gloplib);
646:
647: strcpy (glopath, fma_global_path);
648: stcnv_c2m (glopath);
649:
650: /* allocate args array */
651:
652: /* first dimension */
653: if ((args = (char **) malloc (FMA_MAXARGS * sizeof (char *))) == NULL) {
654: fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n");
655: return 1;
656: }
657:
658: /* second dimension */
659: for (i = 0; i < FMA_MAXARGS; i++) {
660: if ((args[i] = (char *) malloc (STRLEN * sizeof (char *))) == NULL) {
661: fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n");
662: return 1;
663: }
664: }
665:
666: /* allocate opts array */
667:
668: /* first dimension */
669: if ((opts = (char **) malloc (FMA_MAXARGS * sizeof (char *))) == NULL) {
670: fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n");
671: return 1;
672: }
673:
674: /* second dimension */
675: for (i = 0; i < FMA_MAXARGS; i++) {
676: if ((opts[i] = (char *) malloc (STRLEN * sizeof (char *))) == NULL) {
677: fprintf (stderr, "fmadm [FATAL]: could not acquire memory\n");
678: return 1;
679: }
680: }
681:
682:
683: for (;;) {
684:
685: fmarl_buf = readline (fma_prompt);
686:
687: if (fmarl_buf == (char *) NULL) continue;
688:
689: cmdt = strtok (fmarl_buf, " ");
690:
1.2 snw 691: if (cmdt == (char *) NULL) continue;
692:
1.1 snw 693: for (i = 0; i < strlen (cmdt); i++) cmdt[i] = cmdt[i] | 0140;
694:
695: if (strcmp (cmdt, "exit") == 0) cmd = FMAC_EXIT;
696: else if (strcmp (cmdt, "quit") == 0) cmd = FMAC_EXIT;
697: else if (strcmp (cmdt, "select") == 0) cmd = FMAC_SELECT;
698: else if (strcmp (cmdt, "list") == 0) cmd = FMAC_LIST;
699: else if (strcmp (cmdt, "examine") == 0) cmd = FMAC_EXAMINE;
700: else if (strcmp (cmdt, "verify") == 0) cmd = FMAC_VERIFY;
701: else if (strcmp (cmdt, "compact") == 0) cmd = FMAC_COMPACT;
702: else if (strcmp (cmdt, "repair") == 0) cmd = FMAC_REPAIR;
703: else if (strcmp (cmdt, "create") == 0) cmd = FMAC_CREATE;
704: else if (strcmp (cmdt, "import") == 0) cmd = FMAC_IMPORT;
705: else if (strcmp (cmdt, "export") == 0) cmd = FMAC_EXPORT;
706: else if (strcmp (cmdt, "backup") == 0) cmd = FMAC_BACKUP;
707: else if (strcmp (cmdt, "restore") == 0) cmd = FMAC_RESTORE;
708: else if (strcmp (cmdt, "migrate") == 0) cmd = FMAC_MIGRATE;
709: else if (strcmp (cmdt, "edit") == 0) cmd = FMAC_EDIT;
710: else if (strcmp (cmdt, "set") == 0) cmd = FMAC_SET;
711: else if (strcmp (cmdt, "show") == 0) cmd = FMAC_SHOW;
712: else if (strcmp (cmdt, "remove") == 0) cmd = FMAC_REMOVE;
713: else cmd = FMAC_INVALID;
714:
715: i = 0;
716: while ((result = strtok (NULL, " ")) != NULL) {
717: strcpy (args[i++], result);
718: }
719:
720: argc = i;
721: j = 0;
722:
723: for (i = 1; i < argc; i++) {
724: strncpy (opts[j++], args[i], STRLEN - 1);
725: }
726:
727: optc = argc - 1;
728:
729: if (i > 0) {
730:
731: strcpy (obj_str, args[0]);
732:
733: if (strncmp (obj_str, "lock", STRLEN - 1) == 0) obj = OBJ_LOCK;
734: else if (strncmp (obj_str, "journal", STRLEN - 1) == 0) obj = OBJ_JOURNAL;
735: else if (strncmp (obj_str, "namespace", STRLEN - 1) == 0) obj = OBJ_NAMESPACE;
736: else if (strncmp (obj_str, "global", STRLEN - 1) == 0) obj = OBJ_GLOBAL;
737: else if (strncmp (obj_str, "routine", STRLEN - 1) == 0) obj = OBJ_ROUTINE;
738: else if (strncmp (obj_str, "job", STRLEN - 1) == 0) obj = OBJ_JOB;
739:
740: }
741:
742: switch (cmd) {
743:
744:
745: case FMAC_SELECT:
746:
747:
748: break;
749:
750:
751: case FMAC_LIST:
752: fm_list (obj, optc, opts);
753: break;
754:
755:
756: case FMAC_EXAMINE:
757: fm_examine (obj, optc, opts);
758: break;
759:
760:
761: case FMAC_VERIFY:
762: fm_verify (obj, optc, opts);
763: break;
764:
765:
766: case FMAC_COMPACT:
767: fm_compact (obj, optc, opts);
768: break;
769:
770:
771: case FMAC_REPAIR:
772: fm_repair (obj, optc, opts);
773: break;
774:
775:
776: case FMAC_CREATE:
777: fm_create (obj, optc, opts);
778: break;
779:
780:
781: case FMAC_REMOVE:
782: fm_remove (obj, optc, opts);
783: break;
784:
785:
786: case FMAC_IMPORT:
787: fm_import (obj, optc, opts);
788: break;
789:
790:
791: case FMAC_EXPORT:
792: fm_export (obj, optc, opts);
793: break;
794:
795:
796: case FMAC_BACKUP:
797: fm_backup (obj, optc, opts);
798: break;
799:
800:
801: case FMAC_RESTORE:
802: fm_restore (obj, optc, opts);
803: break;
804:
805:
806: case FMAC_MIGRATE:
807: fm_migrate (obj, optc, opts);
808: break;
809:
810:
811: case FMAC_EDIT:
812: fm_edit (obj, optc, opts);
813: break;
814:
815:
816: case FMAC_SET:
817:
818: if (i < 2) {
819: printf ("fmadm: syntax error\n");
820: break;
821: }
822:
823: if (strcmp (args[0], "namespace") == 0) {
824: strcpy (fma_namespace, args[1]);
825:
826: if (get_conf (fma_namespace, "routines_path", fma_routine_path) == FALSE) {
827: fprintf (stderr, "fmadm: cannot determine routine path for namespace %s\n", fma_namespace);
828: return 1;
829: }
830:
831: if (get_conf (fma_namespace, "globals_path", fma_global_path) == FALSE) {
832: fprintf (stderr, "fmadm: cannot determine global path for namespace %s\n", fma_namespace);
833: return 1;
834: }
835:
836: if (get_conf ("SYSTEM", "globals_path", fma_pct_global_path) == FALSE) {
837: fprintf (stderr, "fmadm: cannot determine %% global path for namespace %s\n", "SYSTEM");
838: return 1;
839: }
840:
841: if (get_conf ("SYSTEM", "routines_path", fma_pct_routine_path) == FALSE) {
842: fprintf (stderr, "fmadm: cannot determine %% routine path for namespace %s\n", "SYSTEM");
843: return 1;
844: }
845:
846: if (get_conf ("SYSTEM", "journal_file", fma_journal_path) == FALSE) {
847: strcpy (fma_journal_path, "");
848: }
849:
850: if (get_conf ("SYSTEM", "journal_cut_threshold", fma_journal_cut_threshold) == FALSE) {
851: strcpy (fma_journal_cut_threshold, "1073741824");
852: }
853:
854: strcpy (gloplib, fma_pct_global_path);
855: stcnv_c2m (gloplib);
856:
857: strcpy (glopath, fma_global_path);
858: stcnv_c2m (glopath);
859:
860: snprintf (fma_prompt, STRLEN - 1, "fmadm [%s]> ", fma_namespace);
861:
862: }
863: else if (strcmp (args[0], "maintenance") == 0) {
864: if (strcmp (args[1], "on") == 0) {
865: shm_config->hdr->maintenance_mode = 1;
866: break;
867: }
868: else if (strcmp (args[1], "off") == 0) {
869: shm_config->hdr->maintenance_mode = 0;
870: break;
871: }
872: else {
873: printf ("fmadm: syntax error\n");
874: }
875:
876: printf ("fmadm: syntax error\n");
877:
878: }
879: else {
880: printf ("fmadm: syntax error\n");
881: break;
882: }
883:
884: break;
885:
886:
887: case FMAC_SHOW:
888: printf ("Namespace: %s\n", fma_namespace);
889: printf ("Routine Path: %s\n", fma_routine_path);
890: printf ("%%-Routine Path: %s\n", fma_pct_routine_path);
891: printf ("Global Path: %s\n", fma_global_path);
892: printf ("%%-Global Path: %s\n", fma_pct_global_path);
893: printf ("Journal File: %s\n", fma_journal_path);
1.5 snw 894: printf ("Journal Cut Threshold: %s bytes\n", fma_journal_cut_threshold);
1.1 snw 895: break;
896:
897: case FMAC_EXIT:
898: fmadm_exit (0);
899: break;
900:
901:
902: default:
903: printf ("fmadm: '%s' is not a valid fmadm command\n", cmdt);
904: break;
905:
906: }
907: }
908:
909: #endif
910:
911: }
912:
913: void fmadm_exit (int retval)
914: {
915: locktab_unlock_all ();
916: job_remove (pid);
917:
918: shm_exit ();
919:
920: exit (retval);
921: }
922:
923: int fmadm_usage (void)
924: {
925:
1.29 snw 926: fprintf (stdout, "\nusage: fmadm <action> <object> [-e=<environment] [-n=<namespace>] [-u=<user>] [-g=<group>] [-E=true|false] [OPTIONS]\n");
1.1 snw 927: fprintf (stdout, " fmadm configure\n");
928: fprintf (stdout, " fmadm reconfigure\n");
929:
930: fprintf (stdout, " <action> can be one of:\n");
931: fprintf (stdout, " list, examine, verify, compact, repair, create, remove,\n");
1.21 snw 932: fprintf (stdout, " import, export, backup, restore, migrate, edit, start,\n");
1.29 snw 933: fprintf (stdout, " stop, restart, status\n\n");
1.1 snw 934:
935: fprintf (stdout, " <object> can be one of:\n");
1.24 snw 936: fprintf (stdout, " lock, journal, namespace, global, routine, job,\n");
1.21 snw 937: fprintf (stdout, " environment\n\n");
1.1 snw 938:
939: fprintf (stdout, " Not all actions are valid for all objects. Please see the FreeM manual\n");
940: fprintf (stdout, " for details on fmadm usage and options.\n\n");
941:
942: return 1;
943:
944: } /* fmadm_usage() */
945:
946: int fm_list (short object, int optc, char **options)
947: {
948:
949: switch (object) {
950:
951: case OBJ_LOCK:
952: return fma_locks_list (optc, options);
953:
954: case OBJ_ROUTINE:
955: return fma_routines_list (optc, options);
956:
957: case OBJ_GLOBAL:
958: return fma_globals_list (optc, options);
959:
960: case OBJ_JOB:
961: return fma_jobs_list (optc, options);
962:
963: default:
964: fprintf (stderr, "fmadm: 'list' is an invalid action for '%s'\n", obj_str);
965: return 1;
966:
967: }
968:
969:
970: } /* fm_list() */
971:
972: int fm_examine (short object, int optc, char **options)
973: {
974:
975: switch (object) {
976:
977: case OBJ_ROUTINE:
978: return fma_routines_examine (optc, options);
979:
980: case OBJ_GLOBAL:
981: return fma_globals_examine (optc, options);
982:
983: case OBJ_JOB:
984: return fma_jobs_examine (optc, options);
985:
986: case OBJ_JOURNAL:
987: return fma_journals_examine (optc, options);
988:
989: default:
990: fprintf (stderr, "fmadm: 'examine' is an invalid action for '%s'\n", obj_str);
991: return 1;
992:
993: }
994:
995: } /* fm_examine() */
996:
997: int fm_verify (short object, int optc, char **options)
998: {
999:
1000: switch (object) {
1001:
1002: case OBJ_GLOBAL:
1003: return fma_globals_verify (optc, options);
1004:
1005: default:
1006: fprintf (stderr, "fmadm: 'examine' is an invalid action for '%s'\n", obj_str);
1007: return 1;
1008:
1009: }
1010:
1011: } /* fm_verify() */
1012:
1013: int fm_compact (short object, int optc, char **options)
1014: {
1015:
1016: switch (object) {
1017:
1018: default:
1019: fprintf (stderr, "fmadm: 'compact' is an invalid action for '%s'\n", obj_str);
1020: return 1;
1021:
1022: }
1023:
1024: } /* fm_compact() */
1025:
1026: int fm_repair (short object, int optc, char **options)
1027: {
1028:
1029: switch (object) {
1030:
1031: default:
1032: fprintf (stderr, "fmadm: 'repair' is an invalid action for '%s'\n", obj_str);
1033: return 1;
1034:
1035: }
1036:
1037: } /* fm_repair() */
1038:
1039: int fm_create (short object, int optc, char **options)
1040: {
1041:
1042: switch (object) {
1043:
1044: default:
1045: fprintf (stderr, "fmadm: 'create' is an invalid action for '%s'\n", obj_str);
1046: return 1;
1047:
1048: }
1049: } /* fm_create() */
1050:
1051: int fm_remove (short object, int optc, char **options)
1052: {
1053:
1054: switch (object) {
1055:
1056: case OBJ_JOB:
1057: return fma_jobs_remove (optc, options);
1058:
1059: case OBJ_LOCK:
1060: return fma_locks_remove (optc, options);
1061:
1062: case OBJ_ROUTINE:
1063: return fma_routines_remove (optc, options);
1064:
1065: case OBJ_GLOBAL:
1066: return fma_globals_remove (optc, options);
1067:
1068: default:
1069: fprintf (stderr, "fmadm: 'remove' is an invalid action for '%s'\n", obj_str);
1070: return 1;
1071:
1072: }
1073:
1074: } /* fm_remove() */
1075:
1076: int fm_import (short object, int optc, char **options)
1077: {
1078:
1079: switch (object) {
1080:
1081: case OBJ_ROUTINE:
1082: return fma_routines_import (optc, options);
1083:
1084: default:
1085: fprintf (stderr, "fmadm: 'import' is an invalid action for '%s'\n", obj_str);
1086: return 1;
1087:
1088: }
1089:
1090: } /* fm_import() */
1091:
1092: int fm_export (short object, int optc, char **options)
1093: {
1094:
1095: switch (object) {
1096:
1097: case OBJ_ROUTINE:
1098: return fma_routines_export (optc, options);
1099:
1100: default:
1101: fprintf (stderr, "fmadm: 'export' is an invalid action for '%s'\n", obj_str);
1102: return 1;
1103:
1104: }
1105:
1106: } /* fm_export() */
1107:
1108: int fm_backup (short object, int optc, char **options)
1109: {
1110:
1111: switch (object) {
1112:
1113: case OBJ_ROUTINE:
1114: return fma_routines_backup (optc, options);
1115:
1116: default:
1117: fprintf (stderr, "fmadm: 'backup' is an invalid action for '%s'\n", obj_str);
1118: return 1;
1119:
1120: }
1121:
1122: } /* fm_backup() */
1123:
1124: int fm_restore (short object, int optc, char **options)
1125: {
1126:
1127: switch (object) {
1128:
1129: case OBJ_JOURNAL:
1130: return fma_journals_restore (optc, options);
1131:
1132: default:
1133: fprintf (stderr, "fmadm: 'restore' is an invalid action for '%s'\n", obj_str);
1134: return 1;
1135:
1136: }
1137:
1138: } /* fm_restore() */
1139:
1140: int fm_migrate (short object, int optc, char **options)
1141: {
1142:
1143: switch (object) {
1144:
1145: default:
1146: fprintf (stderr, "fmadm: 'migrate' is an invalid action for '%s'\n", obj_str);
1147: return 1;
1148:
1149: }
1150:
1151: } /* fm_migrate() */
1152:
1153: int fm_edit (short object, int optc, char **options)
1154: {
1155:
1156: switch (object) {
1157:
1158: case OBJ_ROUTINE:
1159: return fma_routines_edit (optc, options);
1160:
1.18 snw 1161: case OBJ_GLOBAL:
1.1 snw 1162: return fma_globals_edit (optc, options);
1.18 snw 1163:
1.1 snw 1164: default:
1165: fprintf (stderr, "fmadm: 'edit' is an invalid action for '%s'\n", obj_str);
1166: return 1;
1167:
1168: }
1169:
1170: } /* fm_edit() */
1171:
1.22 snw 1172: long fm_get_pid (char *env)
1173: {
1174: char pid_file[4096];
1175: char tmp_pid[255];
1176: FILE *fp;
1177:
1178: snprintf (pid_file, 4095, "%s/freem/run/%s.pid", LOCALSTATEDIR, env);
1179:
1180: if ((fp = fopen (pid_file, "r")) != NULL) {
1181: if (fgets (tmp_pid, 255, fp)) {
1182: fclose (fp);
1183: return atol (tmp_pid);
1184: }
1185: else {
1186: fclose (fp);
1187: return -1;
1188: }
1189: }
1190: else {
1191: return -1;
1192: }
1193: }
1194:
1.26 snw 1195: int fm_validate_environment (char *env)
1196: {
1197: FILE *fp;
1198: char line[255];
1199: char chkline[255];
1200:
1201: snprintf (chkline, 254, "[%s]\n", env);
1202:
1203: if ((fp = fopen (env_config_file, "r")) == NULL) {
1204: fprintf (stderr, "fmadm: could not open %s [%s]\n", env_config_file, strerror (errno));
1205: return FALSE;
1206: }
1207:
1208: while (fgets (line, 254, fp)) {
1209: if (strncmp (line, chkline, 254) == 0) {
1210: fclose (fp);
1211: return TRUE;
1212: }
1213: }
1214:
1215: fclose (fp);
1216: return FALSE;
1217: }
1218:
1.31 snw 1219: int fm_start_environment (char *env)
1.26 snw 1220: {
1221: char basecmd[255];
1222: char cmd[4096];
1.27 snw 1223:
1224: if (fm_environment_running (env) == TRUE) {
1225: return TRUE;
1226: }
1.26 snw 1227:
1228: #if !defined(__OS2__)
1229: snprintf (basecmd, 254, "%s/bin/freem", PREFIX);
1230: #else
1231: snprintf (basecmd, 254, "%s/bin/freemd.exe", PREFIX);
1232: #endif
1233:
1234: #if !defined(__OS2__)
1.31 snw 1235: snprintf (cmd, 4095, "%s -d -e %s", basecmd, env);
1.26 snw 1236: #else
1.31 snw 1237: sprintf (cmd, 4095, "%s -d -k -e %s", basecmd, env);
1.26 snw 1238: #endif
1.27 snw 1239:
1240: system (cmd);
1241:
1242: sleep (1);
1.26 snw 1243:
1.27 snw 1244: return (fm_environment_running (env));
1.26 snw 1245: }
1246:
1247: int fm_stop_environment (char *env)
1248: {
1249: long epid;
1250:
1.27 snw 1251: epid = fm_get_pid (env);
1.26 snw 1252: if (epid > -1) {
1253: kill (epid, SIGINT);
1.27 snw 1254: sleep (5);
1255:
1256: if (fm_environment_running (env) == FALSE) {
1257: return TRUE;
1258: }
1259: else {
1260: kill (epid, SIGTERM);
1261: sleep (5);
1262: if (fm_environment_running (env) == FALSE) {
1263: return TRUE;
1264: }
1265: else {
1266: kill (epid, SIGKILL);
1267: sleep (5);
1268: if (fm_environment_running (env) == FALSE) {
1269: return TRUE;
1270: }
1271: else {
1272: return FALSE;
1273: }
1274: }
1275: }
1.26 snw 1276: }
1277: else {
1.27 snw 1278: return FALSE;
1.26 snw 1279: }
1280: }
1281:
1.27 snw 1282: int fm_environment_running (char *env)
1283: {
1284: long epid;
1285: int result;
1286:
1287: epid = fm_get_pid (env);
1288:
1289: if (epid == -1) {
1290: return FALSE;
1291: }
1292: else {
1293: result = kill (epid, 0);
1294:
1295: return ((result == 0) ? TRUE : FALSE);
1296: }
1297: }
1298:
1.21 snw 1299: int fm_daemonctl (short action, short object, int optc, char **options)
1300: {
1301: FILE *ef;
1302: char *envlist;
1303: char env[255];
1304: char line[255];
1305: char tmps[255];
1306: char *cur_env;
1.23 snw 1307: char verb[40];
1.21 snw 1308: char e_user[255];
1309: char e_grp[255];
1310: char e_ena[10];
1311: char *savptr;
1312: int result;
1.22 snw 1313: long epid;
1.30 snw 1314: int retval;
1.26 snw 1315:
1.30 snw 1316: retval = 0;
1.21 snw 1317:
1318: switch (action) {
1319: case ACT_START:
1320: sprintf (verb, "starting");
1321: break;
1322: case ACT_STOP:
1323: sprintf (verb, "stopping");
1324: break;
1325: case ACT_RESTART:
1326: sprintf (verb, "restarting");
1327: break;
1.23 snw 1328: case ACT_STATUS:
1329: sprintf (verb, "checking status of");
1330: break;
1.21 snw 1331: }
1332:
1333: if (optc) {
1334: /* environment list specified as command-line argument */
1.23 snw 1335: envlist = (char *) malloc (sizeof (char) * BIGSTR);
1336: NULLPTRCHK(envlist,"fm_daemonctl");
1337:
1.26 snw 1338: strcpy (envlist, options[1]);
1.21 snw 1339: }
1340: else {
1341: /* no environment specified; do 'action' for all environments */
1342: envlist = (char *) malloc (sizeof (char) * BIGSTR);
1343: NULLPTRCHK(envlist,"fm_daemonctl");
1344:
1345: ef = fopen (env_config_file, "r");
1346:
1347: while (fgets (line, 254, ef)) {
1348: if (line[0] == '[') {
1349: strncpy (env, &(line[1]), 255);
1350: env[strlen (env) - 2] = '\0';
1351: snprintf (tmps, 255, "%s,", env);
1352: strncat (envlist, tmps, BIGSTR - 1);
1353: }
1354: }
1355: envlist[strlen (envlist) - 1] = '\0';
1356:
1357: fclose (ef);
1358: }
1359:
1360: savptr = envlist;
1361: cur_env = strtok_r (envlist, ",", &savptr);
1362: do {
1.26 snw 1363:
1364: if (fm_validate_environment (cur_env) == FALSE) {
1365: fprintf (stderr, "fmadm: %s is not a valid environment\n", cur_env);
1366: continue;
1367: }
1368:
1.21 snw 1369: result = read_profile_string (env_config_file, cur_env, "enabled", e_ena);
1370: if (result == FALSE || strcmp (e_ena, "true") == 0) {
1371:
1372: result = read_profile_string (env_config_file, cur_env, "user", e_user);
1373: if (result == FALSE) {
1374: strcpy (e_user, "freem");
1375: }
1376: result = read_profile_string (env_config_file, cur_env, "group", e_grp);
1377: if (result == FALSE) {
1378: strcpy (e_grp, "freem");
1379: }
1.22 snw 1380:
1.27 snw 1381: switch (action) {
1382: case ACT_START:
1383: case ACT_STOP:
1384: case ACT_RESTART:
1385: fprintf (stderr, "fmadm: %s environment %s... ", verb, cur_env);
1386: break;
1387: case ACT_STATUS:
1388: fprintf (stderr, "fmadm: %s environment %s\n", verb, cur_env);
1389: break;
1390: }
1.21 snw 1391:
1392: switch (action) {
1.26 snw 1393:
1.21 snw 1394: case ACT_START:
1.31 snw 1395: result = fm_start_environment (cur_env);
1.27 snw 1396: if (result == TRUE) {
1397: fprintf (stderr, "[OK]\n");
1398: }
1399: else {
1400: fprintf (stderr, "[FAIL]\n");
1401: }
1.21 snw 1402: break;
1.26 snw 1403:
1.21 snw 1404: case ACT_STOP:
1.26 snw 1405: result = fm_stop_environment (cur_env);
1.27 snw 1406: if (result == TRUE) {
1407: fprintf (stderr, "[OK]\n");
1408: }
1409: else {
1410: fprintf (stderr, "[FAIL]\n");
1.30 snw 1411: retval++;
1.27 snw 1412: }
1.22 snw 1413: break;
1.26 snw 1414:
1.21 snw 1415: case ACT_RESTART:
1.27 snw 1416: if (fm_stop_environment (cur_env) == TRUE) {
1.31 snw 1417: result = fm_start_environment (cur_env);
1.27 snw 1418: if (result == TRUE) {
1419: fprintf (stderr, "[OK]\n");
1420: }
1421: else {
1422: fprintf (stderr, "[FAIL]\n");
1.30 snw 1423: retval++;
1.27 snw 1424: }
1425: }
1426: else {
1427: fprintf (stderr, "[FAIL]\n");
1.30 snw 1428: retval++;
1.27 snw 1429: }
1.22 snw 1430:
1.21 snw 1431: break;
1.26 snw 1432:
1.23 snw 1433: case ACT_STATUS:
1434: epid = fm_get_pid (cur_env);
1435: if (epid > -1) {
1.32 snw 1436: fprintf (stderr, " - %s environment daemon running as pid %ld\n", cur_env, epid);
1.23 snw 1437: }
1438: else {
1439: fprintf (stderr, " - %s environment daemon does not appear to be running\n", cur_env);
1440: }
1.22 snw 1441: }
1.21 snw 1442: }
1443: else {
1444: printf ("fmadm: %s environment is disabled; skipping\n", cur_env);
1445: }
1446: } while ((cur_env = strtok_r (NULL, ",", &savptr)) != NULL);
1447:
1448: free (envlist);
1.30 snw 1449: exit (retval);
1.21 snw 1450:
1451: } /* fm_daemonctl() */
1452:
1.1 snw 1453: void fm_checkperms(void)
1454: {
1455:
1456: } /* fm_checkperms() */
1457:
1458:
1459: void fm_reconfigure(void)
1460: {
1461: char config_backup[4096];
1462:
1463: int retval;
1464:
1465: if (geteuid () != 0) {
1466: fprintf (stderr, "fmadm: not superuser\n");
1467: exit (1);
1468: }
1469:
1470: snprintf (config_backup, 4095, "%s.orig", config_file);
1471:
1472: fprintf (stderr, "fmadm: reconfiguring FreeM with system defaults for %s...\n", FREEM_VERSION_CSTR);
1473: fprintf (stderr, "fmadm: backing up %s to %s...\t", config_file, config_backup);
1474:
1.29 snw 1475: #if !defined(__OS2__)
1476: retval = cp (config_backup, config_file);
1477: #else
1.34 ! snw 1478: retval = DosCopy (config_file, config_backup, 1);
1.29 snw 1479: #endif
1.1 snw 1480:
1481: if (retval == 0) {
1.18 snw 1482: fprintf (stderr, "[OK]\n");
1.1 snw 1483:
1484: fm_configure ();
1485:
1486: fprintf (stderr, "\n\nYou may wish to edit %s if site-specific changes were made to the original FreeM configuration.\n", config_file);
1487: exit (0);
1488: }
1489: else {
1490: fprintf (stderr, "[FAIL (%s)]\n", strerror (errno));
1491: exit (1);
1492: }
1493:
1494: } /* fm_reconfigure() */
1495:
1.29 snw 1496: void update_conf (char *file, char *section, char *key, char *new_value)
1497: {
1498: char old_value[255];
1499: char tbuf[255];
1500:
1501: snprintf (tbuf, 254, "%s.%s", section, key);
1502:
1503: read_profile_string (file, section, key, old_value);
1504: if (strcmp (old_value, new_value) != 0) {
1505: modify_profile_string (file, section, key, new_value);
1506: fprintf (stderr, "\t%-40s%-20s -> %s\n", tbuf, old_value, new_value);
1507: }
1508: else {
1509: fprintf (stderr, "\t%-40s%-20s\n", tbuf, "no change");
1510: }
1511: }
1.1 snw 1512:
1513: void fm_configure (void)
1514: {
1.21 snw 1515: char rundir[4096];
1.19 snw 1516: char varbase[4096];
1.1 snw 1517: char sysrtn[4096];
1518: char sysgbl[4096];
1519: char usrrtn[4096];
1520: char usrgbl[4096];
1521:
1.23 snw 1522: char jnldir[4096];
1.1 snw 1523: char jnlfile[4096];
1524: char jnlmode[4];
1525: char jnlhostid[4096];
1526: char jnlcut[4096];
1527: char hostid[4096];
1528:
1529: char confbase[4096];
1530: char envbase[4096];
1531:
1532: char nsbase[4096];
1533:
1534: char buf[4096];
1535: FILE *fp;
1536:
1.29 snw 1537: int reconfigure = FALSE;
1538:
1.1 snw 1539: struct stat etcstat;
1.19 snw 1540:
1541: DIR *dir;
1542: struct dirent *ent;
1543: char src_dir[4096];
1544: char dest_dir[4096];
1545:
1.20 snw 1546: char *username = env_user;
1547: char *groupname = env_group;
1.28 snw 1548:
1.20 snw 1549: #if !defined(__OS2__)
1.32 snw 1550: struct group *d_grp;
1551: struct passwd *d_user;
1552:
1.24 snw 1553: if (geteuid () != 0) {
1554: fprintf (stderr, "fmadm: not superuser\n");
1555: exit (1);
1556: }
1557:
1.20 snw 1558: if ((d_grp = getgrnam (groupname)) == NULL) {
1559: fprintf (stderr, "fmadm: '%s' group must exist before configuring\n", groupname);
1560: exit (1);
1561: }
1562: if ((d_user = getpwnam (username)) == NULL) {
1563: fprintf (stderr, "fmadm: '%s' user must exist before configuring\n", username);
1564: exit (1);
1565: }
1566: #endif
1.23 snw 1567:
1.19 snw 1568: snprintf (varbase, 4095, "%s/freem", LOCALSTATEDIR);
1.21 snw 1569: snprintf (rundir, 4095, "%s/freem/run", LOCALSTATEDIR);
1.1 snw 1570: snprintf (sysrtn, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment);
1571: snprintf (sysgbl, 4095, "%s/freem/%s/SYSTEM/globals", LOCALSTATEDIR, fma_environment);
1572: snprintf (usrrtn, 4095, "%s/freem/%s/USER/routines", LOCALSTATEDIR, fma_environment);
1573: snprintf (usrgbl, 4095, "%s/freem/%s/USER/globals", LOCALSTATEDIR, fma_environment);
1.23 snw 1574: snprintf (jnldir, 4095, "%s/freem/%s/journals", LOCALSTATEDIR, fma_environment);
1575: snprintf (jnlfile, 4095, "%s/freem_journal_%s.dat", jnldir, fma_environment);
1.1 snw 1576: snprintf (jnlmode, 3, "on");
1577: snprintf (jnlhostid, 4095, "DEFAULT");
1578: snprintf (jnlcut, 4095, "4294967000");
1579:
1580: if (geteuid () != 0) {
1581: fprintf (stderr, "fmadm: not superuser\n");
1582: exit (1);
1583: }
1584:
1585: if (file_exists (config_file)) {
1.29 snw 1586: reconfigure = TRUE;
1.1 snw 1587: }
1.29 snw 1588:
1.1 snw 1589: gethostname (hostid, 4095);
1590: uuid_v4 (buf);
1591:
1592: snprintf (jnlhostid, 4095, "%s:%s", hostid, buf);
1593: snprintf (confbase, 4095, "%s/freem", SYSCONFDIR);
1594: snprintf (envbase, 4095, "%s/freem/%s", SYSCONFDIR, fma_environment);
1595: snprintf (nsbase, 4095, "%s/freem/%s", LOCALSTATEDIR, fma_environment);
1596:
1.9 snw 1597: #if defined(__OS2__)
1598: {
1599: char srcfile[PATHLEN];
1.11 snw 1600: char dstfile[PATHLEN];
1601:
1.9 snw 1602: snprintf (srcfile, PATHLEN, "%s/bin/freem.exe", PREFIX);
1603: snprintf (dstfile, PATHLEN, "%s/bin/freemd.exe", PREFIX);
1.11 snw 1604:
1605: unlink (dstfile);
1.9 snw 1606:
1.10 snw 1607: fprintf (stderr, "fmadm: running on OS/2; will copy %s to %s\n", srcfile, dstfile);
1.12 snw 1608:
1.16 snw 1609: if (DosCopy (srcfile, dstfile, 1) != 0) {
1.9 snw 1610: fprintf (stderr, "fmadm: fatal error copying %s to %s\n", srcfile, dstfile);
1611: exit (1);
1612: }
1.13 snw 1613:
1614: chmod (dstfile, 0755);
1.9 snw 1615: }
1616: #endif
1.1 snw 1617:
1.29 snw 1618: if (reconfigure == FALSE) {
1619: printf ("\nFreeM Initial Environment Configuration\n");
1620: printf ("---------------------------------------\n\n");
1621:
1622: printf ("This utility will create the initial configuration files for ");
1623: printf ("FreeM environment '%s' (owned by %s:%s) in '%s'.\n\n", fma_environment, username, groupname, config_file);
1624: }
1625: else {
1626: printf ("\nFreeM Environment Upgrade/Reconfiguration\n");
1627: printf ("-----------------------------------------\n\n");
1628:
1629: printf ("This utility will update the configuration files for ");
1630: printf ("FreeM environment '%s' (owned by %s:%s) in '%s'.\n\n", fma_environment, username, groupname, config_file);
1631: }
1.9 snw 1632:
1.1 snw 1633: /* check for existence of needed directories */
1634: if (stat (SYSCONFDIR, &etcstat) == -1) {
1.23 snw 1635: fprintf (stderr, "fmadm: creating %s [SYSCONFDIR]\n", SYSCONFDIR);
1.19 snw 1636: mkdir (SYSCONFDIR, 0775);
1.20 snw 1637: set_permissions (SYSCONFDIR, username, groupname, 0775);
1.1 snw 1638: }
1639:
1640: if (stat (confbase, &etcstat) == -1) {
1.23 snw 1641: fprintf (stderr, "fmadm: creating %s [confbase]\n", confbase);
1.19 snw 1642: mkdir (confbase, 0775);
1.20 snw 1643: set_permissions (confbase, username, groupname, 0775);
1.1 snw 1644: }
1645:
1.19 snw 1646: if (stat (varbase, &etcstat) == -1) {
1.23 snw 1647: fprintf (stderr, "fmadm: creating %s [varbase]\n", varbase);
1.19 snw 1648: mkdir (varbase, 0775);
1.20 snw 1649: set_permissions (varbase, username, groupname, 0775);
1.19 snw 1650: }
1.21 snw 1651:
1.23 snw 1652: if (stat (envbase, &etcstat) == -1) {
1653: fprintf (stderr, "fmadm: creating %s [envbase]\n", envbase);
1654: mkdir (envbase, 0775);
1655: set_permissions (envbase, username, groupname, 0775);
1656: }
1657:
1.21 snw 1658: if (stat (rundir, &etcstat) == -1) {
1.23 snw 1659: fprintf (stderr, "fmadm: creating %s [rundir]\n", rundir);
1.21 snw 1660: mkdir (rundir, 0777);
1661: chmod (rundir, 0777);
1662: }
1663:
1.1 snw 1664: if (stat (nsbase, &etcstat) == -1) {
1.23 snw 1665: fprintf (stderr, "fmadm: creating %s [nsbase]\n", nsbase);
1.19 snw 1666: mkdir (nsbase, 0775);
1.20 snw 1667: set_permissions (nsbase, username, groupname, 0775);
1.1 snw 1668: }
1669:
1.23 snw 1670: if (stat (jnldir, &etcstat) == -1) {
1671: fprintf (stderr, "fmadm: creating %s [jnldir]\n", jnldir);
1672: mkdir (jnldir, 0775);
1673: set_permissions (jnldir, username, groupname, 0775);
1674: }
1675:
1676:
1.19 snw 1677: snprintf (src_dir, 4095, "%s/freem/mlib", DATADIR);
1678: snprintf (dest_dir, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment);
1.29 snw 1679:
1680: if (reconfigure == FALSE) {
1681: fprintf (stderr, "fmadm: populating new environment '%s'\n", fma_environment);
1682: }
1683: else {
1684: fprintf (stderr, "fmadm: upgrading environment '%s'\n", fma_environment);
1685: }
1.19 snw 1686:
1687: snprintf (buf, 4095, "%s/freem/%s/SYSTEM", LOCALSTATEDIR, fma_environment);
1688: mkdir (buf, 0775);
1.20 snw 1689: set_permissions (buf, username, groupname, 0775);
1.19 snw 1690:
1691: snprintf (buf, 4095, "%s/freem/%s/USER", LOCALSTATEDIR, fma_environment);
1692: mkdir (buf, 0775);
1.20 snw 1693: set_permissions (buf, username, groupname, 0775);
1.19 snw 1694:
1695: snprintf (buf, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment);
1696: mkdir (buf, 0775);
1.20 snw 1697: set_permissions (buf, username, groupname, 0775);
1.19 snw 1698:
1699: snprintf (buf, 4095, "%s/freem/%s/USER/globals", LOCALSTATEDIR, fma_environment);
1700: mkdir (buf, 0775);
1.20 snw 1701: set_permissions (buf, username, groupname, 0775);
1.19 snw 1702:
1703: snprintf (buf, 4095, "%s/freem/%s/SYSTEM/globals", LOCALSTATEDIR, fma_environment);
1704: mkdir (buf, 0775);
1.20 snw 1705: set_permissions (buf, username, groupname, 0775);
1.19 snw 1706:
1707: snprintf (buf, 4095, "%s/freem/%s/USER/routines", LOCALSTATEDIR, fma_environment);
1708: mkdir (buf, 0775);
1.20 snw 1709: set_permissions (buf, username, groupname, 0775);
1.19 snw 1710:
1.25 snw 1711: fprintf (stderr, "fmadm: copying vendor routines from '%s' to '%s'...\n", src_dir, dest_dir);
1.1 snw 1712:
1.19 snw 1713: if ((dir = opendir (src_dir)) == NULL) {
1714: fprintf (stderr, "\nfmadm: could not open source directory %s\n", src_dir);
1715: exit (1);
1716: }
1717:
1718: while ((ent = readdir (dir)) != NULL) {
1719: char infile[4096];
1720: char outfile[4096];
1.1 snw 1721:
1.25 snw 1722: if ((strcmp (ent->d_name, ".") != 0) && (strcmp (ent->d_name, "..") != 0)) {
1.19 snw 1723:
1724: snprintf (infile, 4095, "%s/%s", src_dir, ent->d_name);
1725: snprintf (outfile, 4095, "%s/%s", dest_dir, ent->d_name);
1.1 snw 1726:
1.25 snw 1727: if (stat (outfile, &etcstat) == 0) {
1728: unlink (outfile);
1729: fprintf (stderr, "\tupgrade -> %s\n", ent->d_name);
1730: }
1731: else {
1732: fprintf (stderr, "\tnew -> %s\n", ent->d_name);
1733: }
1734:
1.19 snw 1735: #if !defined(__OS2__)
1736: if (cp (outfile, infile) != 0) {
1737: fprintf (stderr, "fmadm: failure copying %s to %s\n", infile, outfile);
1738: }
1.20 snw 1739: set_permissions (outfile, username, groupname, 0755);
1.19 snw 1740: #else
1741: if (DosCopy (infile, outfile, 1) != 0) {
1742: fprintf (stderr, "fmadm: failure copying %s to %s\n", infile, outfile);
1.1 snw 1743: }
1.19 snw 1744: #endif
1.1 snw 1745:
1746: }
1747:
1748: }
1.20 snw 1749:
1.28 snw 1750: if (fm_validate_environment (fma_environment) == FALSE) {
1751: fp = fopen (env_config_file, "a+");
1752:
1753: fprintf (stderr, "Creating %s... ", env_config_file);
1754:
1755: snprintf (buf, 4095, "[%s]", fma_environment);
1756: fm_write (fp, buf);
1757:
1758: snprintf (buf, 4095, "user=%s", env_user);
1759: fm_write (fp, buf);
1760:
1761: snprintf (buf, 4095, "group=%s", env_group);
1762: fm_write (fp, buf);
1763:
1.29 snw 1764: snprintf (buf, 4095, "enabled=%s", env_enabled);
1.28 snw 1765: fm_write (fp, buf);
1766:
1767: snprintf (buf, 4095, "env_path=%s/freem/%s", LOCALSTATEDIR, fma_environment);
1768: fm_write (fp, buf);
1769:
1770: fclose (fp);
1771: fprintf (stderr, "[OK]\n");
1772: }
1773: else {
1.29 snw 1774: fprintf (stderr, "\nUpdating %s: \n", env_config_file);
1.20 snw 1775:
1.29 snw 1776: update_conf (env_config_file, fma_environment, "user", env_user);
1777: update_conf (env_config_file, fma_environment, "group", env_group);
1778: update_conf (env_config_file, fma_environment, "enabled", env_enabled);
1.28 snw 1779: }
1.29 snw 1780:
1781: if (reconfigure == FALSE) {
1782: fp = fopen (config_file, "a+");
1783:
1784: fprintf (stderr, "Creating %s... ", config_file);
1785:
1786: snprintf (buf, 4095, "[SYSTEM]");
1787: fm_write (fp, buf);
1788:
1789: snprintf (buf, 4095, "root=%s/freem/%s/SYSTEM", LOCALSTATEDIR, fma_environment);
1790: fm_write (fp, buf);
1791:
1792: snprintf (buf, 4095, "routines_path=%s", sysrtn);
1793: fm_write (fp, buf);
1794:
1795: snprintf (buf, 4095, "globals_path=%s", sysgbl);
1796: fm_write (fp, buf);
1797:
1798: snprintf (buf, 4095, "journal_file=%s", jnlfile);
1799: fm_write (fp, buf);
1800:
1801: snprintf (buf, 4095, "journal_mode=%s", jnlmode);
1802: fm_write (fp, buf);
1803:
1804: snprintf (buf, 4095, "journal_host_id=%s", jnlhostid);
1805: fm_write (fp, buf);
1806:
1807: snprintf (buf, 4095, "journal_cut_threshold=%s", jnlcut);
1808: fm_write (fp, buf);
1809:
1810: snprintf (buf, 4095, "zdate_format=%%x");
1811: fm_write (fp, buf);
1812:
1813: snprintf (buf, 4095, "ztime_format=%%X");
1814: fm_write (fp, buf);
1815:
1816: snprintf (buf, 4095, "\n[USER]");
1817: fm_write (fp, buf);
1818:
1819: snprintf (buf, 4095, "root=%s/freem/%s/USER", LOCALSTATEDIR, fma_environment);
1820: fm_write (fp, buf);
1821:
1822: snprintf (buf, 4095, "routines_path=%s", usrrtn);
1823: fm_write (fp, buf);
1824:
1825: snprintf (buf, 4095, "globals_path=%s", usrgbl);
1826: fm_write (fp, buf);
1827:
1828: fclose (fp);
1829: set_permissions (config_file, username, groupname, 0755);
1830: fprintf (stderr, "[OK]\n");
1.1 snw 1831:
1.29 snw 1832: printf ("FreeM initial configuration is complete.\n\n");
1833: }
1834: else {
1835: char tmpsd[255];
1836: read_profile_string (config_file, "SYSTEM", "journal_host_id", tmpsd);
1837:
1838: /* existing configuration */
1839: fprintf (stderr, "\nUpdating environment configuration for %s:\n", fma_environment);
1.1 snw 1840:
1.29 snw 1841: snprintf (buf, 4095, "%s/freem/%s/SYSTEM", LOCALSTATEDIR, fma_environment);
1842: update_conf (config_file, "SYSTEM", "root", buf);
1843: update_conf (config_file, "SYSTEM", "routines_path", sysrtn);
1844: update_conf (config_file, "SYSTEM", "globals_path", sysgbl);
1845: update_conf (config_file, "SYSTEM", "journal_file", jnlfile);
1846: update_conf (config_file, "SYSTEM", "journal_mode", jnlmode);
1847: update_conf (config_file, "SYSTEM", "journal_host_id", tmpsd);
1848: update_conf (config_file, "SYSTEM", "journal_cut_threshold", jnlcut);
1849:
1850: snprintf (buf, 4095, "%%x");
1851: update_conf (config_file, "SYSTEM", "zdate_format", buf);
1852:
1853: snprintf (buf, 4095, "%%X");
1854: update_conf (config_file, "SYSTEM", "ztime_format", buf);
1855:
1856: /* USER */
1857: snprintf (buf, 4095, "%s/freem/%s/USER", LOCALSTATEDIR, fma_environment);
1858: update_conf (config_file, "USER", "root", buf);
1859: update_conf (config_file, "USER", "routines_path", usrrtn);
1860: update_conf (config_file, "USER", "globals_path", usrgbl);
1.1 snw 1861:
1.29 snw 1862: }
1.1 snw 1863:
1.20 snw 1864:
1.29 snw 1865: printf ("\n\nUSER globals: %s\n", usrgbl);
1866: printf ("USER routines: %s\n", usrrtn);
1867: printf ("SYSTEM globals: %s\n", sysgbl);
1868: printf ("SYSTEM routines: %s\n", sysrtn);
1869: printf ("After-image journal: %s [%s]\n", jnlfile, jnlmode);
1870: printf ("Journal cut threshold: %s bytes\n", jnlcut);
1871: printf ("Distributed journaling host ID: %s\n", jnlhostid);
1.1 snw 1872:
1.29 snw 1873: if (reconfigure == TRUE) {
1874: fprintf (stderr, "\nIf you previously defined environments other than '%s', you should run\n'fmadm reconfigure -e=<environment-name>' on each of them to ensure they have\nthe latest vendor routines and correct, updated settings.\n\n", fma_environment);
1875: }
1.1 snw 1876:
1877: } /* fm_configure */
1878:
1.20 snw 1879: void set_permissions(char *path, char *user, char *grp, int mode)
1880: {
1881:
1882: #if !defined(__OS2__)
1883: struct group *d_grp;
1884: struct passwd *d_user;
1885: gid_t d_gid;
1886: uid_t d_uid;
1887: #endif
1888:
1889:
1890: #if !defined(__OS2__)
1891: if ((d_grp = getgrnam (grp)) == NULL) {
1892: fprintf (stderr, "fmadm: '%s' group must exist before configuring\n", grp);
1893: exit (1);
1894: }
1895: d_gid = d_grp->gr_gid;
1896:
1897: if ((d_user = getpwnam (user)) == NULL) {
1898: fprintf (stderr, "fmadm: '%s' user must exist before configuring\n", user);
1899: exit (1);
1900: }
1901: d_uid = d_user->pw_uid;
1902:
1903: if (chown (path, d_uid, d_gid) != 0) {
1904: fprintf (stderr, "fmadm: error setting ownership on %s\n", path);
1905: exit (1);
1906: }
1907: #endif
1908:
1909: if (chmod (path, mode) != 0) {
1910: fprintf (stderr, "fmadm: error setting permissions on %s to %d\n", path, mode);
1911: exit (1);
1912: }
1913:
1914: }
1915:
1.1 snw 1916: void fm_write (FILE *file, char *buf)
1917: {
1918: fprintf (file, "%s\n", buf);
1919: }
1920:
1921: void fm_sig_attach (int sig, void *handler)
1922: {
1923: struct sigaction act;
1924:
1925: act.sa_handler = handler;
1926: sigaction (sig, &act, NULL);
1927:
1928: }
1929:
1930: void fm_sig_init (void)
1931: {
1932: sig_attach (SIGINT, &fm_on_sigint);
1933: sig_attach (SIGTERM, &fm_on_sigterm);
1934: }
1935:
1936: void fm_on_sigint (void)
1937: {
1938: fprintf (stderr, "\nfmadm: caught SIGINT\n");
1939: fmadm_exit (0);
1940: }
1941:
1942: void fm_on_sigterm (void)
1943: {
1944: fprintf (stderr, "\nfmadm: caught SIGTERM\n");
1945: fmadm_exit (0);
1946: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>