File:  [Coherent Logic Development] / freem / src / fmadm.c
Revision 1.43: download - view: text, annotated - select for diffs
Tue Mar 24 00:25:36 2026 UTC (8 days, 5 hours ago) by snw
Branches: MAIN
CVS tags: HEAD
Fix segfault when running \'fmadm status\' without a second argument

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>