version 1.9, 2025/03/31 20:01:13
|
version 1.28, 2025/05/14 12:22:04
|
Line 24
|
Line 24
|
* along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
* along with FreeM. If not, see <https://www.gnu.org/licenses/>. |
* |
* |
* $Log$ |
* $Log$ |
|
* Revision 1.28 2025/05/14 12:22:04 snw |
|
* Further work on shared memory |
|
* |
|
* Revision 1.27 2025/04/17 00:34:04 snw |
|
* More logging improvements |
|
* |
|
* Revision 1.26 2025/04/16 17:36:12 snw |
|
* Add FreeBSD shm cleanup script |
|
* |
|
* Revision 1.25 2025/04/16 05:57:42 snw |
|
* Remove non-useful procctl calls |
|
* |
|
* Revision 1.24 2025/04/16 05:37:06 snw |
|
* Refine FreeBSD ASLR fix |
|
* |
|
* Revision 1.23 2025/04/16 05:33:15 snw |
|
* Try to use procctl function to fix ASLR problem on FreeBSD |
|
* |
|
* Revision 1.22 2025/04/15 16:49:36 snw |
|
* Make use of logprintf throughout codebase |
|
* |
|
* Revision 1.21 2025/04/15 02:24:43 snw |
|
* Improve FreeM logging capabilities |
|
* |
|
* 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 |
* Revision 1.9 2025/03/31 20:01:13 snw |
* Set d_uid in daemon |
* Set d_uid in daemon |
* |
* |
Line 47
|
Line 104
|
* SPDX-License-Identifier: AGPL-3.0-or-later |
* SPDX-License-Identifier: AGPL-3.0-or-later |
**/ |
**/ |
|
|
|
#define _GNU_SOURCE |
#include <stdlib.h> |
#include <stdlib.h> |
#include <stddef.h> |
#include <stddef.h> |
#include "mpsdef.h" |
#include "mpsdef.h" |
Line 75
|
Line 133
|
#include <errno.h> |
#include <errno.h> |
#include <pwd.h> |
#include <pwd.h> |
#include <grp.h> |
#include <grp.h> |
|
#include "log.h" |
|
|
#if defined(HAVE_GETOPT_H) |
#if defined(HAVE_GETOPT_H) |
# include <getopt.h> |
# include <getopt.h> |
#endif |
#endif |
Line 90 extern char *getenv(const char *name);
|
Line 147 extern char *getenv(const char *name);
|
void freem_usage(void); |
void freem_usage(void); |
void freem_print_version(void); |
void freem_print_version(void); |
void init_ztrap(void); |
void init_ztrap(void); |
void m_log (int, const char *); |
|
|
|
int main (int argc, char **argv, char **envp) |
int main (int argc, char **argv, char **envp) |
{ |
{ |
Line 103 int main (int argc, char **argv, char **
|
Line 159 int main (int argc, char **argv, char **
|
|
|
int option_index = 0; |
int option_index = 0; |
|
|
|
char fm_initialized = FALSE; |
|
|
char dx_mcode[512]; |
char dx_mcode[512]; |
char startup_routine[256]; |
char startup_routine[256]; |
short routine_mode; |
short routine_mode; |
Line 117 int main (int argc, char **argv, char **
|
Line 175 int main (int argc, char **argv, char **
|
gid_t d_gid; |
gid_t d_gid; |
uid_t d_uid; |
uid_t d_uid; |
|
|
short custom_user = FALSE; |
|
short custom_group = FALSE; |
|
|
|
#if defined(HAVE_GETOPT_LONG) |
#if defined(HAVE_GETOPT_LONG) |
struct option long_options[] = { |
struct option long_options[] = { |
{"help", no_argument, 0, 'h'}, |
{"help", no_argument, 0, 'h'}, |
Line 135 int main (int argc, char **argv, char **
|
Line 190 int main (int argc, char **argv, char **
|
{"execute", required_argument, 0, 'x'}, |
{"execute", required_argument, 0, 'x'}, |
{"daemon", no_argument, 0, 'd'}, |
{"daemon", no_argument, 0, 'd'}, |
{"nofork", no_argument, 0, 'k'}, |
{"nofork", no_argument, 0, 'k'}, |
{"pidfile", required_argument, 0, 'p'}, |
|
{"shmsize", required_argument, 0, 'S'}, |
{"shmsize", required_argument, 0, 'S'}, |
{"user", required_argument, 0, 'u'}, |
{"user", required_argument, 0, 'u'}, |
{"group", required_argument, 0, 'g'}, |
{"group", required_argument, 0, 'g'}, |
Line 149 int main (int argc, char **argv, char **
|
Line 203 int main (int argc, char **argv, char **
|
|
|
char *symname = (char *) calloc(STRLEN, sizeof(char)); |
char *symname = (char *) calloc(STRLEN, sizeof(char)); |
char *symval = (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_path[PATH_MAX] = {0}; |
char *cli_rtn_file; |
char *cli_rtn_file; |
char cli_rtn_name[256]; |
char cli_rtn_name[256]; |
|
|
|
char env_ena[25]; |
|
|
routine_mode = FALSE; |
routine_mode = FALSE; |
strcpy (m_dialect, "FREEM"); |
strcpy (m_dialect, "FREEM"); |
|
|
Line 174 int main (int argc, char **argv, char **
|
Line 227 int main (int argc, char **argv, char **
|
strcpy (stack0, argv[0]); |
strcpy (stack0, argv[0]); |
stcnv_c2m (stack0); |
stcnv_c2m (stack0); |
|
|
|
|
/* strncpy (config_file, SYSCONFDIR"/freem.conf", 100); */ |
/* strncpy (config_file, SYSCONFDIR"/freem.conf", 100); */ |
|
|
|
|
Line 186 int main (int argc, char **argv, char **
|
Line 238 int main (int argc, char **argv, char **
|
|
|
while (1) { |
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 == -1) break; |
if (c == '?') freem_usage (); |
if (c == '?') freem_usage (); |
Line 209 int main (int argc, char **argv, char **
|
Line 261 int main (int argc, char **argv, char **
|
break; |
break; |
|
|
case 'e': /* specify FreeM environment */ |
case 'e': /* specify FreeM environment */ |
strncpy (shm_env, optarg, 255); |
strncpy (shm_env, optarg, sizeof (shm_env) - 1); |
break; |
break; |
|
|
case 'R': |
case 'R': |
Line 297 int main (int argc, char **argv, char **
|
Line 349 int main (int argc, char **argv, char **
|
nofork = TRUE; |
nofork = TRUE; |
break; |
break; |
|
|
case 'p': /* --pidfile */ |
|
pid_file_path = strdup (optarg); |
|
break; |
|
|
|
case 'S': /* --shmsize */ |
case 'S': /* --shmsize */ |
shm_init_size = atol (optarg); |
shm_init_size = atol (optarg); |
break; |
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; |
|
|
|
|
|
} |
} |
|
|
Line 326 int main (int argc, char **argv, char **
|
Line 363 int main (int argc, char **argv, char **
|
extern char *optarg; |
extern char *optarg; |
extern int optind, optopt; |
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 (); |
if (c == '?') freem_usage (); |
|
|
Line 349 int main (int argc, char **argv, char **
|
Line 386 int main (int argc, char **argv, char **
|
break; |
break; |
|
|
case 'e': /* specify FreeM environment */ |
case 'e': /* specify FreeM environment */ |
strncpy (shm_env, optarg, 255); |
strncpy (shm_env, optarg, sizeof (shm_env) - 1); |
break; |
break; |
|
|
case 'R': |
case 'R': |
Line 393 int main (int argc, char **argv, char **
|
Line 430 int main (int argc, char **argv, char **
|
nofork = TRUE; |
nofork = TRUE; |
break; |
break; |
|
|
case 'p': /* --pidfile */ |
|
pid_file_path = strdup (optarg); |
|
break; |
|
|
|
case 's': /* --standard */ |
case 's': /* --standard */ |
|
|
if (strcmp (optarg, "M77") == 0) { |
if (strcmp (optarg, "M77") == 0) { |
Line 438 int main (int argc, char **argv, char **
|
Line 471 int main (int argc, char **argv, char **
|
shm_init_size = atol (optarg); |
shm_init_size = atol (optarg); |
break; |
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; |
|
|
|
|
|
} |
} |
} |
} |
} |
} |
Line 461 int main (int argc, char **argv, char **
|
Line 483 int main (int argc, char **argv, char **
|
} |
} |
#endif |
#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)) { |
|
logprintf (FM_LOG_FATAL, "freem: environment catalog does not exist; may need to run fmadm configure"); |
|
} |
|
|
if (custom_group) { |
if (!file_exists (config_file)) { |
d_grp = getgrnam (d_groupname); |
logprintf (FM_LOG_FATAL, "freem: configuration file for %s does not exist; may need to run fmadm configure", shm_env); |
|
} |
|
|
if (d_grp == NULL) { |
if (read_profile_string (env_config_file, shm_env, "user", d_username) == FALSE) { |
fprintf (stderr, "freem: invalid group '%s'\n", d_groupname); |
logprintf (FM_LOG_FATAL, "freem: could not determine owning user for environment %s", shm_env); |
exit (1); |
} |
} |
|
|
|
d_gid = d_grp->gr_gid; |
|
} |
|
|
|
if (custom_user) { |
if (read_profile_string (env_config_file, shm_env, "group", d_groupname) == FALSE) { |
d_user = getpwnam (d_username); |
logprintf (FM_LOG_FATAL, "freem: could not determine owning group for environment %s", shm_env); |
|
} |
|
|
if (d_user == NULL) { |
if (read_profile_string (env_config_file, shm_env, "enabled", env_ena) == FALSE) { |
fprintf (stderr, "freem: invalid user '%s'\n", d_username); |
logprintf (FM_LOG_FATAL, "freem: could not discover enabled state for environment %s", shm_env); |
exit (1); |
} |
} |
|
|
if (strcmp (env_ena, "true") != 0) { |
d_uid = d_user->pw_uid; |
logprintf (FM_LOG_FATAL, "freem: environment %s is administratively disabled", shm_env); |
} |
} |
else { |
|
d_uid = 0; |
d_grp = getgrnam (d_groupname); |
} |
if (d_grp == NULL) { |
|
logprintf (FM_LOG_FATAL, "freem: invalid group '%s'", d_groupname); |
|
} |
|
d_gid = d_grp->gr_gid; |
|
|
|
d_user = getpwnam (d_username); |
|
if (d_user == NULL) { |
|
logprintf (FM_LOG_FATAL, "freem: invalid user '%s'", d_username); |
|
} |
|
d_uid = d_user->pw_uid; |
|
|
|
|
|
#if defined(__linux__) |
|
if (run_daemon == FALSE && group_member (d_gid) == 0) { |
|
logprintf (FM_LOG_FATAL, "freem: you must be a member of the %s group to use environment %s", d_groupname, shm_env); |
|
} |
|
#endif |
|
|
|
|
|
if (run_daemon == TRUE) { |
|
if (geteuid () != 0 && nofork == FALSE) { |
|
logprintf (FM_LOG_FATAL, "freem: forking daemon must be run as root"); |
|
} |
} |
} |
|
|
|
|
if ((nofork == TRUE) && (run_daemon == FALSE)) { |
if ((nofork == TRUE) && (run_daemon == FALSE)) { |
freem_usage (); |
freem_usage (); |
exit (1); |
exit (1); |
Line 500 int main (int argc, char **argv, char **
|
Line 545 int main (int argc, char **argv, char **
|
if ((run_daemon == TRUE) && (nofork == FALSE)) { |
if ((run_daemon == TRUE) && (nofork == FALSE)) { |
|
|
int fork_fd; |
int fork_fd; |
|
|
|
init_log (); |
|
|
/* daemonize */ |
/* daemonize */ |
|
|
fork_pid = fork (); |
fork_pid = fork (); |
|
|
if (fork_pid < 0) { |
if (fork_pid < 0) { |
fprintf (stderr, "freem: failure in fork()\r\n"); |
logprintf (FM_LOG_FATAL, "environment error: failure in initial fork()"); |
m_log (1, "failure in initial fork()\r\n"); |
|
exit (1); |
|
} |
} |
|
|
if (fork_pid > 0) { |
if (fork_pid > 0) { |
Line 516 int main (int argc, char **argv, char **
|
Line 561 int main (int argc, char **argv, char **
|
} |
} |
|
|
if (setsid () < 0) { |
if (setsid () < 0) { |
fprintf (stderr, "freem: failure in setsid()\r\n"); |
logprintf (FM_LOG_FATAL, "environment error: failure in setsid()"); |
m_log (1, "failure in setsid()\r\n"); |
|
exit (1); |
|
} |
} |
|
|
signal (SIGCHLD, SIG_IGN); |
signal (SIGCHLD, SIG_IGN); |
Line 526 int main (int argc, char **argv, char **
|
Line 569 int main (int argc, char **argv, char **
|
fork_pid = fork (); |
fork_pid = fork (); |
|
|
if (fork_pid < 0) { |
if (fork_pid < 0) { |
fprintf (stderr, "freem: failure in fork()\r\n"); |
logprintf (FM_LOG_FATAL, "environment error: failure in second fork()"); |
m_log (1, "failure in second fork()\r\n"); |
|
exit (1); |
|
} |
} |
|
|
if (fork_pid > 0) { |
if (fork_pid > 0) { |
|
logprintf (FM_LOG_DEBUG, "environment: exiting from second fork()"); |
exit (0); |
exit (0); |
m_log (1, "exiting from second fork"); |
|
} |
} |
|
|
umask (0); |
umask (0); |
Line 545 int main (int argc, char **argv, char **
|
Line 586 int main (int argc, char **argv, char **
|
} |
} |
|
|
if (geteuid () == 0) { |
if (geteuid () == 0) { |
/* shed privileges */ |
|
|
|
if (custom_group) { |
/* shed privileges */ |
fprintf (stderr, "freem: switching to group %s\n", d_groupname); |
logprintf (FM_LOG_INFO, "environment: switching to group %s", d_groupname); |
m_log (1, "switching groups"); |
|
|
if (setgid (d_gid) == -1) { |
if (setgid (d_gid) == -1) { |
logprintf (FM_LOG_FATAL, "environment error: failure switching GID"); |
fprintf (stderr, "freem: failure switching GID\n"); |
|
m_log (1, "failure switching GIDs"); |
|
exit (1); |
|
} |
|
} |
} |
|
|
|
|
|
|
|
if (d_uid != geteuid ()) { |
|
|
if (custom_user) { |
logprintf (FM_LOG_INFO, "environment: switching to username %s", d_username); |
fprintf (stderr, "freem: switching to username %s\n", d_username); |
|
m_log (1, "switching users"); |
|
|
|
if (setuid (d_uid) == -1) { |
if (setuid (d_uid) == -1) { |
fprintf (stderr, "freem: failure switching UID\n"); |
logprintf (FM_LOG_FATAL, "environment error: failure switching UID"); |
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); |
|
} |
|
} |
} |
|
|
|
logprintf (FM_LOG_INFO, "environment: privilege shedding complete"); |
|
|
} |
} |
else { |
else { |
fprintf (stderr, "not euid 0"); |
logprintf (FM_LOG_INFO, "environment: not running as superuser; not shedding privileges"); |
} |
} |
|
|
|
logprintf (FM_LOG_INFO, "environment: reopening stdin, stdout, and stderr"); |
freopen ("/dev/null", "r", stdin); |
freopen ("/dev/null", "r", stdin); |
freopen ("/dev/null", "w+", stdout); |
freopen ("/dev/null", "w+", stdout); |
freopen ("/dev/null", "w+", stderr); |
freopen ("/dev/null", "w+", stderr); |
|
logprintf (FM_LOG_INFO, "environment: stdin, stdout, and stderr reopened"); |
|
|
run_daemon = TRUE; |
run_daemon = TRUE; |
nofork = FALSE; |
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]; |
char pidfile_buf[256]; |
int errsav; |
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); |
|
|
|
logprintf (FM_LOG_INFO, "environment: opening pid file %s", pid_file_path); |
pid_fd = open (pid_file_path, O_RDWR | O_CREAT, 0640); |
pid_fd = open (pid_file_path, O_RDWR | O_CREAT, 0640); |
errsav = errno; |
errsav = errno; |
|
|
if (pid_fd < 0) { |
if (pid_fd < 0) { |
m_log (1, "freem: could not open PID file"); |
logprintf (FM_LOG_FATAL, "environment error: could not open PID file %s [%s]", pid_file_path, strerror (errsav)); |
m_log (1, strerror (errsav)); |
|
exit (1); |
|
} |
} |
|
|
if (lockf (pid_fd, F_TLOCK, 0) < 0) { |
if (lockf (pid_fd, F_TLOCK, 0) < 0) { |
errsav = errno; |
errsav = errno; |
m_log (1, "freem: could not lock PID file - perhaps already running?"); |
logprintf (FM_LOG_FATAL, "environment error: could not lock PID file [%s]", strerror (errsav)); |
m_log (1, strerror (errsav)); |
|
exit (1); |
|
} |
} |
|
|
sprintf (pidfile_buf, "%d\n", getpid ()); |
sprintf (pidfile_buf, "%ld\n", (long) getpid ()); |
|
logprintf (FM_LOG_INFO, "environment: writing pid file"); |
write (pid_fd, pidfile_buf, strlen (pidfile_buf)); |
write (pid_fd, pidfile_buf, strlen (pidfile_buf)); |
|
|
} |
} |
|
|
|
|
Line 674 int main (int argc, char **argv, char **
|
Line 676 int main (int argc, char **argv, char **
|
skip_init = 1; |
skip_init = 1; |
|
|
/* initialize FreeM environment */ |
/* initialize FreeM environment */ |
strncpy (nsnbuf, nsname, 255); |
strncpy (nsnbuf, nsname, sizeof (nsnbuf)); |
if (init (nsnbuf) == FALSE) { |
if (init (nsnbuf) == FALSE) { |
|
|
set_io (UNIX); |
if (fm_initialized) set_io (UNIX); |
fprintf (stderr, "\nError initializing FreeM.\n"); |
fprintf (stderr, "\nError initializing FreeM.\n"); |
|
|
exit (1); |
exit (1); |
|
|
} |
} |
|
else { |
|
fm_initialized = TRUE; |
|
} |
|
|
|
|
direct_mode = FALSE; |
direct_mode = FALSE; |
Line 709 int main (int argc, char **argv, char **
|
Line 714 int main (int argc, char **argv, char **
|
/* isolate the path from the routine file */ |
/* isolate the path from the routine file */ |
strncpy (cli_rtn_path, argv[optind], strrchr (argv[optind], '/') - argv[optind]); |
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? */ |
/* do we have a file extension? */ |
Line 730 int main (int argc, char **argv, char **
|
Line 731 int main (int argc, char **argv, char **
|
} |
} |
|
|
/* make this the startup routine */ |
/* 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 |
/* re-work the namespace config to search for the |
routine in the discovered path */ |
routine in the discovered path */ |
if (cli_rtn_name[0] == '%') { |
if (cli_rtn_name[0] == '%') { |
|
|
snprintf (rou0plib, 256, "%s\201", cli_rtn_path); |
snprintf (rou0plib, sizeof (rou0plib) - 1, "%s\201", cli_rtn_path); |
snprintf (rou1plib, 256, "%s\201", cli_rtn_path); |
snprintf (rou1plib, sizeof (rou1plib) - 1, "%s\201", cli_rtn_path); |
|
|
} |
} |
else { |
else { |
|
|
snprintf (rou0path, 256, "%s\201", cli_rtn_path); |
snprintf (rou0path, sizeof (rou0path) - 1, "%s\201", cli_rtn_path); |
snprintf (rou1path, 256, "%s\201", cli_rtn_path); |
snprintf (rou1path, sizeof (rou1path) - 1, "%s\201", cli_rtn_path); |
|
|
} |
} |
|
|
} |
} |
|
|
|
|
if (!file_exists (config_file)) { |
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"); |
fprintf (stderr, "\nFreeM has not been configured. Please run 'fmadm configure'.\n\n\n\n"); |
|
|
exit (2); |
exit (2); |
Line 761 int main (int argc, char **argv, char **
|
Line 763 int main (int argc, char **argv, char **
|
|
|
if (!skip_init) { |
if (!skip_init) { |
/* initialize FreeM environment */ |
/* initialize FreeM environment */ |
strncpy (nsnbuf, nsname, 255); |
strncpy (nsnbuf, nsname, sizeof (nsnbuf)); |
if (init (nsnbuf) == FALSE) { |
if (init (nsnbuf) == FALSE) { |
|
|
set_io (UNIX); |
set_io (UNIX); |
fprintf (stderr, "\nError initializing FreeM.\n"); |
fprintf (stderr, "\nError initializing FreeM.\n"); |
|
|
exit (1); |
exit (1); |
|
|
} |
} |
} |
else { |
|
fm_initialized = TRUE; |
|
} |
|
} |
|
|
if (first_process == TRUE) { |
if (first_process == TRUE) { |
|
|
Line 778 int main (int argc, char **argv, char **
|
Line 781 int main (int argc, char **argv, char **
|
pid_t stop_requester; |
pid_t stop_requester; |
|
|
if (run_daemon == FALSE) { |
if (run_daemon == FALSE) { |
fprintf (stderr, "freem: re-run with --daemon or -d command-line flags\r\n"); |
logprintf (FM_LOG_FATAL, "freem: re-run with --daemon or -d command-line flags"); |
cleanup (); |
|
exit (1); |
|
} |
} |
|
|
stcpy (verstr, FREEM_VERSION_STR); |
stcpy (verstr, FREEM_VERSION_STR); |
stcnv_m2c (verstr); |
stcnv_m2c (verstr); |
|
|
fprintf (stderr, "Coherent Logic Development FreeM version %s\r\n", verstr); |
fprintf (stderr, "Coherent Logic Development FreeM version %s\r\n", verstr); |
fprintf (stderr, "freem: shared memory for environment %s initialized (%ld bytes of shared memory @ '%p')\r\nfreem: system ready\r\n", shm_env, (long) shm_init_size, shm_config->dta); |
logprintf (FM_LOG_INFO, "freem: shared memory for environment %s initialized (%ld bytes of shared memory @ '%p')", shm_env, (long) shm_init_size, shm_config->dta); |
|
|
for (;;) { |
for (;;) { |
|
|
Line 798 int main (int argc, char **argv, char **
|
Line 799 int main (int argc, char **argv, char **
|
|
|
job_slot_t *slot; |
job_slot_t *slot; |
|
|
fprintf (stderr, "freem: entering maintenance mode\r\n"); |
logprintf (FM_LOG_WARNING, "environment: entering maintenance mode"); |
m_log (1, "freem: entering maintenance mode"); |
|
|
|
for (slot = shm_config->hdr->jobtab_head; slot != NULL; slot = slot->next) { |
for (slot = SOA(shm_config->hdr->jobtab_head); slot != NULL; slot = SOA(slot->next)) { |
|
|
if ((slot->pid != pid) && ((slot->flags & JFLG_FMADM) != JFLG_FMADM)) { |
if ((slot->pid != pid) && ((slot->flags & JFLG_FMADM) != JFLG_FMADM)) { |
kill (slot->pid, SIGINT); |
kill (slot->pid, SIGINT); |
Line 818 int main (int argc, char **argv, char **
|
Line 818 int main (int argc, char **argv, char **
|
|
|
connected_jobs = job_count (); |
connected_jobs = job_count (); |
|
|
fprintf (stderr, "freem: STOP requested by pid %d\r\n", stop_requester); |
logprintf (FM_LOG_INFO, "environment: STOP requested by pid %ld", stop_requester); |
fprintf (stderr, "freem: there are %d job(s) connected to this environment\r\n", connected_jobs); |
logprintf (FM_LOG_INFO, "environment: there are %d job(s) connected to this environment", connected_jobs); |
|
|
if (connected_jobs > 1) { |
if (connected_jobs > 1) { |
|
|
fprintf (stderr, "freem: asking non-daemon job(s) to disconnect and halt...\r\n"); |
logprintf (FM_LOG_INFO, "environment: asking non-daemon job(s) to disconnect and halt..."); |
job_request_all_stop (); |
job_request_all_stop (); |
|
|
fprintf (stderr, "freem: waiting 5 seconds for job(s) to disconnect...\r\n"); |
logprintf (FM_LOG_INFO, "environment: waiting 5 seconds for job(s) to disconnect..."); |
sleep (5); |
sleep (5); |
|
|
connected_jobs = job_count (); |
connected_jobs = job_count (); |
if (connected_jobs > 1) { |
if (connected_jobs > 1) { |
fprintf (stderr, "freem: sending SIGTERM to %d job(s)...\r\n", connected_jobs); |
logprintf (FM_LOG_INFO, "environment: sending SIGTERM to %d job(s)...", connected_jobs); |
job_signal_all (SIGTERM); |
job_signal_all (SIGTERM); |
fprintf (stderr, "freem: waiting 5 seconds for job(s) to disconnect...\r\n"); |
logprintf (FM_LOG_INFO, "environment: waiting 5 seconds for job(s) to disconnect..."); |
|
|
sleep (5); |
sleep (5); |
} |
} |
|
|
connected_jobs = job_count (); |
connected_jobs = job_count (); |
if (connected_jobs > 1) { |
if (connected_jobs > 1) { |
fprintf (stderr, "freem: sending SIGKILL to %d job(s)...\r\n", connected_jobs); |
logprintf (FM_LOG_INFO, "environment: sending SIGKILL to %d job(s)...", connected_jobs); |
job_signal_all (SIGKILL); |
job_signal_all (SIGKILL); |
} |
} |
|
|
Line 849 int main (int argc, char **argv, char **
|
Line 849 int main (int argc, char **argv, char **
|
|
|
} |
} |
|
|
fprintf (stderr, "freem: terminating\r\n"); |
logprintf (FM_LOG_INFO, "freem: terminating"); |
cleanup (); |
cleanup (); |
|
|
exit (0); |
exit (0); |
|
|
} |
} |
|
|
job_gc_mark (); |
job_gc_mark (); |
job_set_status (pid, JSTAT_IDLE); |
job_set_status (pid, JSTAT_IDLE); |
sleep (1); |
sleep (1); |
|
|
job_set_status (pid, JSTAT_HOUSEKEEPING); |
job_set_status (pid, JSTAT_HOUSEKEEPING); |
job_gc_sweep (); |
job_gc_sweep (); |
|
|
sleep (1); |
sleep (1); |
} |
} |
|
|
Line 868 int main (int argc, char **argv, char **
|
Line 870 int main (int argc, char **argv, char **
|
|
|
|
|
#if !defined(_AIX) |
#if !defined(_AIX) |
if(import_env == TRUE) { |
if (import_env == TRUE) { |
|
|
int i_maxlen = 255; |
int i_maxlen = 255; |
|
|
for(env = envp; *env != 0; env++) { |
for (env = envp; *env != 0; env++) { |
|
varname = strtok (*env, "="); |
namelen = 0; |
varval = strtok (NULL, "="); |
vallen = 0; |
|
|
|
varname = strtok(*env, "="); |
|
varval = strtok(NULL, "="); |
|
|
|
if(varval != NULL) { |
|
namelen = strlen (varname); |
|
vallen = strlen (varval); |
|
|
|
|
if (varval != NULL) { |
snprintf (symname, i_maxlen, "ENV.%s\201\201", varname); |
snprintf (symname, i_maxlen, "ENV.%s\201\201", varname); |
strncpy (symval, varval, i_maxlen); |
strncpy (symval, varval, i_maxlen - 1); |
|
|
stcnv_c2m (symval); |
stcnv_c2m (symval); |
|
|
Line 904 int main (int argc, char **argv, char **
|
Line 898 int main (int argc, char **argv, char **
|
stcpy (verstr, FREEM_VERSION_STR); |
stcpy (verstr, FREEM_VERSION_STR); |
stcnv_m2c (verstr); |
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); |
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); |
write_m (version); |
|
|
/* |
/* |
Line 924 int main (int argc, char **argv, char **
|
Line 918 int main (int argc, char **argv, char **
|
if (dx_mode) { |
if (dx_mode) { |
char k_buf[512]; |
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); |
symtab (set_sym, k_buf, dx_mcode); |
const_define (k_buf, dx_mcode); |
const_define (k_buf, dx_mcode); |
} |
} |
Line 932 int main (int argc, char **argv, char **
|
Line 926 int main (int argc, char **argv, char **
|
if (routine_mode) { |
if (routine_mode) { |
char k_buf[512]; |
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); |
symtab (set_sym, k_buf, startup_routine); |
const_define (k_buf, startup_routine); |
const_define (k_buf, startup_routine); |
} |
} |
Line 963 void freem_usage(void)
|
Line 957 void freem_usage(void)
|
fprintf (stdout, "\t-x <MCODE>, --execute=<MCODE>\n\t\texecute M code <MCODE> on startup\n\n"); |
fprintf (stdout, "\t-x <MCODE>, --execute=<MCODE>\n\t\texecute M code <MCODE> 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-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-k, --nofork\n\t\trun the FreeM daemon in foreground (requires --daemon)\n\n"); |
fprintf (stdout, "\t-p <PIDFILE>, --pidfile=<PIDFILE>\n\t\tuse <PIDFILE> to record the PID of the FreeM daemon\n\n\n"); |
|
fprintf (stdout, "\t-S <BYTES>, --shmsize=<BYTES>\n\t\tsets the size of the shared memory segment where FreeM stores the job table, lock table, and IPC table.\n"); |
fprintf (stdout, "\t-S <BYTES>, --shmsize=<BYTES>\n\t\tsets the size of the shared memory segment where FreeM stores the job table, lock table, and IPC table.\n"); |
#else |
#else |
fprintf (stdout, "\t-h\n\t\tdisplays this help message\n\n"); |
fprintf (stdout, "\t-h\n\t\tdisplays this help message\n\n"); |
Line 978 void freem_usage(void)
|
Line 971 void freem_usage(void)
|
fprintf (stdout, "\t-x <MCODE>\n\t\texecute M code <MCODE> on startup\n\n"); |
fprintf (stdout, "\t-x <MCODE>\n\t\texecute M code <MCODE> 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-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-k\n\t\trun the FreeM daemon in foreground (requires --daemon)\n\n"); |
fprintf (stdout, "\t-p <PIDFILE>\n\t\tuse <PIDFILE> to record the PID of the FreeM daemon\n\n\n"); |
|
fprintf (stdout, "\t-S <BYTES>\n\t\tsets the size of the shared memory segment where FreeM stores the job table, lock table, and IPC table.\n"); |
fprintf (stdout, "\t-S <BYTES>\n\t\tsets the size of the shared memory segment where FreeM stores the job table, lock table, and IPC table.\n"); |
#endif |
#endif |
fprintf (stdout, "\t\t - Each concurrent job takes %d bytes (1 page) of shared memory\n", PG_SIZE); |
fprintf (stdout, "\t\t - Each concurrent job takes %d bytes (1 page) of shared memory\n", PG_SIZE); |