static void init_sockdev ( void ) { if (init_done) return; InitializeListHead( &bind_head ); initialize_lock( &bind_lock ); hdl_adsc( "term_sockdev", term_sockdev, NULL ); init_done = TRUE; }
void *http_server (void *arg) { int rc; /* Return code */ int lsock; /* Socket for listening */ int csock; /* Socket for conversation */ struct sockaddr_in server; /* Server address structure */ fd_set selset; /* Read bit map for select */ int optval; /* Argument for setsockopt */ TID httptid; /* Negotiation thread id */ struct timeval timeout; /* timeout value */ UNREFERENCED(arg); http_serv.httpshutdown = TRUE; hdl_adsc("http_shutdown",http_shutdown, NULL); /* Set root mode in order to set priority */ SETMODE(ROOT); /* Set server thread priority; ignore any errors */ if(setpriority(PRIO_PROCESS, 0, sysblk.srvprio)) WRMSG(HHC00136, "W", "setpriority()", strerror(errno)); /* Back to user mode */ SETMODE(USER); /* Display thread started message on control panel */ WRMSG (HHC00100, "I", (u_long)thread_id(), getpriority(PRIO_PROCESS,0), "HTTP server"); /* make sure root path is built */ if ( http_root() == NULL ) goto http_server_stop; /* Obtain a socket */ lsock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (lsock < 0) { WRMSG(HHC01800,"E", "socket()", strerror(HSO_errno)); goto http_server_stop; } /* Allow previous instance of socket to be reused */ optval = 1; setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof(optval)); /* Prepare the sockaddr structure for the bind */ memset (&server, 0, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = http_serv.httpport; server.sin_port = htons(server.sin_port); http_serv.httpbinddone = FALSE; /* Attempt to bind the socket to the port */ while (TRUE) { rc = bind (lsock, (struct sockaddr *)&server, sizeof(server)); if (rc == 0 || HSO_errno != HSO_EADDRINUSE) break; WRMSG(HHC01804, "W", http_serv.httpport); SLEEP(10); } /* end while */ if (rc != 0) { WRMSG(HHC01800,"E", "bind()", strerror(HSO_errno)); goto http_server_stop; } else http_serv.httpbinddone = TRUE; /* Put the socket into listening state */ rc = listen (lsock, 32); if (rc < 0) { WRMSG(HHC01800,"E", "listen()", strerror(HSO_errno)); http_serv.httpbinddone = FALSE; goto http_server_stop; } http_serv.httpshutdown = FALSE; WRMSG(HHC01803, "I", http_serv.httpport); /* Handle http requests */ while ( !http_serv.httpshutdown ) { /* Initialize the select parameters */ FD_ZERO (&selset); FD_SET (lsock, &selset); timeout.tv_sec = 0; timeout.tv_usec = 10000; /* until a better way to implement this use standard windows */ #undef select /* Wait for a file descriptor to become ready use NON-BLOCKING select()*/ rc = select ( lsock+1, &selset, NULL, NULL, &timeout ); if ( rc == 0 || http_serv.httpshutdown ) continue; if (rc < 0 ) { if (HSO_errno == HSO_EINTR) continue; WRMSG(HHC01800, "E", "select()", strerror(HSO_errno)); break; } /* If a http request has arrived then accept it */ if (FD_ISSET(lsock, &selset)) { /* Accept the connection and create conversation socket */ csock = accept (lsock, NULL, NULL); if (csock < 0) { WRMSG(HHC01800, "E", "accept()", strerror(HSO_errno)); continue; } /* Create a thread to execute the http request */ rc = create_thread (&httptid, DETACHED, http_request, (void *)(uintptr_t)csock, "http_request"); if(rc) { WRMSG(HHC00102, "E", strerror(rc)); close_socket (csock); } } /* end if(lsock) */ } /* end while */ /* Close the listening socket */ close_socket (lsock); http_server_stop: if ( !sysblk.shutdown ) hdl_rmsc(http_shutdown, NULL); /* Display thread started message on control panel */ WRMSG(HHC00101, "I", (u_long)thread_id(), getpriority(PRIO_PROCESS,0), "HTTP server"); sysblk.httptid = 0; http_serv.httpbinddone = FALSE; signal_condition(&http_serv.http_wait_shutdown); return NULL; } /* end function http_server */
DLL_EXPORT void logger_init(void) { int rc; initialize_condition (&logger_cond); initialize_lock (&logger_lock); logger_init_flg = TRUE; /* this is a conditional macro based upon OPTION_MSGLCK */ INIT_MSGLCK; obtain_lock(&logger_lock); if(fileno(stdin)>=0 || fileno(stdout)>=0 || fileno(stderr)>=0) { logger_syslog[LOG_WRITE] = stderr; /* If standard error is redirected, then use standard error as the log file. */ if(!isatty(STDOUT_FILENO) && !isatty(STDERR_FILENO)) { /* Ignore standard output to the extent that it is treated as standard error */ logger_hrdcpyfd = dup(STDOUT_FILENO); strlcpy(logger_filename, "STDOUT redirected from command line", sizeof(logger_filename)); if(dup2(STDERR_FILENO,STDOUT_FILENO) == -1) { fprintf(stderr, MSG(HHC02102, "E", "dup2()", strerror(errno))); exit(1); } } else { if(!isatty(STDOUT_FILENO)) { logger_hrdcpyfd = dup(STDOUT_FILENO); strlcpy(logger_filename, "STDOUT redirected from command line", sizeof(logger_filename)); if(dup2(STDERR_FILENO,STDOUT_FILENO) == -1) { fprintf(stderr, MSG(HHC02102, "E", "dup2()", strerror(errno))); exit(1); } } if(!isatty(STDERR_FILENO)) { strlcpy(logger_filename, "STDERR redirected from command line", sizeof(logger_filename)); logger_hrdcpyfd = dup(STDERR_FILENO); if(dup2(STDOUT_FILENO,STDERR_FILENO) == -1) { fprintf(stderr, MSG(HHC02102, "E", "dup2()", strerror(errno))); exit(1); } } } if(logger_hrdcpyfd == -1) { logger_hrdcpyfd = 0; fprintf(stderr, MSG(HHC02102, "E", "dup()", strerror(errno))); } if(logger_hrdcpyfd) { if(!(logger_hrdcpy = fdopen(logger_hrdcpyfd,"w"))) fprintf(stderr, MSG(HHC02102, "E", "fdopen()", strerror(errno))); } if(logger_hrdcpy) setvbuf(logger_hrdcpy, NULL, _IONBF, 0); } else { logger_syslog[LOG_WRITE]=fopen("LOG","a"); } logger_bufsize = LOG_DEFSIZE; if(!(logger_buffer = malloc(logger_bufsize))) { char buf[40]; MSGBUF(buf, "malloc(%d)", logger_bufsize); fprintf(stderr, MSG(HHC02102, "E", buf, strerror(errno))); exit(1); } if(create_pipe(logger_syslogfd)) { fprintf(stderr, MSG(HHC02102, "E", "create_pipe()", strerror(errno))); exit(1); /* Hercules running without syslog */ } setvbuf (logger_syslog[LOG_WRITE], NULL, _IONBF, 0); rc = create_thread (&logger_tid, JOINABLE, logger_thread, NULL, "logger_thread"); if (rc) { fprintf(stderr, MSG(HHC00102, "E", strerror(rc))); exit(1); } wait_condition(&logger_cond, &logger_lock); release_lock(&logger_lock); /* call logger_term on system shutdown */ hdl_adsc("logger_term",logger_term, NULL); }
static int IFC_IOCtl( int fd, unsigned long int iRequest, char* argp ) { char* pszCfgCmd; // Interface config command CTLREQ ctlreq; #if defined(DEBUG) || defined(_DEBUG) char* request_name; // debugging: name of ioctl request char unknown_request[] = "Unknown (0x00000000)"; #endif UNREFERENCED( fd ); memset( &ctlreq, 0, CTLREQ_SIZE ); ctlreq.iCtlOp = iRequest; #if defined(DEBUG) || defined(_DEBUG) // Select string to represent ioctl request for debugging. switch (iRequest) { #ifdef OPTION_TUNTAP_CLRIPADDR case SIOCDIFADDR: request_name="SIOCDIFADDR"; break; #endif case SIOCSIFADDR: request_name="SIOCSIFADDR"; break; case SIOCSIFDSTADDR: request_name="SIOCSIFDSTADDR"; break; case SIOCSIFMTU: request_name="SIOCSIFMTU"; break; case SIOCSIFFLAGS: request_name="SIOCSIFFLAGS"; break; case SIOCGIFFLAGS: request_name="SIOCGIFFLAGS"; break; #ifdef OPTION_TUNTAP_SETNETMASK case SIOCSIFNETMASK: request_name="SIOCSIFNETMASK"; break; #endif #ifdef OPTION_TUNTAP_SETMACADDR case SIOCSIFHWADDR: request_name="SIOCSIFHWADDR"; break; #endif #ifdef OPTION_TUNTAP_DELADD_ROUTES case SIOCADDRT: request_name="SIOCADDRT"; break; case SIOCDELRT: request_name="SIOCDELRT"; break; #endif default: sprintf(unknown_request,"Unknown (0x%lx)",iRequest); request_name=unknown_request; } #endif // defined(DEBUG) || defined(_DEBUG) #ifdef OPTION_TUNTAP_DELADD_ROUTES if( iRequest == SIOCADDRT || iRequest == SIOCDELRT ) { strcpy( ctlreq.szIFName, ((struct rtentry*)argp)->rt_dev ); memcpy( &ctlreq.iru.rtentry, argp, sizeof( struct rtentry ) ); ((struct rtentry*)argp)->rt_dev = NULL; } else #endif { memcpy( &ctlreq.iru.hifr, argp, sizeof( struct hifr ) ); } if( ifc_fd[0] == -1 && ifc_fd[1] == -1 ) { if( socketpair( AF_UNIX, SOCK_STREAM, 0, ifc_fd ) < 0 ) { WRMSG( HHC00136, "E", "socketpair()", strerror( errno ) ); return -1; } // Obtain the name of the interface config program or default if( !( pszCfgCmd = getenv( "HERCULES_IFC" ) ) ) pszCfgCmd = HERCIFC_CMD; TRACE(MSG(HHC00147, "I", pszCfgCmd)); // Fork a process to execute the hercifc ifc_pid = fork(); if( ifc_pid < 0 ) { WRMSG( HHC00136, "E", "fork()", strerror( errno ) ); return -1; } // The child process executes the configuration command if( ifc_pid == 0 ) { /* @ISW@ Close all file descriptors * (except ifc_fd[1] and STDOUT FILENO) * (otherwise some devices are never closed) * (ex: SCSI tape devices can never be re-opened) */ struct rlimit rlim; int i; rlim_t file_limit; getrlimit(RLIMIT_NOFILE,&rlim); /* While Linux and Cygwin have limits of 1024 files by default, * Mac OS X does not - its default is -1, or completely unlimited. * The following hack is to defend against trying to close 2 * billion files. -- JRM */ file_limit=rlim.rlim_max; file_limit=(file_limit>1024)?1024:file_limit; TRACE(MSG(HHC00148, "I", file_limit)); for(i=0;(unsigned int)i<file_limit;i++) { if(i!=ifc_fd[1] && i!=STDOUT_FILENO) { close(i); } } /* @ISW@ Close spurious FDs END */ dup2( ifc_fd[1], STDIN_FILENO ); dup2( STDOUT_FILENO, STDERR_FILENO ); // Execute the interface configuration command (void)execlp( pszCfgCmd, pszCfgCmd, NULL ); // The exec function returns only if unsuccessful WRMSG( HHC00136, "E", "execlp()", strerror( errno ) ); exit( 127 ); } /* Terminate TunTap on shutdown */ hdl_adsc("tuntap_term", tuntap_term, NULL); } // Populate some common fields ctlreq.iType = 1; TRACE(MSG(HHC00149,"I",request_name,ifc_fd[0],ifc_fd[1])); write( ifc_fd[0], &ctlreq, CTLREQ_SIZE ); return 0; } // End of function IFC_IOCtl()
/*-------------------------------------------------------------------*/ DLL_EXPORT int impl(int argc, char *argv[]) { char *cfgfile; /* -> Configuration filename */ char pathname[MAX_PATH]; /* work area for filenames */ #if defined ( OPTION_LOCK_CONFIG_FILE ) int fd_cfg = -1; /* fd for config file */ #if !defined ( _MSVC_ ) struct flock fl_cfg; /* file lock for conf file */ #endif #endif int c; /* Work area for getopt */ int arg_error = 0; /* 1=Invalid arguments */ char *msgbuf; /* */ int msgnum; /* */ int msgcnt; /* */ TID rctid; /* RC file thread identifier */ TID logcbtid; /* RC file thread identifier */ int rc; #if defined(EXTERNALGUI) int e_gui = FALSE; /* EXTERNALGUI parm */ #endif #if defined(OPTION_DYNAMIC_LOAD) #define MAX_DLL_TO_LOAD 50 char *dll_load[MAX_DLL_TO_LOAD]; /* Pointers to modnames */ int dll_count; /* index into array */ #endif /* Seed the pseudo-random number generator */ srand( time(NULL) ); /* Clear the system configuration block */ memset( &sysblk, 0, sizeof( SYSBLK ) ); VERIFY( MLOCK( &sysblk, sizeof( SYSBLK )) == 0); #if defined (_MSVC_) _setmaxstdio(2048); #endif /* Initialize EYE-CATCHERS for SYSBLK */ memset(&sysblk.blknam,SPACE,sizeof(sysblk.blknam)); memset(&sysblk.blkver,SPACE,sizeof(sysblk.blkver)); memset(&sysblk.blkend,SPACE,sizeof(sysblk.blkend)); sysblk.blkloc = swap_byte_U64((U64)((uintptr_t)&sysblk)); memcpy(sysblk.blknam,HDL_NAME_SYSBLK,strlen(HDL_NAME_SYSBLK)); memcpy(sysblk.blkver,HDL_VERS_SYSBLK,strlen(HDL_VERS_SYSBLK)); sysblk.blksiz = swap_byte_U32((U32)sizeof(SYSBLK)); { char buf[32]; MSGBUF( buf, "END%13.13s", HDL_NAME_SYSBLK ); memcpy(sysblk.blkend, buf, sizeof(sysblk.blkend)); } /* Initialize SETMODE and set user authority */ SETMODE(INIT); #if defined(OPTION_DYNAMIC_LOAD) for ( dll_count = 0; dll_count < MAX_DLL_TO_LOAD; dll_count++ ) dll_load[dll_count] = NULL; dll_count = -1; #endif SET_THREAD_NAME("impl"); /* Initialize 'hostinfo' BEFORE display_version is called */ init_hostinfo( &hostinfo ); #ifdef _MSVC_ /* Initialize sockets package */ VERIFY( socket_init() == 0 ); #endif /* Ensure hdl_shut is called in case of shutdown hdl_shut will ensure entries are only called once */ atexit(hdl_shut); if ( argc > 0 ) { int i,len; for (len = 0, i = 0; i < argc; i++ ) len += (int)strlen( (char *)argv[i] ) + 1; sysblk.hercules_cmdline = (char *)malloc( len ); strlcpy( sysblk.hercules_cmdline, argv[0], len ); for ( i = 1; i < argc; i++ ) { strlcat( sysblk.hercules_cmdline, " ", len ); strlcat( sysblk.hercules_cmdline, argv[i], len ); } } /* Set program name */ if ( argc > 0 ) { if ( strlen(argv[0]) == 0 ) { sysblk.hercules_pgmname = strdup("hercules"); sysblk.hercules_pgmpath = strdup(""); } else { char path[MAX_PATH]; #if defined( _MSVC_ ) GetModuleFileName( NULL, path, MAX_PATH ); #else strncpy(path,argv[0],sizeof(path)-1); #endif sysblk.hercules_pgmname = strdup(basename(path)); #if !defined( _MSVC_ ) strncpy(path,argv[0],sizeof(path)-1); #endif sysblk.hercules_pgmpath = strdup(dirname(path)); } } else { sysblk.hercules_pgmname = strdup("hercules"); sysblk.hercules_pgmpath = strdup(""); } #if defined( OPTION_CONFIG_SYMBOLS ) /* These were moved from console.c to make them available sooner */ set_symbol( "VERSION", VERSION); set_symbol( "BDATE", __DATE__ ); set_symbol( "BTIME", __TIME__ ); { char num_procs[64]; if ( hostinfo.num_packages != 0 && hostinfo.num_physical_cpu != 0 && hostinfo.num_logical_cpu != 0 ) { MSGBUF( num_procs, "LP=%d, Cores=%d, CPUs=%d", hostinfo.num_logical_cpu, hostinfo.num_physical_cpu, hostinfo.num_packages ); } else { if ( hostinfo.num_procs > 1 ) MSGBUF( num_procs, "MP=%d", hostinfo.num_procs ); else if ( hostinfo.num_procs == 1 ) strlcpy( num_procs, "UP", sizeof(num_procs) ); else strlcpy( num_procs, "", sizeof(num_procs) ); } set_symbol( "HOSTNAME", hostinfo.nodename ); set_symbol( "HOSTOS", hostinfo.sysname ); set_symbol( "HOSTOSREL", hostinfo.release ); set_symbol( "HOSTOSVER", hostinfo.version ); set_symbol( "HOSTARCH", hostinfo.machine ); set_symbol( "HOSTNUMCPUS", num_procs ); } set_symbol( "MODNAME", sysblk.hercules_pgmname ); set_symbol( "MODPATH", sysblk.hercules_pgmpath ); #endif // defined( OPTION_CONFIG_SYMBOLS ) sysblk.sysgroup = DEFAULT_SYSGROUP; sysblk.msglvl = DEFAULT_MLVL; /* Defaults to TERSE and DEVICES */ /* set default console port address */ sysblk.cnslport = strdup("3270"); /* set default tape autoinit value to OFF */ sysblk.noautoinit = TRUE; /* default for system dasd cache is on */ sysblk.dasdcache = TRUE; #if defined(OPTION_MSGCLR) || defined(OPTION_MSGHLD) /* set default error message display (emsg) */ sysblk.emsg = EMSG_ON; #endif #if defined( OPTION_SHUTDOWN_CONFIRMATION ) /* set default quit timeout value (also ssd) */ sysblk.quitmout = QUITTIME_PERIOD; #endif /* Default command separator to off (NULL) */ sysblk.cmdsep = NULL; #if defined(_FEATURE_SYSTEM_CONSOLE) /* set default for scpecho to TRUE */ sysblk.scpecho = TRUE; /* set fault for scpimply to FALSE */ sysblk.scpimply = FALSE; #endif /* set default system state to reset */ sysblk.sys_reset = TRUE; /* set default SHCMDOPT enabled */ sysblk.shcmdopt = SHCMDOPT_ENABLE + SHCMDOPT_DIAG8; /* Save process ID */ sysblk.hercules_pid = getpid(); /* Save thread ID of main program */ sysblk.impltid = thread_id(); /* Save TOD of when we were first IMPL'ed */ time( &sysblk.impltime ); /* Set to LPAR mode with LPAR 1, LPAR ID of 01, and CPUIDFMT 0 */ sysblk.lparmode = 1; /* LPARNUM 1 # LPAR ID 01 */ sysblk.lparnum = 1; /* ... */ sysblk.cpuidfmt = 0; /* CPUIDFMT 0 */ sysblk.operation_mode = om_mif; /* Default to MIF operaitons */ /* set default CPU identifier */ sysblk.cpumodel = 0x0586; sysblk.cpuversion = 0xFD; sysblk.cpuserial = 0x000001; sysblk.cpuid = createCpuId(sysblk.cpumodel, sysblk.cpuversion, sysblk.cpuserial, 0); /* set default Program Interrupt Trace to NONE */ sysblk.pgminttr = OS_NONE; sysblk.timerint = DEF_TOD_UPDATE_USECS; /* set default thread priorities */ sysblk.hercprio = DEFAULT_HERCPRIO; sysblk.todprio = DEFAULT_TOD_PRIO; sysblk.cpuprio = DEFAULT_CPU_PRIO; sysblk.devprio = DEFAULT_DEV_PRIO; sysblk.srvprio = DEFAULT_SRV_PRIO; /* Cap the default priorities at zero if setuid not available */ #if !defined( _MSVC_ ) #if !defined(NO_SETUID) if (sysblk.suid) #endif { if (sysblk.hercprio < 0) sysblk.hercprio = 0; if (sysblk.todprio < 0) sysblk.todprio = 0; if (sysblk.cpuprio < 0) sysblk.cpuprio = 0; if (sysblk.devprio < 0) sysblk.devprio = 0; if (sysblk.srvprio < 0) sysblk.srvprio = 0; } #endif /* set default console keep alive values */ sysblk.kaidle = KEEPALIVE_IDLE_TIME; sysblk.kaintv = KEEPALIVE_PROBE_INTERVAL; sysblk.kacnt = KEEPALIVE_PROBE_COUNT; #if defined(_FEATURE_ECPSVM) sysblk.ecpsvm.available = 0; sysblk.ecpsvm.level = 20; #endif #ifdef PANEL_REFRESH_RATE sysblk.panrate = PANEL_REFRESH_RATE_SLOW; #endif #if defined( OPTION_SHUTDOWN_CONFIRMATION ) /* Set the quitmout value */ sysblk.quitmout = QUITTIME_PERIOD; /* quit timeout value */ #endif #if defined(OPTION_SHARED_DEVICES) sysblk.shrdport = 0; #endif #ifdef OPTION_MSGHLD /* Set the default timeout value */ sysblk.keep_timeout_secs = 120; #endif #if defined(OPTION_CONFIG_SYMBOLS) && defined(OPTION_BUILTIN_SYMBOLS) /* setup defaults for BUILTIN symbols */ { char buf[8]; set_symbol("LPARNAME", str_lparname()); set_symbol("LPARNUM", "1"); set_symbol("CPUIDFMT", "0"); MSGBUF( buf, "%06X", sysblk.cpuserial ); set_symbol( "CPUSERIAL", buf ); MSGBUF( buf, "%04X", sysblk.cpumodel ); set_symbol( "CPUMODEL", buf ); } #endif /* defined(OPTION_CONFIG_SYMBOLS) && defined(OPTION_BUILTIN_SYMBOLS */ #if defined(_FEATURE_CMPSC_ENHANCEMENT_FACILITY) sysblk.zpbits = DEF_CMPSC_ZP_BITS; #endif /* Initialize locks, conditions, and attributes */ initialize_lock (&sysblk.config); initialize_lock (&sysblk.todlock); initialize_lock (&sysblk.mainlock); sysblk.mainowner = LOCK_OWNER_NONE; initialize_lock (&sysblk.intlock); initialize_lock (&sysblk.iointqlk); sysblk.intowner = LOCK_OWNER_NONE; initialize_lock (&sysblk.sigplock); initialize_lock (&sysblk.mntlock); initialize_lock (&sysblk.scrlock); initialize_lock (&sysblk.crwlock); initialize_lock (&sysblk.ioqlock); initialize_condition (&sysblk.ioqcond); #if defined(OPTION_CMDSER) initialize_lock (&sysblk.cmdlock); initialize_condition (&sysblk.cmdcond); #endif /*defined(OPTION_CMDSER)*/ #ifdef FEATURE_MESSAGE_SECURITY_ASSIST_EXTENSION_3 /* Initialize the wrapping key registers lock */ initialize_rwlock(&sysblk.wklock); #endif /* Initialize thread creation attributes so all of hercules can use them at any time when they need to create_thread */ initialize_detach_attr (DETACHED); initialize_join_attr (JOINABLE); initialize_condition (&sysblk.cpucond); { int i; for (i = 0; i < MAX_CPU_ENGINES; i++) initialize_lock (&sysblk.cpulock[i]); } initialize_condition (&sysblk.sync_cond); initialize_condition (&sysblk.sync_bc_cond); /* Copy length for regs */ sysblk.regs_copy_len = (int)((uintptr_t)&sysblk.dummyregs.regs_copy_end - (uintptr_t)&sysblk.dummyregs); /* Set the daemon_mode flag indicating whether we running in background/daemon mode or not (meaning both stdout/stderr are redirected to a non-tty device). Note that this flag needs to be set before logger_init gets called since the logger_logfile_write function relies on its setting. */ sysblk.daemon_mode = !isatty(STDERR_FILENO) && !isatty(STDOUT_FILENO); /* Initialize the logmsg pipe and associated logger thread. This causes all subsequent logmsg's to be redirected to the logger facility for handling by virtue of stdout/stderr being redirected to the logger facility. */ logger_init(); /* Setup the initial codepage */ set_codepage(NULL); /* Now display the version information again after logger_init has been called so that either the panel display thread or the external gui can see the version which was previously possibly only displayed to the actual physical screen the first time we did it further above (depending on whether we're running in daemon_mode (external gui mode) or not). This it the call that the panel thread or the one the external gui actually "sees". The first call further above wasn't seen by either since it was issued before logger_init was called and thus got written directly to the physical screen whereas this one will be inter- cepted and handled by the logger facility thereby allowing the panel thread or external gui to "see" it and thus display it. */ display_version (stdout, "Hercules", TRUE); #ifdef EXTERNALGUI if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0) { e_gui = TRUE; argc--; } #endif #if !defined(WIN32) && !defined(HAVE_STRERROR_R) strerror_r_init(); #endif #if defined(OPTION_SCSI_TAPE) initialize_lock ( &sysblk.stape_lock ); initialize_condition ( &sysblk.stape_getstat_cond ); InitializeListHead ( &sysblk.stape_mount_link ); InitializeListHead ( &sysblk.stape_status_link ); #endif /* defined(OPTION_SCSI_TAPE) */ /* Get name of configuration file or default to hercules.cnf */ if(!(cfgfile = getenv("HERCULES_CNF"))) cfgfile = "hercules.cnf"; /* Process the command line options */ { #define HERCULES_BASE_OPTS "hf:r:db:v" #define HERCULES_SYM_OPTS "" #define HERCULES_HDL_OPTS "" #if defined(OPTION_CONFIG_SYMBOLS) #undef HERCULES_SYM_OPTS #define HERCULES_SYM_OPTS "s:" #endif #if defined(OPTION_DYNAMIC_LOAD) #undef HERCULES_HDL_OPTS #define HERCULES_HDL_OPTS "p:l:" #endif #define HERCULES_OPTS_STRING HERCULES_BASE_OPTS HERCULES_SYM_OPTS HERCULES_HDL_OPTS #if defined(HAVE_GETOPT_LONG) static struct option longopts[] = { { "help", no_argument, NULL, 'h' }, { "config", required_argument, NULL, 'f' }, { "rcfile", required_argument, NULL, 'r' }, { "daemon", no_argument, NULL, 'd' }, { "herclogo", required_argument, NULL, 'b' }, { "verbose", no_argument, NULL, 'v' }, #if defined(OPTION_CONFIG_SYMBOLS) { "defsym", required_argument, NULL, 's' }, #endif #if defined(OPTION_DYNAMIC_LOAD) { "modpath", required_argument, NULL, 'p' }, { "ldmod", required_argument, NULL, 'l' }, #endif { NULL, 0, NULL, 0 } }; while ((c = getopt_long( argc, argv, HERCULES_OPTS_STRING, longopts, NULL )) != EOF) #else while ((c = getopt( argc, argv, HERCULES_OPTS_STRING )) != EOF) #endif { switch (c) { case 'h': arg_error = 1; break; case 'f': cfgfile = optarg; break; case 'r': rcname = optarg; break; #if defined(OPTION_CONFIG_SYMBOLS) case 's': { char *sym = NULL; char *value = NULL; char *strtok_str = NULL; if ( strlen( optarg ) >= 3 ) { sym = strtok_r( optarg, "=", &strtok_str); value = strtok_r( NULL, "=", &strtok_str); if ( sym != NULL && value != NULL ) { int j; for( j = 0; j < (int)strlen( sym ); j++ ) if ( islower( sym[j] ) ) { sym[j] = toupper( sym[j] ); } set_symbol(sym, value); } else WRMSG(HHC01419, "E" ); } else WRMSG(HHC01419, "E"); } break; #endif /* defined(OPTION_CONFIG_SYMBOLS) */ #if defined(OPTION_DYNAMIC_LOAD) case 'p': if(optarg) hdl_setpath(strdup(optarg), FALSE); break; case 'l': { char *dllname, *strtok_str = NULL; for(dllname = strtok_r(optarg,", ",&strtok_str); dllname; dllname = strtok_r(NULL,", ",&strtok_str)) { if (dll_count < MAX_DLL_TO_LOAD - 1) dll_load[++dll_count] = strdup(dllname); else { WRMSG(HHC01406, "W", MAX_DLL_TO_LOAD); break; } } } break; #endif /* defined(OPTION_DYNAMIC_LOAD) */ case 'b': sysblk.logofile = optarg; break; case 'v': sysblk.msglvl |= MLVL_VERBOSE; break; case 'd': sysblk.daemon_mode = 1; break; default: arg_error = 1; } /* end switch(c) */ } /* end while */ } /* end Process the command line options */ /* Treat filename None as special */ if(!strcasecmp(cfgfile,"None")) cfgfile = NULL; if (optind < argc) arg_error = 1; /* Terminate if invalid arguments were detected */ if (arg_error) { char pgm[MAX_PATH]; char* strtok_str = NULL; strncpy(pgm, sysblk.hercules_pgmname, sizeof(pgm)); /* Show them all of our command-line arguments... */ WRMSG (HHC01414, "S", ""); // (blank line) WRMSG (HHC01414, "S", ""); // (blank line) #if defined(OPTION_DYNAMIC_LOAD) // "Usage: %s [-f config-filename] [-d] [-b logo-filename] [-s sym=val]%s [> logfile]" WRMSG (HHC01407, "S", strtok_r(pgm,".",&strtok_str), " [-p dyn-load-dir] [[-l dynmod-to-load]...]"); #else WRMSG (HHC01407, "S", strtok_r(pgm,".", &strtok_str), ""); #endif /* defined(OPTION_DYNAMIC_LOAD) */ WRMSG (HHC01414, "S", ""); // (blank line) WRMSG (HHC01414, "S", ""); // (blank line) fflush(stderr); fflush(stdout); usleep(100000); return(1); } /* Initialize runtime opcode tables */ init_opcode_tables(); #if defined(OPTION_DYNAMIC_LOAD) /* Initialize the hercules dynamic loader */ hdl_main(); /* Load modules requested at startup */ if (dll_count >= 0) { int hl_err = FALSE; for ( dll_count = 0; dll_count < MAX_DLL_TO_LOAD; dll_count++ ) { if (dll_load[dll_count] != NULL) { if (hdl_load(dll_load[dll_count], HDL_LOAD_DEFAULT) != 0) { hl_err = TRUE; } free(dll_load[dll_count]); } else break; } if (hl_err) { usleep(10000); // give logger time to issue error message WRMSG(HHC01408, "S"); delayed_exit(-1); return(1); } } #endif /* defined(OPTION_DYNAMIC_LOAD) */ #ifdef EXTERNALGUI /* Set GUI flag if specified as final argument */ if (e_gui) { #if defined(OPTION_DYNAMIC_LOAD) if (hdl_load("dyngui",HDL_LOAD_DEFAULT) != 0) { usleep(10000); /* (give logger thread time to issue preceding HHC01516E message) */ WRMSG(HHC01409, "S"); delayed_exit(-1); return(1); } #endif /* defined(OPTION_DYNAMIC_LOAD) */ } #endif /*EXTERNALGUI*/ /* Register the SIGINT handler */ if ( signal (SIGINT, sigint_handler) == SIG_ERR ) { WRMSG(HHC01410, "S", "SIGINT", strerror(errno)); delayed_exit(-1); return(1); } /* Register the SIGTERM handler */ if ( signal (SIGTERM, sigterm_handler) == SIG_ERR ) { WRMSG(HHC01410, "S", "SIGTERM", strerror(errno)); delayed_exit(-1); return(1); } #if defined( _MSVC_ ) /* Register the Window console ctrl handlers */ if (!IsDebuggerPresent()) { if (!SetConsoleCtrlHandler( console_ctrl_handler, TRUE )) { WRMSG( HHC01410, "S", "Console-ctrl", strerror( errno )); delayed_exit(-1); return(1); } } #endif #if defined(HAVE_DECL_SIGPIPE) && HAVE_DECL_SIGPIPE /* Ignore the SIGPIPE signal, otherwise Hercules may terminate with Broken Pipe error if the printer driver writes to a closed pipe */ if ( signal (SIGPIPE, SIG_IGN) == SIG_ERR ) { WRMSG(HHC01411, "E", strerror(errno)); } #endif { int fds[2]; initialize_lock(&sysblk.cnslpipe_lock); initialize_lock(&sysblk.sockpipe_lock); sysblk.cnslpipe_flag=0; sysblk.sockpipe_flag=0; VERIFY( create_pipe(fds) >= 0 ); sysblk.cnslwpipe=fds[1]; sysblk.cnslrpipe=fds[0]; VERIFY( create_pipe(fds) >= 0 ); sysblk.sockwpipe=fds[1]; sysblk.sockrpipe=fds[0]; } #if !defined(NO_SIGABEND_HANDLER) { struct sigaction sa; sa.sa_sigaction = (void*)&sigabend_handler; #ifdef SA_NODEFER sa.sa_flags = SA_NODEFER; #else sa.sa_flags = 0; #endif if( sigaction(SIGILL, &sa, NULL) || sigaction(SIGFPE, &sa, NULL) || sigaction(SIGSEGV, &sa, NULL) || sigaction(SIGBUS, &sa, NULL) || sigaction(SIGUSR1, &sa, NULL) || sigaction(SIGUSR2, &sa, NULL) ) { WRMSG(HHC01410, "S", "SIGILL/FPE/SEGV/BUS/USR", strerror(errno)); delayed_exit(-1); return(1); } } #endif /*!defined(NO_SIGABEND_HANDLER)*/ if(cfgfile) { /* attempt to get lock on config file */ hostpath(pathname, cfgfile, sizeof(pathname)); #if defined( OPTION_LOCK_CONFIG_FILE ) /* Test that we can get a read the file */ if ( ( fd_cfg = HOPEN( pathname, O_RDONLY, S_IRUSR | S_IRGRP ) ) < 0 ) { if ( errno == EACCES ) { WRMSG( HHC01453, "S", cfgfile, strerror( errno ) ); delayed_exit(-1); return(1); } } else { if ( lseek(fd_cfg, 0L, 2) < 0 ) { if ( errno == EACCES ) { WRMSG( HHC01453, "S", cfgfile, strerror( errno ) ); delayed_exit(-1); return(1); } } close( fd_cfg ); } /* File was not lock, therefore we can proceed */ #endif // OPTION_LOCK_CONFIG_FILE } /* System initialisation time */ sysblk.todstart = hw_clock() << 8; #if !defined(NO_SIGABEND_HANDLER) /* Start the watchdog */ rc = create_thread (&sysblk.wdtid, DETACHED, watchdog_thread, NULL, "watchdog_thread"); if (rc) { WRMSG(HHC00102, "E", strerror(rc)); delayed_exit(-1); return(1); } #endif /*!defined(NO_SIGABEND_HANDLER)*/ if(log_callback) { // 'herclin' called us. IT'S in charge. Create its requested // logmsg intercept callback function and return back to it. rc = create_thread(&logcbtid,DETACHED, log_do_callback,NULL,"log_do_callback"); if (rc) WRMSG(HHC00102, "E", strerror(rc)); return(0); } hdl_adsc("release_config", release_config, NULL); /* Build system configuration */ if ( build_config (cfgfile) ) { delayed_exit(-1); return(1); } /* Start up the RC file processing thread */ rc = create_thread(&rctid,DETACHED, process_rc_file,NULL,"process_rc_file"); if (rc) WRMSG(HHC00102, "E", strerror(rc)); #if defined( OPTION_LOCK_CONFIG_FILE ) if(cfgfile) { if ( ( fd_cfg = HOPEN( pathname, O_RDONLY, S_IRUSR | S_IRGRP ) ) < 0 ) { WRMSG( HHC01432, "S", pathname, "open()", strerror( errno ) ); delayed_exit(-1); return(1); } else { #if defined( _MSVC_ ) if( ( rc = _locking( fd_cfg, _LK_NBRLCK, 1L ) ) < 0 ) { int rc = errno; WRMSG( HHC01454, "S", pathname, "_locking()", strerror( errno ) ); delayed_exit(-1); return(1); } #else fl_cfg.l_type = F_RDLCK; fl_cfg.l_whence = SEEK_SET; fl_cfg.l_start = 0; fl_cfg.l_len = 1; if ( fcntl(fd_cfg, F_SETLK, &fl_cfg) == -1 ) { if (errno == EACCES || errno == EAGAIN) { WRMSG( HHC01432, "S", pathname, "fcntl()", strerror( errno ) ); delayed_exit(-1); return(1); } } #endif } } #endif // OPTION_LOCK_CONFIG_FILE //--------------------------------------------------------------- // The below functions will not return until Hercules is shutdown //--------------------------------------------------------------- /* Activate the control panel */ if(!sysblk.daemon_mode) panel_display (); else { #if defined(OPTION_DYNAMIC_LOAD) if(daemon_task) daemon_task (); else #endif /* defined(OPTION_DYNAMIC_LOAD) */ { /* Tell RC file and HAO threads they may now proceed */ sysblk.panel_init = 1; /* Retrieve messages from logger and write to stderr */ while (1) if((msgcnt = log_read(&msgbuf, &msgnum, LOG_BLOCK))) if(isatty(STDERR_FILENO)) fwrite(msgbuf,msgcnt,1,stderr); } } // ----------------------------------------------------- // *** Hercules has been shutdown (PAST tense) *** // ----------------------------------------------------- #if defined( OPTION_LOCK_CONFIG_FILE ) if(cfgfile) close( fd_cfg ); // release config file lock #endif // OPTION_LOCK_CONFIG_FILE ASSERT( sysblk.shutdown ); // (why else would we be here?!) #ifdef _MSVC_ SetConsoleCtrlHandler(console_ctrl_handler, FALSE); socket_deinit(); #endif #if defined(OPTION_MSGCLR) || defined(OPTION_MSGHLD) if ( sysblk.emsg & EMSG_TEXT ) fprintf(stdout, HHC01412 ); else #endif fprintf(stdout, MSG(HHC01412, "I")); fflush(stdout); usleep(10000); return 0; } /* end function impl */