Diff for /freem/src/mumps.c between versions 1.11 and 1.28

version 1.11, 2025/04/01 23:21:45 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   *   Revision 1.11  2025/04/01 23:21:45  snw
  *   fmadm commands for stopping, starting, and restarting environments now functional   *   fmadm commands for stopping, starting, and restarting environments now functional
  *   *
Line 53 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 81 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 96  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 109  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 123  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 154  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 179  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 191  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 214  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 304  int main (int argc, char **argv, char ** Line 351  int main (int argc, char **argv, char **
   
             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 327  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:dkS:u:g:")) != -1) {          while ((c = getopt (argc, argv, "hsfiqRr:n:e:vx:dkS:")) != -1) {
   
             if (c == '?') freem_usage ();              if (c == '?') freem_usage ();
                           
Line 350  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 435  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 458  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 497  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 513  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 523  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 542  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);  
                 }                  }
             }              }
   
               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 588  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) {
                 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, "%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 636  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 671  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 692  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 723  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 740  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 760  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 780  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 811  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 831  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 867  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 887  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 895  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 940  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);

Removed from v.1.11  
changed lines
  Added in v.1.28


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>