--- freem/src/fmadm.c 2025/02/26 00:48:27 1.3 +++ freem/src/fmadm.c 2025/04/02 04:50:49 1.25 @@ -1,23 +1,11 @@ /* - * * - * * * - * * * - * *************** - * * * * * - * * MUMPS * - * * * * * - * *************** - * * * - * * * - * * - * - * fmadm.c + * $Id: fmadm.c,v 1.25 2025/04/02 04:50:49 snw Exp $ * FreeM Administration Tool * * - * Author: Serena Willis + * Author: Serena Willis * Copyright (C) 1998 MUG Deutschland - * Copyright (C) 2020, 2023 Coherent Logic Development LLC + * Copyright (C) 2020, 2023, 2025 Coherent Logic Development LLC * * * This file is part of FreeM. @@ -35,10 +23,73 @@ * You should have received a copy of the GNU Affero Public License * along with FreeM. If not, see . * + * $Log: fmadm.c,v $ + * Revision 1.25 2025/04/02 04:50:49 snw + * Allow vendor routines to be upgraded + * + * Revision 1.24 2025/04/02 03:02:42 snw + * Stop requiring users to pass -e to fmadm when -u or -g are passed + * + * Revision 1.23 2025/04/02 02:16:27 snw + * Add fmadm status environment command and move journals to a better location + * + * Revision 1.22 2025/04/01 23:21:45 snw + * fmadm commands for stopping, starting, and restarting environments now functional + * + * Revision 1.21 2025/04/01 20:11:46 snw + * Further work on fmadm + * + * Revision 1.20 2025/04/01 16:37:12 snw + * 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. + * + * Revision 1.19 2025/04/01 14:32:11 snw + * Begin work on environment and namespace reorg + * + * Revision 1.18 2025/03/31 16:33:56 snw + * Work on fmadm edit global + * + * Revision 1.17 2025/03/30 01:36:58 snw + * Make it easier to bring back fma_gedit, fix double-free in global handler, limit $CHAR to 7-bit ASCII + * + * Revision 1.16 2025/03/24 20:59:58 snw + * Try using DosCopy API instead of built-in cp function on OS/2 + * + * Revision 1.15 2025/03/24 20:58:05 snw + * Try using DosCopy API instead of built-in cp function on OS/2 + * + * Revision 1.14 2025/03/24 20:57:06 snw + * Try using DosCopy API instead of built-in cp function on OS/2 + * + * Revision 1.13 2025/03/24 20:15:09 snw + * Set file permissions on freemd.exe on OS/2 in fmadm configure + * + * Revision 1.12 2025/03/24 20:13:34 snw + * Set file permissions on freemd.exe on OS/2 in fmadm configure + * + * Revision 1.11 2025/03/24 19:25:48 snw + * Make fmadm configure copy freem.exe to freemd.exe for daemon operation on OS/2 systems + * + * Revision 1.10 2025/03/24 19:22:16 snw + * Make fmadm configure copy freem.exe to freemd.exe for daemon operation on OS/2 systems + * + * Revision 1.9 2025/03/24 19:19:42 snw + * Make fmadm configure copy freem.exe to freemd.exe for daemon operation on OS/2 systems + * + * Revision 1.8 2025/03/22 18:43:54 snw + * Make STRLEN 255 chars and add BIGSTR macro for larger buffers + * + * Revision 1.7 2025/03/09 19:14:25 snw + * First phase of REUSE compliance and header reformat + * + * + * SPDX-FileCopyrightText: (C) 2025 Coherent Logic Development LLC + * SPDX-License-Identifier: AGPL-3.0-or-later **/ #include #include +#include +#include #include #include #include @@ -46,11 +97,16 @@ #include #include #include +#include #include "config.h" #include "transact.h" #include "namespace.h" #include "fs.h" +#if defined(__OS2__) +# include +#endif + #ifdef HAVE_LIBREADLINE # if defined(HAVE_READLINE_READLINE_H) # include @@ -90,13 +146,13 @@ extern int read_history (); /* namespace configuration */ char fma_environment[STRLEN]; char fma_namespace[STRLEN]; -char fma_routine_path[STRLEN]; -char fma_global_path[STRLEN]; -char fma_journal_path[STRLEN]; -char fma_pct_global_path[STRLEN]; -char fma_pct_routine_path[STRLEN]; +char fma_routine_path[PATHLEN]; +char fma_global_path[PATHLEN]; +char fma_journal_path[PATHLEN]; +char fma_pct_global_path[PATHLEN]; +char fma_pct_routine_path[PATHLEN]; char fma_journal_cut_threshold[STRLEN]; -char fma_locktab[STRLEN]; +char fma_locktab[PATHLEN]; short fma_base_opt = 1; short fma_min_args = 2; short fma_explicit_namespace = FALSE; @@ -106,13 +162,19 @@ short fma_explicit_environment = FALSE; char obj_str[STRLEN]; extern char config_file[4096]; +extern char env_config_file[4096]; +extern char env_user[255]; +extern char env_group[255]; int fm_shell(void); void fm_checkperms(void); void fm_reconfigure(void); void fm_configure(void); +int fm_daemonctl (short action, short object, int optc, char **options); void fm_write (FILE *file, char *buf); int fma_jobs_remove (int optc, char **opts); +void set_permissions(char *path, char *user, char *grp, int mode); +extern int read_profile_string(char *file, char *section, char *key, char *value); int main (int argc, char **argv) { @@ -160,6 +222,41 @@ int main (int argc, char **argv) if (argv[i][0] == '-') { switch (argv[i][1]) { + + case 'u': + if (argv[i][2] != '=') { + fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]); + fmadm_usage (); + exit (1); + } + + k = 0; + + for (j = 3; j < strlen (argv[i]); j++) { + env_user[k++] = argv[i][j]; + } + + base_arg++; + + break; + + case 'g': + if (argv[i][2] != '=') { + fprintf (stderr, "fmadm: missing equals sign in flag -%c\n", argv[i][1]); + fmadm_usage (); + exit (1); + } + + k = 0; + + for (j = 3; j < strlen (argv[i]); j++) { + env_group[k++] = argv[i][j]; + } + + base_arg++; + + break; + case 'e': if (argv[i][2] != '=') { @@ -173,6 +270,11 @@ int main (int argc, char **argv) for (j = 3; j < strlen (argv[i]); j++) { fma_environment[k++] = argv[i][j]; } + + if (strcmp (fma_environment, "all") == 0 ) { + fprintf (stderr, "fmadm: 'all' is an invalid environment name\n"); + exit (1); + } fma_explicit_environment = TRUE; base_arg++; @@ -200,18 +302,31 @@ int main (int argc, char **argv) } } } - - if (!fma_explicit_environment) snprintf (fma_environment, 4096, "DEFAULT"); - if (!fma_explicit_namespace) snprintf (fma_namespace, 4096, "SYSTEM"); - snprintf (config_file, 4096, "%s/freem/%s/freem.conf", SYSCONFDIR, fma_environment); + if (obj != OBJ_DAEMON) { + if (strlen (env_user) == 0) { + snprintf (env_user, 6, "freem"); + } + + if (strlen (env_group) == 0) { + snprintf (env_group, 6, "freem"); + } + + if (!fma_explicit_environment) snprintf (fma_environment, 4096, "DEFAULT"); + if (!fma_explicit_namespace) snprintf (fma_namespace, 4096, "SYSTEM"); + + snprintf (config_file, 4096, "%s/freem/%s/freem.conf", SYSCONFDIR, fma_environment); + } + + snprintf (env_config_file, 4096, "%s/freem/env.conf", SYSCONFDIR); + /* 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]); exit(1); */ - /* override for fmadm configure */ + /* override for fmadm configure and daemon stuff */ if (got_action) { if (strcmp (argv[1], "configure") == 0) { fm_configure (); @@ -221,6 +336,27 @@ int main (int argc, char **argv) fm_reconfigure (); exit (0); } + else if (strcmp (argv[1], "start") == 0 && strcmp (argv[2], "environment") == 0) { + act = ACT_START; + obj = OBJ_DAEMON; + goto act_switch; + } + else if (strcmp (argv[1], "stop") == 0 && strcmp (argv[2], "environment") == 0) { + act = ACT_STOP; + obj = OBJ_DAEMON; + goto act_switch; + } + else if (strcmp (argv[1], "restart") == 0 && strcmp (argv[2], "environment") == 0) { + act = ACT_RESTART; + obj = OBJ_DAEMON; + goto act_switch; + } + else if (strcmp (argv[1], "status") == 0 && strcmp (argv[2], "environment") == 0) { + act = ACT_STATUS; + obj = OBJ_DAEMON; + goto act_switch; + } + } pid = getpid (); @@ -231,7 +367,7 @@ int main (int argc, char **argv) job_init (TRUE); fm_sig_init (); - + /* go to fmadm shell if no arguments passed */ if (!got_action && !got_object) return fm_shell (); @@ -239,71 +375,6 @@ int main (int argc, char **argv) fm_checkperms (); exit (0); } - -#if 0 - /* how many args do we have? */ - switch (argc) { - - case 3: /* action, object */ - strncpy (action, argv[1], STRLEN - 1); - strncpy (obj_str, argv[2], STRLEN - 1); - strncpy (fma_namespace, "SYSTEM", STRLEN - 1); - - optc = argc - 2; - - fma_explicit_namespace = FALSE; - fma_min_args = 1; - base_arg = 3; - - break; - - case 4: /* action, object, namespace */ - - strncpy (action, argv[1], STRLEN - 1); - strncpy (obj_str, argv[2], STRLEN - 1); - - if (validate_namespace (argv[3]) == TRUE) { - strncpy (fma_namespace, argv[3], STRLEN - 1); - fma_min_args = 2; - fma_explicit_namespace = TRUE; - base_arg = 4; - optc = argc - 3; - } - else { - strncpy (fma_namespace, "SYSTEM", 10); - fma_min_args = 1; - fma_explicit_namespace = FALSE; - base_arg = 3; - optc = argc - 2; - } - - break; - - default: - if (argc < 4) fmadm_usage(); - - /* we don't know what any but the first two args actually mean */ - strncpy (action, argv[1], STRLEN - 1); - strncpy (obj_str, argv[2], STRLEN - 1); - - if (validate_namespace (argv[3]) == TRUE) { - strncpy (fma_namespace, argv[3], STRLEN - 1); - fma_min_args = 2; - fma_explicit_namespace = TRUE; - base_arg = 4; - optc = argc - 3; - } - else { - strncpy (fma_namespace, "SYSTEM", 10); - fma_min_args = 1; - fma_explicit_namespace = FALSE; - base_arg = 3; - optc = argc - 2; - } - - - } -#endif set_namespace (fma_namespace, FALSE); @@ -345,18 +416,23 @@ int main (int argc, char **argv) else if (strncmp (action, "backup", STRLEN - 1) == 0) act = ACT_BACKUP; else if (strncmp (action, "restore", STRLEN - 1) == 0) act = ACT_RESTORE; else if (strncmp (action, "migrate", STRLEN - 1) == 0) act = ACT_MIGRATE; - else if (strncmp (action, "edit", STRLEN -1) == 0) act = ACT_EDIT; + else if (strncmp (action, "edit", STRLEN - 1) == 0) act = ACT_EDIT; + else if (strncmp (action, "start", STRLEN - 1) == 0) act = ACT_START; + else if (strncmp (action, "stop", STRLEN - 1) == 0) act = ACT_STOP; + else if (strncmp (action, "restart", STRLEN - 1) == 0) act = ACT_RESTART; else return fmadm_usage(); if (strncmp (obj_str, "lock", STRLEN - 1) == 0) obj = OBJ_LOCK; - else if (strncmp (obj_str, "zallocate", STRLEN - 1) == 0) obj = OBJ_ZALLOC; else if (strncmp (obj_str, "journal", STRLEN - 1) == 0) obj = OBJ_JOURNAL; else if (strncmp (obj_str, "namespace", STRLEN - 1) == 0) obj = OBJ_NAMESPACE; else if (strncmp (obj_str, "global", STRLEN - 1) == 0) obj = OBJ_GLOBAL; else if (strncmp (obj_str, "routine", STRLEN - 1) == 0) obj = OBJ_ROUTINE; else if (strncmp (obj_str, "job", STRLEN - 1) == 0) obj = OBJ_JOB; + else if (strncmp (obj_str, "environment", STRLEN - 1) == 0) obj = OBJ_DAEMON; else return fmadm_usage(); + if (act > ACT_EDIT) goto act_switch; + if (get_conf (fma_namespace, "routines_path", fma_routine_path) == FALSE) { fprintf (stderr, "fmadm: cannot determine routine path for namespace %s\n", fma_namespace); return 1; @@ -392,6 +468,7 @@ int main (int argc, char **argv) stcnv_c2m (glopath); +act_switch: switch (act) { @@ -446,6 +523,11 @@ int main (int argc, char **argv) case ACT_EDIT: fmadm_exit (fm_edit (obj, optc, opts)); + case ACT_START: + case ACT_STOP: + case ACT_RESTART: + case ACT_STATUS: + fmadm_exit (fm_daemonctl (act, obj, optc, opts)); default: return fmadm_usage(); @@ -598,7 +680,6 @@ int fm_shell (void) strcpy (obj_str, args[0]); if (strncmp (obj_str, "lock", STRLEN - 1) == 0) obj = OBJ_LOCK; - else if (strncmp (obj_str, "zallocate", STRLEN - 1) == 0) obj = OBJ_ZALLOC; else if (strncmp (obj_str, "journal", STRLEN - 1) == 0) obj = OBJ_JOURNAL; else if (strncmp (obj_str, "namespace", STRLEN - 1) == 0) obj = OBJ_NAMESPACE; else if (strncmp (obj_str, "global", STRLEN - 1) == 0) obj = OBJ_GLOBAL; @@ -759,7 +840,7 @@ int fm_shell (void) printf ("Global Path: %s\n", fma_global_path); printf ("%%-Global Path: %s\n", fma_pct_global_path); printf ("Journal File: %s\n", fma_journal_path); - printf ("Journal Cut Threshold: %ld bytes\n", fma_journal_cut_threshold); + printf ("Journal Cut Threshold: %s bytes\n", fma_journal_cut_threshold); break; case FMAC_EXIT: @@ -798,10 +879,12 @@ int fmadm_usage (void) fprintf (stdout, " can be one of:\n"); fprintf (stdout, " list, examine, verify, compact, repair, create, remove,\n"); - fprintf (stdout, " import, export, backup, restore, migrate, edit\n\n"); + fprintf (stdout, " import, export, backup, restore, migrate, edit, start,\n"); + fprintf (stdout, " stop, restart\n\n"); fprintf (stdout, " can be one of:\n"); - fprintf (stdout, " lock, zallocate, journal, namespace, global, routine, job\n\n"); + fprintf (stdout, " lock, journal, namespace, global, routine, job,\n"); + fprintf (stdout, " environment\n\n"); fprintf (stdout, " Not all actions are valid for all objects. Please see the FreeM manual\n"); fprintf (stdout, " for details on fmadm usage and options.\n\n"); @@ -1025,11 +1108,9 @@ int fm_edit (short object, int optc, cha case OBJ_ROUTINE: return fma_routines_edit (optc, options); - /* case OBJ_GLOBAL: return fma_globals_edit (optc, options); - */ - + default: fprintf (stderr, "fmadm: 'edit' is an invalid action for '%s'\n", obj_str); return 1; @@ -1038,6 +1119,177 @@ int fm_edit (short object, int optc, cha } /* fm_edit() */ +long fm_get_pid (char *env) +{ + char pid_file[4096]; + char tmp_pid[255]; + long res; + + FILE *fp; + + snprintf (pid_file, 4095, "%s/freem/run/%s.pid", LOCALSTATEDIR, env); + + if ((fp = fopen (pid_file, "r")) != NULL) { + if (fgets (tmp_pid, 255, fp)) { + fclose (fp); + return atol (tmp_pid); + } + else { + fclose (fp); + return -1; + } + } + else { + return -1; + } +} + +int fm_daemonctl (short action, short object, int optc, char **options) +{ + FILE *ef; + char *envlist; + char env[255]; + char line[255]; + char tmps[255]; + char *cur_env; + char cmd[4096]; + char verb[40]; + char e_user[255]; + char e_grp[255]; + char e_ena[10]; + char basecmd[255]; + char *savptr; + int result; + long epid; + +#if !defined(__OS2__) + snprintf (basecmd, 254, "%s/bin/freem", PREFIX); +#else + snprintf (basecmd, 254, "%s/bin/freemd.exe", PREFIX); +#endif + + switch (action) { + case ACT_START: + sprintf (verb, "starting"); + break; + case ACT_STOP: + sprintf (verb, "stopping"); + break; + case ACT_RESTART: + sprintf (verb, "restarting"); + break; + case ACT_STATUS: + sprintf (verb, "checking status of"); + break; + } + + if (optc) { + /* environment list specified as command-line argument */ + envlist = (char *) malloc (sizeof (char) * BIGSTR); + NULLPTRCHK(envlist,"fm_daemonctl"); + + strcpy (envlist, options[0]); + } + else { + /* no environment specified; do 'action' for all environments */ + envlist = (char *) malloc (sizeof (char) * BIGSTR); + NULLPTRCHK(envlist,"fm_daemonctl"); + + ef = fopen (env_config_file, "r"); + + while (fgets (line, 254, ef)) { + if (line[0] == '[') { + strncpy (env, &(line[1]), 255); + env[strlen (env) - 2] = '\0'; + snprintf (tmps, 255, "%s,", env); + strncat (envlist, tmps, BIGSTR - 1); + } + } + envlist[strlen (envlist) - 1] = '\0'; + + fclose (ef); + } + + savptr = envlist; + cur_env = strtok_r (envlist, ",", &savptr); + do { + result = read_profile_string (env_config_file, cur_env, "enabled", e_ena); + if (result == FALSE || strcmp (e_ena, "true") == 0) { + + result = read_profile_string (env_config_file, cur_env, "user", e_user); + if (result == FALSE) { + strcpy (e_user, "freem"); + } + result = read_profile_string (env_config_file, cur_env, "group", e_grp); + if (result == FALSE) { + strcpy (e_grp, "freem"); + } + + printf ("fmadm: %s environment %s\n", verb, cur_env); + + switch (action) { + case ACT_START: +#if !defined(__OS2__) + snprintf (cmd, 4095, "%s -d -e %s -u %s -g %s", basecmd, cur_env, e_user, e_grp); +#else + sprintf (cmd, 4095, "%s -d -k -e %s -u %s -g %s", basecmd, cur_env, e_user, e_grp); +#endif + system (cmd); + break; + case ACT_STOP: + epid = fm_get_pid (cur_env); + if (epid > -1) { + fprintf (stderr, "fmadm: stopping environment daemon pid %d\n", epid); + kill (epid, SIGINT); + kill (epid, SIGTERM); + } + else { + fprintf (stderr, "fmadm: could not obtain environment daemon pid\n"); + } + + break; + case ACT_RESTART: + epid = fm_get_pid (cur_env); + if (epid > -1) { + fprintf (stderr, "fmadm: stopping environment daemon pid %d\n", epid); + kill (epid, SIGINT); + kill (epid, SIGTERM); + } + else { + fprintf (stderr, "fmadm: could not obtain environment daemon pid\n"); + } + fprintf (stderr, "fmadm: waiting 2 seconds\n"); + sleep (2); + fprintf (stderr, "fmadm: starting environment %s\n", cur_env); +#if !defined(__OS2__) + snprintf (cmd, 4095, "%s -d -e %s -u %s -g %s", basecmd, cur_env, e_user, e_grp); +#else + sprintf (cmd, 4095, "%s -d -k -e %s -u %s -g %s", basecmd, cur_env, e_user, e_grp); +#endif + system (cmd); + + + break; + case ACT_STATUS: + epid = fm_get_pid (cur_env); + if (epid > -1) { + fprintf (stderr, " - %s environment daemon running as pid %d\n", cur_env, epid); + } + else { + fprintf (stderr, " - %s environment daemon does not appear to be running\n", cur_env); + } + } + } + else { + printf ("fmadm: %s environment is disabled; skipping\n", cur_env); + } + } while ((cur_env = strtok_r (NULL, ",", &savptr)) != NULL); + + free (envlist); + exit (0); + +} /* fm_daemonctl() */ + void fm_checkperms(void) { @@ -1064,7 +1316,7 @@ void fm_reconfigure(void) retval = rename (config_file, config_backup); if (retval == 0) { - fprintf (stderr, "[OK]\n\n"); + fprintf (stderr, "[OK]\n"); fm_configure (); @@ -1081,14 +1333,14 @@ void fm_reconfigure(void) void fm_configure (void) { - + char rundir[4096]; + char varbase[4096]; char sysrtn[4096]; char sysgbl[4096]; char usrrtn[4096]; char usrgbl[4096]; - char locktab[4096]; - char zalloctab[4096]; + char jnldir[4096]; char jnlfile[4096]; char jnlmode[4]; char jnlhostid[4096]; @@ -1105,14 +1357,47 @@ void fm_configure (void) struct stat etcstat; int stat_result; - + + DIR *dir; + struct dirent *ent; + char src_dir[4096]; + char dest_dir[4096]; + + char *username = env_user; + char *groupname = env_group; + +#if !defined(__OS2__) + if (geteuid () != 0) { + fprintf (stderr, "fmadm: not superuser\n"); + exit (1); + } + + struct group *d_grp; + struct passwd *d_user; + gid_t d_gid; + uid_t d_uid; + + if ((d_grp = getgrnam (groupname)) == NULL) { + fprintf (stderr, "fmadm: '%s' group must exist before configuring\n", groupname); + exit (1); + } + d_gid = d_grp->gr_gid; + + if ((d_user = getpwnam (username)) == NULL) { + fprintf (stderr, "fmadm: '%s' user must exist before configuring\n", username); + exit (1); + } + d_uid = d_user->pw_uid; +#endif + + snprintf (varbase, 4095, "%s/freem", LOCALSTATEDIR); + snprintf (rundir, 4095, "%s/freem/run", LOCALSTATEDIR); snprintf (sysrtn, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment); snprintf (sysgbl, 4095, "%s/freem/%s/SYSTEM/globals", LOCALSTATEDIR, fma_environment); snprintf (usrrtn, 4095, "%s/freem/%s/USER/routines", LOCALSTATEDIR, fma_environment); snprintf (usrgbl, 4095, "%s/freem/%s/USER/globals", LOCALSTATEDIR, fma_environment); - snprintf (locktab, 4095, "/tmp/locktab"); - snprintf (zalloctab, 4095, "/tmp/zalloctab"); - snprintf (jnlfile, 4095, "/tmp/freem_journal_%s.dat", fma_environment); + snprintf (jnldir, 4095, "%s/freem/%s/journals", LOCALSTATEDIR, fma_environment); + snprintf (jnlfile, 4095, "%s/freem_journal_%s.dat", jnldir, fma_environment); snprintf (jnlmode, 3, "on"); snprintf (jnlhostid, 4095, "DEFAULT"); snprintf (jnlcut, 4095, "4294967000"); @@ -1123,115 +1408,185 @@ void fm_configure (void) } if (file_exists (config_file)) { - fprintf (stderr, "fmadm: '%s' already exists.\n\n", config_file); - fprintf (stderr, "'fmadm configure' may only be used on a fresh installation of FreeM.\n"); - exit (1); + fprintf (stderr, "fmadm: '%s' already exists; running fmadm reconfigure instead\n", config_file); + fm_reconfigure (); + return; } - gethostname (hostid, 4095); uuid_v4 (buf); snprintf (jnlhostid, 4095, "%s:%s", hostid, buf); - snprintf (confbase, 4095, "%s/freem", SYSCONFDIR); snprintf (envbase, 4095, "%s/freem/%s", SYSCONFDIR, fma_environment); snprintf (nsbase, 4095, "%s/freem/%s", LOCALSTATEDIR, fma_environment); +#if defined(__OS2__) + { + char srcfile[PATHLEN]; + char dstfile[PATHLEN]; + + snprintf (srcfile, PATHLEN, "%s/bin/freem.exe", PREFIX); + snprintf (dstfile, PATHLEN, "%s/bin/freemd.exe", PREFIX); + + unlink (dstfile); + + fprintf (stderr, "fmadm: running on OS/2; will copy %s to %s\n", srcfile, dstfile); + + if (DosCopy (srcfile, dstfile, 1) != 0) { + fprintf (stderr, "fmadm: fatal error copying %s to %s\n", srcfile, dstfile); + exit (1); + } + + chmod (dstfile, 0755); + } +#else + fprintf (stderr, "fmadm: not running on OS/2\n"); +#endif + printf ("\nFreeM Initial Configuration\n"); printf ("---------------------------\n\n"); printf ("This utility will create the initial configuration file for "); - printf ("FreeM environment '%s' in %s.\n\n", fma_environment, config_file); - + printf ("FreeM environment '%s' (owned by %s:%s) in '%s'.\n\n", fma_environment, username, groupname, config_file); /* check for existence of needed directories */ if (stat (SYSCONFDIR, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", SYSCONFDIR); - mkdir (SYSCONFDIR, 0755); + fprintf (stderr, "fmadm: creating %s [SYSCONFDIR]\n", SYSCONFDIR); + mkdir (SYSCONFDIR, 0775); + set_permissions (SYSCONFDIR, username, groupname, 0775); } if (stat (confbase, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", confbase); - mkdir (confbase, 0755); + fprintf (stderr, "fmadm: creating %s [confbase]\n", confbase); + mkdir (confbase, 0775); + set_permissions (confbase, username, groupname, 0775); + } + + if (stat (varbase, &etcstat) == -1) { + fprintf (stderr, "fmadm: creating %s [varbase]\n", varbase); + mkdir (varbase, 0775); + set_permissions (varbase, username, groupname, 0775); } if (stat (envbase, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", envbase); - mkdir (envbase, 0755); + fprintf (stderr, "fmadm: creating %s [envbase]\n", envbase); + mkdir (envbase, 0775); + set_permissions (envbase, username, groupname, 0775); + } + + if (stat (rundir, &etcstat) == -1) { + fprintf (stderr, "fmadm: creating %s [rundir]\n", rundir); + mkdir (rundir, 0777); + chmod (rundir, 0777); } if (stat (nsbase, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", nsbase); - mkdir (nsbase, 0755); + fprintf (stderr, "fmadm: creating %s [nsbase]\n", nsbase); + mkdir (nsbase, 0775); + set_permissions (nsbase, username, groupname, 0775); } - - - if (strcmp (fma_environment, "DEFAULT") != 0) { + if (stat (jnldir, &etcstat) == -1) { + fprintf (stderr, "fmadm: creating %s [jnldir]\n", jnldir); + mkdir (jnldir, 0775); + set_permissions (jnldir, username, groupname, 0775); + } - DIR *dir; - struct dirent *ent; - char src_dir[4096]; - char dest_dir[4096]; + + snprintf (src_dir, 4095, "%s/freem/mlib", DATADIR); + snprintf (dest_dir, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment); + + fprintf (stderr, "fmadm: populating new environment '%s'\n", fma_environment); + + snprintf (buf, 4095, "%s/freem/%s/SYSTEM", LOCALSTATEDIR, fma_environment); + mkdir (buf, 0775); + set_permissions (buf, username, groupname, 0775); + + snprintf (buf, 4095, "%s/freem/%s/USER", LOCALSTATEDIR, fma_environment); + mkdir (buf, 0775); + set_permissions (buf, username, groupname, 0775); + + snprintf (buf, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment); + mkdir (buf, 0775); + set_permissions (buf, username, groupname, 0775); + + snprintf (buf, 4095, "%s/freem/%s/USER/globals", LOCALSTATEDIR, fma_environment); + mkdir (buf, 0775); + set_permissions (buf, username, groupname, 0775); + + snprintf (buf, 4095, "%s/freem/%s/SYSTEM/globals", LOCALSTATEDIR, fma_environment); + mkdir (buf, 0775); + set_permissions (buf, username, groupname, 0775); + + snprintf (buf, 4095, "%s/freem/%s/USER/routines", LOCALSTATEDIR, fma_environment); + mkdir (buf, 0775); + set_permissions (buf, username, groupname, 0775); + + fprintf (stderr, "fmadm: copying vendor routines from '%s' to '%s'...\n", src_dir, dest_dir); - snprintf (src_dir, 4095, "%s/freem/DEFAULT/SYSTEM/routines", LOCALSTATEDIR); - snprintf (dest_dir, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment); - - fprintf (stderr, "fmadm: populating new environment '%s'\n", fma_environment); + if ((dir = opendir (src_dir)) == NULL) { + fprintf (stderr, "\nfmadm: could not open source directory %s\n", src_dir); + exit (1); + } + + while ((ent = readdir (dir)) != NULL) { + char infile[4096]; + char outfile[4096]; - snprintf (buf, 4095, "%s/freem/%s/SYSTEM", LOCALSTATEDIR, fma_environment); - mkdir (buf, 0755); - - snprintf (buf, 4095, "%s/freem/%s/USER", LOCALSTATEDIR, fma_environment); - mkdir (buf, 0755); - - snprintf (buf, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment); - mkdir (buf, 0755); - - snprintf (buf, 4095, "%s/freem/%s/USER/globals", LOCALSTATEDIR, fma_environment); - mkdir (buf, 0755); - - snprintf (buf, 4095, "%s/freem/%s/SYSTEM/globals", LOCALSTATEDIR, fma_environment); - mkdir (buf, 0755); - - snprintf (buf, 4095, "%s/freem/%s/USER/routines", LOCALSTATEDIR, fma_environment); - mkdir (buf, 0755); - - fprintf (stderr, "fmadm: copying routines from '%s' to '%s'...\n", src_dir, dest_dir); - - if ((dir = opendir (src_dir)) == NULL) { - fprintf (stderr, "\nfmadm: could not open source directory %s\n", src_dir); - exit (1); - } - - while ((ent = readdir (dir)) != NULL) { - char infile[4096]; - char outfile[4096]; - - if ((strcmp (ent->d_name, ".") != 0) && (strcmp (ent->d_name, "..") != 0)) { - - fprintf (stderr, "\t%s\n", ent->d_name); - - snprintf (infile, 4095, "%s/%s", src_dir, ent->d_name); - snprintf (outfile, 4095, "%s/%s", dest_dir, ent->d_name); - - if (cp (outfile, infile) != 0) { - fprintf (stderr, "fmadm: failure copying %s to %s\n", infile, outfile); - } + if ((strcmp (ent->d_name, ".") != 0) && (strcmp (ent->d_name, "..") != 0)) { + + snprintf (infile, 4095, "%s/%s", src_dir, ent->d_name); + snprintf (outfile, 4095, "%s/%s", dest_dir, ent->d_name); + if (stat (outfile, &etcstat) == 0) { + unlink (outfile); + fprintf (stderr, "\tupgrade -> %s\n", ent->d_name); + } + else { + fprintf (stderr, "\tnew -> %s\n", ent->d_name); } - } +#if !defined(__OS2__) + if (cp (outfile, infile) != 0) { + fprintf (stderr, "fmadm: failure copying %s to %s\n", infile, outfile); + } + set_permissions (outfile, username, groupname, 0755); +#else + if (DosCopy (infile, outfile, 1) != 0) { + fprintf (stderr, "fmadm: failure copying %s to %s\n", infile, outfile); + } +#endif + } } + + fp = fopen (env_config_file, "a+"); + + fprintf (stderr, "Creating %s... ", env_config_file); + + snprintf (buf, 4095, "[%s]", fma_environment); + fm_write (fp, buf); + + snprintf (buf, 4095, "user=%s", env_user); + fm_write (fp, buf); + + snprintf (buf, 4095, "group=%s", env_group); + fm_write (fp, buf); + + snprintf (buf, 4095, "enabled=true"); + fm_write (fp, buf); + snprintf (buf, 4095, "env_path=%s/freem/%s", LOCALSTATEDIR, fma_environment); + fm_write (fp, buf); + + fclose (fp); + fprintf (stderr, "[OK]\n"); fp = fopen (config_file, "a+"); - - printf ("Creating %s... ", config_file); + fprintf (stderr, "Creating %s... ", config_file); snprintf (buf, 4095, "[SYSTEM]"); fm_write (fp, buf); @@ -1274,32 +1629,11 @@ void fm_configure (void) snprintf (buf, 4095, "globals_path=%s", usrgbl); fm_write (fp, buf); - - + fclose (fp); + set_permissions (config_file, username, groupname, 0755); + fprintf (stderr, "[OK]\n"); - printf ("[OK]\n\n"); - -/* - printf ("Setting USER namespace permissions... "); - - snprintf (buf, 4095, "%s/freem/USER/globals", LOCALSTATEDIR); - chmod (buf, 0777); - - snprintf (buf, 4095, "%s/freem/USER/routines", LOCALSTATEDIR); - chmod (buf, 0777); - - printf ("[OK]\n"); - printf ("Setting SYSTEM namespace permissions... "); - - snprintf (buf, 4095, "%s/freem/SYSTEM/globals", LOCALSTATEDIR); - chmod (buf, 0755); - - snprintf (buf, 4095, "%s/freem/SYSTEM/routines", LOCALSTATEDIR); - chmod (buf, 0755); - - printf ("[OK]\n\n\n"); -*/ printf ("FreeM initial configuration is complete.\n\n"); printf (" USER globals: %s\n", usrgbl); @@ -1313,6 +1647,43 @@ void fm_configure (void) } /* fm_configure */ +void set_permissions(char *path, char *user, char *grp, int mode) +{ + +#if !defined(__OS2__) + struct group *d_grp; + struct passwd *d_user; + gid_t d_gid; + uid_t d_uid; +#endif + + +#if !defined(__OS2__) + if ((d_grp = getgrnam (grp)) == NULL) { + fprintf (stderr, "fmadm: '%s' group must exist before configuring\n", grp); + exit (1); + } + d_gid = d_grp->gr_gid; + + if ((d_user = getpwnam (user)) == NULL) { + fprintf (stderr, "fmadm: '%s' user must exist before configuring\n", user); + exit (1); + } + d_uid = d_user->pw_uid; + + if (chown (path, d_uid, d_gid) != 0) { + fprintf (stderr, "fmadm: error setting ownership on %s\n", path); + exit (1); + } +#endif + + if (chmod (path, mode) != 0) { + fprintf (stderr, "fmadm: error setting permissions on %s to %d\n", path, mode); + exit (1); + } + +} + void fm_write (FILE *file, char *buf) { fprintf (file, "%s\n", buf);