*** apache_base:[src.main]http_main.c;1	Wed Mar 17 23:05:43 1999

--- apache_cur:[src.main]http_main.c;113	Wed Jul  7 16:00:12 1999

***************

*** 76,81 ****

--- 76,86 ----

   *

   * April-July '95 rst

   *      Extensive rework for Apache.

+  *

+  * January 99 PV

+  *	Porting to OpenVMS

+  * June 1999 DLJ

+  *      Porting to OpenVMS.

   */

  

  #ifndef SHARED_CORE_BOOTSTRAP

***************

*** 124,129 ****

--- 129,142 ----

  #include <bstring.h>		/* for IRIX, FD_SET calls bzero() */

  #endif

  

+ #if defined(VMS) && !defined(UCX$C_AUXS)

+ /*

+  * We can not include ucx$inetdef.h because it redefines already included 

+  * constants.

+  */

+ #define UCX$C_AUXS 127

+ #endif

+ 

  #ifdef MULTITHREAD

  /* special debug stuff -- PCS */

  

***************

*** 306,311 ****

--- 319,342 ----

   */

  

  static int one_process = 0;

+ #ifdef VMS

+ /*

+  * Since VMS doesn't have a fork, server processes identify themselves as

+  * children by the -n option on the command line, with optarg being the

+  * scoreboard slot number allocated by the caretaker process.  The child_id

+  * global is set to this slot number or -1 for the caretaker.

+  *

+  * The children have to do all the initialization done by the caretaker

+  * before calling child_main.

+  */

+ int vms_child_id = -1;

+ #define child_id vms_child_id

+ #ifdef DEBUG

+ #define DBG_PRINT if ( vms_child_id  == -2 ) 0; else printf

+ #else

+ #define DBG_PRINT if ( vms_child_id != -2 ) 0; else printf

+ #endif

+ #endif

  

  /* set if timeouts are to be handled by the children and not by the parent.

   * i.e. child_timeouts = !standalone || one_process.

***************

*** 1000,1005 ****

--- 1031,1039 ----

      fprintf(stderr, "  -L               : list available configuration directives\n");

      fprintf(stderr, "  -S               : show parsed settings (currently only vhost settings)\n");

      fprintf(stderr, "  -t               : run syntax test for configuration files only\n");

+ #ifdef VMS

+     fprintf(stderr, "  -n number        : Assign slot number to child.\n");

+ #endif

  #ifdef WIN32

      fprintf(stderr, "  -k shutdown      : tell running Apache to shutdown\n");

      fprintf(stderr, "  -k restart       : tell running Apache to do a graceful restart\n");

***************

*** 1024,1029 ****

--- 1058,1067 ----

  {

      void *dirconf;

  

+ #ifdef VMS

+ DBG_PRINT("(%d) recieved timeout alarm, blocked: %d, exitafter: %d, cur: %x req: %x\n", 

+ child_id, alarms_blocked, exit_after_unblock, current_conn, timeout_req );

+ #endif

      if (alarms_blocked) {

  	alarm_pending = 1;

  	return;

***************

*** 1072,1085 ****

  	    ap_log_transaction(log_req);

  

  	ap_bsetflag(save_req->connection->client, B_EOUT, 1);

  	ap_bclose(save_req->connection->client);

  

  	if (!ap_standalone)

  	    exit(0);

! 

  	ap_longjmp(jmpbuffer, 1);

      }

      else {			/* abort the connection */

  	ap_bsetflag(current_conn->client, B_EOUT, 1);

  	ap_bclose(current_conn->client);

  	current_conn->aborted = 1;

--- 1110,1132 ----

  	    ap_log_transaction(log_req);

  

  	ap_bsetflag(save_req->connection->client, B_EOUT, 1);

+ #ifdef VMS

+ DBG_PRINT("(%d) timeout is closing connection (fd=%d,%d)\n", child_id,

+ save_req->connection->client->fd, save_req->connection->client->fd_in );

+ #endif

  	ap_bclose(save_req->connection->client);

  

  	if (!ap_standalone)

  	    exit(0);

! #ifdef VMS

! DBG_PRINT("(%d) timeout is issuing longjump\n", child_id );

