Annotation of freem/src/fmadm.c, revision 1.43

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

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