Getty.c++
上传用户:weiyuanprp
上传日期:2020-05-20
资源大小:1169k
文件大小:6k
源码类别:

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: Getty.c++,v 1.5 2008/04/26 22:34:28 faxguy Exp $ */
  2. /*
  3.  * Copyright (c) 1990-1996 Sam Leffler
  4.  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
  5.  * HylaFAX is a trademark of Silicon Graphics
  6.  *
  7.  * Permission to use, copy, modify, distribute, and sell this software and 
  8.  * its documentation for any purpose is hereby granted without fee, provided
  9.  * that (i) the above copyright notices and this permission notice appear in
  10.  * all copies of the software and related documentation, and (ii) the names of
  11.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  12.  * publicity relating to the software without the specific, prior written
  13.  * permission of Sam Leffler and Silicon Graphics.
  14.  * 
  15.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  16.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  17.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  18.  * 
  19.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  20.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  21.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  22.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  23.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  24.  * OF THIS SOFTWARE.
  25.  */
  26. #include "Getty.h"
  27. #include "UUCPLock.h"
  28. #include <termios.h>
  29. #include <sys/param.h>
  30. #include "Sys.h"
  31. /*
  32.  * FAX Server Getty Support Base Class.
  33.  */
  34. Getty::Getty(const char* p, const fxStr& l, const fxStr& s)
  35.     : getty(p)
  36.     , line(l)
  37.     , speed(s)
  38.     , tzVar("TZ")
  39.     , langVar("LANG")
  40. {
  41.     pid = 0;
  42.     argv[0] = NULL;
  43.     argv[1] = NULL;
  44. }
  45. Getty::~Getty()
  46. {
  47. }
  48. pid_t Getty::getPID() const { return pid; }
  49. void Getty::setPID(pid_t p) { pid = p; }
  50. const char* Getty::getLine() const { return line; }
  51. static void
  52. sigHUP(int)
  53. {
  54.     Sys::close(STDIN_FILENO);
  55.     Sys::close(STDOUT_FILENO);
  56.     Sys::close(STDERR_FILENO);
  57.     sleep(5);
  58.     _exit(1);
  59. }
  60. /*
  61.  * Parse the getty argument string and
  62.  * substitute runtime parameters:
  63.  *
  64.  *    %l tty device name
  65.  *    %s current baud rate
  66.  *
  67.  * The resultant argv array is used to
  68.  * exec getty below.
  69.  */
  70. void
  71. Getty::setupArgv(const char* args, const CallID& callid)
  72. {
  73.     argbuf = args;
  74.     u_int l;
  75.     /*
  76.      * Substitute escape sequences.
  77.      */
  78.     for (l = 0; l < argbuf.length();) {
  79. l = argbuf.next(l, '%');
  80. if (l >= argbuf.length()-1)
  81.     break;
  82. switch (argbuf[l+1]) {
  83. case 'l': // %l = tty device name
  84.     argbuf.remove(l,2);
  85.     argbuf.insert(line, l);
  86.     l += line.length(); // avoid loops
  87.     break;
  88. case 's': // %s = tty speed
  89.     argbuf.remove(l,2);
  90.     argbuf.insert(speed, l);
  91.     l += speed.length(); // avoid loops
  92.     break;
  93. case 'a': // undocumented backwards compatibility, CIDName
  94.     argbuf.remove(l-1,3);
  95.     if (callid.size() > 1) {
  96. argbuf.insert(callid.id(1), l);
  97. l += callid.length(1);
  98.     }
  99.     break;
  100. case 'u': // undocumented backwards compatibility, CIDNumber
  101.     argbuf.remove(l-1,3);
  102.     if (callid.size()) {
  103. argbuf.insert(callid.id(0), l);
  104. l += callid.length(0);
  105.     }
  106.     break;            
  107. case '1': case '2': case '3': case '4': case '5': 
  108. case '6': case '7': case '8': case '9':
  109.     {
  110. u_int id = argbuf[l+1] - 0x31;
  111. argbuf.remove(l,2);
  112. if (id < callid.size()) {
  113.     argbuf.insert(callid.id(id), l);
  114.     l += callid.length(id);
  115. }
  116.     }
  117.     break;
  118. case '%': // %% = %
  119.     argbuf.remove(l,1);
  120.     break;
  121. }
  122.     }
  123.     /*
  124.      * Crack argument string and setup argv.
  125.      */
  126.     argv[0] = &getty[getty.nextR(getty.length(), '/')];
  127.     u_int nargs = 1;
  128.     for (l = 0; l < argbuf.length() && nargs < GETTY_MAXARGS-1;) {
  129. l = argbuf.skip(l, " t");
  130. u_int token = l;
  131. l = argbuf.next(l, " t");
  132. if (l > token) {
  133.     if (l < argbuf.length())
  134. argbuf[l++] = ''; // null terminate argument
  135.     argv[nargs++] = &argbuf[token];
  136. }
  137.     }
  138.     argv[nargs] = NULL;
  139. }
  140. fxStr
  141. Getty::getCmdLine() const
  142. {
  143.     fxStr s(getty);
  144.     for (u_int i = 1; argv[i] != NULL; i++) {
  145. s.append(' ');
  146. s.append(argv[i]);
  147.     }
  148.     return (s);
  149. }
  150. void
  151. Getty::addEnvVar(int& envc, char* env[], fxStr& var)
  152. {
  153.     const char* val = getenv(var);
  154.     if (val) {
  155.         var.append(fxStr::format("=%s", val));
  156.         const char* v = var;
  157.         env[envc++] = (char*)v;
  158.     }
  159. }
  160. /*
  161.  * Setup a getty session and if successful exec the
  162.  * getty program.  Note that this is always run in
  163.  * the child.
  164.  */
  165. void
  166. Getty::run(int fd, bool parentIsInit)
  167. {
  168.     if (Sys::chdir(_PATH_DEV) < 0)
  169. fatal("chdir: %m");
  170.     /*
  171.      * Reset signals known to be handled
  172.      * by the current process (XXX).
  173.      */
  174.     signal(SIGTERM, fxSIGHANDLER(SIG_DFL));
  175.     signal(SIGHUP, fxSIGHANDLER(sigHUP));
  176.     /*
  177.      * After the session is properly setup, the
  178.      * stdio streams should be hooked to the tty
  179.      * and the modem descriptor should be closed.
  180.      */
  181.     setupSession(fd);
  182.     /*
  183.      * If this getty is not being started from init
  184.      * then pass a restricted environment.  Otherwise
  185.      * just pass everything through.
  186.      */
  187.     if (!parentIsInit) {
  188.         char* env[10];
  189.         int envc = 0;
  190.         addEnvVar(envc, env, tzVar); // timezone
  191.         addEnvVar(envc, env, langVar); // for locale
  192.         env[envc] = NULL;
  193.         Sys::execve(getty, argv, env);
  194.     } else
  195.         Sys::execv(getty, argv);
  196.     _exit(127);
  197. }
  198. /*
  199.  * Setup descriptors for stdout, and stderr.
  200.  */
  201. void
  202. Getty::setupSession(int fd)
  203. {
  204.     struct stat sb;
  205.     Sys::fstat(fd, sb);
  206. #if HAS_FCHOWN
  207.     int ignore = fchown(fd, 0, sb.st_gid);
  208. #else
  209.     Sys::chown(getLine(), 0, sb.st_gid);
  210. #endif
  211. #if HAS_FCHMOD
  212.     fchmod(fd, 0622);
  213. #else
  214.     Sys::chmod(getLine(), 0622);
  215. #endif
  216.     if (dup2(fd, STDOUT_FILENO) < 0)
  217. fatal("Unable to dup stdin to stdout: %m");
  218.     if (dup2(fd, STDERR_FILENO) < 0)
  219. fatal("Unable to dup stdin to stderr: %m");
  220. }
  221. bool
  222. Getty::wait(int& status, bool block)
  223. {
  224.     return (Sys::waitpid(pid, status, block ? 0 : WNOHANG) == pid);
  225. }
  226. void
  227. Getty::hangup()
  228. {
  229.     // NB: this is executed in the parent
  230.     fxStr device = fxStr::format("%s" | line, _PATH_DEV);
  231.     Sys::chown(device, UUCPLock::getUUCPUid(), UUCPLock::getUUCPGid());
  232.     Sys::chmod(device, 0600); // reset protection
  233. }
  234. extern void vlogError(const char* fmt, va_list ap);
  235. void
  236. Getty::fatal(const char* fmt ...)
  237. {
  238.     va_list ap;
  239.     va_start(ap, fmt);
  240.     vlogError(fmt, ap);
  241.     hangup();
  242.     va_end(ap);
  243. }