! #endif

  	ap_longjmp(jmpbuffer, 1);

      }

      else {			/* abort the connection */

+ #ifdef VMS

+ DBG_PRINT("(%d) timeout is closing(abort) connection\n", child_id );

+ #endif

  	ap_bsetflag(current_conn->client, B_EOUT, 1);

  	ap_bclose(current_conn->client);

  	current_conn->aborted = 1;

***************

*** 1130,1135 ****

--- 1177,1185 ----

  #ifndef WIN32

  static void alrm_handler(int sig)

  {

+ #ifdef VMS

+     DBG_PRINT("(%d) alarm triggered, alarm_fn: %x\n", child_id, alarm_fn );

+ #endif

      if (alarm_fn) {

  	(*alarm_fn) (sig);

      }

***************

*** 1171,1176 ****

--- 1221,1229 ----

  	old = ap_scoreboard_image->servers[my_child_num].timeout_len;

  	ap_scoreboard_image->servers[my_child_num].timeout_len = x;

  	++ap_scoreboard_image->servers[my_child_num].cur_vtime;

+ #ifdef VMS

+ 	DBG_PRINT("(%d) setting timer for %d to %d\n", child_id, my_child_num, x );

+ #endif

      }

  #endif

  #endif

***************

*** 1253,1258 ****

--- 1306,1314 ----

  

  API_EXPORT(void) ap_kill_timeout(request_rec *dummy)

  {

+ #ifdef VMS

+     DBG_PRINT("(%d) killing timeout\n", child_id );

+ #endif

      ap_set_callback_and_alarm(NULL, 0);

      timeout_req = NULL;

      timeout_name = NULL;

***************

*** 1755,1760 ****

--- 1811,1819 ----

  	close(fd);

  	unlink(mfile);

      }

+ #elif defined(VMS)

+     /* Create global section */

+     m = vms_create_scoreboard ( SCOREBOARD_SIZE, (child_id < 0) ? 1 : 0 );

  #else

      m = mmap((caddr_t) 0, SCOREBOARD_SIZE,

  	     PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);

***************

*** 1951,1956 ****

--- 2010,2018 ----

      if (ap_scoreboard_image == NULL) {

  	setup_shared_mem(p);

      }

+ #ifdef VMS

+     if ( child_id >= 0 ) return;	/* children don't init the section */

+ #endif

      memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);

      ap_scoreboard_image->global.running_generation = running_gen;

  #else

***************

*** 2547,2558 ****

--- 2609,2634 ----

  

  static int volatile usr1_just_die = 1;

  static int volatile deferred_die;

+ #ifdef VMS

+ static int volatile accept_fd = -1;

+ #include <ssdef.h>			/* sys. serv. return codes: SS$_CANCEL */

+ #endif

  

  static void usr1_handler(int sig)

  {

      if (usr1_just_die) {

  	just_die(sig);

      }

+ #ifdef VMS

+     else if ( accept_fd >= 0 ) {

+ 	/*

+ 	 * Issue cancel on accept in progress.

+ 	 */

+ 	int vms_chan, SYS$CANCEL();

+ 	vms_chan = vaxc$get_sdc ( accept_fd );

+ 	if ( vms_chan >= 0 ) SYS$CANCEL ( vms_chan );

+     }

+ #endif

      deferred_die = 1;

  }

  

***************

*** 2808,2814 ****

      int x;

  

      chdir("/");

! #if !defined(MPE) && !defined(OS2) && !defined(TPF)

  /* Don't detach for MPE because child processes can't survive the death of

     the parent. */

      if ((x = fork()) > 0)

--- 2884,2890 ----

      int x;

  

      chdir("/");

! #if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(VMS)

  /* Don't detach for MPE because child processes can't survive the death of

     the parent. */

      if ((x = fork()) > 0)

***************

*** 2832,2838 ****

  	fprintf(stderr, "%s: setpgrp or getpgrp failed\n", ap_server_argv0);

  	exit(1);

      }

! #elif defined(OS2) || defined(TPF)

      /* OS/2 don't support process group IDs */

      pgrp = getpid();

  #elif defined(MPE)

--- 2908,2914 ----

  	fprintf(stderr, "%s: setpgrp or getpgrp failed\n", ap_server_argv0);

  	exit(1);

      }

! #elif defined(OS2) || defined(TPF) || defined(VMS)

      /* OS/2 don't support process group IDs */

      pgrp = getpid();

  #elif defined(MPE)

***************

*** 2847,2852 ****

--- 2923,2929 ----

  #endif

  

      /* close out the standard file descriptors */

+ #ifndef VMS

      if (freopen("/dev/null", "r", stdin) == NULL) {

  	fprintf(stderr, "%s: unable to replace stdin with /dev/null: %s\n",

  		ap_server_argv0, strerror(errno));

***************

*** 2860,2865 ****

--- 2937,2943 ----

  	fprintf(stderr, "%s: unable to replace stdout with /dev/null: %s\n",

  		ap_server_argv0, strerror(errno));

      }

+ #endif

      /* stderr is a tricky one, we really want it to be the error_log,

       * but we haven't opened that yet.  So leave it alone for now and it'll

       * be reopened moments later.

***************

*** 3016,3027 ****

--- 3094,3119 ----

  

      /* note that because we're about to slack we don't use psocket */

      ap_block_alarms();

+ #ifndef VMS

      if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {

  	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,

  		    "make_sock: failed to get a socket for %s", addr);

  	ap_unblock_alarms();

  	exit(1);

      }

+ #else

+     /*

+      * Must set special attribute on socket to allow driver to share

+      * listen socket among several processes.

+      */

+     if ( (s=vms_create_shared_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP))

+ 	< 0 ) {

+ 	ap_log_error(APLOG_MARK, APLOG_CRIT, server_conf,

+ 		    "make_sock: failed to get a (shared) socket for %s", addr);

+ 	ap_unblock_alarms();

+ 	exit(1);

+     }

+ #endif

  

      /* Solaris (probably versions 2.4, 2.5, and 2.5.1 with various levels

       * of tcp patches) has some really weird bugs where if you dup the

***************

*** 3230,3241 ****

--- 3322,3363 ----

  {

      listen_rec *lr;

      int fd;

+ #ifdef VMS

+     struct vms_shared_socket *list, *ss; int status;

+ 

+     if ( child_id >= 0 ) {

+ 	/*

+ 	 * We are a child process, get the list of shared listen sockets

+ 	 * and initialize their names.

+ 	 */

+ 	list = (struct vms_shared_socket *) 0;

+ 	status = vms_import_shared_socket ( "APACHE_SHARED_SOCKET", &list );

+ 	if ( (status&1) == 1 ) {

+ 	    for ( ss = list; ss; ss = ss->next ) {

+ 		ss->name = malloc ( sizeof(struct sockaddr) );

+ 		ss->namelen = sizeof(struct sockaddr);

+ 		status = getsockname ( ss->fd, (struct sockaddr *) &ss->name, 

+ 			(size_t *) &ss->namelen );

+ 	    }

+ 	}

+         else fprintf(stderr,"import of shared socket failed: %d\n", status );

+ 	ss = list;

+     }

+ #endif

  

      listenmaxfd = -1;

      FD_ZERO(&listenfds);

      lr = ap_listeners;

      for (;;) {

  	fd = find_listener(lr);

+ #ifdef VMS

+ 	if ( (child_id >= 0) && (fd < 0) && ss ) {

+ 	    /* Locate matching address  (to be done later) */

+ 	    fd = ss->fd;

+ 	    ss = ss->next;

+ 	}

+ 	else

+ #endif

  	if (fd < 0) {

  	    fd = make_sock(p, &lr->local_addr);

  	}

***************

*** 3257,3262 ****

--- 3379,3398 ----

      head_listener = ap_listeners;

      close_unused_listeners();

  

+ #ifdef VMS

+     if ( child_id < 0 ) {

+ 	/*

+ 	 * We are caretaker process, build logical name that lists

+ 	 * the names of the shared socket devices.

+ 	 */

+ 	int status;

+ 	status = vms_export_shared_sockets ( "APACHE_SHARED_SOCKET" );

+         if ( (status&1) == 0 ) {

+ 	    fprintf(stderr,"Error exporting shared listen socket names: %d\n",

+ 		status );

+ 	}

+     }

+ #endif

  #ifdef NO_SERIALIZED_ACCEPT

      /* warn them about the starvation problem if they're using multiple

       * sockets

***************

*** 3673,3680 ****

--- 3809,3833 ----

  	    deferred_die = 0;

  	    usr1_just_die = 0;

  	    for (;;) {

+ 		struct sockaddr_in *sa_client_in;

  		clen = sizeof(sa_client);

+ 		errno = 0;

+ 

+ #ifdef VMS

+ 		accept_fd = sd;

  		csd = accept(sd, &sa_client, &clen);

+ 		accept_fd = -1;

+ 		if ( csd < 0 ) {

+ 		    /* Convert cancel to EINTR errno */

+ 		    if ( (errno == EVMSERR) && (vaxc$errno == SS$_CANCEL) )

+ 			errno = EINTR;

+ 		}

+ sa_client_in = (struct sockaddr_in *) &sa_client;

+ DBG_PRINT("(%d) accept() returned csd: %d(port: %d), errno: %d/%d, die: %d\n", 

+ child_id, csd, ntohs(sa_client_in->sin_port), errno, vaxc$errno, deferred_die);

+ #else

+ 		csd = accept(sd, &sa_client, &clen);

+ #endif

  		if (csd >= 0 || errno != EINTR)

  		    break;

  		if (deferred_die) {

***************

*** 3916,3926 ****

--- 4069,4088 ----

      }

  

      if (one_process) {

+ #ifdef VMS

+ 	/*

+ 	 * mimic the rotation of the ring 'start'

+ 	 */

+ 	int i;

+ 	for ( i = 0; i < slot; i++ ) head_listener = head_listener->next;

+ 	if ( (child_id >= 0) ) slot = child_id;

+ #endif

  	signal(SIGHUP, just_die);

  	signal(SIGINT, just_die);

  	signal(SIGQUIT, SIG_DFL);

  	signal(SIGTERM, just_die);

  	child_main(slot);

+ 	return -1;

      }

  

      /* avoid starvation */

***************

*** 3929,3935 ****

--- 4091,4118 ----

      Explain1("Starting new child in slot %d", slot);

      (void) ap_update_child_status(slot, SERVER_STARTING, (request_rec *) NULL);

  

+ #ifdef VMS

+     pid = 0;

+     if ( !one_process ) {

+ 	/*

+ 	 * Rather than fork, create a sub-process running a script.

+ 	 * If symbol httpc defined, spawn command "httpc n", otherwise

+ 	 * spawn command "httpd -n n".

+ 	 */

+ 	static char *val, command[256];

+ 	static int command_init = 0;

+ 	int status;

+ 	if ( 0 == command_init ) {

+ 	    command_init = 1;		/* only call getenv once */

+ 	    val = getenv ( "httpc" );

+ 	}

+ 	sprintf ( command, "%s %d", val ? "httpc" : "httpd -n", slot );

+ 	status = vms_create_child ( command, (long *) &pid );

+ 	if ( (status&1) == 0 ) pid = 0;

+     } else pid = getpid();

  

