📄 umd.cpp
字号:
// Copyright (C) 2000 Open Source Telecom Corporation.// // This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.// // This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// // You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.#include <config.h>#include <getopt.h>#include <lockfile.h>#include <realtime.h>#include <sched.h>#include <stdlib.h>#include <sys/mman.h>#include <sys/resource.h>#include <scheduler.h>#include <shell.h>#include <script.h>#include <dso.h>#include <module.h>#include <pwd.h>#include <cc++/file.h>#include <vocab.h>#include "server.h"#include "trunk.h"#include "session.h"keydata_t *keypaths, *keytimers, *keyldap, *keyscript, *keyaudio, *keythread, *keyphone;Thread *scheduler;Shell *sh;typedef struct{ char *key; char *data;} KEYDEFS;static KEYDEFS defthreads[] = {{"scheduling", "0"}, {"audio", "0"}, {"gateways", "1"}, {"service", "0"}, {NULL, NULL}};static KEYDEFS defpaths[] = {{"pidfile", "/var/lock/umd.pid"}, {"runfile", "/var/run/umd"}, {"ctrlfile", "/var/run/umdctrl"}, {"datafiles", "/var/ACS"}, {"schedule", "/etc/umd.sched"}, {"prompts", "/usr/share/aaprompts"}, {"scripts", "/usr/share/aascripts"}, {"libexec", "/usr/libexec/tgi"}, {"logpath", "/var/log/acs"}, {NULL, NULL}};static KEYDEFS defscript[] = {{"default", "default"}, {NULL, NULL}};static KEYDEFS defldap[] = {{"context", "o=DEFAULT, c=US"}, {"servers", "localhost"}, {NULL, NULL}};static KEYDEFS defaudio[] = {{"buffers", "16"}, {"frames", "2"}, {"min", "16"}, {"trim", "1"}, {"timer", "60"}, {"inputgain", "10"}, {"outputgain", "10"}, {NULL, NULL}};static KEYDEFS defphone[] = {{"prefix", "/dev/phone"}, {"lines", "1"}, {"first", "0"}, {"digittimer", "80"}, {"interdigittimer", "40"}, {NULL, NULL}};static void loadkeys(keydata_t *keys, KEYDEFS *defs){ while(defs->key) { if(!getkeyfirst(keys, defs->key)) setkeyvalue(keys, defs->key, defs->data); ++defs; }}static RETSIGTYPE final(int signo){ char *pidfile = getkeylast(keypaths, "pidfile"); signal(SIGSEGV, SIG_DFL); unlockmem();#ifdef HAVE_MODULES stopModules();#endif stopDriver();#ifdef HAVE_MODULES unload();#endif if(scheduler) { delete scheduler; scheduler = NULL; } if(sh) { delete sh; sh = NULL; } endScript(); unloadVocab(); if(pidfile) remove(pidfile); if(signo) syslog(LOG_INFO, "exiting; reason %d", signo); else syslog(LOG_INFO, "exiting"); remove(getkeyfirst(keypaths, "ctrlfile")); closelog(); _exit(signo);}void initial(int argc, char **argv){ static bool daemon = false; static bool usage = false; static bool test = false; static int pri = 0, svc = 0, pid; static int lines = 0; static int first = 0; static char *scr = NULL; struct passwd *pwd; char *ctrlfile; int uid, pool, stack; char *p; char pstr[11]; sigset_t sigs; char cwd[256]; char env[256]; char *cwp; static struct option long_options[] = { {"background", 0, 0, 'D'}, {"foreground", 0, 0, 'F'}, {"daemon", 0, 0, 'D'}, {"priority", 1, 0, 'p'}, {"lines", 1, 0, 'l'}, {"test", 0, 0, 't'}, {"help", 0, 0, 'h'}, {"debug", 0, 0, 'x'}, {0, 0, 0, 0} }; char *cp; int opt, opt_index; sigemptyset(&sigs); sigaddset(&sigs, SIGTERM); sigaddset(&sigs, SIGQUIT); sigaddset(&sigs, SIGINT); pthread_sigmask(SIG_BLOCK, &sigs, NULL); while(EOF != (opt = getopt_long(argc, argv, "DFhtp:l:x:f:", long_options, &opt_index))) switch(opt) { case 'x': _debug = atoi(optarg); break; case 't': if(!_debug) _debug = 5; test = true; break; case 'f': first = atoi(optarg); break; case 'l': lines = atoi(optarg); break; case 'p': pri = atoi(optarg); break; case 'D': daemon = true; break; case 'F': daemon = false; break; case 'h': default: usage = true; } if(optind < argc) scr = argv[optind++]; if(usage || optind < argc) { printf( "use: umd [-options] [script-override]\n" "The following options are available:\n\n" "-t, --test run in test mode from source tree\n" "-f, --first=n first line device to use\n" "-l, --lines=n enable only up to 'n' lines\n" "-p, --priority=n default process priority\n" "-F, --foreground execute in foreground\n" "-D, --daemon execute in daemon mode\n" ); exit(-1); } if(test) { getcwd(cwd, sizeof(cwd)); cwp = cwd + strlen(cwd); // DR next line commented to support gdb //if(!strchr(argv[0], '/') || argv[0][0] == '.') cwp = strrchr(cwd, '/'); strcpy(cwp, "/etc/"); setenv("CONFIG_KEYDATA", cwd, 1); } keypaths = getkeydata("/umd/paths"); keythread = getkeydata("/umd/threads"); keyldap = getkeydata("/umd/ldap"); keyscript = getkeydata("/umd/script"); keyaudio = getkeydata("/umd/audio"); keyphone = getkeydata("/umd/phone"); openlog("umd", LOG_PERROR | LOG_NDELAY, LOG_DAEMON); if(!keypaths || !keythread || !keyldap || !keyscript || !keyaudio || !keyphone) throw(keypaths); loadkeys(keypaths, defpaths); loadkeys(keyldap, defldap); loadkeys(keythread, defthreads); loadkeys(keyscript, defscript); loadkeys(keyaudio, defaudio); loadkeys(keyphone, defphone); if(test) { strcpy(cwp, "/etc/umd.sched"); setkeyvalue(keypaths, "schedule", cwd); strcpy(cwp, "/aascripts"); setkeyvalue(keypaths, "scripts", cwd); strcpy(cwp, "/aaprompts"); setkeyvalue(keypaths, "prompts", cwd); strcpy(cwp, "/utils"); setkeyvalue(keypaths, "libexec", cwd); p = getkeyfirst(keypaths, "lockfiles"); if(p) { p = strtok(p, " \t\n"); while(p) { while((pid = lockfile(p, "umd"))) { if(pid < 0) throw(pid); sleep(2); } p = strtok(NULL, " \t\n"); } } } File pidfile(getkeylast(keypaths, "pidfile"), FILE_OPEN_WRITEONLY, 0644); sprintf(pstr, "%010d", getpid()); write(pidfile, pstr); if(!pri) { cp = getkeylast(keythread, "pri"); if(!cp) cp = getkeylast(keythread, "priority"); if(cp) pri = atoi(cp); } if(!svc) svc = atoi(getkeylast(keythread, "service")); endkeydata(NULL); pwd = getpwnam("mail"); if(!pwd) throw(pwd); uid = pwd->pw_uid; setgid(pwd->pw_gid); p = getkeylast(keypaths, "datafiles"); mkdir(p, 0750); chdir(p); mkdir("tmp", 0770); if(!test) { p = getkeylast(keypaths, "prompts"); chmod(p, 0775); chown(p, 0, pwd->pw_gid); p = getkeylast(keypaths, "scripts"); chmod(p, 0700); } endpwent(); if(daemon) { closelog(); close(0); close(1); close(2); openlog("umd", LOG_NDELAY, LOG_DAEMON); pdetach(); } setenv("SERVER_PLATFORM", "phone", 1); setenv("SERVER_LIBEXEC", getkeylast(keypaths, "libexec"), 1); setenv("SERVER_SOFTWARE", "ACS", 1); setenv("SERVER_VERSION", "1.0", 1); setenv("SERVER_PROMPTS", getkeylast(keypaths, "prompts"), 1); setenv("SERVER_RUNTIME", getkeylast(keypaths, "datafiles"), 1); loadVocab(keypaths); ctrlfile = getkeyfirst(keypaths, "ctrlfile"); remove(ctrlfile); mkfifo(ctrlfile, 0600); pool = atoi(getkeyfirst(keythread, "gateways")); sh = new Shell(ctrlfile, uid, pool);#ifdef HAVE_MODULES load();#endif if(pri) { pri = getpriority(PRIO_PROCESS, 0) - pri -1; setpriority(PRIO_PROCESS, 0, pri); } p = getkeyfirst(keythread, "scheduler"); if(p) pri = atoi(p); else pri = 0; p = getkeyfirst(keythread, "stack"); if(p) stack = atoi(p); else stack = 0; scheduler = new Scheduler(getkeylast(keypaths, "schedule"), pri); new Script(getkeylast(keypaths, "scripts"), keyscript); if(!scheduler) throw(scheduler); if(!first) first = atoi(getkeylast(keyphone, "first")); if(!lines) lines = atoi(getkeylast(keyphone, "lines")); initDriver(scr, first, lines, svc); scheduler->Start();#ifdef HAVE_MODULES startModules();#endif signal(SIGTERM, final); signal(SIGQUIT, final); signal(SIGINT, final); signal(SIGABRT, final); pthread_sigmask(SIG_UNBLOCK, &sigs, NULL); syslog(LOG_INFO, "startup"); if(stack) { signal(SIGSEGV, final); if(lockmem(stack)) final(SIGSEGV); }}int main(int argc, char **argv){ int fd; unsigned bpos; char buf[128]; char *args[32]; int len; char *ctrlfile; Sessionmap *session; try { initial(argc, argv); } catch(keydata_t *p) { syslog(LOG_CRIT, "umd.conf: missing or incomplete"); exit(-1); } catch(Scheduler *sc) { syslog(LOG_CRIT, "umd.sched: missing or incomplete"); exit(-1); } catch(Script *scr) { syslog(LOG_CRIT, "script files missing"); exit(-1); } catch(Vocab *voc) { syslog(LOG_CRIT, "vocabulary load failed"); exit(-1); } catch(File *fp) { syslog(LOG_CRIT, "initialization file failure"); exit(-1); } catch(int card) { syslog(LOG_CRIT, "linux phone cards missing or failed"); exit(-1); } catch(...) { syslog(LOG_CRIT, "initialization failure"); exit(-1); } ctrlfile = getkeyfirst(keypaths, "ctrlfile"); fd = open(ctrlfile, O_RDWR); if(fd < 0) { syslog(LOG_CRIT, "%s: failed", ctrlfile); final(-1); } debug(4, "waiting on fifo <%s>", ctrlfile); session = getSessionHandler(); for(;;) { debug(6, "waiting for fifo input"); bpos = 0; while(bpos < sizeof(buf) - 1) { len = read(fd, buf + bpos, 1); if(len < 1) continue; if(buf[bpos] == '\n') break; ++bpos; } buf[bpos]=0; debug(4, "command received <%s>", buf); argc = 0; args[argc] = strtok(buf, " \t\n"); while(args[argc] && argc < 31) args[++argc] = strtok(NULL, " \t\n"); len = argc; while(len < 32) args[len++] = NULL; if(!stricmp(args[0], "down")) break; if(!stricmp(args[0], "compile")) { new Script(getkeylast(keypaths, "scripts"), keyscript); continue; } if(!stricmp(args[0], "exit")) session->exitTGI(atoi(args[1]), atoi(args[2])); if(!stricmp(args[0], "wait")) session->setTGI(atoi(args[1]), atoi(args[2])); if(!stricmp(args[0], "busy")) { len = 1; while(--argc) session->setBusy(atoi(args[len++])); } if(!stricmp(args[0], "idle")) { len = 1; while(--argc) session->setIdle(atoi(args[len++])); } if(!stricmp(args[0], "start")) session->callTrunk(atoi(args[1]), args[2]); if(!stricmp(args[0], "set")) session->setVariable(atoi(args[1]), args[2], args[3]); if(!stricmp(args[0], "put")) session->putSymbol(args[1], args[2]); if(!stricmp(args[0], "ring")) session->ringTrunk(atoi(args[1])); #ifdef HAVE_MODULES fifoModule(argc, args);#endif } final(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -