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

传真(Fax)编程

开发平台:

C/C++

  1. /* $Id: GettySysV.c++,v 1.1.1.1 2005/11/11 21:32:02 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 "config.h"
  27. #include <limits.h>
  28. #include <stddef.h>
  29. #include <termios.h>
  30. #include <sys/ioctl.h>
  31. extern "C" {
  32. #if HAS_UTMPX
  33. #if !HAS_EXIT_STATUS
  34. /* workaround SVR4.0.3 header braindamage */
  35. struct exit_status {
  36. short e_termination;    /* Process termination status */
  37. short e_exit;           /* Process exit status */
  38. };
  39. #endif /* !HAS_EXIT_STATUS */
  40. #define __USE_GNU
  41. #include <utmpx.h>
  42. #undef __USE_GNU
  43. #define utmp          utmpx
  44. #undef  ut_time
  45. #ifdef __linux__
  46. #ifdef __GLIBC__
  47. #define ut_time       ut_tv.tv_sec
  48. #endif
  49. #else
  50. #define ut_time       ut_xtime
  51. #endif
  52. #define getutent      getutxent
  53. #define getutid       getutxid
  54. #define getutline     getutxline
  55. #define pututline     pututxline
  56. #define setutent      setutxent
  57. #define endutent      endutxent
  58. #else /* HAS_UTMPX */
  59. #include <utmp.h>
  60. #endif
  61. }
  62. #include "Sys.h"
  63. #include "GettySysV.h"
  64. /*
  65.  * FAX Server System V Getty&co. Support.
  66.  */
  67. /*
  68.  * System V subprocess support; used by getty-style processes.
  69.  */
  70. SysVSubProc::SysVSubProc(const char* path, const fxStr& l, const fxStr& s) : Getty(path,l,s)
  71. {
  72. }
  73. SysVSubProc::~SysVSubProc()
  74. {
  75. }
  76. /*
  77.  * ``Open'' the device and setup the initial tty state
  78.  * so that the normal stdio routines can be used.
  79.  */
  80. void
  81. SysVSubProc::setupSession(int modemFd)
  82. {
  83.     int fd;
  84.     /*
  85.      * Close everything down except the modem so
  86.      * that the remote side doesn't get hung up on.
  87.      */
  88.     for (fd = Sys::getOpenMax()-1; fd >= 0; fd--)
  89. if (fd != modemFd)
  90.     Sys::close(fd);
  91.     fclose(stdin);
  92.     fd = Sys::open(getLine(), O_RDWR|O_NONBLOCK|O_NOCTTY);
  93.     if (fd != STDIN_FILENO)
  94. fatal("Can not setup "%s" as stdin", getLine());
  95.     if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) &~ O_NONBLOCK))
  96. fatal("Can not reset O_NONBLOCK: %m");
  97.     Sys::close(modemFd); // done with this, pitch it
  98.     Getty::setupSession(fd);
  99. }
  100. /*
  101.  * System V getty/login-specific subprocess support.
  102.  */
  103. SysVGetty::SysVGetty(const char* path, const fxStr& l, const fxStr& s) : SysVSubProc(path,l,s)
  104. {
  105. }
  106. SysVGetty::~SysVGetty()
  107. {
  108. }
  109. /*
  110.  * ``Open'' the device and setup the initial tty state
  111.  * so that the normal stdio routines can be used.
  112.  */
  113. void
  114. SysVGetty::setupSession(int modemFd)
  115. {
  116.     int fd;
  117.     /*
  118.      * Close everything down except the modem so
  119.      * that the remote side doesn't get hung up on.
  120.      */
  121.     for (fd = Sys::getOpenMax()-1; fd >= 0; fd--)
  122.         if (fd != modemFd)
  123.             Sys::close(fd);
  124.     fclose(stdin);
  125.     /*
  126.      * Now make the line be the controlling tty
  127.      * and create a new process group/session for
  128.      * the login process that follows.
  129.      */
  130.     setsid();
  131. #ifndef sco
  132.     fd = Sys::open(getLine(), O_RDWR|O_NONBLOCK);
  133. #else
  134.     // NB: workaround kernel bug
  135.     fd = Sys::open(getLine(), O_RDWR|O_NONBLOCK|O_NOCTTY);
  136. #endif
  137.     if (fd != STDIN_FILENO)
  138. fatal("Can not setup "%s" as stdin", getLine());
  139.     if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) &~ O_NONBLOCK))
  140. fatal("Can not reset O_NONBLOCK: %m");
  141.     Sys::close(modemFd); // done with this, pitch it
  142.     /*
  143.      * Turn off CLOCAL so that SIGHUP is sent on modem disconnect.
  144.      */
  145.     struct termios term;
  146.     if (tcgetattr(fd, &term) == 0) {
  147. term.c_cflag &= ~CLOCAL;
  148. tcsetattr(fd, TCSAFLUSH, &term);
  149.     }
  150. #ifdef TIOCSSOFTCAR
  151.     /* turn the Solaris 2 soft carrier "feature" off */
  152.     { int off = 0; ioctl(fd, TIOCSSOFTCAR, &off); }
  153. #endif
  154.     Getty::setupSession(fd);
  155.     loginAccount();
  156. }
  157. void
  158. SysVGetty::writeWtmp(utmp* ut)
  159. {
  160.     // append record of login to wtmp file
  161. #if HAS_UTMPX
  162.     updwtmpx(_PATH_WTMPX, ut);
  163. #else
  164.     int fd = Sys::open(_PATH_WTMP, O_WRONLY|O_APPEND);
  165.     if (fd >= 0) {
  166. Sys::write(fd, (char *)ut, sizeof (*ut));
  167. Sys::close(fd);
  168.     }
  169. #endif
  170. }
  171. /*
  172.  * Record the login session.
  173.  */
  174. void
  175. SysVGetty::loginAccount()
  176. {
  177.     static utmp ut; // zero unset fields
  178.     ut.ut_pid = getpid();
  179.     ut.ut_type = LOGIN_PROCESS;
  180. #if HAS_UTEXIT
  181.     ut.ut_exit.e_exit = 0;
  182.     ut.ut_exit.e_termination = 0;
  183. #endif
  184.     ut.ut_time = Sys::now();
  185.     // mark utmp entry as a login
  186.     strncpy(ut.ut_user, "LOGIN", sizeof (ut.ut_user));
  187.     /*
  188.      * For SVR4 systems, use the trailing component of
  189.      * the pathname to avoid problems where truncation
  190.      * results in non-unique identifiers.
  191.      */
  192.     fxStr id(getLine());
  193.     if (id.length() > sizeof (ut.ut_id))
  194. id.remove(0, id.length() - sizeof (ut.ut_id));
  195.     strncpy(ut.ut_id, (const char*) id, sizeof (ut.ut_id));
  196.     strncpy(ut.ut_line, getLine(), sizeof (ut.ut_line));
  197.     setutent();
  198.     pututline(&ut);
  199.     endutent();
  200.     writeWtmp(&ut);
  201. }
  202. /*
  203.  * Record the termination of login&co and
  204.  * reset the state of the tty device.  Note
  205.  * that this is called in the parent and
  206.  * that we're entered with effective uid set
  207.  * to the fax user and real uid of root.  Thus
  208.  * we have to play games with uids in order
  209.  * to write the utmp&wtmp entries, etc.
  210.  */
  211. void
  212. SysVGetty::hangup()
  213. {
  214.     // at this point we're root and we can reset state
  215.     struct utmp* ut;
  216.     setutent();
  217.     while ((ut = getutent()) != NULL) { 
  218. if (!strneq(ut->ut_line, getLine(), sizeof (ut->ut_line)))
  219.     continue;
  220. memset(ut->ut_user, 0, sizeof (ut->ut_user));
  221. ut->ut_type = DEAD_PROCESS;
  222. #if HAS_UTEXIT
  223. ut->ut_exit.e_exit = (exitStatus >> 8) & 0xff; // XXX
  224. ut->ut_exit.e_termination = exitStatus & 0xff; // XXX
  225. #endif
  226. ut->ut_time = Sys::now();
  227. pututline(ut);
  228. writeWtmp(ut);
  229. break;
  230.     }
  231.     endutent();
  232.     Getty::hangup();
  233. }
  234. bool
  235. SysVGetty::wait(int& status, bool block)
  236. {
  237.     if (Getty::wait(status, block)) {
  238. exitStatus = status;
  239. return (true);
  240.     } else
  241. return (false);
  242. }
  243. /*
  244.  * Public Interfaces.
  245.  */
  246. Getty*
  247. OSnewGetty(const fxStr& dev, const fxStr& speed)
  248. {
  249.     return (new SysVGetty(_PATH_GETTY, dev, speed));
  250. }
  251. Getty*
  252. OSnewVGetty(const fxStr& dev, const fxStr& speed)
  253. {
  254.     return (new SysVSubProc(_PATH_VGETTY, dev, speed));
  255. }
  256. Getty*
  257. OSnewEGetty(const fxStr& dev, const fxStr& speed)
  258. {
  259.     return (new SysVSubProc(_PATH_EGETTY, dev, speed));
  260. }