--- freem/src/mumps.c 2025/03/31 20:01:13 1.9
+++ freem/src/mumps.c 2025/04/13 04:22:43 1.20
@@ -1,5 +1,5 @@
/*
- * $Id: mumps.c,v 1.9 2025/03/31 20:01:13 snw Exp $
+ * $Id: mumps.c,v 1.20 2025/04/13 04:22:43 snw Exp $
* main module of freem
*
*
@@ -24,6 +24,39 @@
* along with FreeM. If not, see .
*
* $Log: mumps.c,v $
+ * Revision 1.20 2025/04/13 04:22:43 snw
+ * Fix snprintf calls
+ *
+ * Revision 1.19 2025/04/10 01:24:38 snw
+ * Remove C++ style comments
+ *
+ * Revision 1.18 2025/04/09 19:52:02 snw
+ * Eliminate as many warnings as possible while building with -Wall
+ *
+ * Revision 1.17 2025/04/04 21:28:16 snw
+ * Remove custom_user and custom_group vars from freem and shed privileges per environment catalog settings
+ *
+ * Revision 1.16 2025/04/04 19:43:18 snw
+ * Switch to using environment catalog to determine user and group for environment, and remove -u and -g flags from freem
+ *
+ * Revision 1.15 2025/04/03 20:48:14 snw
+ * Improve daemon error diagnostics and bump to 0.63.0-rc3
+ *
+ * Revision 1.14 2025/04/02 04:50:49 snw
+ * Allow vendor routines to be upgraded
+ *
+ * Revision 1.13 2025/04/02 03:26:22 snw
+ * Don't corrupt the terminal if FreeM runs before fmadm configure has been run
+ *
+ * Revision 1.12 2025/04/02 02:16:27 snw
+ * Add fmadm status environment command and move journals to a better location
+ *
+ * Revision 1.11 2025/04/01 23:21:45 snw
+ * fmadm commands for stopping, starting, and restarting environments now functional
+ *
+ * Revision 1.10 2025/04/01 20:11:46 snw
+ * Further work on fmadm
+ *
* Revision 1.9 2025/03/31 20:01:13 snw
* Set d_uid in daemon
*
@@ -47,6 +80,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
**/
+#define _GNU_SOURCE
#include
#include
#include "mpsdef.h"
@@ -103,6 +137,8 @@ int main (int argc, char **argv, char **
int option_index = 0;
+ char fm_initialized = FALSE;
+
char dx_mcode[512];
char startup_routine[256];
short routine_mode;
@@ -117,9 +153,6 @@ int main (int argc, char **argv, char **
gid_t d_gid;
uid_t d_uid;
- short custom_user = FALSE;
- short custom_group = FALSE;
-
#if defined(HAVE_GETOPT_LONG)
struct option long_options[] = {
{"help", no_argument, 0, 'h'},
@@ -135,7 +168,6 @@ int main (int argc, char **argv, char **
{"execute", required_argument, 0, 'x'},
{"daemon", no_argument, 0, 'd'},
{"nofork", no_argument, 0, 'k'},
- {"pidfile", required_argument, 0, 'p'},
{"shmsize", required_argument, 0, 'S'},
{"user", required_argument, 0, 'u'},
{"group", required_argument, 0, 'g'},
@@ -149,14 +181,13 @@ int main (int argc, char **argv, char **
char *symname = (char *) calloc(STRLEN, sizeof(char));
char *symval = (char *) calloc(STRLEN, sizeof(char));
-
- int namelen;
- int vallen;
-
+
char cli_rtn_path[PATH_MAX] = {0};
char *cli_rtn_file;
char cli_rtn_name[256];
+ char env_ena[25];
+
routine_mode = FALSE;
strcpy (m_dialect, "FREEM");
@@ -186,7 +217,7 @@ int main (int argc, char **argv, char **
while (1) {
- c = getopt_long (argc, argv, "hsfiqRr:n:e:vx:dkpS:u:g:", long_options, &option_index);
+ c = getopt_long (argc, argv, "hsfiqRr:n:e:vx:dkpS", long_options, &option_index);
if (c == -1) break;
if (c == '?') freem_usage ();
@@ -209,7 +240,7 @@ int main (int argc, char **argv, char **
break;
case 'e': /* specify FreeM environment */
- strncpy (shm_env, optarg, 255);
+ strncpy (shm_env, optarg, sizeof (shm_env) - 1);
break;
case 'R':
@@ -297,24 +328,9 @@ int main (int argc, char **argv, char **
nofork = TRUE;
break;
- case 'p': /* --pidfile */
- pid_file_path = strdup (optarg);
- break;
-
case 'S': /* --shmsize */
shm_init_size = atol (optarg);
- break;
-
- case 'u': /* --user */
- strncpy (d_username, optarg, 40);
- custom_user = TRUE;
- break;
-
- case 'g': /* --group */
- strncpy (d_groupname, optarg, 40);
- custom_group = TRUE;
- break;
-
+ break;
}
@@ -326,7 +342,7 @@ int main (int argc, char **argv, char **
extern char *optarg;
extern int optind, optopt;
- while ((c = getopt (argc, argv, "hsfiqRr:n:e:vx:dkpS:u:g:")) != -1) {
+ while ((c = getopt (argc, argv, "hsfiqRr:n:e:vx:dkS:")) != -1) {
if (c == '?') freem_usage ();
@@ -349,7 +365,7 @@ int main (int argc, char **argv, char **
break;
case 'e': /* specify FreeM environment */
- strncpy (shm_env, optarg, 255);
+ strncpy (shm_env, optarg, sizeof (shm_env) - 1);
break;
case 'R':
@@ -393,10 +409,6 @@ int main (int argc, char **argv, char **
nofork = TRUE;
break;
- case 'p': /* --pidfile */
- pid_file_path = strdup (optarg);
- break;
-
case 's': /* --standard */
if (strcmp (optarg, "M77") == 0) {
@@ -438,17 +450,6 @@ int main (int argc, char **argv, char **
shm_init_size = atol (optarg);
break;
- case 'u': /* --user */
- strncpy (d_username, optarg, 40);
- custom_user = TRUE;
- break;
-
- case 'g': /* --group */
- strncpy (d_groupname, optarg, 40);
- custom_group = TRUE;
- break;
-
-
}
}
}
@@ -461,35 +462,66 @@ int main (int argc, char **argv, char **
}
#endif
- snprintf (config_file, 4096, "%s/freem/%s/freem.conf", SYSCONFDIR, shm_env);
+ snprintf (config_file, sizeof (config_file) - 1, "%s/freem/%s/freem.conf", SYSCONFDIR, shm_env);
+ snprintf (env_config_file, sizeof (config_file) - 1, "%s/freem/env.conf", SYSCONFDIR);
- if (run_daemon == TRUE && geteuid() == 0) {
+ if (!file_exists (env_config_file)) {
+ fprintf (stderr, "freem: environment catalog does not exist; may need to run fmadm configure\n");
+ exit (1);
+ }
- if (custom_group) {
- d_grp = getgrnam (d_groupname);
+ if (!file_exists (config_file)) {
+ fprintf (stderr, "freem: configuration file for %s does not exist; may need to run fmadm configure\n", shm_env);
+ exit (1);
+ }
- if (d_grp == NULL) {
- fprintf (stderr, "freem: invalid group '%s'\n", d_groupname);
- exit (1);
- }
-
- d_gid = d_grp->gr_gid;
- }
+ if (read_profile_string (env_config_file, shm_env, "user", d_username) == FALSE) {
+ fprintf (stderr, "freem: could not determine owning user for environment %s\n", shm_env);
+ exit (1);
+ }
- if (custom_user) {
- d_user = getpwnam (d_username);
+ if (read_profile_string (env_config_file, shm_env, "group", d_groupname) == FALSE) {
+ fprintf (stderr, "freem: could not determine owning group for environment %s\n", shm_env);
+ exit (1);
+ }
- if (d_user == NULL) {
- fprintf (stderr, "freem: invalid user '%s'\n", d_username);
- exit (1);
- }
-
- d_uid = d_user->pw_uid;
- }
- else {
- d_uid = 0;
- }
+ if (read_profile_string (env_config_file, shm_env, "enabled", env_ena) == FALSE) {
+ fprintf (stderr, "freem: could not discover enabled state for environment %s\n", shm_env);
+ exit (1);
+ }
+
+ if (strcmp (env_ena, "true") != 0) {
+ fprintf (stderr, "freem: environment %s is administratively disabled\n", shm_env);
+ exit (1);
+ }
+
+ d_grp = getgrnam (d_groupname);
+ if (d_grp == NULL) {
+ fprintf (stderr, "freem: invalid group '%s'\n", d_groupname);
+ exit (1);
+ }
+ d_gid = d_grp->gr_gid;
+ d_user = getpwnam (d_username);
+ if (d_user == NULL) {
+ fprintf (stderr, "freem: invalid user '%s'\n", d_username);
+ exit (1);
+ }
+ d_uid = d_user->pw_uid;
+
+
+#if defined(__linux__)
+ if (run_daemon == FALSE && group_member (d_gid) == 0) {
+ fprintf (stderr, "freem: you must be a member of the %s group to use environment %s\n", d_groupname, shm_env);
+ exit (1);
+ }
+#endif
+
+ if (run_daemon == TRUE) {
+ if (geteuid () != 0 && nofork == FALSE) {
+ fprintf (stderr, "freem: forking daemon must be run as root\n");
+ exit (1);
+ }
}
if ((nofork == TRUE) && (run_daemon == FALSE)) {
@@ -547,19 +579,19 @@ int main (int argc, char **argv, char **
if (geteuid () == 0) {
/* shed privileges */
- if (custom_group) {
- fprintf (stderr, "freem: switching to group %s\n", d_groupname);
- m_log (1, "switching groups");
-
- if (setgid (d_gid) == -1) {
- fprintf (stderr, "freem: failure switching GID\n");
- m_log (1, "failure switching GIDs");
- exit (1);
- }
+
+ fprintf (stderr, "freem: switching to group %s\n", d_groupname);
+ m_log (1, "switching groups");
+
+ if (setgid (d_gid) == -1) {
+ fprintf (stderr, "freem: failure switching GID\n");
+ m_log (1, "failure switching GIDs");
+ exit (1);
}
+
- if (custom_user) {
+ if (d_uid != geteuid ()) {
fprintf (stderr, "freem: switching to username %s\n", d_username);
m_log (1, "switching users");
@@ -568,11 +600,6 @@ int main (int argc, char **argv, char **
m_log (1, "failure switching UIDs");
exit (1);
}
- if (chdir (d_user->pw_dir) == -1) {
- fprintf (stderr, "freem: chdir failure\n");
- m_log (1, "failure in chdir");
- exit (1);
- }
}
}
@@ -587,49 +614,20 @@ int main (int argc, char **argv, char **
run_daemon = TRUE;
nofork = FALSE;
- if (pid_file_path == NULL) {
- /* no PID file specified. choose one. */
- uid_t pid_uid;
- char *home_directory;
-
- pid_file_path = (char *) calloc (PATH_MAX, sizeof (char));
- NULLPTRCHK(pid_file_path,"main");
-
- home_directory = (char *) calloc (PATH_MAX, sizeof (char));
- NULLPTRCHK(home_directory,"main");
-
- pid_uid = geteuid ();
-
- if (pid_uid == 0) {
- /* we're running as root */
- strcpy (pid_file_path, "/var/run/freem.pid");
- }
- else {
- /* our user is a normie */
- struct passwd *pw = getpwuid (pid_uid);
-
- if (pw == NULL) {
- m_log (1, "main: failure in getpwuid()");
- }
-
- strcpy (home_directory, pw->pw_dir);
- snprintf (pid_file_path, PATH_MAX - 1, "%s/.freem.pid", home_directory);
- }
-
- free (home_directory);
-
- }
-
{
char pidfile_buf[256];
int errsav;
- m_log (1, pid_file_path);
+ pid_file_path = (char *) malloc (PATH_MAX * sizeof (char));
+ NULLPTRCHK(pid_file_path,"main");
+
+ snprintf (pid_file_path, PATH_MAX - 1, "%s/freem/run/%s.pid", LOCALSTATEDIR, shm_env);
pid_fd = open (pid_file_path, O_RDWR | O_CREAT, 0640);
errsav = errno;
if (pid_fd < 0) {
+ fprintf (stderr, "freem: could not open PID file %s [%s]\n", pid_file_path, strerror (errsav));
m_log (1, "freem: could not open PID file");
m_log (1, strerror (errsav));
exit (1);
@@ -637,14 +635,15 @@ int main (int argc, char **argv, char **
if (lockf (pid_fd, F_TLOCK, 0) < 0) {
errsav = errno;
+ fprintf (stderr, "freem: could not lock PID file [%s]\n", strerror (errsav));
m_log (1, "freem: could not lock PID file - perhaps already running?");
m_log (1, strerror (errsav));
exit (1);
}
- sprintf (pidfile_buf, "%d\n", getpid ());
+ sprintf (pidfile_buf, "%ld\n", (long) getpid ());
write (pid_fd, pidfile_buf, strlen (pidfile_buf));
-
+
}
@@ -674,15 +673,18 @@ int main (int argc, char **argv, char **
skip_init = 1;
/* initialize FreeM environment */
- strncpy (nsnbuf, nsname, 255);
+ strncpy (nsnbuf, nsname, sizeof (nsnbuf));
if (init (nsnbuf) == FALSE) {
- set_io (UNIX);
+ if (fm_initialized) set_io (UNIX);
fprintf (stderr, "\nError initializing FreeM.\n");
exit (1);
- }
+ }
+ else {
+ fm_initialized = TRUE;
+ }
direct_mode = FALSE;
@@ -709,10 +711,6 @@ int main (int argc, char **argv, char **
/* isolate the path from the routine file */
strncpy (cli_rtn_path, argv[optind], strrchr (argv[optind], '/') - argv[optind]);
-/* set_io (UNIX);
- printf ("cli_rtn_name = '%s' cli_rtn_path = '%s'\n", cli_rtn_name, cli_rtn_path);
- set_io (MUMPS);
-*/
}
/* do we have a file extension? */
@@ -730,29 +728,30 @@ int main (int argc, char **argv, char **
}
/* make this the startup routine */
- snprintf (startuprou, 256, "^%s\201", cli_rtn_name);
+ snprintf (startuprou, sizeof (startuprou) - 1, "^%s\201", cli_rtn_name);
/* re-work the namespace config to search for the
routine in the discovered path */
if (cli_rtn_name[0] == '%') {
- snprintf (rou0plib, 256, "%s\201", cli_rtn_path);
- snprintf (rou1plib, 256, "%s\201", cli_rtn_path);
+ snprintf (rou0plib, sizeof (rou0plib) - 1, "%s\201", cli_rtn_path);
+ snprintf (rou1plib, sizeof (rou1plib) - 1, "%s\201", cli_rtn_path);
}
else {
- snprintf (rou0path, 256, "%s\201", cli_rtn_path);
- snprintf (rou1path, 256, "%s\201", cli_rtn_path);
+ snprintf (rou0path, sizeof (rou0path) - 1, "%s\201", cli_rtn_path);
+ snprintf (rou1path, sizeof (rou1path) - 1, "%s\201", cli_rtn_path);
}
}
-
+
if (!file_exists (config_file)) {
- set_io (UNIX);
+ if (fm_initialized == TRUE) set_io (UNIX);
+
fprintf (stderr, "\nFreeM has not been configured. Please run 'fmadm configure'.\n\n\n\n");
exit (2);
@@ -761,15 +760,16 @@ int main (int argc, char **argv, char **
if (!skip_init) {
/* initialize FreeM environment */
- strncpy (nsnbuf, nsname, 255);
- if (init (nsnbuf) == FALSE) {
-
+ strncpy (nsnbuf, nsname, sizeof (nsnbuf));
+ if (init (nsnbuf) == FALSE) {
set_io (UNIX);
fprintf (stderr, "\nError initializing FreeM.\n");
exit (1);
-
}
+ else {
+ fm_initialized = TRUE;
+ }
}
if (first_process == TRUE) {
@@ -851,6 +851,7 @@ int main (int argc, char **argv, char **
fprintf (stderr, "freem: terminating\r\n");
cleanup ();
+
exit (0);
}
@@ -868,24 +869,16 @@ int main (int argc, char **argv, char **
#if !defined(_AIX)
- if(import_env == TRUE) {
-
+ if (import_env == TRUE) {
int i_maxlen = 255;
- for(env = envp; *env != 0; env++) {
-
- namelen = 0;
- vallen = 0;
-
- varname = strtok(*env, "=");
- varval = strtok(NULL, "=");
-
- if(varval != NULL) {
- namelen = strlen (varname);
- vallen = strlen (varval);
+ for (env = envp; *env != 0; env++) {
+ varname = strtok (*env, "=");
+ varval = strtok (NULL, "=");
+ if (varval != NULL) {
snprintf (symname, i_maxlen, "ENV.%s\201\201", varname);
- strncpy (symval, varval, i_maxlen);
+ strncpy (symval, varval, i_maxlen - 1);
stcnv_c2m (symval);
@@ -904,10 +897,10 @@ int main (int argc, char **argv, char **
stcpy (verstr, FREEM_VERSION_STR);
stcnv_m2c (verstr);
- snprintf (version, 255, "\r\nCoherent Logic Development FreeM version %s [DIALECT: %s%s]\r\n\201", verstr, m_dialect, (restricted_mode == TRUE ? "/RESTRICTED" : ""));
+ snprintf (version, sizeof (version) - 1, "\r\nCoherent Logic Development FreeM version %s [DIALECT: %s%s]\r\n\201", verstr, m_dialect, (restricted_mode == TRUE ? "/RESTRICTED" : ""));
write_m (version);
- snprintf (version, 255, "Copyright (C) 2014, 2020, 2021, 2023, 2025 Coherent Logic Development LLC\r\n\r\n\201");
+ snprintf (version, sizeof (version) - 1, "Copyright (C) 2014, 2020, 2021, 2023, 2025 Coherent Logic Development LLC\r\n\r\n\201");
write_m (version);
/*
@@ -924,7 +917,7 @@ int main (int argc, char **argv, char **
if (dx_mode) {
char k_buf[512];
- snprintf (k_buf, 512 - 1, "%%TMPINITMCODE\201\201");
+ snprintf (k_buf, sizeof (k_buf) - 1, "%%TMPINITMCODE\201\201");
symtab (set_sym, k_buf, dx_mcode);
const_define (k_buf, dx_mcode);
}
@@ -932,7 +925,7 @@ int main (int argc, char **argv, char **
if (routine_mode) {
char k_buf[512];
- snprintf (k_buf, 512 - 1, "%%TMPINITROUTINE\201\201");
+ snprintf (k_buf, sizeof (k_buf) - 1, "%%TMPINITROUTINE\201\201");
symtab (set_sym, k_buf, startup_routine);
const_define (k_buf, startup_routine);
}
@@ -963,7 +956,6 @@ void freem_usage(void)
fprintf (stdout, "\t-x , --execute=\n\t\texecute M code on startup\n\n");
fprintf (stdout, "\t-d, --daemon\n\t\trun the FreeM daemon (one and only one FreeM daemon must always be running)\n\n");
fprintf (stdout, "\t-k, --nofork\n\t\trun the FreeM daemon in foreground (requires --daemon)\n\n");
- fprintf (stdout, "\t-p , --pidfile=\n\t\tuse to record the PID of the FreeM daemon\n\n\n");
fprintf (stdout, "\t-S , --shmsize=\n\t\tsets the size of the shared memory segment where FreeM stores the job table, lock table, and IPC table.\n");
#else
fprintf (stdout, "\t-h\n\t\tdisplays this help message\n\n");
@@ -978,7 +970,6 @@ void freem_usage(void)
fprintf (stdout, "\t-x \n\t\texecute M code on startup\n\n");
fprintf (stdout, "\t-d\n\t\trun the FreeM daemon (one and only one FreeM daemon must always be running)\n\n");
fprintf (stdout, "\t-k\n\t\trun the FreeM daemon in foreground (requires --daemon)\n\n");
- fprintf (stdout, "\t-p \n\t\tuse to record the PID of the FreeM daemon\n\n\n");
fprintf (stdout, "\t-S \n\t\tsets the size of the shared memory segment where FreeM stores the job table, lock table, and IPC table.\n");
#endif
fprintf (stdout, "\t\t - Each concurrent job takes %d bytes (1 page) of shared memory\n", PG_SIZE);