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