📄 statserv.c
字号:
} /* release dad */ yaz_log(LOG_DEBUG, "Releasing parent"); close(hand[1]); } else { iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset listener */ ++no_sessions; }#if YAZ_POSIX_THREADS if (control_block.threads) { pthread_t child_thread; pthread_create (&child_thread, 0, new_session, new_line); pthread_detach (child_thread); } else new_session(new_line);#elif YAZ_GNU_THREADS if (control_block.threads) { pth_attr_t attr; pth_t child_thread; attr = pth_attr_new (); pth_attr_set (attr, PTH_ATTR_JOINABLE, FALSE); pth_attr_set (attr, PTH_ATTR_STACK_SIZE, 32*1024); pth_attr_set (attr, PTH_ATTR_NAME, "session"); yaz_log (LOG_LOG, "pth_spawn begin"); child_thread = pth_spawn (attr, new_session, new_line); yaz_log (LOG_LOG, "pth_spawn finish"); pth_attr_destroy (attr); } else new_session(new_line);#else new_session(new_line);#endif } else if (event == EVENT_TIMEOUT) { yaz_log(LOG_LOG, "Shutting down listener."); iochan_destroy(h); } else { yaz_log(LOG_FATAL, "Bad event on listener."); iochan_destroy(h); }}static void *new_session (void *vp){ char *a; association *newas; IOCHAN new_chan; COMSTACK new_line = (COMSTACK) vp; unsigned cs_get_mask, cs_accept_mask, mask = ((new_line->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) | ((new_line->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0); if (mask) { cs_accept_mask = mask; /* accept didn't complete */ cs_get_mask = 0; } else { cs_accept_mask = 0; /* accept completed. */ cs_get_mask = mask = EVENT_INPUT; } if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session, mask))) { yaz_log(LOG_FATAL, "Failed to create iochan"); return 0; } if (!(newas = create_association(new_chan, new_line))) { yaz_log(LOG_FATAL, "Failed to create new assoc."); return 0; } newas->cs_accept_mask = cs_accept_mask; newas->cs_get_mask = cs_get_mask; iochan_setdata(new_chan, newas); iochan_settimeout(new_chan, 60);#if 1 a = cs_addrstr(new_line);#else a = 0;#endif yaz_log(LOG_LOG, "Starting session %d from %s", no_sessions, a ? a : "[Unknown]"); if (max_sessions && no_sessions == max_sessions) control_block.one_shot = 1; if (control_block.threads) { event_loop(&new_chan); } else { new_chan->next = pListener; pListener = new_chan; } return 0;}/* UNIX */#endifstatic void inetd_connection(int what){ COMSTACK line; IOCHAN chan; association *assoc; char *addr; if ((line = cs_createbysocket(0, tcpip_type, 0, what))) { if ((chan = iochan_create(cs_fileno(line), ir_session, EVENT_INPUT))) { if ((assoc = create_association(chan, line))) { iochan_setdata(chan, assoc); iochan_settimeout(chan, 60); addr = cs_addrstr(line); yaz_log(LOG_LOG, "Inetd association from %s", addr ? addr : "[UNKNOWN]"); assoc->cs_get_mask = EVENT_INPUT; } else { yaz_log(LOG_FATAL, "Failed to create association structure"); } chan->next = pListener; pListener = chan; } else { yaz_log(LOG_FATAL, "Failed to create iochan"); } } else { yaz_log(LOG_ERRNO|LOG_FATAL, "Failed to create comstack on socket 0"); }}/* * Set up a listening endpoint, and give it to the event-handler. */static int add_listener(char *where, int what){ COMSTACK l; void *ap; IOCHAN lst = NULL; const char *mode; if (control_block.dynamic) mode = "dynamic"; else if (control_block.threads) mode = "threaded"; else mode = "static"; yaz_log(LOG_LOG, "Adding %s %s listener on %s", mode, what == PROTO_SR ? "SR" : "Z3950", where); l = cs_create_host(where, 0, &ap); if (!l) { yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to listen on %s", where); return -1; } if (cs_bind(l, ap, CS_SERVER) < 0) { yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to bind to %s", where); cs_close (l); return -1; } if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT | EVENT_EXCEPT))) { yaz_log(LOG_FATAL|LOG_ERRNO, "Failed to create IOCHAN-type"); cs_close (l); return -1; } iochan_setdata(lst, l); /* Ensure our listener chain is setup properly */ lst->next = pListener; pListener = lst; return 0; /* OK */}#ifndef WIN32/* UNIX only (for windows we don't need to catch the signals) */static void catchchld(int num){ while (waitpid(-1, 0, WNOHANG) > 0) ; signal(SIGCHLD, catchchld);}#endifstatserv_options_block *statserv_getcontrol(void){ static statserv_options_block cb; memcpy(&cb, &control_block, sizeof(cb)); return &cb;}void statserv_setcontrol(statserv_options_block *block){ memcpy(&control_block, block, sizeof(*block));}static void statserv_reset(void){}int statserv_start(int argc, char **argv){ int ret;#ifdef WIN32 /* We need to initialize the thread list */ ThreadList_Initialize();/* WIN32 */#endif #ifdef WIN32 if ((me = strrchr (argv[0], '\\'))) me++; else me = argv[0];#else me = argv[0];#endif if (control_block.options_func(argc, argv)) return(1); if (control_block.bend_start) (*control_block.bend_start)(&control_block);#ifdef WIN32 yaz_log (LOG_LOG, "Starting server %s", me);#else/* UNIX */ if (control_block.inetd) inetd_connection(control_block.default_proto); else { yaz_log (LOG_LOG, "Starting server %s pid=%d", me, getpid());#if 0 sigset_t sigs_to_block; sigemptyset(&sigs_to_block); sigaddset (&sigs_to_block, SIGTERM); pthread_sigmask (SIG_BLOCK, &sigs_to_block, 0); /* missing... */#endif if (control_block.dynamic) signal(SIGCHLD, catchchld); } signal (SIGPIPE, SIG_IGN); signal (SIGTERM, sigterm); if (*control_block.setuid) { struct passwd *pw; if (!(pw = getpwnam(control_block.setuid))) { yaz_log(LOG_FATAL, "%s: Unknown user", control_block.setuid); return(1); } if (setuid(pw->pw_uid) < 0) { yaz_log(LOG_FATAL|LOG_ERRNO, "setuid"); exit(1); } }/* UNIX */#endif if ((pListener == NULL) && *control_block.default_listen) add_listener(control_block.default_listen, control_block.default_proto); if (pListener == NULL) ret = 1; else { yaz_log(LOG_LOG, "Entering event loop."); ret = event_loop(&pListener); } return ret;}int check_options(int argc, char **argv){ int ret = 0, r; char *arg; while ((ret = options("1a:iszSTl:v:u:c:w:t:k:d:D:", argv, argc, &arg)) != -2) { switch (ret) { case 0: if (add_listener(arg, control_block.default_proto)) return 1; /* failed to create listener */ break; case '1': control_block.one_shot = 1; control_block.dynamic = 0; break; case 'z': control_block.default_proto = PROTO_Z3950; break; case 's': fprintf (stderr, "%s: SR protocol no longer supported\n", me); exit (1); break; case 'S': control_block.dynamic = 0; break; case 'T':#if YAZ_POSIX_THREADS control_block.dynamic = 0; control_block.threads = 1;#elif YAZ_GNU_THREADS control_block.dynamic = 0; control_block.threads = 1;#else fprintf(stderr, "%s: Threaded mode not available.\n", me); return 1;#endif break; case 'l': strcpy(control_block.logfile, arg ? arg : ""); yaz_log_init(control_block.loglevel, me, control_block.logfile); break; case 'v': control_block.loglevel = yaz_log_mask_str(arg); yaz_log_init(control_block.loglevel, me, control_block.logfile); break; case 'a': strcpy(control_block.apdufile, arg ? arg : ""); break; case 'u': strcpy(control_block.setuid, arg ? arg : ""); break; case 'c': strcpy(control_block.configname, arg ? arg : ""); break; case 'd': strcpy(control_block.daemon_name, arg ? arg : ""); break; case 't': if (!arg || !(r = atoi(arg))) { fprintf(stderr, "%s: Specify positive timeout for -t.\n", me); return(1); } control_block.idle_timeout = r; break; case 'k': if (!arg || !(r = atoi(arg))) { fprintf(stderr, "%s: Specify positive size for -k.\n", me); return(1); } control_block.maxrecordsize = r * 1024; break; case 'i': control_block.inetd = 1; break; case 'w': if (chdir(arg)) { perror(arg); return 1; } break; case 'D': max_sessions = atoi(arg); break; default: fprintf(stderr, "Usage: %s [ -a <pdufile> -v <loglevel>" " -l <logfile> -u <user> -c <config> -t <minutes>" " -k <kilobytes> -d <daemon>" " -ziST1 -w <directory> <listender-addr>... ]\n", me); return 1; } } return 0;}#ifdef WIN32typedef struct _Args{ char **argv; int argc;} Args; static Args ArgDetails;/* name of the executable */#define SZAPPNAME "server"/* list of service dependencies - "dep1\0dep2\0\0" */#define SZDEPENDENCIES ""int statserv_main(int argc, char **argv, bend_initresult *(*bend_init)(bend_initrequest *r), void (*bend_close)(void *handle)){ statserv_options_block *cb = statserv_getcontrol(); cb->bend_init = bend_init; cb->bend_close = bend_close; statserv_setcontrol(cb); /* Lets setup the Arg structure */ ArgDetails.argc = argc; ArgDetails.argv = argv; /* Now setup the service with the service controller */ SetupService(argc, argv, &ArgDetails, SZAPPNAME, cb->service_name, /* internal service name */ cb->service_display_name, /* displayed name */ SZDEPENDENCIES); return 0;}int StartAppService(void *pHandle, int argc, char **argv){ /* Initializes the App */ return 1;}void RunAppService(void *pHandle){ Args *pArgs = (Args *)pHandle; /* Starts the app running */ statserv_start(pArgs->argc, pArgs->argv);}void StopAppService(void *pHandle){ /* Stops the app */ statserv_closedown(); statserv_reset();}/* WIN32 */#else/* UNIX */int statserv_main(int argc, char **argv, bend_initresult *(*bend_init)(bend_initrequest *r), void (*bend_close)(void *handle)){ int ret; statserv_options_block *cb = statserv_getcontrol(); cb->bend_init = bend_init; cb->bend_close = bend_close; statserv_setcontrol(cb); ret = statserv_start (argc, argv); statserv_closedown (); statserv_reset(); return ret;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -