static int
shell_log_dump_entry(struct log *log, void *arg, void *dptr, uint16_t len)
{
    struct log_entry_hdr ueh;
    char data[128];
    int dlen;
    int rc;

    rc = log_read(log, dptr, &ueh, 0, sizeof(ueh));
    if (rc != sizeof(ueh)) {
        goto err;
    }

    dlen = min(len-sizeof(ueh), 128);

    rc = log_read(log, dptr, data, sizeof(ueh), dlen);
    if (rc < 0) {
        goto err;
    }
    data[rc] = 0;

    /* XXX: This is evil.  newlib printf does not like 64-bit
     * values, and this causes memory to be overwritten.  Cast to a
     * unsigned 32-bit value for now.
     */
    console_printf("[%lu] %s\n", (unsigned long) ueh.ue_ts, data);

    return (0);
err:
    return (rc);
}
Exemple #2
0
/*---------------------------------------------------------------------------*/
static void* hao_thread(void* dummy)
{
  char*  msgbuf  = NULL;
  int    msgidx  = -1;
  int    msgamt  = 0;
  char*  msgend  = NULL;
  char   svchar  = 0;
  int    bufamt  = 0;

  UNREFERENCED(dummy);

  logmsg(HHCAO001I, thread_id(), getpriority(PRIO_PROCESS,0), getpid());

  /* Wait for panel thread to engage */
  while (!sysblk.panel_init && !sysblk.shutdown)
    usleep( 10 * 1000 );

  /* Do until shutdown */
  while (!sysblk.shutdown && msgamt >= 0)
  {
    /* wait for message data */
    if ((msgamt = log_read(&msgbuf, &msgidx, LOG_BLOCK)) > 0 )
    {
      /* append to existing data */
      if (msgamt > (int)((sizeof(ao_msgbuf) - 1) - bufamt) )
          msgamt = (int)((sizeof(ao_msgbuf) - 1) - bufamt);
      strncpy( &ao_msgbuf[bufamt], msgbuf, msgamt );
      ao_msgbuf[bufamt += msgamt] = 0;
      msgbuf = ao_msgbuf;

      /* process only complete messages */
      while (NULL != (msgend = strchr(msgbuf,'\n')))
      {
        /* null terminate message */
        svchar = *(msgend+1);
        *(msgend+1) = 0;

        /* process message */
        hao_message(msgbuf);

        /* restore destroyed byte */
        *(msgend+1) = svchar;
        msgbuf = msgend+1;
      }

      /* shift message buffer */
      memmove( ao_msgbuf, msgbuf, bufamt -= (msgbuf - ao_msgbuf) );
    }
  }

  logmsg(HHCAO002I);
  return NULL;
}
Exemple #3
0
void *log_do_callback(void *dummy)
{
    char *msgbuf;
    int msgcnt = -1,msgnum;
    UNREFERENCED(dummy);
    while(msgcnt)
    {
        if((msgcnt = log_read(&msgbuf, &msgnum, LOG_BLOCK)))
        {
            log_callback(msgbuf,msgcnt);
        }
    }
    return(NULL);
}
Exemple #4
0
DLL_EXPORT int log_line(int linenumber)
{
    char *msgbuf[2] = {NULL, NULL}, *tmpbuf = NULL;
    int  msgidx[2] = { -1, -1 };
    int  msgcnt[2] = {0, 0};
    int  i;

    if(!linenumber++)
        return logger_currmsg;

    /* Find the last two blocks in the log */
    do {
        msgidx[0] = msgidx[1];
        msgbuf[0] = msgbuf[1];
        msgcnt[0] = msgcnt[1];
    } while((msgcnt[1] = log_read(&msgbuf[1], &msgidx[1], LOG_NOBLOCK)));

    for(i = 0; i < 2 && linenumber; i++)
        if(msgidx[i] != -1)
        {
            for(; linenumber > 0; linenumber--)
            {
                if(!(tmpbuf = (void *)memrchr(msgbuf[i],'\n',msgcnt[i])))
                    break;
                msgcnt[i] = (int)(tmpbuf - msgbuf[i]);
            }
            if(!linenumber)
                break;
        }

    while(i < 2 && tmpbuf && (*tmpbuf == '\r' || *tmpbuf == '\n'))
    {
        tmpbuf++;
        msgcnt[i]++;
    }

    return i ? msgcnt[i] + msgidx[0] : msgcnt[i];
}
Exemple #5
0
int base_get(struct base *base,
	     const char *key, unsigned key_sz,
	     char *buf, unsigned buf_sz)
{
	uint128_t key_hash = md5(key, key_sz);

	uint64_t log_remno;
	int hpos;
	int r = itree_get2(base->itree, key_hash, &log_remno, &hpos);
	if (r < 0) {
		return -1;
	}
	struct log *log = log_by_remno(base->logs, log_remno);
	/* TODO: get rid of the awful malloc */
	unsigned data_sz = log_buffer_size(log, hpos);
	char *data = malloc(data_sz);
	struct keyvalue kv;
	r = log_read(log, hpos, data, data_sz, &kv);
	if (r < 0) {
		free(data);
		return -2;
	}
	if (kv.value_sz > buf_sz) {
		free(data);
		return -3;
	}
	if (key_sz != kv.key_sz || memcmp(key, kv.key, key_sz) != 0) {
		log_error(base->db, "Congratulations! You just found a "
			  "collision! Apparently key %*s has the same md5 hash as %*s!",
			  key_sz, key,
			  kv.key_sz, kv.key);
		free(data);
		return -1;
	}
	memcpy(buf, kv.value, kv.value_sz);
	free(data);
	return kv.value_sz;
}
Exemple #6
0
void utox_friend_init(Tox *tox, uint32_t friend_number){
        int size;
        // get friend pointer
        FRIEND *f = &friend[friend_number];
        uint8_t name[TOX_MAX_NAME_LENGTH];

        // Set scroll position to bottom of window.
        f->msg.scroll = 1.0;

        // Get and set the public key for this friend number and set it.
        tox_friend_get_public_key(tox, friend_number, f->cid, 0);

        // Set the friend number we got from toxcore
        f->number = friend_number;

        // Get and set friend name and length
        size = tox_friend_get_name_size(tox, friend_number, 0);
        tox_friend_get_name(tox, friend_number, name, 0);
        // Set the name for utox as well
        friend_setname(f, name, size);

        // Get and set the status message
        size = tox_friend_get_status_message_size(tox, friend_number, 0);
        f->status_message = malloc(size);
        tox_friend_get_status_message(tox, friend_number, f->status_message, 0);
        f->status_length = size;

        // Get the hex version of this friends ID
        char_t cid[TOX_PUBLIC_KEY_SIZE * 2];
        cid_to_string(cid, f->cid);
        init_avatar(&f->avatar, cid, NULL, NULL);

        // Get the chat backlog
        log_read(tox, friend_number);

        // Load the meta data, if it exists.
        friend_meta_data_read(tox, friend_number);
}
Exemple #7
0
void cgibin_syslog(WEBBLK *webblk)
{
int     num_bytes;
int     logbuf_idx;
char   *logbuf_ptr;
char   *command;
char   *value;
int     autorefresh = 0;
int     refresh_interval = 5;
int     msgcount = 22;

    if ((command = cgi_variable(webblk,"command")))
    {
        panel_command(command);
        // Wait a bit before proceeding in case
        // the command issues a lot of messages
        usleep(50000);
    }

    if((value = cgi_variable(webblk,"msgcount")))
        msgcount = atoi(value);
    else
        if((value = cgi_cookie(webblk,"msgcount")))
            msgcount = atoi(value);

    if ((value = cgi_variable(webblk,"refresh_interval")))
        refresh_interval = atoi(value);

    if (cgi_variable(webblk,"autorefresh"))
        autorefresh = 1;
    else if (cgi_variable(webblk,"norefresh"))
        autorefresh = 0;
    else if (cgi_variable(webblk,"refresh"))
        autorefresh = 1;

    html_header(webblk);

    hprintf(webblk->sock,"<script language=\"JavaScript\">\n"
                          "<!--\n"
                          "document.cookie = \"msgcount=%d\";\n"
                          "//-->\n"
                          "</script>\n",
                          msgcount);

    hprintf(webblk->sock, "<H2>Hercules System Log</H2>\n");
    hprintf(webblk->sock, "<PRE>\n");

    // Get the index to our desired starting message...

    logbuf_idx = msgcount ? log_line( msgcount ) : -1;

    // Now read the logfile starting at that index. The return
    // value is the total #of bytes of messages data there is.

    if ( (num_bytes = log_read( &logbuf_ptr, &logbuf_idx, LOG_NOBLOCK )) > 0 )
    {
        // Copy the message data to a work buffer for processing.
        // This is to allow for the possibility, however remote,
        // that the logfile buffer actually wraps around and over-
        // lays the message data we were going to display (which
        // could happen if there's a sudden flood of messages)

        int   sav_bytes  =         num_bytes;
        char *wrk_bufptr = malloc( num_bytes );

        if ( wrk_bufptr ) strncpy( wrk_bufptr,  logbuf_ptr, num_bytes );
        else                       wrk_bufptr = logbuf_ptr;

        // We need to convert certain characters that might
        // possibly be erroneously interpretted as HTML code

#define  AMP_LT    "&lt;"       // (HTML code for '<')
#define  AMP_GT    "&gt;"       // (HTML code for '>')
#define  AMP_AMP   "&amp;"      // (HTML code for '&')

        while ( num_bytes-- )
        {
            switch ( *wrk_bufptr )
            {
            case '<':
                hwrite( webblk->sock, AMP_LT     , sizeof(AMP_LT) );
                break;
            case '>':
                hwrite( webblk->sock, AMP_GT     , sizeof(AMP_GT) );
                break;
            case '&':
                hwrite( webblk->sock, AMP_AMP    , sizeof(AMP_AMP));
                break;
            default:
                hwrite( webblk->sock, wrk_bufptr , 1              );
                break;
            }

            wrk_bufptr++;
        }

        // (free our work buffer if it's really ours)

        if ( ( wrk_bufptr -= sav_bytes ) != logbuf_ptr )
            free( wrk_bufptr );
    }

    hprintf(webblk->sock, "</PRE>\n");

    hprintf(webblk->sock, "<FORM method=post>Command:\n");
    hprintf(webblk->sock, "<INPUT type=text name=command size=80>\n");
    hprintf(webblk->sock, "<INPUT type=submit name=send value=\"Send\">\n");
    hprintf(webblk->sock, "<INPUT type=hidden name=%srefresh value=1>\n",autorefresh ? "auto" : "no");
    hprintf(webblk->sock, "<INPUT type=hidden name=refresh_interval value=%d>\n",refresh_interval);
    hprintf(webblk->sock, "<INPUT type=hidden name=msgcount value=%d>\n",msgcount);
    hprintf(webblk->sock, "</FORM>\n<BR>\n");

    hprintf(webblk->sock, "<A name=bottom>\n");

    hprintf(webblk->sock, "<FORM method=post>\n");
    if(!autorefresh)
    {
        hprintf(webblk->sock, "<INPUT type=submit value=\"Auto Refresh\" name=autorefresh>\n");
        hprintf(webblk->sock, "Refresh Interval: ");
        hprintf(webblk->sock, "<INPUT type=text name=\"refresh_interval\" size=2 value=%d>\n",
           refresh_interval);
    }
    else
    {
        hprintf(webblk->sock, "<INPUT type=submit name=norefresh value=\"Stop Refreshing\">\n");
        hprintf(webblk->sock, "<INPUT type=hidden name=refresh_interval value=%d>\n",refresh_interval);
        hprintf(webblk->sock, " Refresh Interval: %2d \n", refresh_interval);
    }
    hprintf(webblk->sock, "<INPUT type=hidden name=msgcount value=%d>\n",msgcount);
    hprintf(webblk->sock, "</FORM>\n");

    hprintf(webblk->sock, "<FORM method=post>\n");
    hprintf(webblk->sock, "Only show last ");
    hprintf(webblk->sock, "<INPUT type=text name=msgcount size=3 value=%d>",msgcount);
    hprintf(webblk->sock, " lines (zero for all loglines)\n");
    hprintf(webblk->sock, "<INPUT type=hidden name=%srefresh value=1>\n",autorefresh ? "auto" : "no");
    hprintf(webblk->sock, "<INPUT type=hidden name=refresh_interval value=%d>\n",refresh_interval);
    hprintf(webblk->sock, "</FORM>\n");

    if (autorefresh)
    {
        /* JavaScript to cause automatic page refresh */
        hprintf(webblk->sock, "<script language=\"JavaScript\">\n");
        hprintf(webblk->sock, "<!--\nsetTimeout('window.location.replace(\"%s"
               "?refresh_interval=%d"
               "&refresh=1"
               "&msgcount=%d"
               "\")', %d)\n",
               cgi_baseurl(webblk),
               refresh_interval,
               msgcount,
               refresh_interval*1000);
        hprintf(webblk->sock, "//-->\n</script>\n");
    }

    html_footer(webblk);

}
Exemple #8
0
/*---------------------------------------------------------------------------*/
static void* hao_thread(void* dummy)
{
  char*  msgbuf  = NULL;
  int    msgidx  = -1;
  int    msgamt  = 0;
  char*  msgend  = NULL;
  char   svchar  = 0;
  int    bufamt  = 0;

  UNREFERENCED(dummy);

  /* Do not start HAO if no logger is active 
   * the next hao command will restart the thread
   */
  if(!logger_status())
  {
    haotid = 0;
    return NULL;
  }

  WRMSG(HHC00100, "I", (u_long)thread_id(), getpriority(PRIO_PROCESS,0), "Hercules Automatic Operator");

  /* Wait for panel thread to engage */
  /* Do until shutdown */
  while(!sysblk.shutdown && msgamt >= 0)
  {
    /* wait for message data */
    msgamt = log_read(&msgbuf, &msgidx, LOG_BLOCK);
    if(msgamt > 0)
    {
      /* append to existing data */
      if(msgamt > (int)((sizeof(ao_msgbuf) - 1) - bufamt))
        msgamt = (int)((sizeof(ao_msgbuf) - 1) - bufamt);
      strncpy( &ao_msgbuf[bufamt], msgbuf, msgamt );
      ao_msgbuf[bufamt += msgamt] = 0;
      msgbuf = ao_msgbuf;

      /* process only complete messages */
      msgend = strchr(msgbuf,'\n');
      while(msgend)
      {
        /* null terminate message */
        svchar = *(msgend+1);
        *(msgend+1) = 0;

        /* process message */
        hao_message(msgbuf);

        /* restore destroyed byte */
        *(msgend+1) = svchar;
        msgbuf = msgend+1;
        msgend = strchr(msgbuf,'\n');
      }

      /* shift message buffer */
      memmove( ao_msgbuf, msgbuf, bufamt -= (msgbuf - ao_msgbuf) );
    }
  }

  WRMSG(HHC00101, "I", (u_long)thread_id(), getpriority(PRIO_PROCESS,0), "Hercules Automatic Operator");
  return NULL;
}
Exemple #9
0
static void logger_term(void *arg)
{
    char *lmsbuf = NULL;             /* xxx                       */
    int   lmsnum = -1;               /* xxx                       */
    int   lmscnt = -1;               /* xxx                       */
    char* term_msg = MSG(HHC02103, "I");

    UNREFERENCED(arg);

    log_wakeup(NULL);
    usleep(1000);

    /* Flush all pending logger o/p before redirecting?? */
    fflush(stdout);

    if(logger_active)
    {
        /* Redirect all output to stderr */
        dup2(STDERR_FILENO, STDOUT_FILENO);

        /* Tell logger thread we want it to exit */
        logger_active = 0;
        log_wakeup(NULL);
        usleep(1000);

        if ( logger_tid != 0 && !sysblk.shutdown )
        {
            sleep(2);
            /* Logger is now terminating */
            obtain_lock(&logger_lock);

            /* Wait for the logger to terminate */
            join_thread( logger_tid, NULL );
            detach_thread( logger_tid );

            release_lock(&logger_lock);

        }

        if ( fwrite("\n",1,1,stderr) ) {
            perror(QLINE "fwrite failure/HHC02102 ");
        }
        /* Read and display any msgs still remaining in the system log */
        lmsnum = log_line(-1);
        while((lmscnt = log_read(&lmsbuf, &lmsnum, LOG_BLOCK)))
        {
            char *p = NULL;
            char *strtok_str = NULL;

            lmsbuf[lmscnt-1] = '\0';

            p = strtok_r( lmsbuf, "\n", &strtok_str );
            while ( (p = strtok_r(NULL, "\n", &strtok_str ) ) != NULL )
            {
                char*   pLeft = p;
                int     nLeft = (int)strlen(p);

#if defined( OPTION_MSGCLR )
                /* Remove "<pnl,..." color string if it exists */
                if (1
                        && nLeft > 5
                        && strncasecmp( pLeft, "<pnl", 4 ) == 0
                        && (pLeft = memchr( pLeft+4, '>', nLeft-4 )) != NULL
                   )
                {
                    pLeft++;
                    nLeft -= (int)(pLeft - p);
                }
#endif // defined( OPTION_MSGCLR )
                if (nLeft)
                {
                    if ( fwrite(pLeft,nLeft,1,stderr) ) {
                        perror(QLINE "fwrite failure/HHC02102 ");
                    }
                    if ( fwrite("\n",1,1,stderr) ) {
                        perror(QLINE "fwrite failure/HHC02102 ");
                    }
                }
            }
        }
        if ( fwrite( term_msg, strlen(term_msg), 1, stderr ) ) {
            perror(QLINE "fwrite failure/HHC02102 ");
        }

        fflush(stderr);
    }
}
Exemple #10
0
static _Bool load_save(Tox *tox)
{
    {
        uint8_t path[512], *p;
        uint32_t size;

        p = path + datapath(path);
        strcpy((char*)p, "tox_save");

        void *data = file_raw((char*)path, &size);
        if(!data) {
            p = path + datapath_old(path);
            strcpy((char*)p, "tox_save");
            data = file_raw((char*)path, &size);
            if (!data) {
                data = file_raw("tox_save", &size);
                if(!data) {
                    return 0;
                }
            }
        }

        tox_load(tox, data, size);
        free(data);
    }

    friends = tox_count_friendlist(tox);

    uint32_t i = 0;
    while(i != friends) {
        int size;
        FRIEND *f = &friend[i];
        uint8_t name[TOX_MAX_NAME_LENGTH];

        f->msg.scroll = 1.0;

        tox_get_client_id(tox, i, f->cid);

        size = tox_get_name(tox, i, name);

        friend_setname(f, name, size);

        size = tox_get_status_message_size(tox, i);
        f->status_message = malloc(size);
        tox_get_status_message(tox, i, f->status_message, size);
        f->status_length = size;

        log_read(tox, i);

        i++;
    }

    self.name_length = tox_get_self_name(tox, self.name);
    self.statusmsg_length = tox_get_self_status_message_size(tox);
    self.statusmsg = malloc(self.statusmsg_length);
    tox_get_self_status_message(tox, self.statusmsg, self.statusmsg_length);
    self.status = tox_get_self_user_status(tox);


    return 1;
}
/**
 * Log encode entry
 * @param log structure, arg:struct passed locally, dataptr, len
 * @return 0 on success; non-zero on failure
 */
static int
log_nmgr_encode_entry(struct log *log, void *arg, void *dptr, uint16_t len)
{
    struct encode_off *encode_off = (struct encode_off *)arg;
    struct log_entry_hdr ueh;
    char data[128];
    int dlen;
    struct json_value jv;
    int rc;
    int rsp_len;

    rc = log_read(log, dptr, &ueh, 0, sizeof(ueh));
    if (rc != sizeof(ueh)) {
        rc = OS_ENOENT;
        goto err;
    }
    rc = OS_OK;

    /* Matching timestamps and indices for sending a log entry */
    if (ueh.ue_ts < encode_off->eo_ts   ||
        (ueh.ue_ts == encode_off->eo_ts &&
         ueh.ue_index <= encode_off->eo_index)) {
        goto err;
    }

    dlen = min(len-sizeof(ueh), 128);

    rc = log_read(log, dptr, data, sizeof(ueh), dlen);
    if (rc < 0) {
        rc = OS_ENOENT;
        goto err;
    }
    data[rc] = 0;

    rsp_len = encode_off->rsp_len;
    /* Calculating entry len */
    rsp_len += strlen(data);

    /* Pre calculating MAX length of the json string */
    rsp_len += (sizeof(STR(INT64_MAX))  + sizeof("{,ts:")    +
                sizeof(STR(UINT8_MAX))  + sizeof(",level:")  +
                sizeof(STR(UINT32_MAX)) + sizeof(",index:")  +
                sizeof(STR(UINT16_MAX)) + sizeof(",module:}"));

    if (rsp_len > NMGR_MAX_MTU) {
        rc = OS_ENOMEM;
        goto err;
    }

    json_encode_object_start(encode_off->eo_encoder);

    JSON_VALUE_STRINGN(&jv, data, rc);
    rc = json_encode_object_entry(encode_off->eo_encoder, "msg", &jv);
    if (rc) {
        goto err;
    }

    JSON_VALUE_INT(&jv, ueh.ue_ts);
    rc = json_encode_object_entry(encode_off->eo_encoder, "ts", &jv);
    if (rc) {
        goto err;
    }

    JSON_VALUE_UINT(&jv, ueh.ue_level);
    rc = json_encode_object_entry(encode_off->eo_encoder, "level", &jv);
    if (rc) {
        goto err;
    }

    JSON_VALUE_UINT(&jv, ueh.ue_index);
    rc = json_encode_object_entry(encode_off->eo_encoder, "index", &jv);
    if (rc) {
        goto err;
    }

    JSON_VALUE_UINT(&jv, ueh.ue_module);
    rc = json_encode_object_entry(encode_off->eo_encoder, "module", &jv);
    if (rc) {
        goto err;
    }

    json_encode_object_finish(encode_off->eo_encoder);
    encode_off->rsp_len += rsp_len;

    return (0);
err:
    return (rc);
}
Exemple #12
0
/*-------------------------------------------------------------------*/
DLL_EXPORT int impl(int argc, char *argv[])
{
    char   *cfgfile;                        /* -> Configuration filename */
    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 */

    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);

    set_codepage(NULL);

    /* Clear the system configuration block */
    memset (&sysblk, 0, sizeof(SYSBLK));

    /* Save thread ID of main program */
    sysblk.impltid = thread_id();

    /* Save TOD of when we were first IMPL'ed */
    time( &sysblk.impltime );

#ifdef OPTION_MSGHLD
    /* Set the default timeout value */
    sysblk.keep_timeout_secs = 120;
#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);

    /* 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();

    /* 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);

#if defined(OPTION_DYNAMIC_LOAD)
    /* Initialize the hercules dynamic loader */
    hdl_main();
#endif /* defined(OPTION_DYNAMIC_LOAD) */

#if defined(ENABLE_NLS)
    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, HERC_LOCALEDIR);
    textdomain(PACKAGE);
#endif

#ifdef EXTERNALGUI
    /* Set GUI flag if specified as final argument */
    if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0)
    {
#if defined(OPTION_DYNAMIC_LOAD)
        if (hdl_load("dyngui",HDL_LOAD_DEFAULT) != 0)
        {
            usleep(10000); /* (give logger thread time to issue
                               preceding HHCHD007E message) */
            logmsg(_("HHCIN008S DYNGUI.DLL load failed; Hercules terminated.\n"));
            delayed_exit(1);
        }
#endif /* defined(OPTION_DYNAMIC_LOAD) */
        argc--;
    }
#endif /*EXTERNALGUI*/

#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 */
    while ((c = getopt(argc, argv, "f:p:l:db:")) != EOF)
    {

        switch (c) {
        case 'f':
            cfgfile = optarg;
            break;
#if defined(OPTION_DYNAMIC_LOAD)
        case 'p':
            if(optarg)
                hdl_setpath(strdup(optarg));
            break;
        case 'l':
        {
            char *dllname, *strtok_str;
            for(dllname = strtok_r(optarg,", ",&strtok_str);
                    dllname;
                    dllname = strtok_r(NULL,", ",&strtok_str))
                hdl_load(dllname, HDL_LOAD_DEFAULT);
        }
        break;
#endif /* defined(OPTION_DYNAMIC_LOAD) */
        case 'b':
            sysblk.logofile=optarg;
            break;
        case 'd':
            sysblk.daemon_mode = 1;
            break;
        default:
            arg_error = 1;

        } /* end switch(c) */
    } /* end while */

    if (optind < argc)
        arg_error = 1;

    /* Terminate if invalid arguments were detected */
    if (arg_error)
    {
        logmsg("usage: %s [-f config-filename] [-d] [-b logo-filename]"
#if defined(OPTION_DYNAMIC_LOAD)
               " [-p dyn-load-dir] [[-l dynmod-to-load]...]"
#endif /* defined(OPTION_DYNAMIC_LOAD) */
               " [> logfile]\n",
               argv[0]);
        delayed_exit(1);
    }

    /* Register the SIGINT handler */
    if ( signal (SIGINT, sigint_handler) == SIG_ERR )
    {
        logmsg(_("HHCIN001S Cannot register SIGINT handler: %s\n"),
               strerror(errno));
        delayed_exit(1);
    }

    /* Register the SIGTERM handler */
    if ( signal (SIGTERM, sigterm_handler) == SIG_ERR )
    {
        logmsg(_("HHCIN009S Cannot register SIGTERM handler: %s\n"),
               strerror(errno));
        delayed_exit(1);
    }

#if defined( _MSVC_ )
    /* Register the Window console ctrl handlers */
    if (SetConsoleCtrlHandler(console_ctrl_handler, TRUE) == FALSE)
    {
        logmsg(_("HHCIN010S Cannot register ConsoleCtrl handler: %s\n"),
               strerror(errno));
        delayed_exit(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 )
    {
        logmsg(_("HHCIN002E Cannot suppress SIGPIPE signal: %s\n"),
               strerror(errno));
    }
#endif

#if defined( OPTION_WAKEUP_SELECT_VIA_PIPE )
    {
        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];
    }
#endif // defined( OPTION_WAKEUP_SELECT_VIA_PIPE )

#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) )
        {
            logmsg(_("HHCIN003S Cannot register SIGILL/FPE/SEGV/BUS/USR "
                     "handler: %s\n"),
                   strerror(errno));
            delayed_exit(1);
        }
    }
#endif /*!defined(NO_SIGABEND_HANDLER)*/

    /* Build system configuration */
    build_config (cfgfile);

    /* System initialisation time */
    sysblk.todstart = hw_clock() << 8;

#ifdef OPTION_MIPS_COUNTING
    /* Initialize "maxrates" command reporting intervals */
    curr_int_start_time = time( NULL );
    prev_int_start_time = curr_int_start_time;
