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