File:  [Coherent Logic Development] / freem / src / fmadm.c
Revision 1.40: download - view: text, annotated - select for diffs
Tue Apr 15 18:19:40 2025 UTC (11 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Further attempts to fix FreeBSD

    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>