#endif

#if !defined(NO_SIGABEND_HANDLER)
    /* Start the watchdog */
    if ( create_thread (&sysblk.wdtid, DETACHED,
                        watchdog_thread, NULL, "watchdog_thread") )
    {
        logmsg(_("HHCIN004S Cannot create watchdog thread: %s\n"),
               strerror(errno));
        delayed_exit(1);
    }
#endif /*!defined(NO_SIGABEND_HANDLER)*/

#ifdef OPTION_SHARED_DEVICES
    /* Start the shared server */
    if (sysblk.shrdport)
        if ( create_thread (&sysblk.shrdtid, DETACHED,
                            shared_server, NULL, "shared_server") )
        {
            logmsg(_("HHCIN006S Cannot create shared_server thread: %s\n"),
                   strerror(errno));
            delayed_exit(1);
        }

    /* Retry pending connections */
    {
        DEVBLK *dev;
        TID     tid;

        for (dev = sysblk.firstdev; dev != NULL; dev = dev->nextdev)
            if (dev->connecting)
                if ( create_thread (&tid, DETACHED,
                                    *dev->hnd->init, dev, "device connecting thread")
                   )
                {
                    logmsg(_("HHCIN007S Cannot create %4.4X connection thread: %s\n"),
                           dev->devnum, strerror(errno));
                    delayed_exit(1);
                }
    }
