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