+     if ( (pid == 0) ) {   /* failure */

+ #else

  #ifndef _OSD_POSIX

      if ((pid = fork()) == -1) {

  #else /*_OSD_POSIX*/

***************

*** 3937,3942 ****

--- 4120,4126 ----

      if ((pid = os_fork(ap_user_name)) == -1) {

  #endif /*_OSD_POSIX*/

  	ap_log_error(APLOG_MARK, APLOG_ERR, s, "fork: Unable to fork new process");

+ #endif /* VMS */

  

  	/* fork didn't succeed. Fix the scoreboard or else

  	 * it will say SERVER_STARTING forever and ever

***************

*** 3995,4001 ****

  {

      int i;

      time_t now = time(0);

- 

      for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {

  	if (ap_scoreboard_image->servers[i].status != SERVER_DEAD) {

  	    continue;

--- 4179,4184 ----

***************

*** 4041,4052 ****

      total_non_dead = 0;

  

      ap_sync_scoreboard_image();

!     for (i = 0; i < ap_daemons_limit; ++i) {

  	int status;

  

  	if (i >= max_daemons_limit && free_length == idle_spawn_rate)

  	    break;

  	ss = &ap_scoreboard_image->servers[i];

  	status = ss->status;

  	if (status == SERVER_DEAD) {

  	    /* try to keep children numbers as low as possible */

--- 4224,4239 ----

      total_non_dead = 0;

  

      ap_sync_scoreboard_image();

! /*printf("starting caretaker maintainence round, limit: %d\n", ap_daemons_limit);

! */    for (i = 0; i < ap_daemons_limit; ++i) {

  	int status;

  

  	if (i >= max_daemons_limit && free_length == idle_spawn_rate)

  	    break;

  	ss = &ap_scoreboard_image->servers[i];

+ if ( ss->status && (ss->status != SERVER_READY) )

+ DBG_PRINT ( "  child[%d].status = %d, timeout: %d\n", i, ss->status,

+ ss->timeout_len );

  	status = ss->status;

  	if (status == SERVER_DEAD) {

  	    /* try to keep children numbers as low as possible */

***************

*** 4087,4092 ****

--- 4274,4282 ----

  		    ps->last_vtime = ss->cur_vtime;

  		}

  		else if (ps->last_rtime + ss->timeout_len < now) {

+ #ifdef VMS

+ DBG_PRINT("  Signalling child[%d] (%x)\n", i, ps->pid );

+ #endif

  		    /* no progress, and the timeout length has been exceeded */

  		    ss->timeout_len = 0;

  		    kill(ps->pid, SIGALRM);

***************

*** 4270,4275 ****

--- 4460,4478 ----

  #endif

  

  	set_signals();

+ #ifdef VMS

+ 	/*

+ 	 * If we are really a child process, skip all the make_child stuff

+ 	 */

+ 	if ( child_id >= 0 ) {

+ 	    signal(SIGHUP, just_die);

+ 	    signal(SIGINT, just_die);

+ 	    signal(SIGQUIT, SIG_DFL);

+ 	    signal(SIGTERM, just_die);

+ 	    child_main(child_id);

+ 	    return;

+ 	}

+ #endif

  

  	if (ap_daemons_max_free < ap_daemons_min_free + 1)	/* Don't thrash... */

  	    ap_daemons_max_free = ap_daemons_min_free + 1;

***************

*** 4499,4505 ****

  

  #ifndef TPF

      while ((c = getopt(argc, argv,

! 				    "D:C:c:Xd:f:vVlLR:Sth"

  #ifdef DEBUG_SIGSTOP

  				    "Z:"

  #endif

--- 4702,4708 ----

  

  #ifndef TPF

      while ((c = getopt(argc, argv,

! 				    "D:C:c:Xd:f:n:vVlLR:Sth"

  #ifdef DEBUG_SIGSTOP

  				    "Z:"

  #endif

***************

*** 4556,4561 ****

--- 4759,4769 ----

  	     */

  	    break;

  #endif

+ #ifdef VMS

+ 	case 'n':

+ 	    child_id = atoi ( optarg );

+ 	    break;

+ #endif

  	case 'S':

  	    ap_dump_settings = 1;

  	    break;

***************

*** 4639,4644 ****

--- 4847,4866 ----

     in ebw000 */

      sock_in = * (int*)(&(ecbptr()->ebw000));

      sock_out = * (int*)(&(ecbptr()->ebw000));

+ 

+ #elif defined(VMS)

+ 

+ /* TCP/IP Services for OpenVMS defines the Auxiliary server which accepts the 

+  * connection. Howver, remember that Apache.Org depricates ServerType inetd

+  */

+ 

+     if ((sock_in = socket(UCX$C_AUXS, SOCK_STREAM, IPPROTO_TCP)) < 0) {

+         fprintf(stderr, "Error getting network socket\n");

+ 	perror("socket");

+ 	exit(1);

+     }

+     sock_out = sock_in;

+ 

  #elif defined(MPE)

  /* HP MPE 5.5 inetd only passes the incoming socket as stdin (fd 0), whereas

     HPUX inetd passes the incoming socket as stdin (fd 0) and stdout (fd 1).

***************

*** 6147,6150 ****

  }

  

  #endif /* ndef SHARED_CORE_BOOTSTRAP */

- 

--- 6369,6371 ----

