File:  [Coherent Logic Development] / freem / src / fmadm.c
Revision 1.42: download - view: text, annotated - select for diffs
Tue May 13 20:03:53 2025 UTC (2 months, 2 weeks ago) by snw
Branches: MAIN
CVS tags: HEAD
Error-check fopen in fm_daemonctl

    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>