--- freem/src/fmadm.c 2025/04/01 20:11:46 1.21 +++ freem/src/fmadm.c 2025/04/02 15:36:25 1.27 @@ -1,5 +1,5 @@ /* - * $Id: fmadm.c,v 1.21 2025/04/01 20:11:46 snw Exp $ + * $Id: fmadm.c,v 1.27 2025/04/02 15:36:25 snw Exp $ * FreeM Administration Tool * * @@ -24,6 +24,24 @@ * along with FreeM. If not, see . * * $Log: fmadm.c,v $ + * Revision 1.27 2025/04/02 15:36:25 snw + * Do extensive result checking for environment stop/start/restart in fmadm + * + * Revision 1.26 2025/04/02 14:37:57 snw + * Improve environment control parts of fmadm + * + * 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 * @@ -162,6 +180,7 @@ int fm_daemonctl (short action, short ob 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); +int fm_environment_running (char *env); extern int read_profile_string(char *file, char *section, char *key, char *value); int main (int argc, char **argv) @@ -224,7 +243,6 @@ int main (int argc, char **argv) env_user[k++] = argv[i][j]; } - fma_explicit_environment = TRUE; base_arg++; break; @@ -242,7 +260,6 @@ int main (int argc, char **argv) env_group[k++] = argv[i][j]; } - fma_explicit_environment = TRUE; base_arg++; break; @@ -292,7 +309,7 @@ int main (int argc, char **argv) } } } - + if (obj != OBJ_DAEMON) { if (strlen (env_user) == 0) { snprintf (env_user, 6, "freem"); @@ -311,10 +328,10 @@ int main (int argc, char **argv) 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 and daemon stuff */ if (got_action) { @@ -329,18 +346,24 @@ int main (int argc, char **argv) else if (strcmp (argv[1], "start") == 0 && strcmp (argv[2], "environment") == 0) { act = ACT_START; obj = OBJ_DAEMON; - goto act_switch; + goto process_args; } else if (strcmp (argv[1], "stop") == 0 && strcmp (argv[2], "environment") == 0) { act = ACT_STOP; obj = OBJ_DAEMON; - goto act_switch; + goto process_args; } else if (strcmp (argv[1], "restart") == 0 && strcmp (argv[2], "environment") == 0) { act = ACT_RESTART; obj = OBJ_DAEMON; - goto act_switch; + goto process_args; + } + else if (strcmp (argv[1], "status") == 0 && strcmp (argv[2], "environment") == 0) { + act = ACT_STATUS; + obj = OBJ_DAEMON; + goto process_args; } + } pid = getpid (); @@ -361,7 +384,8 @@ int main (int argc, char **argv) } set_namespace (fma_namespace, FALSE); - + +process_args: /* allocate opts array */ /* first dimension */ @@ -384,7 +408,8 @@ int main (int argc, char **argv) j = 1; for (i = base_arg; i < argc; i++) { - if (i > FMA_MAXARGS) return fmadm_usage(); /* bail if we're going to overrun the array */ + if (i > FMA_MAXARGS) return fmadm_usage(); + /* bail if we're going to overrun the array */ strncpy (opts[j++], argv[i], STRLEN - 1); } @@ -404,10 +429,10 @@ int main (int argc, char **argv) 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 if (strncmp (action, "status", STRLEN - 1) == 0) act = ACT_STATUS; 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; @@ -511,6 +536,7 @@ act_switch: case ACT_START: case ACT_STOP: case ACT_RESTART: + case ACT_STATUS: fmadm_exit (fm_daemonctl (act, obj, optc, opts)); default: @@ -664,7 +690,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; @@ -868,7 +893,7 @@ int fmadm_usage (void) fprintf (stdout, " stop, restart\n\n"); fprintf (stdout, " can be one of:\n"); - fprintf (stdout, " lock, zallocate, journal, namespace, global, routine, job,\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"); @@ -1104,6 +1129,135 @@ 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_validate_environment (char *env) +{ + FILE *fp; + char line[255]; + char chkline[255]; + + snprintf (chkline, 254, "[%s]\n", env); + + if ((fp = fopen (env_config_file, "r")) == NULL) { + fprintf (stderr, "fmadm: could not open %s [%s]\n", env_config_file, strerror (errno)); + return FALSE; + } + + while (fgets (line, 254, fp)) { + if (strncmp (line, chkline, 254) == 0) { + fclose (fp); + return TRUE; + } + } + + fclose (fp); + return FALSE; +} + +int fm_start_environment (char *env, char *e_user, char *e_grp) +{ + char basecmd[255]; + char cmd[4096]; + + if (fm_environment_running (env) == TRUE) { + return TRUE; + } + +#if !defined(__OS2__) + snprintf (basecmd, 254, "%s/bin/freem", PREFIX); +#else + snprintf (basecmd, 254, "%s/bin/freemd.exe", PREFIX); +#endif + +#if !defined(__OS2__) + snprintf (cmd, 4095, "%s -d -e %s -u %s -g %s", basecmd, env, e_user, e_grp); +#else + sprintf (cmd, 4095, "%s -d -k -e %s -u %s -g %s", basecmd, env, e_user, e_grp); +#endif + + system (cmd); + + sleep (1); + + return (fm_environment_running (env)); +} + +int fm_stop_environment (char *env) +{ + long epid; + + epid = fm_get_pid (env); + if (epid > -1) { + kill (epid, SIGINT); + sleep (5); + + if (fm_environment_running (env) == FALSE) { + return TRUE; + } + else { + kill (epid, SIGTERM); + sleep (5); + if (fm_environment_running (env) == FALSE) { + return TRUE; + } + else { + kill (epid, SIGKILL); + sleep (5); + if (fm_environment_running (env) == FALSE) { + return TRUE; + } + else { + return FALSE; + } + } + } + } + else { + return FALSE; + } +} + +int fm_environment_running (char *env) +{ + long epid; + int result; + + epid = fm_get_pid (env); + + if (epid == -1) { + return FALSE; + } + else { + result = kill (epid, 0); + + return ((result == 0) ? TRUE : FALSE); + } +} + int fm_daemonctl (short action, short object, int optc, char **options) { FILE *ef; @@ -1112,20 +1266,14 @@ int fm_daemonctl (short action, short ob char line[255]; char tmps[255]; char *cur_env; - char cmd[4096]; - char verb[20]; + char verb[40]; char e_user[255]; char e_grp[255]; char e_ena[10]; - char basecmd[255]; char *savptr; int result; - -#if !defined(__OS2__) - snprintf (basecmd, 254, "%s/bin/freem", PREFIX); -#else - snprintf (basecmd, 254, "%s/bin/freemd.exe", PREFIX); -#endif + long epid; + switch (action) { case ACT_START: @@ -1137,11 +1285,17 @@ int fm_daemonctl (short action, short ob 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 = options[0]; + envlist = (char *) malloc (sizeof (char) * BIGSTR); + NULLPTRCHK(envlist,"fm_daemonctl"); + + strcpy (envlist, options[1]); } else { /* no environment specified; do 'action' for all environments */ @@ -1166,6 +1320,12 @@ int fm_daemonctl (short action, short ob savptr = envlist; cur_env = strtok_r (envlist, ",", &savptr); do { + + if (fm_validate_environment (cur_env) == FALSE) { + fprintf (stderr, "fmadm: %s is not a valid environment\n", cur_env); + continue; + } + result = read_profile_string (env_config_file, cur_env, "enabled", e_ena); if (result == FALSE || strcmp (e_ena, "true") == 0) { @@ -1177,24 +1337,65 @@ int fm_daemonctl (short action, short ob 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 - break; case ACT_STOP: case ACT_RESTART: - printf ("fmadm: stop and restart not yet implemented\n"); + fprintf (stderr, "fmadm: %s environment %s... ", verb, cur_env); + break; + case ACT_STATUS: + fprintf (stderr, "fmadm: %s environment %s\n", verb, cur_env); break; } - system (cmd); + switch (action) { + + case ACT_START: + result = fm_start_environment (cur_env, e_user, e_grp); + if (result == TRUE) { + fprintf (stderr, "[OK]\n"); + } + else { + fprintf (stderr, "[FAIL]\n"); + } + break; + + case ACT_STOP: + result = fm_stop_environment (cur_env); + if (result == TRUE) { + fprintf (stderr, "[OK]\n"); + } + else { + fprintf (stderr, "[FAIL]\n"); + } + break; + + case ACT_RESTART: + if (fm_stop_environment (cur_env) == TRUE) { + result = fm_start_environment (cur_env, e_user, e_grp); + if (result == TRUE) { + fprintf (stderr, "[OK]\n"); + } + else { + fprintf (stderr, "[FAIL]\n"); + } + } + else { + fprintf (stderr, "[FAIL]\n"); + } + + 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); @@ -1256,8 +1457,7 @@ void fm_configure (void) char usrrtn[4096]; char usrgbl[4096]; - char locktab[4096]; - char zalloctab[4096]; + char jnldir[4096]; char jnlfile[4096]; char jnlmode[4]; char jnlhostid[4096]; @@ -1284,6 +1484,11 @@ void fm_configure (void) 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; @@ -1301,17 +1506,15 @@ void fm_configure (void) } 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"); @@ -1366,41 +1569,48 @@ void fm_configure (void) /* check for existence of needed directories */ if (stat (SYSCONFDIR, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", SYSCONFDIR); + 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); + fprintf (stderr, "fmadm: creating %s [confbase]\n", confbase); mkdir (confbase, 0775); set_permissions (confbase, username, groupname, 0775); } - if (stat (envbase, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", envbase); - mkdir (envbase, 0775); - set_permissions (envbase, username, groupname, 0775); - } - if (stat (varbase, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", varbase); + 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 [envbase]\n", envbase); + mkdir (envbase, 0775); + set_permissions (envbase, username, groupname, 0775); + } + if (stat (rundir, &etcstat) == -1) { - fprintf (stderr, "fmadm: creating %s\n", rundir); + 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); + fprintf (stderr, "fmadm: creating %s [nsbase]\n", nsbase); mkdir (nsbase, 0775); set_permissions (nsbase, username, groupname, 0775); } + if (stat (jnldir, &etcstat) == -1) { + fprintf (stderr, "fmadm: creating %s [jnldir]\n", jnldir); + mkdir (jnldir, 0775); + set_permissions (jnldir, username, groupname, 0775); + } + + snprintf (src_dir, 4095, "%s/freem/mlib", DATADIR); snprintf (dest_dir, 4095, "%s/freem/%s/SYSTEM/routines", LOCALSTATEDIR, fma_environment); @@ -1430,7 +1640,7 @@ void fm_configure (void) mkdir (buf, 0775); set_permissions (buf, username, groupname, 0775); - fprintf (stderr, "fmadm: copying routines from '%s' to '%s'...\n", src_dir, dest_dir); + fprintf (stderr, "fmadm: copying vendor 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); @@ -1441,13 +1651,19 @@ void fm_configure (void) 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); + 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);