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