version 1.20, 2025/04/13 04:22:43
|
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 |
* Revision 1.20 2025/04/13 04:22:43 snw |
* Fix snprintf calls |
* Fix snprintf calls |
* |
* |
Line 109
|
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 124 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 205 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 466 int main (int argc, char **argv, char **
|
Line 487 int main (int argc, char **argv, char **
|
snprintf (env_config_file, sizeof (config_file) - 1, "%s/freem/env.conf", SYSCONFDIR); |
snprintf (env_config_file, sizeof (config_file) - 1, "%s/freem/env.conf", SYSCONFDIR); |
|
|
if (!file_exists (env_config_file)) { |
if (!file_exists (env_config_file)) { |
fprintf (stderr, "freem: environment catalog does not exist; may need to run fmadm configure\n"); |
logprintf (FM_LOG_FATAL, "freem: environment catalog does not exist; may need to run fmadm configure"); |
exit (1); |
|
} |
} |
|
|
if (!file_exists (config_file)) { |
if (!file_exists (config_file)) { |
fprintf (stderr, "freem: configuration file for %s does not exist; may need to run fmadm configure\n", shm_env); |
logprintf (FM_LOG_FATAL, "freem: configuration file for %s does not exist; may need to run fmadm configure", shm_env); |
exit (1); |
|
} |
} |
|
|
if (read_profile_string (env_config_file, shm_env, "user", d_username) == FALSE) { |
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); |
logprintf (FM_LOG_FATAL, "freem: could not determine owning user for environment %s", shm_env); |
exit (1); |
|
} |
} |
|
|
if (read_profile_string (env_config_file, shm_env, "group", d_groupname) == FALSE) { |
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); |
logprintf (FM_LOG_FATAL, "freem: could not determine owning group for environment %s", shm_env); |
exit (1); |
|
} |
} |
|
|
if (read_profile_string (env_config_file, shm_env, "enabled", env_ena) == FALSE) { |
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); |
logprintf (FM_LOG_FATAL, "freem: could not discover enabled state for environment %s", shm_env); |
exit (1); |
|
} |
} |
|
|
if (strcmp (env_ena, "true") != 0) { |
if (strcmp (env_ena, "true") != 0) { |
fprintf (stderr, "freem: environment %s is administratively disabled\n", shm_env); |
logprintf (FM_LOG_FATAL, "freem: environment %s is administratively disabled", shm_env); |
exit (1); |
|
} |
} |
|
|
d_grp = getgrnam (d_groupname); |
d_grp = getgrnam (d_groupname); |
if (d_grp == NULL) { |
if (d_grp == NULL) { |
fprintf (stderr, "freem: invalid group '%s'\n", d_groupname); |
logprintf (FM_LOG_FATAL, "freem: invalid group '%s'", d_groupname); |
exit (1); |
|
} |
} |
d_gid = d_grp->gr_gid; |
d_gid = d_grp->gr_gid; |
|
|
d_user = getpwnam (d_username); |
d_user = getpwnam (d_username); |
if (d_user == NULL) { |
if (d_user == NULL) { |
fprintf (stderr, "freem: invalid user '%s'\n", d_username); |
logprintf (FM_LOG_FATAL, "freem: invalid user '%s'", d_username); |
exit (1); |
|
} |
} |
d_uid = d_user->pw_uid; |
d_uid = d_user->pw_uid; |
|
|
|
|
#if defined(__linux__) |
#if defined(__linux__) |
if (run_daemon == FALSE && group_member (d_gid) == 0) { |
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); |
logprintf (FM_LOG_FATAL, "freem: you must be a member of the %s group to use environment %s", d_groupname, shm_env); |
exit (1); |
|
} |
} |
#endif |
#endif |
|
|
|
|
if (run_daemon == TRUE) { |
if (run_daemon == TRUE) { |
if (geteuid () != 0 && nofork == FALSE) { |
if (geteuid () != 0 && nofork == FALSE) { |
fprintf (stderr, "freem: forking daemon must be run as root\n"); |
logprintf (FM_LOG_FATAL, "freem: forking daemon must be run as root"); |
exit (1); |
|
} |
} |
} |
} |
|
|
|
|
if ((nofork == TRUE) && (run_daemon == FALSE)) { |
if ((nofork == TRUE) && (run_daemon == FALSE)) { |
freem_usage (); |
freem_usage (); |
exit (1); |
exit (1); |
Line 532 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 548 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 558 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 577 int main (int argc, char **argv, char **
|
Line 586 int main (int argc, char **argv, char **
|
} |
} |
|
|
if (geteuid () == 0) { |
if (geteuid () == 0) { |
/* shed privileges */ |
|
|
|
|
/* 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) { |
fprintf (stderr, "freem: failure switching GID\n"); |
logprintf (FM_LOG_FATAL, "environment error: failure switching GID"); |
m_log (1, "failure switching GIDs"); |
|
exit (1); |
|
} |
} |
|
|
|
|
|
|
if (d_uid != geteuid ()) { |
if (d_uid != geteuid ()) { |
fprintf (stderr, "freem: switching to username %s\n", d_username); |
|
m_log (1, "switching users"); |
logprintf (FM_LOG_INFO, "environment: switching to username %s", d_username); |
|
|
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); |
|
} |
} |
} |
} |
|
|
|
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; |
Line 623 int main (int argc, char **argv, char **
|
Line 630 int main (int argc, char **argv, char **
|
|
|
snprintf (pid_file_path, PATH_MAX - 1, "%s/freem/run/%s.pid", LOCALSTATEDIR, shm_env); |
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) { |
fprintf (stderr, "freem: could not open PID file %s [%s]\n", pid_file_path, strerror (errsav)); |
logprintf (FM_LOG_FATAL, "environment error: could not open PID file %s [%s]", pid_file_path, strerror (errsav)); |
m_log (1, "freem: could not open PID file"); |
|
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; |
fprintf (stderr, "freem: could not lock PID file [%s]\n", strerror (errsav)); |
logprintf (FM_LOG_FATAL, "environment error: could not lock PID file [%s]", strerror (errsav)); |
m_log (1, "freem: could not lock PID file - perhaps already running?"); |
|
m_log (1, strerror (errsav)); |
|
exit (1); |
|
} |
} |
|
|
sprintf (pidfile_buf, "%ld\n", (long) 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 770 int main (int argc, char **argv, char **
|
Line 773 int main (int argc, char **argv, char **
|
else { |
else { |
fm_initialized = TRUE; |
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); |
} |
} |
|
|