#endif

    /* Start up the RC file processing thread */
    create_thread(&rctid,DETACHED,
                  process_rc_file,NULL,"process_rc_file");

    if(log_callback)
    {
        // 'herclin' called us. IT'S in charge. Create its requested
        // logmsg intercept callback function and return back to it.
        create_thread(&logcbtid,DETACHED,
                      log_do_callback,NULL,"log_do_callback");
        return(0);
    }

    //---------------------------------------------------------------
    // 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) ***
    //  -----------------------------------------------------

    ASSERT( sysblk.shutdown );  // (why else would we be here?!)

#ifdef _MSVC_
    SetConsoleCtrlHandler(console_ctrl_handler, FALSE);
    socket_deinit();
#endif
#ifdef DEBUG
    fprintf(stdout, _("IMPL EXIT\n"));
#endif
    fprintf(stdout, _("HHCIN099I Hercules terminated\n"));
    fflush(stdout);
    usleep(10000);
    return 0;
} /* end function main */
Exemple #13
0
/*-------------------------------------------------------------------*/
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 */
/**
 * Log encode entry
 * @param log structure, arg:struct passed locally, dataptr, len
 * @return 0 on success; non-zero on failure
 */
static int
log_nmgr_encode_entry(struct log *log, void *arg, void *dptr, uint16_t len)
{
    struct encode_off *encode_off = (struct encode_off *)arg;
    struct log_entry_hdr ueh;
    char data[128];
    int dlen;
    int rc;
    int rsp_len;
    CborError g_err = CborNoError;
    CborEncoder *penc = encode_off->eo_encoder;
    CborEncoder rsp;
    struct CborCntWriter cnt_writer;
    CborEncoder cnt_encoder;

    rc = log_read(log, dptr, &ueh, 0, sizeof(ueh));
    if (rc != sizeof(ueh)) {
        rc = OS_ENOENT;
        goto err;
    }
    rc = OS_OK;

    /* Matching timestamps and indices for sending a log entry */
    if (ueh.ue_ts < encode_off->eo_ts   ||
        (ueh.ue_ts == encode_off->eo_ts &&
         ueh.ue_index <= encode_off->eo_index)) {
        goto err;
    }

    dlen = min(len-sizeof(ueh), 128);

    rc = log_read(log, dptr, data, sizeof(ueh), dlen);
    if (rc < 0) {
        rc = OS_ENOENT;
        goto err;
    }
    data[rc] = 0;

    /*calculate whether this would fit */
    /* create a counting encoder for cbor */
    cbor_cnt_writer_init(&cnt_writer);
    cbor_encoder_init(&cnt_encoder, &cnt_writer.enc, 0);

    /* NOTE This code should exactly match what is below */
    g_err |= cbor_encoder_create_map(&cnt_encoder, &rsp, CborIndefiniteLength);
    g_err |= cbor_encode_text_stringz(&rsp, "msg");
    g_err |= cbor_encode_text_stringz(&rsp, data);
    g_err |= cbor_encode_text_stringz(&rsp, "ts");
    g_err |= cbor_encode_int(&rsp, ueh.ue_ts);
    g_err |= cbor_encode_text_stringz(&rsp, "level");
    g_err |= cbor_encode_uint(&rsp, ueh.ue_level);
    g_err |= cbor_encode_text_stringz(&rsp, "index");
    g_err |= cbor_encode_uint(&rsp,  ueh.ue_index);
    g_err |= cbor_encode_text_stringz(&rsp, "module");
    g_err |= cbor_encode_uint(&rsp,  ueh.ue_module);
    g_err |= cbor_encoder_close_container(&cnt_encoder, &rsp);
    rsp_len = encode_off->rsp_len;
    rsp_len += cbor_encode_bytes_written(&cnt_encoder);
    if (rsp_len > 400) {
        rc = OS_ENOMEM;
        goto err;
    }
    encode_off->rsp_len = rsp_len;

    g_err |= cbor_encoder_create_map(penc, &rsp, CborIndefiniteLength);
    g_err |= cbor_encode_text_stringz(&rsp, "msg");
    g_err |= cbor_encode_text_stringz(&rsp, data);
    g_err |= cbor_encode_text_stringz(&rsp, "ts");
    g_err |= cbor_encode_int(&rsp, ueh.ue_ts);
    g_err |= cbor_encode_text_stringz(&rsp, "level");
    g_err |= cbor_encode_uint(&rsp, ueh.ue_level);
    g_err |= cbor_encode_text_stringz(&rsp, "index");
    g_err |= cbor_encode_uint(&rsp,  ueh.ue_index);
    g_err |= cbor_encode_text_stringz(&rsp, "module");
    g_err |= cbor_encode_uint(&rsp,  ueh.ue_module);
    g_err |= cbor_encoder_close_container(penc, &rsp);

    if (g_err) {
        return MGMT_ERR_ENOMEM;
    }
    return (0);
err:
    return (rc);
}