home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / screen35 / part03 < prev    next >
Encoding:
Text File  |  1993-07-25  |  105.9 KB  |  4,157 lines

  1. Newsgroups: comp.sources.unix
  2. From: mlschroe@immd4.informatik.uni-erlangen.de (Michael Schroeder)
  3. Subject: v26i302: screen-3.5 - screen manager with VT100/ANSI terminal emulation, V3.5, Part03/10
  4. Sender: unix-sources-moderator@gw.home.vix.com
  5. Approved: vixie@gw.home.vix.com
  6.  
  7. Submitted-By: mlschroe@immd4.informatik.uni-erlangen.de (Michael Schroeder)
  8. Posting-Number: Volume 26, Issue 302
  9. Archive-Name: screen-3.5/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 10)."
  18. # Contents:  COPYING attacher.c fileio.c help.c termcap.c utmp.c
  19. # Wrapped by vixie@gw.home.vix.com on Sun Jul 25 12:57:16 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'COPYING' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'COPYING'\"
  23. else
  24. echo shar: Extracting \"'COPYING'\" \(17982 characters\)
  25. sed "s/^X//" >'COPYING' <<'END_OF_FILE'
  26. X            GNU GENERAL PUBLIC LICENSE
  27. X               Version 2, June 1991
  28. X
  29. X Copyright (C) 1989, 1991 Free Software Foundation, Inc.
  30. X                          675 Mass Ave, Cambridge, MA 02139, USA
  31. X Everyone is permitted to copy and distribute verbatim copies
  32. X of this license document, but changing it is not allowed.
  33. X
  34. X                Preamble
  35. X
  36. X  The licenses for most software are designed to take away your
  37. Xfreedom to share and change it.  By contrast, the GNU General Public
  38. XLicense is intended to guarantee your freedom to share and change free
  39. Xsoftware--to make sure the software is free for all its users.  This
  40. XGeneral Public License applies to most of the Free Software
  41. XFoundation's software and to any other program whose authors commit to
  42. Xusing it.  (Some other Free Software Foundation software is covered by
  43. Xthe GNU Library General Public License instead.)  You can apply it to
  44. Xyour programs, too.
  45. X
  46. X  When we speak of free software, we are referring to freedom, not
  47. Xprice.  Our General Public Licenses are designed to make sure that you
  48. Xhave the freedom to distribute copies of free software (and charge for
  49. Xthis service if you wish), that you receive source code or can get it
  50. Xif you want it, that you can change the software or use pieces of it
  51. Xin new free programs; and that you know you can do these things.
  52. X
  53. X  To protect your rights, we need to make restrictions that forbid
  54. Xanyone to deny you these rights or to ask you to surrender the rights.
  55. XThese restrictions translate to certain responsibilities for you if you
  56. Xdistribute copies of the software, or if you modify it.
  57. X
  58. X  For example, if you distribute copies of such a program, whether
  59. Xgratis or for a fee, you must give the recipients all the rights that
  60. Xyou have.  You must make sure that they, too, receive or can get the
  61. Xsource code.  And you must show them these terms so they know their
  62. Xrights.
  63. X
  64. X  We protect your rights with two steps: (1) copyright the software, and
  65. X(2) offer you this license which gives you legal permission to copy,
  66. Xdistribute and/or modify the software.
  67. X
  68. X  Also, for each author's protection and ours, we want to make certain
  69. Xthat everyone understands that there is no warranty for this free
  70. Xsoftware.  If the software is modified by someone else and passed on, we
  71. Xwant its recipients to know that what they have is not the original, so
  72. Xthat any problems introduced by others will not reflect on the original
  73. Xauthors' reputations.
  74. X
  75. X  Finally, any free program is threatened constantly by software
  76. Xpatents.  We wish to avoid the danger that redistributors of a free
  77. Xprogram will individually obtain patent licenses, in effect making the
  78. Xprogram proprietary.  To prevent this, we have made it clear that any
  79. Xpatent must be licensed for everyone's free use or not licensed at all.
  80. X
  81. X  The precise terms and conditions for copying, distribution and
  82. Xmodification follow.
  83. X
  84. X            GNU GENERAL PUBLIC LICENSE
  85. X   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  86. X
  87. X  0. This License applies to any program or other work which contains
  88. Xa notice placed by the copyright holder saying it may be distributed
  89. Xunder the terms of this General Public License.  The "Program", below,
  90. Xrefers to any such program or work, and a "work based on the Program"
  91. Xmeans either the Program or any derivative work under copyright law:
  92. Xthat is to say, a work containing the Program or a portion of it,
  93. Xeither verbatim or with modifications and/or translated into another
  94. Xlanguage.  (Hereinafter, translation is included without limitation in
  95. Xthe term "modification".)  Each licensee is addressed as "you".
  96. X
  97. XActivities other than copying, distribution and modification are not
  98. Xcovered by this License; they are outside its scope.  The act of
  99. Xrunning the Program is not restricted, and the output from the Program
  100. Xis covered only if its contents constitute a work based on the
  101. XProgram (independent of having been made by running the Program).
  102. XWhether that is true depends on what the Program does.
  103. X
  104. X  1. You may copy and distribute verbatim copies of the Program's
  105. Xsource code as you receive it, in any medium, provided that you
  106. Xconspicuously and appropriately publish on each copy an appropriate
  107. Xcopyright notice and disclaimer of warranty; keep intact all the
  108. Xnotices that refer to this License and to the absence of any warranty;
  109. Xand give any other recipients of the Program a copy of this License
  110. Xalong with the Program.
  111. X
  112. XYou may charge a fee for the physical act of transferring a copy, and
  113. Xyou may at your option offer warranty protection in exchange for a fee.
  114. X
  115. X  2. You may modify your copy or copies of the Program or any portion
  116. Xof it, thus forming a work based on the Program, and copy and
  117. Xdistribute such modifications or work under the terms of Section 1
  118. Xabove, provided that you also meet all of these conditions:
  119. X
  120. X    a) You must cause the modified files to carry prominent notices
  121. X    stating that you changed the files and the date of any change.
  122. X
  123. X    b) You must cause any work that you distribute or publish, that in
  124. X    whole or in part contains or is derived from the Program or any
  125. X    part thereof, to be licensed as a whole at no charge to all third
  126. X    parties under the terms of this License.
  127. X
  128. X    c) If the modified program normally reads commands interactively
  129. X    when run, you must cause it, when started running for such
  130. X    interactive use in the most ordinary way, to print or display an
  131. X    announcement including an appropriate copyright notice and a
  132. X    notice that there is no warranty (or else, saying that you provide
  133. X    a warranty) and that users may redistribute the program under
  134. X    these conditions, and telling the user how to view a copy of this
  135. X    License.  (Exception: if the Program itself is interactive but
  136. X    does not normally print such an announcement, your work based on
  137. X    the Program is not required to print an announcement.)
  138. X
  139. XThese requirements apply to the modified work as a whole.  If
  140. Xidentifiable sections of that work are not derived from the Program,
  141. Xand can be reasonably considered independent and separate works in
  142. Xthemselves, then this License, and its terms, do not apply to those
  143. Xsections when you distribute them as separate works.  But when you
  144. Xdistribute the same sections as part of a whole which is a work based
  145. Xon the Program, the distribution of the whole must be on the terms of
  146. Xthis License, whose permissions for other licensees extend to the
  147. Xentire whole, and thus to each and every part regardless of who wrote it.
  148. X
  149. XThus, it is not the intent of this section to claim rights or contest
  150. Xyour rights to work written entirely by you; rather, the intent is to
  151. Xexercise the right to control the distribution of derivative or
  152. Xcollective works based on the Program.
  153. X
  154. XIn addition, mere aggregation of another work not based on the Program
  155. Xwith the Program (or with a work based on the Program) on a volume of
  156. Xa storage or distribution medium does not bring the other work under
  157. Xthe scope of this License.
  158. X
  159. X  3. You may copy and distribute the Program (or a work based on it,
  160. Xunder Section 2) in object code or executable form under the terms of
  161. XSections 1 and 2 above provided that you also do one of the following:
  162. X
  163. X    a) Accompany it with the complete corresponding machine-readable
  164. X    source code, which must be distributed under the terms of Sections
  165. X    1 and 2 above on a medium customarily used for software interchange; or,
  166. X
  167. X    b) Accompany it with a written offer, valid for at least three
  168. X    years, to give any third party, for a charge no more than your
  169. X    cost of physically performing source distribution, a complete
  170. X    machine-readable copy of the corresponding source code, to be
  171. X    distributed under the terms of Sections 1 and 2 above on a medium
  172. X    customarily used for software interchange; or,
  173. X
  174. X    c) Accompany it with the information you received as to the offer
  175. X    to distribute corresponding source code.  (This alternative is
  176. X    allowed only for noncommercial distribution and only if you
  177. X    received the program in object code or executable form with such
  178. X    an offer, in accord with Subsection b above.)
  179. X
  180. XThe source code for a work means the preferred form of the work for
  181. Xmaking modifications to it.  For an executable work, complete source
  182. Xcode means all the source code for all modules it contains, plus any
  183. Xassociated interface definition files, plus the scripts used to
  184. Xcontrol compilation and installation of the executable.  However, as a
  185. Xspecial exception, the source code distributed need not include
  186. Xanything that is normally distributed (in either source or binary
  187. Xform) with the major components (compiler, kernel, and so on) of the
  188. Xoperating system on which the executable runs, unless that component
  189. Xitself accompanies the executable.
  190. X
  191. XIf distribution of executable or object code is made by offering
  192. Xaccess to copy from a designated place, then offering equivalent
  193. Xaccess to copy the source code from the same place counts as
  194. Xdistribution of the source code, even though third parties are not
  195. Xcompelled to copy the source along with the object code.
  196. X
  197. X  4. You may not copy, modify, sublicense, or distribute the Program
  198. Xexcept as expressly provided under this License.  Any attempt
  199. Xotherwise to copy, modify, sublicense or distribute the Program is
  200. Xvoid, and will automatically terminate your rights under this License.
  201. XHowever, parties who have received copies, or rights, from you under
  202. Xthis License will not have their licenses terminated so long as such
  203. Xparties remain in full compliance.
  204. X
  205. X  5. You are not required to accept this License, since you have not
  206. Xsigned it.  However, nothing else grants you permission to modify or
  207. Xdistribute the Program or its derivative works.  These actions are
  208. Xprohibited by law if you do not accept this License.  Therefore, by
  209. Xmodifying or distributing the Program (or any work based on the
  210. XProgram), you indicate your acceptance of this License to do so, and
  211. Xall its terms and conditions for copying, distributing or modifying
  212. Xthe Program or works based on it.
  213. X
  214. X  6. Each time you redistribute the Program (or any work based on the
  215. XProgram), the recipient automatically receives a license from the
  216. Xoriginal licensor to copy, distribute or modify the Program subject to
  217. Xthese terms and conditions.  You may not impose any further
  218. Xrestrictions on the recipients' exercise of the rights granted herein.
  219. XYou are not responsible for enforcing compliance by third parties to
  220. Xthis License.
  221. X
  222. X  7. If, as a consequence of a court judgment or allegation of patent
  223. Xinfringement or for any other reason (not limited to patent issues),
  224. Xconditions are imposed on you (whether by court order, agreement or
  225. Xotherwise) that contradict the conditions of this License, they do not
  226. Xexcuse you from the conditions of this License.  If you cannot
  227. Xdistribute so as to satisfy simultaneously your obligations under this
  228. XLicense and any other pertinent obligations, then as a consequence you
  229. Xmay not distribute the Program at all.  For example, if a patent
  230. Xlicense would not permit royalty-free redistribution of the Program by
  231. Xall those who receive copies directly or indirectly through you, then
  232. Xthe only way you could satisfy both it and this License would be to
  233. Xrefrain entirely from distribution of the Program.
  234. X
  235. XIf any portion of this section is held invalid or unenforceable under
  236. Xany particular circumstance, the balance of the section is intended to
  237. Xapply and the section as a whole is intended to apply in other
  238. Xcircumstances.
  239. X
  240. XIt is not the purpose of this section to induce you to infringe any
  241. Xpatents or other property right claims or to contest validity of any
  242. Xsuch claims; this section has the sole purpose of protecting the
  243. Xintegrity of the free software distribution system, which is
  244. Ximplemented by public license practices.  Many people have made
  245. Xgenerous contributions to the wide range of software distributed
  246. Xthrough that system in reliance on consistent application of that
  247. Xsystem; it is up to the author/donor to decide if he or she is willing
  248. Xto distribute software through any other system and a licensee cannot
  249. Ximpose that choice.
  250. X
  251. XThis section is intended to make thoroughly clear what is believed to
  252. Xbe a consequence of the rest of this License.
  253. X
  254. X  8. If the distribution and/or use of the Program is restricted in
  255. Xcertain countries either by patents or by copyrighted interfaces, the
  256. Xoriginal copyright holder who places the Program under this License
  257. Xmay add an explicit geographical distribution limitation excluding
  258. Xthose countries, so that distribution is permitted only in or among
  259. Xcountries not thus excluded.  In such case, this License incorporates
  260. Xthe limitation as if written in the body of this License.
  261. X
  262. X  9. The Free Software Foundation may publish revised and/or new versions
  263. Xof the General Public License from time to time.  Such new versions will
  264. Xbe similar in spirit to the present version, but may differ in detail to
  265. Xaddress new problems or concerns.
  266. X
  267. XEach version is given a distinguishing version number.  If the Program
  268. Xspecifies a version number of this License which applies to it and "any
  269. Xlater version", you have the option of following the terms and conditions
  270. Xeither of that version or of any later version published by the Free
  271. XSoftware Foundation.  If the Program does not specify a version number of
  272. Xthis License, you may choose any version ever published by the Free Software
  273. XFoundation.
  274. X
  275. X  10. If you wish to incorporate parts of the Program into other free
  276. Xprograms whose distribution conditions are different, write to the author
  277. Xto ask for permission.  For software which is copyrighted by the Free
  278. XSoftware Foundation, write to the Free Software Foundation; we sometimes
  279. Xmake exceptions for this.  Our decision will be guided by the two goals
  280. Xof preserving the free status of all derivatives of our free software and
  281. Xof promoting the sharing and reuse of software generally.
  282. X
  283. X                NO WARRANTY
  284. X
  285. X  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  286. XFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
  287. XOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  288. XPROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  289. XOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  290. XMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
  291. XTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
  292. XPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  293. XREPAIR OR CORRECTION.
  294. X
  295. X  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  296. XWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  297. XREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  298. XINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  299. XOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  300. XTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  301. XYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  302. XPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  303. XPOSSIBILITY OF SUCH DAMAGES.
  304. X
  305. X             END OF TERMS AND CONDITIONS
  306. X
  307. X    Appendix: How to Apply These Terms to Your New Programs
  308. X
  309. X  If you develop a new program, and you want it to be of the greatest
  310. Xpossible use to the public, the best way to achieve this is to make it
  311. Xfree software which everyone can redistribute and change under these terms.
  312. X
  313. X  To do so, attach the following notices to the program.  It is safest
  314. Xto attach them to the start of each source file to most effectively
  315. Xconvey the exclusion of warranty; and each file should have at least
  316. Xthe "copyright" line and a pointer to where the full notice is found.
  317. X
  318. X    <one line to give the program's name and a brief idea of what it does.>
  319. X    Copyright (C) 19yy  <name of author>
  320. X
  321. X    This program is free software; you can redistribute it and/or modify
  322. X    it under the terms of the GNU General Public License as published by
  323. X    the Free Software Foundation; either version 2 of the License, or
  324. X    (at your option) any later version.
  325. X
  326. X    This program is distributed in the hope that it will be useful,
  327. X    but WITHOUT ANY WARRANTY; without even the implied warranty of
  328. X    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  329. X    GNU General Public License for more details.
  330. X
  331. X    You should have received a copy of the GNU General Public License
  332. X    along with this program; if not, write to the Free Software
  333. X    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  334. X
  335. XAlso add information on how to contact you by electronic and paper mail.
  336. X
  337. XIf the program is interactive, make it output a short notice like this
  338. Xwhen it starts in an interactive mode:
  339. X
  340. X    Gnomovision version 69, Copyright (C) 19yy name of author
  341. X    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
  342. X    This is free software, and you are welcome to redistribute it
  343. X    under certain conditions; type `show c' for details.
  344. X
  345. XThe hypothetical commands `show w' and `show c' should show the appropriate
  346. Xparts of the General Public License.  Of course, the commands you use may
  347. Xbe called something other than `show w' and `show c'; they could even be
  348. Xmouse-clicks or menu items--whatever suits your program.
  349. X
  350. XYou should also get your employer (if you work as a programmer) or your
  351. Xschool, if any, to sign a "copyright disclaimer" for the program, if
  352. Xnecessary.  Here is a sample; alter the names:
  353. X
  354. X  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  355. X  `Gnomovision' (which makes passes at compilers) written by James Hacker.
  356. X
  357. X  <signature of Ty Coon>, 1 April 1989
  358. X  Ty Coon, President of Vice
  359. X
  360. XThis General Public License does not permit incorporating your program into
  361. Xproprietary programs.  If your program is a subroutine library, you may
  362. Xconsider it more useful to permit linking proprietary applications with the
  363. Xlibrary.  If this is what you want to do, use the GNU Library General
  364. XPublic License instead of this License.
  365. END_OF_FILE
  366. if test 17982 -ne `wc -c <'COPYING'`; then
  367.     echo shar: \"'COPYING'\" unpacked with wrong size!
  368. fi
  369. # end of 'COPYING'
  370. fi
  371. if test -f 'attacher.c' -a "${1}" != "-c" ; then 
  372.   echo shar: Will not clobber existing file \"'attacher.c'\"
  373. else
  374. echo shar: Extracting \"'attacher.c'\" \(18578 characters\)
  375. sed "s/^X//" >'attacher.c' <<'END_OF_FILE'
  376. X/* Copyright (c) 1993
  377. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  378. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  379. X * Copyright (c) 1987 Oliver Laumann
  380. X *
  381. X * This program is free software; you can redistribute it and/or modify
  382. X * it under the terms of the GNU General Public License as published by
  383. X * the Free Software Foundation; either version 2, or (at your option)
  384. X * any later version.
  385. X *
  386. X * This program is distributed in the hope that it will be useful,
  387. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  388. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  389. X * GNU General Public License for more details.
  390. X *
  391. X * You should have received a copy of the GNU General Public License
  392. X * along with this program (see the file COPYING); if not, write to the
  393. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  394. X *
  395. X ****************************************************************
  396. X */
  397. X
  398. X#include "rcs.h"
  399. XRCS_ID("$Id: attacher.c,v 1.3 1993/07/21 15:42:48 mlschroe Exp $ FAU")
  400. X
  401. X#include <sys/types.h>
  402. X#include <sys/stat.h>
  403. X#include <fcntl.h>
  404. X#include <signal.h>
  405. X#include <pwd.h>
  406. X#include "config.h"
  407. X#include "screen.h"
  408. X#include "extern.h"
  409. X
  410. X#ifdef SHADOWPW
  411. X# include <shadow.h>
  412. X#endif /* SHADOWPW */
  413. X
  414. Xstatic sig_t AttacherSigInt __P(SIGPROTOARG);
  415. X#ifdef PASSWORD
  416. Xstatic void  trysend __P((int, struct msg *, char *));
  417. X#endif
  418. X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
  419. Xstatic sig_t AttacherWinch __P(SIGPROTOARG);
  420. X#endif
  421. X#ifdef LOCK
  422. Xstatic sig_t DoLock __P(SIGPROTOARG);
  423. Xstatic void  LockTerminal __P((void));
  424. Xstatic sig_t LockHup __P(SIGPROTOARG);
  425. Xstatic void  screen_builtin_lck __P((void));
  426. X#endif
  427. X#ifdef DEBUG
  428. Xstatic sig_t AttacherChld __P(SIGPROTOARG);
  429. X#endif
  430. X
  431. Xextern int real_uid, real_gid, eff_uid, eff_gid;
  432. Xextern char *SockName, *SockNamePtr, SockPath[];
  433. Xextern struct passwd *ppp;
  434. Xextern char *attach_tty, *attach_term, *LoginName;
  435. Xextern int xflag, dflag, rflag, quietflag, adaptflag;
  436. Xextern struct mode attach_Mode;
  437. Xextern int MasterPid;
  438. Xextern int nethackflag;
  439. X
  440. X#ifdef MULTIUSER
  441. Xextern char *multi;
  442. Xextern int multiattach, multi_uid, own_uid;
  443. Xextern int tty_mode, tty_oldmode;
  444. X# ifdef NOREUID
  445. Xstatic int multipipe[2];
  446. X# endif
  447. X#endif
  448. X
  449. X
  450. X
  451. X/*
  452. X *  Send message to a screen backend.
  453. X *  returns 1 if we could attach one, or 0 if none.
  454. X */
  455. X
  456. Xint
  457. XAttach(how)
  458. Xint how;
  459. X{
  460. X  int lasts;
  461. X  struct msg m;
  462. X  struct stat st;
  463. X  char *s;
  464. X
  465. X  debug2("Attach: how=%d, tty=%s\n", how, attach_tty);
  466. X#ifdef MULTIUSER
  467. X# ifdef NOREUID
  468. X  while ((how == MSG_ATTACH || how == MSG_CONT) && multiattach)
  469. X    {
  470. X      int ret;
  471. X
  472. X      if (pipe(multipipe))
  473. X    Panic(errno, "pipe");
  474. X      eff_uid = -1;    /* make UserContext fork */
  475. X      real_uid = multi_uid;
  476. X      if ((ret = UserContext()) <= 0)
  477. X    {
  478. X      char dummy;
  479. X          eff_uid = 0;
  480. X      real_uid = own_uid;
  481. X      if (ret < 0)
  482. X        Panic(errno, "UserContext");
  483. X      close(multipipe[1]);
  484. X      read(multipipe[0], &dummy, 1);
  485. X      if (tty_oldmode >= 0)
  486. X        {
  487. X          chmod(attach_tty, tty_oldmode);
  488. X          tty_oldmode = -1;
  489. X        }
  490. X      ret = UserStatus();
  491. X#ifdef LOCK
  492. X      if (ret == SIG_LOCK)
  493. X        LockTerminal();
  494. X      else
  495. X#endif
  496. X#ifdef SIGTSTP
  497. X      if (ret == SIG_STOP)
  498. X        kill(getpid(), SIGTSTP);
  499. X      else
  500. X#endif
  501. X      if (ret == SIG_POWER_BYE)
  502. X        {
  503. X          int ppid;
  504. X          setuid(real_uid);
  505. X          setgid(real_gid);
  506. X          if ((ppid = getppid()) > 1)
  507. X        Kill(ppid, SIGHUP);
  508. X          exit(0);
  509. X        }
  510. X      else
  511. X            exit(ret);
  512. X      dflag = 0;
  513. X#ifdef MULTI
  514. X      xflag = 1;
  515. X#endif
  516. X      how = MSG_ATTACH;
  517. X      continue;
  518. X    }
  519. X      close(multipipe[0]);
  520. X      eff_uid  = real_uid;
  521. X      break;
  522. X    }
  523. X# else /* NOREUID */
  524. X  if ((how == MSG_ATTACH || how == MSG_CONT) && multiattach)
  525. X    {
  526. X      real_uid = multi_uid;
  527. X      eff_uid  = own_uid;
  528. X      setreuid(real_uid, eff_uid);
  529. X      if (chmod(attach_tty, 0666))
  530. X    Panic(errno, "chmod %s", attach_tty);
  531. X      tty_oldmode = tty_mode;
  532. X    }
  533. X# endif /* NOREUID */
  534. X#endif /* MULTIUSER */
  535. X
  536. X  bzero((char *) &m, sizeof(m));
  537. X  m.type = how;
  538. X  strcpy(m.m_tty, attach_tty);
  539. X
  540. X  if (how == MSG_WINCH)
  541. X    {
  542. X      if ((lasts = MakeClientSocket(0, SockName)) >= 0)
  543. X    {
  544. X          write(lasts, (char *)&m, sizeof(m));
  545. X          close(lasts);
  546. X    }
  547. X      return 0;
  548. X    }
  549. X
  550. X  if (how == MSG_CONT)
  551. X    {
  552. X      if ((lasts = MakeClientSocket(0, SockName)) < 0)
  553. X        {
  554. X          Panic(0, "Sorry, cannot contact session \"%s\" again\r\n",
  555. X                 SockName ? SockName : "<NULL>");
  556. X        }
  557. X    }
  558. X  else
  559. X    {
  560. X      switch (FindSocket(how, &lasts))
  561. X    {
  562. X    case 0:
  563. X      if (rflag == 2)
  564. X        return 0;
  565. X      if (quietflag)
  566. X        eexit(10);
  567. X      Panic(0, SockName && *SockName ? "There is no screen to be %sed matching %s." : "There is no screen to be %sed.",
  568. X        xflag ? "attach" :
  569. X        dflag ? "detach" :
  570. X                        "resum", SockName);
  571. X      /* NOTREACHED */
  572. X    case 1:
  573. X      break;
  574. X    default:
  575. X      Panic(0, "Type \"screen [-d] -r [pid.]tty.host\" to resume one of them.");
  576. X      /* NOTREACHED */
  577. X    }
  578. X    }
  579. X  /*
  580. X   * Go in UserContext. Advantage is, you can kill your attacher
  581. X   * when things go wrong. Any disadvantages? jw.
  582. X   * Do this before the attach to prevent races!
  583. X   */
  584. X#ifdef MULTIUSER
  585. X  if (!multiattach)
  586. X#endif
  587. X    setuid(real_uid);
  588. X#if defined(MULTIUSER) && !defined(NOREUID)
  589. X  else
  590. X    setreuid(eff_uid, real_uid);
  591. X#endif
  592. X  setgid(real_gid);
  593. X
  594. X  debug2("Attach: uid %d euid %d\n", getuid(), geteuid());
  595. X  SockName = SockNamePtr;
  596. X  MasterPid = 0;
  597. X  while (*SockName)
  598. X    {
  599. X      if (*SockName > '9' || *SockName < '0')
  600. X    break;
  601. X      MasterPid = 10 * MasterPid + *SockName - '0';
  602. X      SockName++;
  603. X    }
  604. X  SockName = SockNamePtr;
  605. X  debug1("Attach decided, it is '%s'\n", SockPath);
  606. X  debug1("Attach found MasterPid == %d\n", MasterPid);
  607. X  if (stat(SockPath, &st) == -1)
  608. X    Panic(errno, "stat %s", SockPath);
  609. X  if ((st.st_mode & 0600) != 0600)
  610. X    Panic(0, "Socket is in wrong mode (%03o)", st.st_mode);
  611. X  if ((dflag || !xflag) && (st.st_mode & 0700) != (dflag ? 0700 : 0600))
  612. X    Panic(0, "That screen is %sdetached.", dflag ? "already " : "not ");
  613. X#ifdef REMOTE_DETACH
  614. X  if (dflag &&
  615. X      (how == MSG_ATTACH || how == MSG_DETACH || how == MSG_POW_DETACH))
  616. X    {
  617. X      m.m.detach.dpid = getpid();
  618. X      strncpy(m.m.detach.duser, LoginName, sizeof(m.m.detach.duser) - 1); 
  619. X      m.m.detach.duser[sizeof(m.m.detach.duser) - 1] = 0;
  620. X# ifdef POW_DETACH
  621. X      if (dflag == 2)
  622. X    m.type = MSG_POW_DETACH;
  623. X      else
  624. X# endif
  625. X    m.type = MSG_DETACH;
  626. X      if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m))
  627. X    Panic(errno, "write");
  628. X      close(lasts);
  629. X      if (how != MSG_ATTACH)
  630. X    return 0;    /* we detached it. jw. */
  631. X      sleep(1);    /* we dont want to overrun our poor backend. jw. */
  632. X      if ((lasts = MakeClientSocket(0, SockName)) == -1)
  633. X    Panic(0, "Cannot contact screen again. Shit.");
  634. X      m.type = how;
  635. X    }
  636. X#endif
  637. X  strcpy(m.m.attach.envterm, attach_term);
  638. X  debug1("attach: sending %d bytes... ", sizeof m);
  639. X
  640. X  strncpy(m.m.attach.auser, LoginName, sizeof(m.m.attach.auser) - 1); 
  641. X  m.m.attach.auser[sizeof(m.m.attach.auser) - 1] = 0;
  642. X  m.m.attach.apid = getpid();
  643. X  m.m.attach.adaptflag = adaptflag;
  644. X  m.m.attach.lines = m.m.attach.columns = 0;
  645. X  if ((s = getenv("LINES")))
  646. X    m.m.attach.lines = atoi(s);
  647. X  if ((s = getenv("COLUMNS")))
  648. X    m.m.attach.columns = atoi(s);
  649. X
  650. X#ifdef PASSWORD
  651. X  if (how == MSG_ATTACH || how == MSG_CONT)
  652. X    trysend(lasts, &m, m.m.attach.password);
  653. X  else
  654. X#endif
  655. X    {
  656. X      if (write(lasts, (char *) &m, sizeof(m)) != sizeof(m))
  657. X    Panic(errno, "write");
  658. X      close(lasts);
  659. X    }
  660. X  debug1("Attach(%d): sent\n", m.type);
  661. X#ifdef MULTIUSER
  662. X  if (multi && (how == MSG_ATTACH || how == MSG_CONT))
  663. X    {
  664. X# ifndef PASSWORD
  665. X      pause();
  666. X# endif
  667. X# ifdef NOREUID
  668. X      close(multipipe[1]);
  669. X# else
  670. X      setreuid(real_uid, eff_uid);
  671. X      if (tty_oldmode >= 0)
  672. X        if (chmod(attach_tty, tty_oldmode))
  673. X          Panic(errno, "chmod %s", attach_tty);
  674. X      tty_oldmode = -1;
  675. X      setreuid(eff_uid, real_uid);
  676. X# endif
  677. X    }
  678. X#endif
  679. X  rflag = 0;
  680. X  return 1;
  681. X}
  682. X
  683. X
  684. X#ifdef PASSWORD
  685. X
  686. Xstatic trysendstatok, trysendstatfail;
  687. X
  688. Xstatic sig_t
  689. Xtrysendok(SIGDEFARG)
  690. X{
  691. X  trysendstatok = 1;
  692. X}
  693. X
  694. Xstatic sig_t
  695. Xtrysendfail(SIGDEFARG)
  696. X{
  697. X# ifdef SYSVSIGS
  698. X  signal(SIG_PW_FAIL, trysendfail);
  699. X# endif /* SYSVSIGS */
  700. X  trysendstatfail = 1;
  701. X}
  702. X
  703. Xstatic char screenpw[9];
  704. X
  705. Xstatic void
  706. Xtrysend(fd, m, pwto)
  707. Xint fd;
  708. Xstruct msg *m;
  709. Xchar *pwto;
  710. X{
  711. X  char *npw = NULL;
  712. X  sig_t (*sighup)__P(SIGPROTOARG);
  713. X  sig_t (*sigusr1)__P(SIGPROTOARG);
  714. X  int tries;
  715. X
  716. X  sigusr1 = signal(SIG_PW_OK, trysendok);
  717. X  sighup = signal(SIG_PW_FAIL, trysendfail);
  718. X  for (tries = 0; ; )
  719. X    {
  720. X      strcpy(pwto, screenpw);
  721. X      trysendstatok = trysendstatfail = 0;
  722. X      if (write(fd, (char *) m, sizeof(*m)) != sizeof(*m))
  723. X    Panic(errno, "write");
  724. X      close(fd);
  725. X      while (trysendstatok == 0 && trysendstatfail == 0)
  726. X    pause();
  727. X      if (trysendstatok)
  728. X    {
  729. X      signal(SIG_PW_OK, sigusr1);
  730. X      signal(SIG_PW_FAIL, sighup);
  731. X      if (trysendstatfail)
  732. X        kill(getpid(), SIG_PW_FAIL);
  733. X      return;
  734. X    }
  735. X      if (++tries > 1 || (npw = getpass("Screen Password:")) == 0 || *npw == 0)
  736. X    {
  737. X#ifdef NETHACK
  738. X      if (nethackflag)
  739. X        Panic(0, "The guard slams the door in your face.");
  740. X      else
  741. X#endif
  742. X      Panic(0, "Password incorrect.");
  743. X    }
  744. X      strncpy(screenpw, npw, 8);
  745. X      if ((fd = MakeClientSocket(0, SockName)) == -1)
  746. X    Panic(0, "Cannot contact screen again. Shit.");
  747. X    }
  748. X}
  749. X#endif /* PASSWORD */
  750. X
  751. X
  752. X#ifdef DEBUG
  753. Xstatic int AttacherPanic;
  754. X
  755. Xstatic sig_t
  756. XAttacherChld(SIGDEFARG)
  757. X{
  758. X  AttacherPanic=1;
  759. X#ifndef SIGVOID
  760. X  return((sig_t) 0);
  761. X#endif
  762. X}
  763. X#endif
  764. X
  765. X/*
  766. X * the frontend's Interrupt handler
  767. X * we forward SIGINT to the poor backend
  768. X */
  769. Xstatic sig_t 
  770. XAttacherSigInt(SIGDEFARG)
  771. X{
  772. X  signal(SIGINT, AttacherSigInt);
  773. X  Kill(MasterPid, SIGINT);
  774. X# ifndef SIGVOID
  775. X  return (sig_t) 0;
  776. X# endif
  777. X}
  778. X
  779. X/*
  780. X * Unfortunatelly this is also the SIGHUP handler, so we have to
  781. X * check, if the backend is already detached.
  782. X */
  783. X
  784. Xsig_t
  785. XAttacherFinit(SIGDEFARG)
  786. X{
  787. X  struct stat statb;
  788. X  struct msg m;
  789. X  int s;
  790. X
  791. X  debug("AttacherFinit();\n");
  792. X  signal(SIGHUP, SIG_IGN);
  793. X  /* Check if signal comes from backend */
  794. X  if (SockName)
  795. X    {
  796. X      strcpy(SockNamePtr, SockName);
  797. X      if (stat(SockPath, &statb) == 0 && (statb.st_mode & 0777) != 0600)
  798. X    {
  799. X      debug("Detaching backend!\n");
  800. X      bzero((char *) &m, sizeof(m));
  801. X      strcpy(m.m_tty, attach_tty);
  802. X          debug1("attach_tty is %s\n", attach_tty);
  803. X      m.m.detach.dpid = getpid();
  804. X      m.type = MSG_HANGUP;
  805. X      if ((s = MakeClientSocket(0, SockName)) >= 0)
  806. X        {
  807. X          write(s, (char *)&m, sizeof(m));
  808. X          close(s);
  809. X        }
  810. X    }
  811. X    }
  812. X#ifdef MULTIUSER
  813. X  if (tty_oldmode >= 0)
  814. X    {
  815. X      setuid(own_uid);
  816. X      chmod(attach_tty, tty_oldmode);
  817. X    }
  818. X#endif
  819. X  exit(0);
  820. X#ifndef SIGVOID
  821. X  return((sig_t) 0);
  822. X#endif
  823. X}
  824. X
  825. X#ifdef POW_DETACH
  826. Xstatic sig_t
  827. XAttacherFinitBye(SIGDEFARG)
  828. X{
  829. X  int ppid;
  830. X  debug("AttacherFintBye()\n");
  831. X#if defined(MULTIUSER) && defined(NOREUID)
  832. X  if (multiattach)
  833. X    exit(SIG_POWER_BYE);
  834. X#endif
  835. X#ifdef MULTIUSER
  836. X  setuid(own_uid);
  837. X#else
  838. X  setuid(real_uid);
  839. X#endif
  840. X  setgid(real_gid);
  841. X  /* we don't want to disturb init (even if we were root), eh? jw */
  842. X  if ((ppid = getppid()) > 1)
  843. X    Kill(ppid, SIGHUP);        /* carefully say good bye. jw. */
  844. X  exit(0);
  845. X#ifndef SIGVOID
  846. X  return((sig_t) 0);
  847. X#endif
  848. X}
  849. X#endif
  850. X
  851. Xstatic int SuspendPlease;
  852. X
  853. Xstatic sig_t
  854. XSigStop(SIGDEFARG)
  855. X{
  856. X  debug("SigStop()\n");
  857. X  SuspendPlease = 1;
  858. X#ifndef SIGVOID
  859. X  return((sig_t) 0);
  860. X#endif
  861. X}
  862. X
  863. X#ifdef LOCK
  864. Xstatic int LockPlease;
  865. X
  866. Xstatic sig_t
  867. XDoLock(SIGDEFARG)
  868. X{
  869. X# ifdef SYSVSIGS
  870. X  signal(SIG_LOCK, DoLock);
  871. X# endif
  872. X  debug("DoLock()\n");
  873. X  LockPlease = 1;
  874. X# ifndef SIGVOID
  875. X  return((sig_t) 0);
  876. X# endif
  877. X}
  878. X#endif
  879. X
  880. X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
  881. Xstatic int SigWinchPlease;
  882. X
  883. Xstatic sig_t
  884. XAttacherWinch(SIGDEFARG)
  885. X{
  886. X  debug("AttacherWinch()\n");
  887. X  SigWinchPlease = 1;
  888. X# ifndef SIGVOID
  889. X  return((sig_t) 0);
  890. X# endif
  891. X}
  892. X#endif
  893. X
  894. X
  895. X/*
  896. X *  Attacher loop - no return
  897. X */
  898. X
  899. Xvoid
  900. XAttacher()
  901. X{
  902. X  signal(SIGHUP, AttacherFinit);
  903. X  signal(SIG_BYE, AttacherFinit);
  904. X#ifdef POW_DETACH
  905. X  signal(SIG_POWER_BYE, AttacherFinitBye);
  906. X#endif
  907. X#ifdef LOCK
  908. X  signal(SIG_LOCK, DoLock);
  909. X#endif
  910. X  signal(SIGINT, AttacherSigInt);
  911. X#ifdef BSDJOBS
  912. X  signal(SIG_STOP, SigStop);
  913. X#endif
  914. X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
  915. X  signal(SIGWINCH, AttacherWinch);
  916. X#endif
  917. X#ifdef DEBUG
  918. X  signal(SIGCHLD, AttacherChld);
  919. X#endif
  920. X  debug("attacher: going for a nap.\n");
  921. X  dflag = 0;
  922. X#ifdef MULTI
  923. X  xflag = 1;
  924. X#endif
  925. X  for (;;)
  926. X    {
  927. X      pause();
  928. X      debug("attacher: huh! a signal!\n");
  929. X#ifdef DEBUG
  930. X      if (AttacherPanic)
  931. X        {
  932. X      fcntl(0, F_SETFL, 0);
  933. X      SetTTY(0, &attach_Mode);
  934. X      printf("\nSuddenly the Dungeon collapses!! - You die...\n");
  935. X      eexit(1);
  936. X        }
  937. X#endif
  938. X#ifdef BSDJOBS
  939. X      if (SuspendPlease)
  940. X    {
  941. X      SuspendPlease = 0;
  942. X#if defined(MULTIUSER) && defined(NOREUID)
  943. X      if (multiattach)
  944. X        exit(SIG_STOP);
  945. X#endif
  946. X      signal(SIGTSTP, SIG_DFL);
  947. X      debug("attacher: killing myself SIGTSTP\n");
  948. X      kill(getpid(), SIGTSTP);
  949. X      debug("attacher: continuing from stop\n");
  950. X      signal(SIG_STOP, SigStop);
  951. X      (void) Attach(MSG_CONT);
  952. X    }
  953. X#endif
  954. X#ifdef LOCK
  955. X      if (LockPlease)
  956. X    {
  957. X      LockPlease = 0;
  958. X#if defined(MULTIUSER) && defined(NOREUID)
  959. X      if (multiattach)
  960. X        exit(SIG_LOCK);
  961. X#endif
  962. X      LockTerminal();
  963. X# ifdef SYSVSIGS
  964. X      signal(SIG_LOCK, DoLock);
  965. X# endif
  966. X      (void) Attach(MSG_CONT);
  967. X    }
  968. X#endif    /* LOCK */
  969. X#if defined(SIGWINCH) && defined(TIOCGWINSZ)
  970. X      if (SigWinchPlease)
  971. X    {
  972. X      SigWinchPlease = 0;
  973. X# ifdef SYSVSIGS
  974. X      signal(SIGWINCH, AttacherWinch);
  975. X# endif
  976. X      (void) Attach(MSG_WINCH);
  977. X    }
  978. X#endif    /* SIGWINCH */
  979. X    }
  980. X}
  981. X
  982. X#ifdef LOCK
  983. X
  984. X/* ADDED by Rainer Pruy 10/15/87 */
  985. X/* POLISHED by mls. 03/10/91 */
  986. X
  987. Xstatic char LockEnd[] = "Welcome back to screen !!\n";
  988. X
  989. Xstatic sig_t
  990. XLockHup(SIGDEFARG)
  991. X{
  992. X  int ppid = getppid();
  993. X  setuid(real_uid);
  994. X  setgid(real_gid);
  995. X  if (ppid > 1)
  996. X    Kill(ppid, SIGHUP);
  997. X  exit(0);
  998. X}
  999. X
  1000. Xstatic void
  1001. XLockTerminal()
  1002. X{
  1003. X  char *prg;
  1004. X  int sig, pid;
  1005. X  sig_t (*sigs[NSIG])__P(SIGPROTOARG);
  1006. X
  1007. X  for (sig = 1; sig < NSIG; sig++)
  1008. X    {
  1009. X      sigs[sig] = signal(sig, SIG_IGN);
  1010. X    }
  1011. X  signal(SIGHUP, LockHup);
  1012. X  printf("\n");
  1013. X
  1014. X  prg = getenv("LOCKPRG");
  1015. X  if (prg && strcmp(prg, "builtin") && !access(prg, X_OK))
  1016. X    {
  1017. X      signal(SIGCHLD, SIG_DFL);
  1018. X      debug1("lockterminal: '%s' seems executable, execl it!\n", prg);
  1019. X      if ((pid = fork()) == 0)
  1020. X        {
  1021. X          /* Child */
  1022. X          setuid(real_uid);    /* this should be done already */
  1023. X          setgid(real_gid);
  1024. X          closeallfiles(0);    /* important: /etc/shadow may be open */
  1025. X          execl(prg, "SCREEN-LOCK", NULL);
  1026. X          exit(errno);
  1027. X        }
  1028. X      if (pid == -1)
  1029. X        {
  1030. X#ifdef NETHACK
  1031. X          if (nethackflag)
  1032. X            Msg(errno, "Cannot fork terminal - lock failed");
  1033. X          else
  1034. X#endif
  1035. X          Msg(errno, "Cannot lock terminal - fork failed");
  1036. X        }
  1037. X      else
  1038. X        {
  1039. X#ifdef BSDWAIT
  1040. X          union wait wstat;
  1041. X#else
  1042. X          int wstat;
  1043. X#endif
  1044. X          int wret;
  1045. X
  1046. X#ifdef hpux
  1047. X          signal(SIGCHLD, SIG_DFL);
  1048. X#endif
  1049. X          errno = 0;
  1050. X          while (((wret = wait(&wstat)) != pid) ||
  1051. X             ((wret == -1) && (errno == EINTR))
  1052. X             )
  1053. X        errno = 0;
  1054. X    
  1055. X          if (errno)
  1056. X        {
  1057. X          Msg(errno, "Lock");
  1058. X          sleep(2);
  1059. X        }
  1060. X      else if (WTERMSIG(wstat) != 0)
  1061. X        {
  1062. X          fprintf(stderr, "Lock: %s: Killed by signal: %d%s\n", prg,
  1063. X              WTERMSIG(wstat), WIFCORESIG(wstat) ? " (Core dumped)" : "");
  1064. X          sleep(2);
  1065. X        }
  1066. X      else if (WEXITSTATUS(wstat))
  1067. X        {
  1068. X          debug2("Lock: %s: return code %d\n", prg, WEXITSTATUS(wstat));
  1069. X        }
  1070. X          else
  1071. X        printf(LockEnd);
  1072. X        }
  1073. X    }
  1074. X  else
  1075. X    {
  1076. X      if (prg)
  1077. X    {
  1078. X          debug1("lockterminal: '%s' seems NOT executable, we use our builtin\n", prg);
  1079. X    }
  1080. X      else
  1081. X    {
  1082. X      debug("lockterminal: using buitin.\n");
  1083. X    }
  1084. X      screen_builtin_lck();
  1085. X    }
  1086. X  /* reset signals */
  1087. X  for (sig = 1; sig < NSIG; sig++)
  1088. X    {
  1089. X      if (sigs[sig] != (sig_t(*)__P(SIGPROTOARG)) -1)
  1090. X    signal(sig, sigs[sig]);
  1091. X    }
  1092. X}                /* LockTerminal */
  1093. X
  1094. X/* -- original copyright by Luigi Cannelloni 1985 (luigi@faui70.UUCP) -- */
  1095. Xstatic void
  1096. Xscreen_builtin_lck()
  1097. X{
  1098. X  char fullname[100], *cp1, message[BUFSIZ];
  1099. X  char c, *pass, mypass[9];
  1100. X#ifdef SHADOWPW
  1101. X  struct spwd *sss = NULL;
  1102. X#endif
  1103. X  int t;
  1104. X
  1105. X#ifdef undef
  1106. X  /* get password entry */
  1107. X  if ((ppp = getpwuid(real_uid)) == NULL)
  1108. X    {
  1109. X      fprintf(stderr, "screen_builtin_lck: No passwd entry.\007\n");
  1110. X      sleep(2);
  1111. X      return;
  1112. X    }
  1113. X  if (!isatty(0))
  1114. X    {
  1115. X      fprintf(stderr, "screen_builtin_lck: Not a tty.\007\n");
  1116. X      sleep(2);
  1117. X      return;
  1118. X    }
  1119. X#endif
  1120. X  pass = ppp->pw_passwd;
  1121. X#ifdef SHADOWPW
  1122. Xrealpw:
  1123. X#endif /* SHADOWPW */
  1124. X  for (t = 0; t < 13; t++)
  1125. X    {
  1126. X      c = pass[t];
  1127. X      if (!(c == '.' || c == '/' ||
  1128. X            (c >= '0' && c <= '9') || 
  1129. X            (c >= 'a' && c <= 'z') || 
  1130. X            (c >= 'A' && c <= 'Z'))) 
  1131. X        break;
  1132. X    }
  1133. X  if (t < 13)
  1134. X    {
  1135. X      debug("builtin_lock: ppp->pw_passwd bad, has it a shadow?\n");
  1136. X#ifdef SHADOWPW
  1137. X      setspent(); /* rewind shadow file */
  1138. X      if ((sss == NULL) && (sss = getspnam(ppp->pw_name)))
  1139. X        {
  1140. X          pass = sss->sp_pwdp;
  1141. X          goto realpw;
  1142. X        }
  1143. X#endif /* SHADOWPW */
  1144. X      if ((pass = getpass("Key:   ")))
  1145. X        {
  1146. X          strncpy(mypass, pass, 8);
  1147. X          mypass[8] = 0;
  1148. X          if (*mypass == 0)
  1149. X            return;
  1150. X          if ((pass = getpass("Again: ")))
  1151. X            {
  1152. X              if (strcmp(mypass, pass))
  1153. X                {
  1154. X                  fprintf(stderr, "Passwords don't match.\007\n");
  1155. X                  sleep(2);
  1156. X                  return;
  1157. X                }
  1158. X            }
  1159. X        }
  1160. X      if (pass == 0)
  1161. X        {
  1162. X          fprintf(stderr, "Getpass error.\007\n");
  1163. X          sleep(2);
  1164. X          return;
  1165. X        }
  1166. X      pass = 0;
  1167. X    }
  1168. X
  1169. X  debug("screen_builtin_lck looking in gcos field\n");
  1170. X  strcpy(fullname, ppp->pw_gecos);
  1171. X  if ((cp1 = index(fullname, ',')) != NULL)
  1172. X    *cp1 = '\0';
  1173. X  if ((cp1 = index(fullname, '&')) != NULL)
  1174. X    {
  1175. X      sprintf(cp1, "%s", ppp->pw_name);
  1176. X      if (*cp1 >= 'a' && *cp1 <= 'z')
  1177. X    *cp1 -= 'a' - 'A';
  1178. X    }
  1179. X
  1180. X  sprintf(message, "Screen used by %s <%s>.\nPassword:\007",
  1181. X          fullname, ppp->pw_name);
  1182. X
  1183. X  /* loop here to wait for correct password */
  1184. X  for (;;)
  1185. X    {
  1186. X      debug("screen_builtin_lck awaiting password\n");
  1187. X      errno = 0;
  1188. X      if ((cp1 = getpass(message)) == NULL)
  1189. X        {
  1190. X          AttacherFinit(SIGARG);
  1191. X          /* NOTREACHED */
  1192. X        }
  1193. X      debug3("getpass(%d): %x == %s\n", errno, (unsigned int)cp1, cp1);
  1194. X      if (pass)
  1195. X        {
  1196. X          if (!strcmp(crypt(cp1, pass), pass))
  1197. X            break;
  1198. X        }
  1199. X      else
  1200. X        {
  1201. X          if (!strcmp(cp1, mypass))
  1202. X            break;
  1203. X        }
  1204. X      debug("screen_builtin_lck: NO!!!!!\n");
  1205. X    }
  1206. X  debug("password ok.\n");
  1207. X}
  1208. X
  1209. X#endif    /* LOCK */
  1210. END_OF_FILE
  1211. if test 18578 -ne `wc -c <'attacher.c'`; then
  1212.     echo shar: \"'attacher.c'\" unpacked with wrong size!
  1213. fi
  1214. # end of 'attacher.c'
  1215. fi
  1216. if test -f 'fileio.c' -a "${1}" != "-c" ; then 
  1217.   echo shar: Will not clobber existing file \"'fileio.c'\"
  1218. else
  1219. echo shar: Extracting \"'fileio.c'\" \(15658 characters\)
  1220. sed "s/^X//" >'fileio.c' <<'END_OF_FILE'
  1221. X/* Copyright (c) 1993
  1222. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  1223. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  1224. X * Copyright (c) 1987 Oliver Laumann
  1225. X *
  1226. X * This program is free software; you can redistribute it and/or modify
  1227. X * it under the terms of the GNU General Public License as published by
  1228. X * the Free Software Foundation; either version 2, or (at your option)
  1229. X * any later version.
  1230. X *
  1231. X * This program is distributed in the hope that it will be useful,
  1232. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1233. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1234. X * GNU General Public License for more details.
  1235. X *
  1236. X * You should have received a copy of the GNU General Public License
  1237. X * along with this program (see the file COPYING); if not, write to the
  1238. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1239. X *
  1240. X ****************************************************************
  1241. X */
  1242. X
  1243. X#include "rcs.h"
  1244. XRCS_ID("$Id: fileio.c,v 1.2 1993/06/23 17:46:30 jnweiger Exp $ FAU")
  1245. X
  1246. X
  1247. X#include <sys/types.h>
  1248. X#ifndef sgi
  1249. X# include <sys/file.h>
  1250. X#endif /* sgi */
  1251. X#include <sys/stat.h>
  1252. X#include <fcntl.h>
  1253. X
  1254. X#include <signal.h>
  1255. X
  1256. X#include "config.h" 
  1257. X#include "screen.h"
  1258. X#include "extern.h"
  1259. X
  1260. X#ifdef NETHACK
  1261. Xextern nethackflag;
  1262. X#endif
  1263. X
  1264. Xextern struct display *display;
  1265. Xextern struct win *fore;
  1266. Xextern int real_uid, eff_uid;
  1267. Xextern int real_gid, eff_gid;
  1268. Xextern char *extra_incap, *extra_outcap;
  1269. Xextern char *home, *RcFileName;
  1270. Xextern char SockPath[], *SockNamePtr;
  1271. X#ifdef COPY_PASTE
  1272. Xextern char *BufferFile;
  1273. X#endif
  1274. Xextern int hardcopy_append;
  1275. Xextern char *hardcopydir;
  1276. X
  1277. Xstatic char *CatExtra __P((char *, char *));
  1278. X
  1279. X
  1280. Xstatic FILE *fp = NULL;
  1281. Xchar *rc_name;
  1282. X
  1283. Xstatic char *
  1284. XCatExtra(str1, str2)
  1285. Xregister char *str1, *str2;
  1286. X{
  1287. X  register char *cp;
  1288. X  register int len1, len2, add_colon;
  1289. X
  1290. X  len1 = strlen(str1);
  1291. X  if (len1 == 0)
  1292. X    return(str2);
  1293. X  add_colon = (str1[len1 - 1] != ':');
  1294. X  if (str2)
  1295. X    {
  1296. X      len2 = strlen(str2);
  1297. X      if ((cp = realloc(str2, (unsigned) len1 + len2 + add_colon + 1)) == NULL)
  1298. X    Panic(0, strnomem);
  1299. X      bcopy(cp, cp + len1 + add_colon, len2 + 1);
  1300. X    }
  1301. X  else
  1302. X    {
  1303. X      if (len1 == 0)
  1304. X    return 0;
  1305. X      if ((cp = malloc((unsigned) len1 + add_colon + 1)) == NULL)
  1306. X    Panic(0, strnomem);
  1307. X      cp[len1 + add_colon] = '\0'; 
  1308. X    }
  1309. X  bcopy(str1, cp, len1);
  1310. X  if (add_colon)
  1311. X    cp[len1] = ':';
  1312. X
  1313. X  return cp;
  1314. X}
  1315. X
  1316. Xstatic char *
  1317. Xfindrcfile(rcfile)
  1318. Xchar *rcfile;
  1319. X{
  1320. X  static char buf[256];
  1321. X  char *rc, *p;
  1322. X
  1323. X  if (rcfile)
  1324. X    {
  1325. X      rc = SaveStr(rcfile);
  1326. X      debug1("findrcfile: you specified '%s'\n", rcfile);
  1327. X    }
  1328. X  else
  1329. X    {
  1330. X      debug("findrcfile: you specified nothing...\n");
  1331. X      if ((p = getenv("ISCREENRC")) != NULL && *p != '\0')
  1332. X    {
  1333. X      debug1("  ... but $ISCREENRC has: '%s'\n", p);
  1334. X      rc = SaveStr(p);
  1335. X    }
  1336. X      else if ((p = getenv("SCREENRC")) != NULL && *p != '\0')
  1337. X    {
  1338. X      debug1("  ... but $SCREENRC has: '%s'\n", p);
  1339. X      rc = SaveStr(p);
  1340. X    }
  1341. X      else
  1342. X    {
  1343. X      debug("  ...nothing in $SCREENRC, defaulting $HOME/.screenrc\n");
  1344. X      if (strlen(home) > 244)
  1345. X        Panic(0, "Rc: home too large");
  1346. X      sprintf(buf, "%s/.iscreenrc", home);
  1347. X          if (access(buf, R_OK))
  1348. X        sprintf(buf, "%s/.screenrc", home);
  1349. X      rc = SaveStr(buf);
  1350. X    }
  1351. X    }
  1352. X  return rc;
  1353. X}
  1354. X
  1355. X/*
  1356. X * this will be called twice:
  1357. X * 1) rcfilename = "/etc/screenrc"
  1358. X * 2) rcfilename = RcFileName
  1359. X */
  1360. Xvoid
  1361. XStartRc(rcfilename)
  1362. Xchar *rcfilename;
  1363. X{
  1364. X  register int argc, len;
  1365. X  register char *p, *cp;
  1366. X  char buf[256];
  1367. X  char *args[MAXARGS];
  1368. X
  1369. X  rc_name = findrcfile(rcfilename);
  1370. X
  1371. X  if ((fp = secfopen(rc_name, "r")) == NULL)
  1372. X    {
  1373. X      if (RcFileName && strcmp(RcFileName, rc_name) == 0)
  1374. X    {
  1375. X          /*
  1376. X           * User explicitly gave us that name,
  1377. X           * this is the only case, where we get angry, if we can't read
  1378. X           * the file.
  1379. X           */
  1380. X      debug3("StartRc: '%s','%s', '%s'\n", RcFileName, rc_name, rcfilename);
  1381. X          Panic(0, "Unable to open \"%s\".", rc_name);
  1382. X      /* NOTREACHED */
  1383. X    }
  1384. X      debug1("StartRc: '%s' no good. ignored\n", rc_name);
  1385. X      Free(rc_name);
  1386. X      rc_name = "";
  1387. X      return;
  1388. X    }
  1389. X  while (fgets(buf, sizeof buf, fp) != NULL)
  1390. X    {
  1391. X      if ((p = rindex(buf, '\n')) != NULL)
  1392. X    *p = '\0';
  1393. X      if ((argc = Parse(buf, args)) == 0)
  1394. X    continue;
  1395. X      if (strcmp(args[0], "echo") == 0)
  1396. X    {
  1397. X      if (!display)
  1398. X        continue;
  1399. X      if (argc < 2 || (argc == 3 && strcmp(args[1], "-n")) || argc > 3)
  1400. X        {
  1401. X          Msg(0, "%s: 'echo [-n] \"string\"' expected.", rc_name);
  1402. X          continue;
  1403. X        }
  1404. X      AddStr(args[argc - 1]);
  1405. X      if (argc != 3)
  1406. X        {
  1407. X          AddStr("\r\n");
  1408. X          Flush();
  1409. X        }
  1410. X    }
  1411. X      else if (strcmp(args[0], "sleep") == 0)
  1412. X    {
  1413. X      if (!display)
  1414. X        continue;
  1415. X      debug("sleeeeeeep\n");
  1416. X      if (argc != 2)
  1417. X        {
  1418. X          Msg(0, "%s: sleep: one numeric argument expected.", rc_name);
  1419. X          continue;
  1420. X        }
  1421. X      DisplaySleep(atoi(args[1]));
  1422. X    }
  1423. X#ifdef TERMINFO
  1424. X      else if (strcmp(args[0], "terminfo") == 0)
  1425. X#else
  1426. X      else if (strcmp(args[0], "termcap") == 0)
  1427. X#endif
  1428. X    {
  1429. X      if (!display)
  1430. X        continue;
  1431. X      if (argc < 3 || argc > 4)
  1432. X        {
  1433. X          Msg(0, "%s: %s: incorrect number of arguments.", rc_name, args[0]);
  1434. X          continue;
  1435. X        }
  1436. X      for (p = args[1]; p && *p; p = cp)
  1437. X        {
  1438. X          if ((cp = index(p, '|')) != 0)
  1439. X        *cp++ = '\0';
  1440. X          len = strlen(p);
  1441. X          if (p[len - 1] == '*')
  1442. X        {
  1443. X          if (!(len - 1) || !strncmp(p, d_termname, len - 1))
  1444. X            break;
  1445. X        }
  1446. X          else if (!strcmp(p, d_termname))
  1447. X        break;
  1448. X        }
  1449. X      if (!(p && *p))
  1450. X        continue;
  1451. X      extra_incap = CatExtra(args[2], extra_incap);
  1452. X      if (argc == 4)
  1453. X        extra_outcap = CatExtra(args[3], extra_outcap);
  1454. X    }
  1455. X    }
  1456. X  fclose(fp);
  1457. X  Free(rc_name);
  1458. X  rc_name = "";
  1459. X}
  1460. X
  1461. Xvoid
  1462. XFinishRc(rcfilename)
  1463. Xchar *rcfilename;
  1464. X{
  1465. X  char buf[256];
  1466. X
  1467. X  rc_name = findrcfile(rcfilename);
  1468. X
  1469. X  if ((fp = secfopen(rc_name, "r")) == NULL)
  1470. X    {
  1471. X      if (RcFileName && strcmp(RcFileName, rc_name) == 0)
  1472. X    {
  1473. X          /*
  1474. X        * User explicitly gave us that name, 
  1475. X       * this is the only case, where we get angry, if we can't read
  1476. X       * the file.
  1477. X       */
  1478. X        debug3("FinishRc:'%s','%s','%s'\n", RcFileName, rc_name, rcfilename);
  1479. X          Panic(0, "Unable to open \"%s\".", rc_name);
  1480. X      /* NOTREACHED */
  1481. X    }
  1482. X      debug1("FinishRc: '%s' no good. ignored\n", rc_name);
  1483. X      Free(rc_name);
  1484. X      rc_name = "";
  1485. X      return;
  1486. X    }
  1487. X
  1488. X  debug("finishrc is going...\n");
  1489. X  while (fgets(buf, sizeof buf, fp) != NULL)
  1490. X    {
  1491. X      RcLine(buf);
  1492. X    }
  1493. X  (void) fclose(fp);
  1494. X  Free(rc_name);
  1495. X  rc_name = "";
  1496. X}
  1497. X
  1498. X/*
  1499. X *    "$HOST blafoo"       -> "localhost blafoo"
  1500. X *    "${HOST}blafoo"          -> "localhostblafoo"
  1501. X *    "\$HOST blafoo"     -> "$HOST blafoo"
  1502. X *    "\\$HOST blafoo"    -> "\localhost blafoo"
  1503. X *    "'$HOST ${HOST}'"    -> "'$HOST ${HOST}'" 
  1504. X *    "'\$HOST'"           -> "'\$HOST'"
  1505. X *    "\'$HOST' $HOST"       -> "'localhost' $HOST"
  1506. X *
  1507. X *    "$:termcapname:"    -> "termcapvalue"
  1508. X *    "$:terminfoname:"    -> "termcapvalue"
  1509. X *
  1510. X *    "\101"            -> "A"
  1511. X */
  1512. Xchar *
  1513. Xexpand_vars(ss)
  1514. Xchar *ss;
  1515. X{
  1516. X  static char ebuf[2048];
  1517. X  register int esize = 2047, vtype, quofl = 0;
  1518. X  register char *e = ebuf;
  1519. X  register char *s = ss;
  1520. X  register char *v;
  1521. X  char xbuf[11];
  1522. X
  1523. X  while (*s && *s != '\0' && *s != '\n' && esize > 0)
  1524. X    {
  1525. X      if (*s == '\'')
  1526. X    quofl ^= 1;
  1527. X      if (*s == '$' && !quofl)
  1528. X    {
  1529. X      char *p, c;
  1530. X
  1531. X      p = ++s;
  1532. X      switch (*s)
  1533. X        {
  1534. X        case '{':
  1535. X          p = ++s;
  1536. X          while (*p != '}')
  1537. X            if (*p++ == '\0')
  1538. X              return ss;
  1539. X          vtype = 0;        /* env var */
  1540. X          break;
  1541. X        case ':':
  1542. X          p = ++s;
  1543. X          while (*p != ':')
  1544. X        if (*p++ == '\0')
  1545. X          return ss;
  1546. X          vtype = 1;        /* termcap string */
  1547. X          break;
  1548. X        default:
  1549. X          while (*p != ' ' && *p != '\0' && *p != '\n')
  1550. X        p++;
  1551. X          vtype = 0;        /* env var */
  1552. X        }
  1553. X      c = *p;
  1554. X      debug1("exp: c='%c'\n", c);
  1555. X      *p = '\0';
  1556. X      if (vtype == 0)
  1557. X        {
  1558. X          v = xbuf;
  1559. X          if (strcmp(s, "TERM") == 0)
  1560. X        v = display ? d_termname : "unknown";
  1561. X          else if (strcmp(s, "COLUMNS") == 0)
  1562. X        sprintf(xbuf, "%d", display ? d_width : -1);
  1563. X          else if (strcmp(s, "LINES") == 0)
  1564. X        sprintf(xbuf, "%d", display ? d_height : -1);
  1565. X          else
  1566. X        v = getenv(s);
  1567. X        }
  1568. X      else
  1569. X        v = gettermcapstring(s);
  1570. X      if (v)
  1571. X        {
  1572. X          debug2("exp: $'%s'='%s'\n", s, v);
  1573. X          while (*v && esize-- > 0)
  1574. X            *e++ = *v++;
  1575. X        }
  1576. X      else 
  1577. X        debug1("exp: '%s' not env\n", s);  /* {-: */
  1578. X      if ((*p = c) == '}' || c == ':')
  1579. X        p++;
  1580. X      s = p;
  1581. X    }
  1582. X      else
  1583. X    {
  1584. X      /*
  1585. X       * \$, \\$, \\, \\\, \012 are reduced here, 
  1586. X       * d_other sequences starting whith \ are passed through.
  1587. X       */
  1588. X      if (s[0] == '\\' && !quofl)
  1589. X        {
  1590. X          if (s[1] >= '0' && s[1] <= '7')
  1591. X        {
  1592. X          int i;
  1593. X
  1594. X          s++;
  1595. X          i = *s - '0';
  1596. X          s++;
  1597. X          if (*s >= '0' && *s <= '7')
  1598. X            {
  1599. X              i = i * 8 + *s - '0';
  1600. X              s++;
  1601. X              if (*s >= '0' && *s <= '7')
  1602. X            {
  1603. X              i = i * 8 + *s - '0';
  1604. X              s++;
  1605. X            }
  1606. X            }
  1607. X          debug2("expandvars: octal coded character %o (%d)\n", i, i);
  1608. X          *e++ = i;
  1609. X        }
  1610. X          else
  1611. X        {
  1612. X          if (s[1] == '$' || 
  1613. X              (s[1] == '\\' && s[2] == '$') ||
  1614. X              s[1] == '\'' || 
  1615. X              (s[1] == '\\' && s[2] == '\''))
  1616. X            s++;
  1617. X        }
  1618. X        }
  1619. X      *e++ = *s++;
  1620. X      esize--;
  1621. X    }
  1622. X    }
  1623. X  if (esize <= 0)
  1624. X    Msg(0, "expand_vars: buffer overflow\n");
  1625. X  *e = '\0';
  1626. X  return ebuf;
  1627. X}
  1628. X
  1629. Xvoid
  1630. XRcLine(ubuf)
  1631. Xchar *ubuf;
  1632. X{
  1633. X  char *args[MAXARGS], *buf;
  1634. X  struct action act;
  1635. X
  1636. X  buf = expand_vars(ubuf); 
  1637. X  if (Parse(buf, args) <= 0)
  1638. X    return;
  1639. X  if ((act.nr = FindCommnr(*args)) == RC_ILLEGAL)
  1640. X    {
  1641. X      Msg(0, "%s: unknown command '%s'", rc_name, *args);
  1642. X      return;
  1643. X    }
  1644. X  act.args = args + 1;
  1645. X  DoAction(&act, -1);
  1646. X}
  1647. X
  1648. X
  1649. Xvoid
  1650. XWriteFile(dump)
  1651. Xint dump;
  1652. X{
  1653. X  /* dump==0:    create .termcap,
  1654. X   * dump==1:    hardcopy,
  1655. X   * #ifdef COPY_PASTE
  1656. X   * dump==2:    BUFFERFILE
  1657. X   * #endif COPY_PASTE 
  1658. X   */
  1659. X  register int i, j, k;
  1660. X  register char *p;
  1661. X  register FILE *f;
  1662. X  char fn[1024];
  1663. X  char *mode = "w";
  1664. X
  1665. X  switch (dump)
  1666. X    {
  1667. X    case DUMP_TERMCAP:
  1668. X      i = SockNamePtr - SockPath;
  1669. X      strncpy(fn, SockPath, i);
  1670. X      strcpy(fn + i, ".termcap");
  1671. X      break;
  1672. X    case DUMP_HARDCOPY:
  1673. X      if (hardcopydir)
  1674. X    sprintf(fn, "%s/hardcopy.%d", hardcopydir, fore->w_number);
  1675. X      else
  1676. X        sprintf(fn, "hardcopy.%d", fore->w_number);
  1677. X      if (hardcopy_append && !access(fn, W_OK))
  1678. X    mode = "a";
  1679. X      break;
  1680. X#ifdef COPY_PASTE
  1681. X    case DUMP_EXCHANGE:
  1682. X      sprintf(fn, "%s", BufferFile);
  1683. X      umask(0);
  1684. X      break;
  1685. X#endif
  1686. X    }
  1687. X
  1688. X  debug2("WriteFile(%d) %s\n", dump, fn);
  1689. X  if (UserContext() > 0)
  1690. X    {
  1691. X      debug("Writefile: usercontext\n");
  1692. X      if ((f = fopen(fn, mode)) == NULL)
  1693. X    {
  1694. X      debug2("WriteFile: fopen(%s,\"%s\") failed\n", fn, mode);
  1695. X      UserReturn(0);
  1696. X    }
  1697. X      else
  1698. X    {
  1699. X      switch (dump)
  1700. X        {
  1701. X        case DUMP_HARDCOPY:
  1702. X          if (*mode == 'a')
  1703. X        {
  1704. X          putc('>', f);
  1705. X          for (j = d_width - 2; j > 0; j--)
  1706. X            putc('=', f);
  1707. X          fputs("<\n", f);
  1708. X        }
  1709. X          for (i = 0; i < d_height; i++)
  1710. X        {
  1711. X          p = fore->w_image[i];
  1712. X          for (k = d_width - 1; k >= 0 && p[k] == ' '; k--)
  1713. X            ;
  1714. X          for (j = 0; j <= k; j++)
  1715. X            putc(p[j], f);
  1716. X          putc('\n', f);
  1717. X        }
  1718. X          break;
  1719. X        case DUMP_TERMCAP:
  1720. X          if ((p = index(MakeTermcap(fore->w_aflag), '=')) != NULL)
  1721. X        {
  1722. X          fputs(++p, f);
  1723. X          putc('\n', f);
  1724. X        }
  1725. X          break;
  1726. X#ifdef COPY_PASTE
  1727. X        case DUMP_EXCHANGE:
  1728. X          p = d_copybuffer;
  1729. X          for (i = 0; i < d_copylen; i++)
  1730. X        putc(*p++, f);
  1731. X          break;
  1732. X#endif
  1733. X        }
  1734. X      (void) fclose(f);
  1735. X      UserReturn(1);
  1736. X    }
  1737. X    }
  1738. X  if (UserStatus() <= 0)
  1739. X    Msg(0, "Cannot open \"%s\"", fn);
  1740. X  else
  1741. X    {
  1742. X      switch (dump)
  1743. X    {
  1744. X    case DUMP_TERMCAP:
  1745. X      Msg(0, "Termcap entry written to \"%s\".", fn);
  1746. X      break;
  1747. X    case DUMP_HARDCOPY:
  1748. X      Msg(0, "Screen image %s to \"%s\".",
  1749. X          (*mode == 'a') ? "appended" : "written", fn);
  1750. X      break;
  1751. X#ifdef COPY_PASTE
  1752. X    case DUMP_EXCHANGE:
  1753. X      Msg(0, "Copybuffer written to \"%s\".", fn);
  1754. X#endif
  1755. X    }
  1756. X    }
  1757. X}
  1758. X
  1759. X#ifdef COPY_PASTE
  1760. X
  1761. Xvoid
  1762. XReadFile()
  1763. X{
  1764. X  int i, l, size;
  1765. X  char fn[1024], c;
  1766. X  struct stat stb;
  1767. X
  1768. X  sprintf(fn, "%s", BufferFile);
  1769. X  debug1("ReadFile(%s)\n", fn);
  1770. X  if ((i = secopen(fn, O_RDONLY, 0)) < 0)
  1771. X    {
  1772. X      Msg(errno, "no %s -- no slurp", fn);
  1773. X      return;
  1774. X    }
  1775. X  if (fstat(i, &stb))
  1776. X    {
  1777. X      Msg(errno, "no good %s -- no slurp", fn);
  1778. X      close(i);
  1779. X      return;
  1780. X    }
  1781. X  size = stb.st_size;
  1782. X  if (d_copybuffer)
  1783. X    free(d_copybuffer);
  1784. X  d_copylen = 0;
  1785. X  if ((d_copybuffer = malloc(size)) == NULL)
  1786. X    {
  1787. X      close(i);
  1788. X      Msg(0, strnomem);
  1789. X      return;
  1790. X    }
  1791. X  errno = 0;
  1792. X  if ((l = read(i, d_copybuffer, size)) != size)
  1793. X    {
  1794. X      d_copylen = (l > 0) ? l : 0;
  1795. X#ifdef NETHACK
  1796. X      if (nethackflag)
  1797. X        Msg(errno, "You choke on your food: %d bytes", d_copylen);
  1798. X      else
  1799. X#endif
  1800. X      Msg(errno, "Got only %d bytes from %s", d_copylen, fn);
  1801. X      close(i);
  1802. X      return;
  1803. X    }
  1804. X  d_copylen = l;
  1805. X  if (read(i, &c, 1) > 0)
  1806. X    Msg(0, "Slurped only %d characters into buffer - try again", d_copylen);
  1807. X  else
  1808. X    Msg(0, "Slurped %d characters into buffer", d_copylen);
  1809. X  close(i);
  1810. X  return;
  1811. X}
  1812. X
  1813. Xvoid
  1814. XKillBuffers()
  1815. X{
  1816. X  char fn[1024];
  1817. X  sprintf(fn, "%s", BufferFile);
  1818. X  errno = 0;
  1819. X#ifndef NOREUID
  1820. X  setreuid(eff_uid, real_uid);
  1821. X  setregid(eff_gid, real_gid);
  1822. X#else
  1823. X  if (access(fn, W_OK) == -1)
  1824. X    {
  1825. X      Msg(errno, "%s not removed", fn);
  1826. X      return;
  1827. X    }
  1828. X#endif
  1829. X  unlink(fn);
  1830. X  Msg(errno, "%s removed", fn);
  1831. X#ifndef NOREUID
  1832. X  setreuid(real_uid, eff_uid);
  1833. X  setregid(real_gid, eff_gid);
  1834. X#endif
  1835. X}
  1836. X#endif    /* COPY_PASTE */
  1837. X
  1838. X
  1839. X/*
  1840. X * (Almost) secure open and fopen...
  1841. X */
  1842. X
  1843. XFILE *
  1844. Xsecfopen(name, mode)
  1845. Xchar *name;
  1846. Xchar *mode;
  1847. X{
  1848. X  FILE *fi;
  1849. X#ifdef NOREUID
  1850. X  int flags, fd;
  1851. X#endif
  1852. X
  1853. X  debug2("secfopen(%s, %s)\n", name, mode);
  1854. X#ifndef NOREUID
  1855. X  setreuid(eff_uid, real_uid);
  1856. X  setregid(eff_gid, real_gid);
  1857. X  fi = fopen(name, mode);
  1858. X  setreuid(real_uid, eff_uid);
  1859. X  setregid(real_gid, eff_gid);
  1860. X  return fi;
  1861. X#else
  1862. X  if (eff_uid == real_uid)
  1863. X    return(fopen(name, mode));
  1864. X  if (mode[0] && mode[1] == '+')
  1865. X    flags = O_RDWR;
  1866. X  else
  1867. X    flags = (mode[0] == 'r') ? O_RDONLY : O_WRONLY;
  1868. X  if (mode[0] == 'w')
  1869. X    flags |= O_CREAT | O_TRUNC;
  1870. X  else if (mode[0] == 'a')
  1871. X    flags |= O_CREAT | O_APPEND;
  1872. X  else if (mode[0] != 'r')
  1873. X    {
  1874. X      errno = EINVAL;
  1875. X      return(0);
  1876. X    }
  1877. X  if ((fd = secopen(name, flags, 0666)) < 0)
  1878. X    return(0);
  1879. X  if ((fi = fdopen(fd, mode)) == 0)
  1880. X    {
  1881. X      close(fd);
  1882. X      return(0);
  1883. X    }
  1884. X  return(fi);
  1885. X#endif
  1886. X}
  1887. X
  1888. X
  1889. Xint
  1890. Xsecopen(name, flags, mode)
  1891. Xchar *name;
  1892. Xint flags;
  1893. Xint mode;
  1894. X{
  1895. X  int fd;
  1896. X#ifdef NOREUID
  1897. X  int q;
  1898. X  struct stat stb;
  1899. X#endif
  1900. X
  1901. X  debug3("secopen(%s, 0x%x, 0%03o)\n", name, flags, mode);
  1902. X#ifndef NOREUID
  1903. X  setreuid(eff_uid, real_uid);
  1904. X  setregid(eff_gid, real_gid);
  1905. X  fd = open(name, flags, mode);
  1906. X  setreuid(real_uid, eff_uid);
  1907. X  setregid(real_gid, eff_gid);
  1908. X  return fd;
  1909. X#else
  1910. X  if (eff_uid == real_uid)
  1911. X    return(open(name, flags, mode));
  1912. X  /* Truncation/creation is done in UserContext */
  1913. X  if ((flags & O_TRUNC) || ((flags & O_CREAT) && access(name, F_OK)))
  1914. X    {
  1915. X      if (UserContext() > 0)
  1916. X    {
  1917. X          if ((fd = open(name, flags, mode)) >= 0)
  1918. X        {
  1919. X          close(fd);
  1920. X          UserReturn(0);
  1921. X            }
  1922. X      if (errno == 0)
  1923. X        errno = EACCES;
  1924. X      UserReturn(errno);
  1925. X    }
  1926. X      if (q = UserStatus())
  1927. X    {
  1928. X      if (q > 0)
  1929. X        errno = q;
  1930. X          return(-1);
  1931. X    }
  1932. X    }
  1933. X  if (access(name, F_OK))
  1934. X    return(-1);
  1935. X  if ((fd = open(name, flags & ~(O_TRUNC | O_CREAT), 0)) < 0)
  1936. X    return(-1);
  1937. X  debug("open successful\n");
  1938. X  if (fstat(fd, &stb))
  1939. X    {
  1940. X      close(fd);
  1941. X      return(-1);
  1942. X    }
  1943. X  debug("fstat successful\n");
  1944. X  if (stb.st_uid != real_uid)
  1945. X    {
  1946. X      switch (flags & (O_RDONLY | O_WRONLY | O_RDWR))
  1947. X        {
  1948. X    case O_RDONLY:
  1949. X      q = 0004;
  1950. X      break;
  1951. X    case O_WRONLY:
  1952. X      q = 0002;
  1953. X      break;
  1954. X    default:
  1955. X      q = 0006;
  1956. X      break;
  1957. X        }
  1958. X      if ((stb.st_mode & q) != q)
  1959. X    {
  1960. X          debug("secopen: permission denied\n");
  1961. X      close(fd);
  1962. X      errno = EACCES;
  1963. X      return(-1);
  1964. X    }
  1965. X    }
  1966. X  debug1("secopen ok - returning %d\n", fd);
  1967. X  return(fd);
  1968. X#endif
  1969. X}
  1970. END_OF_FILE
  1971. if test 15658 -ne `wc -c <'fileio.c'`; then
  1972.     echo shar: \"'fileio.c'\" unpacked with wrong size!
  1973. fi
  1974. # end of 'fileio.c'
  1975. fi
  1976. if test -f 'help.c' -a "${1}" != "-c" ; then 
  1977.   echo shar: Will not clobber existing file \"'help.c'\"
  1978. else
  1979. echo shar: Extracting \"'help.c'\" \(15096 characters\)
  1980. sed "s/^X//" >'help.c' <<'END_OF_FILE'
  1981. X/* Copyright (c) 1993
  1982. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  1983. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  1984. X * Copyright (c) 1987 Oliver Laumann
  1985. X *
  1986. X * This program is free software; you can redistribute it and/or modify
  1987. X * it under the terms of the GNU General Public License as published by
  1988. X * the Free Software Foundation; either version 2, or (at your option)
  1989. X * any later version.
  1990. X *
  1991. X * This program is distributed in the hope that it will be useful,
  1992. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1993. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1994. X * GNU General Public License for more details.
  1995. X *
  1996. X * You should have received a copy of the GNU General Public License
  1997. X * along with this program (see the file COPYING); if not, write to the
  1998. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1999. X *
  2000. X ****************************************************************
  2001. X */
  2002. X
  2003. X#include "rcs.h"
  2004. XRCS_ID("$Id: help.c,v 1.1.1.1 1993/06/16 23:51:12 jnweiger Exp $ FAU")
  2005. X
  2006. X#include <stdio.h>
  2007. X#include <sys/types.h>
  2008. X
  2009. X#include "config.h"
  2010. X
  2011. X#include "screen.h"
  2012. X#include "extern.h"
  2013. X
  2014. Xchar version[40];      /* initialised by main() */
  2015. Xextern char Esc, MetaEsc;
  2016. Xextern struct display *display;
  2017. Xextern char *noargs[];
  2018. X
  2019. X
  2020. Xvoid
  2021. Xexit_with_usage(myname)
  2022. Xchar *myname;
  2023. X{
  2024. X  printf("Use: %s [-opts] [cmd [args]]\n", myname);
  2025. X  printf(" or: %s -r [host.tty]\n\nOptions:\n", myname);
  2026. X  printf("-a           Force all capabilities into each window's termcap.\n");
  2027. X  printf("-A -[r|R]    Adapt all windows to the new display width & height.\n");
  2028. X  printf("-c file      Read configuration file instead of '.screenrc'.\n");
  2029. X#ifdef REMOTE_DETACH
  2030. X  printf("-d (-r)      Detach the elsewhere running screen (and reattach here).\n");
  2031. X  printf("-D (-r)      Detach and logout remote (and reattach here).\n");
  2032. X#endif
  2033. X  printf("-e xy        Change command characters.\n");
  2034. X  printf("-f           Flow control on, -fn = off, -fa = auto.\n");
  2035. X  printf("-h lines     Set the size of the scrollback history buffer.\n");
  2036. X  printf("-i           Interrupt output sooner when flow control is on.\n");
  2037. X  printf("-l           Login mode on (update %s), -ln = off.\n", UTMPFILE);
  2038. X  printf("-list        or -ls. Do nothing, just list our SockDir.\n");
  2039. X  printf("-L           Terminal's last character can be safely updated.\n");
  2040. X  printf("-m           ignore $STY variable, do create a new screen session.\n");
  2041. X  printf("-O           Choose optimal output rather than exact vt100 emulation.\n");
  2042. X  printf("-q           Quiet startup. Exits with non-zero return code if unsuccessful.\n");
  2043. X  printf("-r           Reattach to a detached screen process.\n");
  2044. X  printf("-R           Reattach if possible, otherwise start a new session.\n");
  2045. X  printf("-s shell     Shell to execute rather than $SHELL.\n");
  2046. X  printf("-S sockname  Name this session <pid>.sockname instead of <pid>.<tty>.<host>.\n");
  2047. X  printf("-t title     Set command's a.k.a. (window title).\n");
  2048. X  printf("-T term      Use term as $TERM for windows, rather than \"screen\".\n");
  2049. X  printf("-v           Print \"Screen version %s\".\n", version);
  2050. X  printf("-wipe        Do nothing, just clean up SockDir.\n");
  2051. X#ifdef MULTI
  2052. X  printf("-x           Attach to a not detached screen. (Multi display mode).\n");
  2053. X#endif /* MULTI */
  2054. X  exit(1);
  2055. X}
  2056. X
  2057. X
  2058. X/*
  2059. X**   Here come the help page routines
  2060. X*/
  2061. X
  2062. Xextern struct comm comms[];
  2063. Xextern struct action ktab[];
  2064. X
  2065. Xstatic void HelpProcess __P((char **, int *));
  2066. Xstatic void HelpAbort __P((void));
  2067. Xstatic void HelpRedisplayLine __P((int, int, int, int));
  2068. Xstatic void HelpSetCursor __P((void));
  2069. Xstatic void add_key_to_buf __P((char *, int));
  2070. Xstatic int  helppage __P((void));
  2071. X
  2072. Xstruct helpdata
  2073. X{
  2074. X  int    maxrow, grow, numcols, numrows, num_names;
  2075. X  int    numskip, numpages;
  2076. X  int    command_search, command_bindings;
  2077. X  int   refgrow, refcommand_search;
  2078. X  int   inter, mcom, mkey;
  2079. X  int   nact[RC_LAST + 1];
  2080. X};
  2081. X
  2082. X#define MAXKLEN 256
  2083. X
  2084. Xstatic struct LayFuncs HelpLf =
  2085. X{
  2086. X  HelpProcess,
  2087. X  HelpAbort,
  2088. X  HelpRedisplayLine,
  2089. X  DefClearLine,
  2090. X  DefRewrite,
  2091. X  HelpSetCursor,
  2092. X  DefResize,
  2093. X  DefRestore
  2094. X};
  2095. X
  2096. X
  2097. Xvoid
  2098. Xdisplay_help()
  2099. X{
  2100. X  int i, n, key, mcom, mkey, l;
  2101. X  struct helpdata *helpdata;
  2102. X  int used[RC_LAST + 1];
  2103. X
  2104. X  if (d_height < 6)
  2105. X    {
  2106. X      Msg(0, "Window height too small for help page");
  2107. X      return;
  2108. X    }
  2109. X  if (InitOverlayPage(sizeof(*helpdata), &HelpLf, 0))
  2110. X    return;
  2111. X
  2112. X  helpdata = (struct helpdata *)d_lay->l_data;
  2113. X  helpdata->num_names = helpdata->command_bindings = 0;
  2114. X  helpdata->command_search = 0;
  2115. X  for (n = 0; n <= RC_LAST; n++)
  2116. X    used[n] = 0;
  2117. X  mcom = 0;
  2118. X  mkey = 0;
  2119. X  for (key = 0; key < 256; key++)
  2120. X    {
  2121. X      n = ktab[key].nr;
  2122. X      if (n == RC_ILLEGAL)
  2123. X    continue;
  2124. X      if (ktab[key].args == noargs)
  2125. X    {
  2126. X          used[n] += (key <= ' ' || key == 0x7f) ? 3 :
  2127. X                     (key > 0x7f) ? 5 : 2;
  2128. X    }
  2129. X      else
  2130. X    helpdata->command_bindings++;
  2131. X    }
  2132. X  for (n = i = 0; n <= RC_LAST; n++)
  2133. X    if (used[n])
  2134. X      {
  2135. X    l = strlen(comms[n].name);
  2136. X    if (l > mcom)
  2137. X      mcom = l;
  2138. X    if (used[n] > mkey)
  2139. X      mkey = used[n];
  2140. X        helpdata->nact[i++] = n;
  2141. X      }
  2142. X  debug1("help: %d commands bound to keys with no arguments\n", i);
  2143. X  debug2("mcom: %d  mkey: %d\n", mcom, mkey);
  2144. X  helpdata->num_names = i;
  2145. X
  2146. X  if (mkey > MAXKLEN)
  2147. X    mkey = MAXKLEN;
  2148. X  helpdata->numcols = (d_width - !CLP)/(mcom + mkey + 1);
  2149. X  if (helpdata->numcols == 0)
  2150. X    {
  2151. X      HelpAbort();
  2152. X      Msg(0, "Width too small");
  2153. X      return;
  2154. X    }
  2155. X  helpdata->inter = (d_width - !CLP - (mcom + mkey) * helpdata->numcols) / (helpdata->numcols + 1);
  2156. X  if (helpdata->inter <= 0)
  2157. X    helpdata->inter = 1;
  2158. X  debug1("inter: %d\n", helpdata->inter);
  2159. X  helpdata->mcom = mcom;
  2160. X  helpdata->mkey = mkey;
  2161. X  helpdata->numrows = (helpdata->num_names + helpdata->numcols - 1) / helpdata->numcols;
  2162. X  debug1("Numrows: %d\n", helpdata->numrows);
  2163. X  helpdata->numskip = d_height-5 - (2 + helpdata->numrows);
  2164. X  while (helpdata->numskip < 0)
  2165. X    helpdata->numskip += d_height-5;
  2166. X  helpdata->numskip %= d_height-5;
  2167. X  debug1("Numskip: %d\n", helpdata->numskip);
  2168. X  if (helpdata->numskip > d_height/3 || helpdata->numskip > helpdata->command_bindings)
  2169. X    helpdata->numskip = 1;
  2170. X  helpdata->maxrow = 2 + helpdata->numrows + helpdata->numskip + helpdata->command_bindings;
  2171. X  helpdata->grow = 0;
  2172. X
  2173. X  helpdata->numpages = (helpdata->maxrow + d_height-6) / (d_height-5);
  2174. X  helppage();
  2175. X}
  2176. X
  2177. Xstatic void
  2178. XHelpSetCursor()
  2179. X{
  2180. X  GotoPos(0, d_height - 1);
  2181. X}
  2182. X
  2183. Xstatic void
  2184. XHelpProcess(ppbuf, plen)
  2185. Xchar **ppbuf;
  2186. Xint *plen;
  2187. X{
  2188. X  int done = 0;
  2189. X
  2190. X  GotoPos(0, d_height-1);
  2191. X  while (!done && *plen > 0)
  2192. X    {
  2193. X      switch (**ppbuf)
  2194. X    {
  2195. X    case ' ':
  2196. X      if (helppage() == 0)
  2197. X            break;
  2198. X      /* FALLTHROUGH */
  2199. X    case '\r':
  2200. X    case '\n':
  2201. X      done = 1;
  2202. X      break;
  2203. X    default:
  2204. X      break;
  2205. X    }
  2206. X      ++*ppbuf;
  2207. X      --*plen;
  2208. X    }
  2209. X  if (done)
  2210. X    HelpAbort();
  2211. X}
  2212. X
  2213. Xstatic void
  2214. XHelpAbort()
  2215. X{
  2216. X  LAY_CALL_UP(Activate(0));
  2217. X  ExitOverlayPage();
  2218. X}
  2219. X
  2220. X
  2221. Xstatic int
  2222. Xhelppage()
  2223. X{
  2224. X  struct helpdata *helpdata;
  2225. X  int col, crow, n, key;
  2226. X  char buf[MAXKLEN], Esc_buf[5], cbuf[256];
  2227. X
  2228. X  helpdata = (struct helpdata *)d_lay->l_data;
  2229. X
  2230. X  if (helpdata->grow >= helpdata->maxrow)
  2231. X    { 
  2232. X      return(-1);
  2233. X    }
  2234. X  helpdata->refgrow = helpdata->grow;
  2235. X  helpdata->refcommand_search = helpdata->command_search;
  2236. X
  2237. X  /* Clear the help screen */
  2238. X  SetAttrFont(0, ASCII);
  2239. X  ClearDisplay();
  2240. X  
  2241. X  sprintf(cbuf,"Screen key bindings, page %d of %d.", helpdata->grow / (d_height-5) + 1, helpdata->numpages);
  2242. X  centerline(cbuf);
  2243. X  AddChar('\n');
  2244. X  crow = 2;
  2245. X
  2246. X  *Esc_buf = '\0';
  2247. X  add_key_to_buf(Esc_buf, Esc);
  2248. X
  2249. X  for (; crow < d_height - 3; crow++)
  2250. X    {
  2251. X      if (helpdata->grow < 1)
  2252. X        {
  2253. X         *buf = '\0';
  2254. X          add_key_to_buf(buf, MetaEsc);
  2255. X          sprintf(cbuf,"Command key:  %s   Literal %s:  %s", Esc_buf, Esc_buf, buf);
  2256. X          centerline(cbuf);
  2257. X      helpdata->grow++;
  2258. X        }
  2259. X      else if (helpdata->grow >= 2 && helpdata->grow-2 < helpdata->numrows)
  2260. X    {
  2261. X      for (col = 0; col < helpdata->numcols && (n = helpdata->numrows * col + (helpdata->grow-2)) < helpdata->num_names; col++)
  2262. X        {
  2263. X          AddStrn("", helpdata->inter - !col);
  2264. X          n = helpdata->nact[n];
  2265. X          debug1("help: searching key %d\n", n);
  2266. X          buf[0] = '\0';
  2267. X          for (key = 0; key < 256; key++)
  2268. X        if (ktab[key].nr == n && ktab[key].args == noargs)
  2269. X          {
  2270. X            strcat(buf, " ");
  2271. X            add_key_to_buf(buf, key);
  2272. X          }
  2273. X          AddStrn(comms[n].name, helpdata->mcom);
  2274. X          AddStrn(buf, helpdata->mkey);
  2275. X        }
  2276. X      AddStr("\r\n");
  2277. X          helpdata->grow++;
  2278. X        }
  2279. X      else if (helpdata->grow-2-helpdata->numrows >= helpdata->numskip 
  2280. X               && helpdata->grow-2-helpdata->numrows-helpdata->numskip < helpdata->command_bindings)
  2281. X        {
  2282. X          char **pp, *cp;
  2283. X
  2284. X      while ((n = ktab[helpdata->command_search].nr) == RC_ILLEGAL
  2285. X         || ktab[helpdata->command_search].args == noargs)
  2286. X        {
  2287. X          if (++helpdata->command_search >= 256)
  2288. X        return -1;
  2289. X        }
  2290. X      buf[0] = '\0';
  2291. X      add_key_to_buf(buf, helpdata->command_search);
  2292. X      AddStrn(buf, 4);
  2293. X      col = 4;
  2294. X      AddStr(comms[n].name);
  2295. X      AddChar(' ');
  2296. X      col += strlen(comms[n].name) + 1;
  2297. X      pp = ktab[helpdata->command_search++].args;
  2298. X      while (pp && (cp = *pp) != NULL)
  2299. X        {
  2300. X          if (!*cp || (index(cp, ' ') != NULL))
  2301. X        {
  2302. X          if (index(cp, '\'') != NULL)
  2303. X            *buf = '"';
  2304. X          else
  2305. X            *buf = '\'';
  2306. X          sprintf(buf + 1, "%s%c", cp, *buf);
  2307. X          cp = buf;
  2308. X        }
  2309. X          if ((col += strlen(cp) + 1) >= d_width)
  2310. X        {
  2311. X          col = d_width - (col - (strlen(cp) + 1)) - 2;
  2312. X          if (col >= 0)
  2313. X            {
  2314. X              n = cp[col];
  2315. X              cp[col] = '\0';
  2316. X              AddStr(*pp);
  2317. X              AddChar('$');
  2318. X              cp[col] = (char) n;
  2319. X              }
  2320. X              break;
  2321. X            }
  2322. X          AddStr(cp);
  2323. X          AddChar((d_width - col != 1 || !pp[1]) ? ' ' : '$');
  2324. X          pp++;
  2325. X        }
  2326. X      AddStr("\r\n");
  2327. X      helpdata->grow++;
  2328. X    }
  2329. X      else
  2330. X    {
  2331. X          AddChar('\n');
  2332. X      helpdata->grow++;
  2333. X    }
  2334. X    }
  2335. X  AddChar('\n');
  2336. X  sprintf(cbuf,"[Press Space %s Return to end.]",
  2337. X     helpdata->grow < helpdata->maxrow ? "for next page;" : "or");
  2338. X  centerline(cbuf);
  2339. X  SetLastPos(0, d_height-1);
  2340. X  return(0);
  2341. X}
  2342. X
  2343. Xstatic void
  2344. Xadd_key_to_buf(buf, key)
  2345. Xchar *buf;
  2346. Xint key;
  2347. X{
  2348. X  debug1("help: key found: %c\n", key);
  2349. X  buf += strlen(buf);
  2350. X  if (key == ' ')
  2351. X    sprintf(buf, "sp");
  2352. X  else if (key < ' ' || key == 0x7f)
  2353. X    sprintf(buf, "^%c", (key ^ 0x40));
  2354. X  else if (key >= 0x80)
  2355. X    sprintf(buf, "\\%03o", key);
  2356. X  else
  2357. X    sprintf(buf, "%c", key);
  2358. X}
  2359. X
  2360. X
  2361. Xstatic void
  2362. XHelpRedisplayLine(y, xs, xe, isblank)
  2363. Xint y, xs, xe, isblank;
  2364. X{
  2365. X  if (y < 0)
  2366. X    {
  2367. X      struct helpdata *helpdata;
  2368. X
  2369. X      helpdata = (struct helpdata *)d_lay->l_data;
  2370. X      helpdata->grow = helpdata->refgrow;
  2371. X      helpdata->command_search = helpdata->refcommand_search;
  2372. X      helppage();
  2373. X      return;
  2374. X    }
  2375. X  if (y != 0 && y != d_height - 1)
  2376. X    return;
  2377. X  if (isblank)
  2378. X    return;
  2379. X  Clear(xs, y, xe, y);
  2380. X}
  2381. X
  2382. X
  2383. X/*
  2384. X**
  2385. X**    here is all the copyright stuff 
  2386. X**
  2387. X*/
  2388. X
  2389. Xstatic void CopyrightProcess __P((char **, int *));
  2390. Xstatic void CopyrightRedisplayLine __P((int, int, int, int));
  2391. Xstatic void CopyrightAbort __P((void));
  2392. Xstatic void CopyrightSetCursor __P((void));
  2393. Xstatic void copypage __P((void));
  2394. X
  2395. Xstruct copydata
  2396. X{
  2397. X  char    *cps, *savedcps;    /* position in the message */
  2398. X  char    *refcps, *refsavedcps;    /* backup for redisplaying */
  2399. X};
  2400. X
  2401. Xstatic struct LayFuncs CopyrightLf =
  2402. X{
  2403. X  CopyrightProcess,
  2404. X  CopyrightAbort,
  2405. X  CopyrightRedisplayLine,
  2406. X  DefClearLine,
  2407. X  DefRewrite,
  2408. X  CopyrightSetCursor,
  2409. X  DefResize,
  2410. X  DefRestore
  2411. X};
  2412. X
  2413. Xstatic const char cpmsg[] = "\
  2414. X\n\
  2415. XiScreen version %v\n\
  2416. X\n\
  2417. XCopyright (c) 1993 Juergen Weigert, Michael Schroeder\n\
  2418. XCopyright (c) 1987 Oliver Laumann\n\
  2419. X\n\
  2420. XThis program is free software; you can redistribute it and/or \
  2421. Xmodify it under the terms of the GNU General Public License as published \
  2422. Xby the Free Software Foundation; either version 1, or (at your option) \
  2423. Xany later version.\n\
  2424. X\n\
  2425. XThis program is distributed in the hope that it will be useful, \
  2426. Xbut WITHOUT ANY WARRANTY; without even the implied warranty of \
  2427. XMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \
  2428. XGNU General Public License for more details.\n\
  2429. X\n\
  2430. XYou should have received a copy of the GNU General Public License \
  2431. Xalong with this program (see the file COPYING); if not, write to the \
  2432. XFree Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\
  2433. X\n\
  2434. XSend bugreports, fixes, enhancements, t-shirts, money, beer & pizza to \
  2435. Xscreen@informatik.uni-erlangen.de\n";
  2436. X
  2437. X
  2438. Xstatic void
  2439. XCopyrightSetCursor()
  2440. X{
  2441. X  GotoPos(0, d_height - 1);
  2442. X}
  2443. X
  2444. Xstatic void
  2445. XCopyrightProcess(ppbuf, plen)
  2446. Xchar **ppbuf;
  2447. Xint *plen;
  2448. X{
  2449. X  int done = 0;
  2450. X  struct copydata *copydata;
  2451. X
  2452. X  copydata = (struct copydata *)d_lay->l_data;
  2453. X  GotoPos(0, d_height - 1);
  2454. X  while (!done && *plen > 0)
  2455. X    {
  2456. X      switch (**ppbuf)
  2457. X    {
  2458. X    case ' ':
  2459. X          if (*copydata->cps)
  2460. X        {
  2461. X          copypage();
  2462. X          break;
  2463. X        }
  2464. X      /* FALLTHROUGH */
  2465. X    case '\r':
  2466. X    case '\n':
  2467. X      CopyrightAbort();
  2468. X      done = 1;
  2469. X      break;
  2470. X    default:
  2471. X      break;
  2472. X    }
  2473. X      ++*ppbuf;
  2474. X      --*plen;
  2475. X    }
  2476. X}
  2477. X
  2478. Xstatic void
  2479. XCopyrightAbort()
  2480. X{
  2481. X  LAY_CALL_UP(Activate(0));
  2482. X  ExitOverlayPage();
  2483. X}
  2484. X
  2485. Xvoid
  2486. Xdisplay_copyright()
  2487. X{
  2488. X  struct copydata *copydata;
  2489. X
  2490. X  if (d_width < 10 || d_height < 5)
  2491. X    {
  2492. X      Msg(0, "Window size too small for copyright page");
  2493. X      return;
  2494. X    }
  2495. X  if (InitOverlayPage(sizeof(*copydata), &CopyrightLf, 0))
  2496. X    return;
  2497. X  copydata = (struct copydata *)d_lay->l_data;
  2498. X  copydata->cps = (char *)cpmsg;
  2499. X  copydata->savedcps = 0;
  2500. X  copypage();
  2501. X}
  2502. X
  2503. X
  2504. Xstatic void
  2505. Xcopypage()
  2506. X{
  2507. X  register char *cps;
  2508. X  char *ws;
  2509. X  int x, y, l;
  2510. X  char cbuf[80];
  2511. X  struct copydata *copydata;
  2512. X
  2513. X  copydata = (struct copydata *)d_lay->l_data;
  2514. X  SetAttrFont(0, ASCII);
  2515. X  ClearDisplay();
  2516. X  x = y = 0;
  2517. X  cps = copydata->cps;
  2518. X  copydata->refcps = cps;
  2519. X  copydata->refsavedcps = copydata->savedcps;
  2520. X  while (*cps && y < d_height - 3)
  2521. X    {
  2522. X      ws = cps;
  2523. X      while (*cps == ' ')
  2524. X    cps++;
  2525. X      if (strncmp(cps, "%v", 2) == 0)
  2526. X    {
  2527. X      copydata->savedcps = cps + 2;
  2528. X      cps = version;
  2529. X      continue;
  2530. X    }
  2531. X      while (*cps && *cps != ' ' && *cps != '\n')
  2532. X    cps++;
  2533. X      l = cps - ws;
  2534. X      cps = ws;
  2535. X      if (l > d_width - 1)
  2536. X    l = d_width - 1;
  2537. X      if (x && x + l >= d_width - 2)
  2538. X    {
  2539. X      AddStr("\r\n");
  2540. X      x = 0;
  2541. X      y++;
  2542. X      continue;
  2543. X    }
  2544. X      if (x)
  2545. X    {
  2546. X      AddChar(' ');
  2547. X      x++;
  2548. X    }
  2549. X      if (l)
  2550. X        AddStrn(ws, l);
  2551. X      x += l;
  2552. X      cps += l;
  2553. X      if (*cps == 0 && copydata->savedcps)
  2554. X    {
  2555. X      cps = copydata->savedcps;
  2556. X      copydata->savedcps = 0;
  2557. X    }
  2558. X      if (*cps == '\n')
  2559. X    {
  2560. X      AddStr("\r\n");
  2561. X      x = 0;
  2562. X      y++;
  2563. X    }
  2564. X      if (*cps == ' ' || *cps == '\n')
  2565. X    cps++;
  2566. X    }
  2567. X  while (*cps == '\n')
  2568. X    cps++;
  2569. X  while (y++ < d_height - 2)
  2570. X    AddStr("\r\n");
  2571. X  sprintf(cbuf,"[Press Space %s Return to end.]",
  2572. X     *cps ? "for next page;" : "or");
  2573. X  centerline(cbuf);
  2574. X  SetLastPos(0, d_height-1);
  2575. X  copydata->cps = cps;
  2576. X}
  2577. X
  2578. Xstatic void
  2579. XCopyrightRedisplayLine(y, xs, xe, isblank)
  2580. Xint y, xs, xe, isblank;
  2581. X{
  2582. X  if (y < 0)
  2583. X    {
  2584. X      struct copydata *copydata;
  2585. X
  2586. X      copydata = (struct copydata *)d_lay->l_data;
  2587. X      copydata->cps = copydata->refcps;
  2588. X      copydata->savedcps = copydata->refsavedcps;
  2589. X      copypage();
  2590. X      return;
  2591. X    }
  2592. X  if (y != 0 && y != d_height - 1)
  2593. X    return;
  2594. X  if (isblank)
  2595. X    return;
  2596. X  Clear(xs, y, xe, y);
  2597. X}
  2598. X
  2599. END_OF_FILE
  2600. if test 15096 -ne `wc -c <'help.c'`; then
  2601.     echo shar: \"'help.c'\" unpacked with wrong size!
  2602. fi
  2603. # end of 'help.c'
  2604. fi
  2605. if test -f 'termcap.c' -a "${1}" != "-c" ; then 
  2606.   echo shar: Will not clobber existing file \"'termcap.c'\"
  2607. else
  2608. echo shar: Extracting \"'termcap.c'\" \(14829 characters\)
  2609. sed "s/^X//" >'termcap.c' <<'END_OF_FILE'
  2610. X/* Copyright (c) 1993
  2611. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  2612. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  2613. X * Copyright (c) 1987 Oliver Laumann
  2614. X *
  2615. X * This program is free software; you can redistribute it and/or modify
  2616. X * it under the terms of the GNU General Public License as published by
  2617. X * the Free Software Foundation; either version 2, or (at your option)
  2618. X * any later version.
  2619. X *
  2620. X * This program is distributed in the hope that it will be useful,
  2621. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2622. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2623. X * GNU General Public License for more details.
  2624. X *
  2625. X * You should have received a copy of the GNU General Public License
  2626. X * along with this program (see the file COPYING); if not, write to the
  2627. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  2628. X *
  2629. X ****************************************************************
  2630. X */
  2631. X
  2632. X#include "rcs.h"
  2633. XRCS_ID("$Id: termcap.c,v 1.3 1993/07/21 15:43:35 mlschroe Exp $ FAU")
  2634. X
  2635. X#include <sys/types.h>
  2636. X#include "config.h"
  2637. X#include "screen.h"
  2638. X#include "extern.h"
  2639. X
  2640. Xextern struct display *display;
  2641. X
  2642. Xstatic void  AddCap __P((char *));
  2643. Xstatic void  MakeString __P((char *, char *, int, char *));
  2644. Xstatic char *findcap __P((char *, char **, int));
  2645. Xstatic char *e_tgetstr __P((char *, char **));
  2646. Xstatic int   e_tgetflag __P((char *));
  2647. Xstatic int   e_tgetnum __P((char *));
  2648. X
  2649. Xextern struct term term[];    /* terminal capabilities */
  2650. Xextern struct NewWindow nwin_undef, nwin_default, nwin_options;
  2651. Xextern int force_vt, assume_LP;
  2652. Xextern int Z0width, Z1width;
  2653. X
  2654. Xchar Termcap[TERMCAP_BUFSIZE + 8];    /* new termcap +8:"TERMCAP=" */
  2655. Xstatic int Termcaplen;
  2656. Xstatic int tcLineLen;
  2657. Xchar Term[MAXSTR+5];        /* +5: "TERM=" */
  2658. Xchar screenterm[20];        /* new $TERM, usually "screen" */
  2659. X
  2660. Xchar *extra_incap, *extra_outcap;
  2661. X
  2662. Xstatic const char TermcapConst[] = "\\\n\
  2663. X\t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\
  2664. X\t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\
  2665. X\t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\
  2666. X\t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:";
  2667. X
  2668. Xchar *
  2669. Xgettermcapstring(s)
  2670. Xchar *s;
  2671. X{
  2672. X  int i;
  2673. X
  2674. X  if (display == 0 || s == 0)
  2675. X    return 0;
  2676. X  for (i = 0; i < T_N; i++)
  2677. X    {
  2678. X      if (term[i].type != T_STR)
  2679. X    continue;
  2680. X      if (strcmp(term[i].tcname, s) == 0)
  2681. X    return d_tcs[i].str;
  2682. X    }
  2683. X  return 0;
  2684. X}
  2685. X
  2686. Xint
  2687. XInitTermcap(wi, he)
  2688. Xint wi;
  2689. Xint he;
  2690. X{
  2691. X  register char *s;
  2692. X  int i;
  2693. X  char tbuf[TERMCAP_BUFSIZE], *tp;
  2694. X
  2695. X  ASSERT(display);
  2696. X  bzero(tbuf, sizeof(tbuf));
  2697. X  debug1("InitTermcap: looking for tgetent('%s')\n", d_termname);
  2698. X  if (tgetent(tbuf, d_termname) != 1)
  2699. X    {
  2700. X      Msg(0, "Cannot find termcap entry for %s.", d_termname);
  2701. X      return -1;
  2702. X    }
  2703. X  debug1("got it:\n%s\n",tbuf);
  2704. X#ifdef DEBUG
  2705. X  if (extra_incap)
  2706. X    debug1("Extra incap: %s\n", extra_incap);
  2707. X  if (extra_outcap)
  2708. X    debug1("Extra outcap: %s\n", extra_outcap);
  2709. X#endif
  2710. X  tp = d_tentry;
  2711. X
  2712. X  for (i = 0; i < T_N; i++)
  2713. X    {
  2714. X      switch(term[i].type)
  2715. X    {
  2716. X    case T_FLG:
  2717. X      d_tcs[i].flg = e_tgetflag(term[i].tcname);
  2718. X      break;
  2719. X    case T_NUM:
  2720. X      d_tcs[i].num = e_tgetnum(term[i].tcname);
  2721. X      break;
  2722. X    case T_STR:
  2723. X      d_tcs[i].str = e_tgetstr(term[i].tcname, &tp);
  2724. X      /* no empty strings, please */
  2725. X      if (d_tcs[i].str && *d_tcs[i].str == 0)
  2726. X        d_tcs[i].str = 0;
  2727. X      break;
  2728. X    default:
  2729. X      Panic(0, "Illegal tc type in entry #%d", i);
  2730. X      /*NOTREACHED*/
  2731. X    }
  2732. X    }
  2733. X  if (HC)
  2734. X    {
  2735. X      Msg(0, "You can't run screen on a hardcopy terminal.");
  2736. X      return -1;
  2737. X    }
  2738. X  if (OS)
  2739. X    {
  2740. X      Msg(0, "You can't run screen on a terminal that overstrikes.");
  2741. X      return -1;
  2742. X    }
  2743. X  if (NS)
  2744. X    {
  2745. X      Msg(0, "Terminal must support scrolling.");
  2746. X      return -1;
  2747. X    }
  2748. X  if (!CL)
  2749. X    {
  2750. X      Msg(0, "Clear screen capability required.");
  2751. X      return -1;
  2752. X    }
  2753. X  if (!CM)
  2754. X    {
  2755. X      Msg(0, "Addressable cursor capability required.");
  2756. X      return -1;
  2757. X    }
  2758. X  if ((s = getenv("COLUMNS")) && (i = atoi(s)) > 0)
  2759. X    CO = i;
  2760. X  if ((s = getenv("LINES")) && (i = atoi(s)) > 0)
  2761. X    LI = i;
  2762. X  if (wi)
  2763. X    CO = wi;
  2764. X  if (he)
  2765. X    LI = he;
  2766. X  if (CO <= 0)
  2767. X    CO = 80;
  2768. X  if (LI <= 0)
  2769. X    LI = 24;
  2770. X
  2771. X  if (nwin_options.flowflag == nwin_undef.flowflag)
  2772. X    nwin_default.flowflag = CNF ? FLOW_NOW * 0 : 
  2773. X                XO ? FLOW_NOW * 1 :
  2774. X                FLOW_AUTOFLAG;
  2775. X  CLP |= assume_LP || !AM || XV || XN ||
  2776. X     (!extra_incap && !strncmp(d_termname, "vt", 2));
  2777. X  if (!(BL = e_tgetstr("bl", &tp)))
  2778. X  if (!BL)
  2779. X    BL = "\007";
  2780. X  if (!BC)
  2781. X    {
  2782. X      if (BS)
  2783. X    BC = "\b";
  2784. X      else
  2785. X    BC = LE;
  2786. X    }
  2787. X  if (!CR)
  2788. X    CR = "\r";
  2789. X  if (!NL)
  2790. X    NL = "\n";
  2791. X  if (SG <= 0 && UG <= 0)
  2792. X    {
  2793. X      /*
  2794. X       * Does ME also reverse the effect of SO and/or US?  This is not
  2795. X       * clearly specified by the termcap manual. Anyway, we should at
  2796. X       * least look whether ME and SE/UE are equal:
  2797. X       */
  2798. X      if (UE && ((SE && strcmp(SE, UE) == 0) || (ME && strcmp(ME, UE) == 0)))
  2799. X    UE = 0;
  2800. X      if (SE && (ME && strcmp(ME, SE) == 0))
  2801. X    SE = 0;
  2802. X
  2803. X      for (i = 0; i < NATTR; i++)
  2804. X    d_attrtab[i] = d_tcs[T_ATTR + i].str;
  2805. X      /* Set up missing entries */
  2806. X      s = 0;
  2807. X      for (i = NATTR-1; i >= 0; i--)
  2808. X    if (d_attrtab[i])
  2809. X      s = d_attrtab[i];
  2810. X      for (i = 0; i < NATTR; i++)
  2811. X    {
  2812. X      if (d_attrtab[i] == 0)
  2813. X        d_attrtab[i] = s;
  2814. X      else
  2815. X        s = d_attrtab[i];
  2816. X    }
  2817. X    }
  2818. X  else
  2819. X    {
  2820. X      MS = 1;
  2821. X      for (i = 0; i < NATTR; i++)
  2822. X    d_attrtab[i] = d_tcs[T_ATTR + i].str = 0;
  2823. X    }
  2824. X  if (!DO)
  2825. X    DO = NL;
  2826. X  if (!SF)
  2827. X    SF = NL;
  2828. X  if (IN)
  2829. X    IC = IM = 0;
  2830. X  if (EI == 0)
  2831. X    IM = 0;
  2832. X  /* some strange termcap entries have IC == IM */
  2833. X  if (IC && IM && strcmp(IC, IM) == 0)
  2834. X    IC = 0;
  2835. X  if (KE == 0)
  2836. X    KS = 0;
  2837. X  if (CCE == 0)
  2838. X    CCS = 0;
  2839. X  if (CG0)
  2840. X    {
  2841. X      if (CS0 == 0)
  2842. X#ifdef TERMINFO
  2843. X        CS0 = "\033(%p1%c";
  2844. X#else
  2845. X        CS0 = "\033(%.";
  2846. X#endif
  2847. X      if (CE0 == 0)
  2848. X        CE0 = "\033(B";
  2849. X    }
  2850. X  else if (AS && AE)
  2851. X    {
  2852. X      CG0 = 1;
  2853. X      CS0 = AS;
  2854. X      CE0 = AE;
  2855. X      CC0 = AC;
  2856. X    }
  2857. X  else
  2858. X    {
  2859. X      CS0 = CE0 = "";
  2860. X      CC0 = "g.h.i'j-k-l-m-n+o~p\"q-r-s_t+u+v+w+x|y<z>";
  2861. X    }
  2862. X  for (i = 0; i < 256; i++)
  2863. X    d_c0_tab[i] = i;
  2864. X  if (CC0)
  2865. X    for (i = strlen(CC0) & ~1; i >= 0; i -= 2)
  2866. X      d_c0_tab[(unsigned int)CC0[i]] = CC0[i + 1];
  2867. X  debug1("ISO2022 = %d\n", CG0);
  2868. X  if (PF == 0)
  2869. X    PO = 0;
  2870. X  debug2("terminal size is %d, %d (says TERMCAP)\n", CO, LI);
  2871. X
  2872. X  /* Termcap fields Z0 & Z1 contain width-changing sequences. */
  2873. X  if (CZ1 == 0)
  2874. X    CZ0 = 0;
  2875. X  Z0width = 132;
  2876. X  Z1width = 80;
  2877. X
  2878. X  CheckScreenSize(0);
  2879. X
  2880. X  if (TS == 0 || FS == 0 || DS == 0)
  2881. X    HS = 0;
  2882. X  if (HS)
  2883. X    {
  2884. X      debug("oy! we have a hardware status line, says termcap\n");
  2885. X      if (WS <= 0)
  2886. X        WS = d_width;
  2887. X    }
  2888. X
  2889. X  d_UPcost = CalcCost(UP);
  2890. X  d_DOcost = CalcCost(DO);
  2891. X  d_NLcost = CalcCost(NL);
  2892. X  d_LEcost = CalcCost(BC);
  2893. X  d_NDcost = CalcCost(ND);
  2894. X  d_CRcost = CalcCost(CR);
  2895. X  d_IMcost = CalcCost(IM);
  2896. X  d_EIcost = CalcCost(EI);
  2897. X
  2898. X#ifdef AUTO_NUKE
  2899. X  if (CAN)
  2900. X    {
  2901. X      debug("termcap has AN, setting autonuke\n");
  2902. X      d_auto_nuke = 1;
  2903. X    }
  2904. X#endif
  2905. X  if (COL > 0)
  2906. X    {
  2907. X      debug1("termcap has OL (%d), setting limit\n", COL);
  2908. X      d_obufmax = COL;
  2909. X    }
  2910. X
  2911. X  d_tcinited = 1;
  2912. X  MakeTermcap(0);
  2913. X  return 0;
  2914. X}
  2915. X
  2916. X
  2917. Xstatic void
  2918. XAddCap(s)
  2919. Xchar *s;
  2920. X{
  2921. X  register int n;
  2922. X
  2923. X  if (tcLineLen + (n = strlen(s)) > 55 && Termcaplen < TERMCAP_BUFSIZE - 4)
  2924. X    {
  2925. X      strcpy(Termcap + Termcaplen, "\\\n\t:");
  2926. X      Termcaplen += 4;
  2927. X      tcLineLen = 0;
  2928. X    }
  2929. X  if (Termcaplen + n < TERMCAP_BUFSIZE)
  2930. X    {
  2931. X      strcpy(Termcap + Termcaplen, s);
  2932. X      Termcaplen += n;
  2933. X      tcLineLen += n;
  2934. X    }
  2935. X  else
  2936. X    Panic(0, "TERMCAP overflow - sorry.");
  2937. X}
  2938. X
  2939. Xchar *
  2940. XMakeTermcap(aflag)
  2941. Xint aflag;
  2942. X{
  2943. X  char buf[TERMCAP_BUFSIZE];
  2944. X  register char *p, *cp, *s, ch, *tname;
  2945. X  int i, wi, he;
  2946. X
  2947. X  if (display)
  2948. X    {
  2949. X      wi = d_width;
  2950. X      he = d_height;
  2951. X      tname = d_termname;
  2952. X    }
  2953. X  else
  2954. X    {
  2955. X      wi = 80;
  2956. X      he = 24;
  2957. X      tname = "vt100";
  2958. X    }
  2959. X  debug1("MakeTermcap(%d)\n", aflag);
  2960. X  if ((s = getenv("SCREENCAP")) && strlen(s) < TERMCAP_BUFSIZE)
  2961. X    {
  2962. X      sprintf(Termcap, "TERMCAP=%s", s);     /* TERMCAP_BUFSIZE + ... ? XXX */
  2963. X      sprintf(Term, "TERM=screen");
  2964. X      debug("getenvSCREENCAP o.k.\n");
  2965. X      return Termcap;
  2966. X    }
  2967. X  Termcaplen = 0;
  2968. X  debug1("MakeTermcap screenterm='%s'\n", screenterm);
  2969. X  debug1("MakeTermcap termname='%s'\n", tname);
  2970. X  if (*screenterm == '\0')
  2971. X    {
  2972. X      debug("MakeTermcap sets screenterm=screen\n");
  2973. X      strcpy(screenterm, "screen");
  2974. X    }
  2975. X  do
  2976. X    {
  2977. X      sprintf(Term, "TERM=");
  2978. X      p = Term + 5;
  2979. X      if (!aflag && strlen(screenterm) + strlen(tname) < MAXSTR-1)
  2980. X    {
  2981. X      sprintf(p, "%s.%s", screenterm, tname);
  2982. X      if (tgetent(buf, p) == 1)
  2983. X        break;
  2984. X    }
  2985. X      if (wi >= 132)
  2986. X    {
  2987. X      sprintf(p, "%s-w", screenterm);
  2988. X          if (tgetent(buf, p) == 1)
  2989. X        break;
  2990. X    }
  2991. X      sprintf(p, "%s", screenterm);
  2992. X      if (tgetent(buf, p) == 1)
  2993. X    break;
  2994. X      sprintf(p, "vt100");
  2995. X    }
  2996. X  while (0);        /* Goto free programming... */
  2997. X  tcLineLen = 100;    /* Force NL */
  2998. X  sprintf(Termcap,
  2999. X      "TERMCAP=SC|%s|VT 100/ANSI X3.64 virtual terminal|", Term + 5);
  3000. X  Termcaplen = strlen(Termcap);
  3001. X  debug1("MakeTermcap decided '%s'\n", p);
  3002. X  if (extra_outcap && *extra_outcap)
  3003. X    {
  3004. X      for (cp = extra_outcap; (p = index(cp, ':')); cp = p)
  3005. X    {
  3006. X      ch = *++p;
  3007. X      *p = '\0';
  3008. X      AddCap(cp);
  3009. X      *p = ch;
  3010. X    }
  3011. X      tcLineLen = 100;    /* Force NL */
  3012. X    }
  3013. X  debug1("MakeTermcap after outcap '%s'\n", (char *)TermcapConst);
  3014. X  if (Termcaplen + strlen(TermcapConst) < TERMCAP_BUFSIZE)
  3015. X    {
  3016. X      strcpy(Termcap + Termcaplen, (char *)TermcapConst);
  3017. X      Termcaplen += strlen(TermcapConst);
  3018. X    }
  3019. X  sprintf(buf, "li#%d:co#%d:", he, wi);
  3020. X  AddCap(buf);
  3021. X  AddCap("am:");
  3022. X  if (aflag || (force_vt && !COP) || CLP || !AM)
  3023. X    {
  3024. X      AddCap("xn:");
  3025. X      AddCap("xv:");
  3026. X      AddCap("LP:");
  3027. X    }
  3028. X  if (aflag || (CS && SR) || AL || CAL)
  3029. X    {
  3030. X      AddCap("sr=\\EM:");
  3031. X      AddCap("al=\\E[L:");
  3032. X      AddCap("AL=\\E[%dL:");
  3033. X    }
  3034. X  else if (SR)
  3035. X    AddCap("sr=\\EM:");
  3036. X  if (aflag || CS)
  3037. X    AddCap("cs=\\E[%i%d;%dr:");
  3038. X  if (aflag || CS || DL || CDL)
  3039. X    {
  3040. X      AddCap("dl=\\E[M:");
  3041. X      AddCap("DL=\\E[%dM:");
  3042. X    }
  3043. X  if (aflag || DC || CDC)
  3044. X    {
  3045. X      AddCap("dc=\\E[P:");
  3046. X      AddCap("DC=\\E[%dP:");
  3047. X    }
  3048. X  if (aflag || CIC || IC || IM)
  3049. X    {
  3050. X      AddCap("im=\\E[4h:");
  3051. X      AddCap("ei=\\E[4l:");
  3052. X      AddCap("mi:");
  3053. X      AddCap("IC=\\E[%d@:");
  3054. X    }
  3055. X  if (display)
  3056. X    {
  3057. X      if (US)
  3058. X    {
  3059. X      AddCap("us=\\E[4m:");
  3060. X      AddCap("ue=\\E[24m:");
  3061. X    }
  3062. X      if (SO)
  3063. X    {
  3064. X      AddCap("so=\\E[3m:");
  3065. X      AddCap("se=\\E[23m:");
  3066. X    }
  3067. X      if (MB)
  3068. X    AddCap("mb=\\E[5m:");
  3069. X      if (MD)
  3070. X    AddCap("md=\\E[1m:");
  3071. X      if (MH)
  3072. X    AddCap("mh=\\E[2m:");
  3073. X      if (MR)
  3074. X    AddCap("mr=\\E[7m:");
  3075. X      if (MB || MD || MH || MR)
  3076. X    AddCap("me=\\E[m:ms:");
  3077. X      if (VB)
  3078. X    AddCap("vb=\\E[?5h\\E[?5l:");
  3079. X      if (KS)
  3080. X    {
  3081. X      AddCap("ks=\\E=:");
  3082. X      AddCap("ke=\\E>:");
  3083. X    }
  3084. X      if (CCS)
  3085. X    {
  3086. X      AddCap("CS=\\E[?1h:");
  3087. X      AddCap("CE=\\E[?1l:");
  3088. X    }
  3089. X      if (CG0)
  3090. X    {
  3091. X      AddCap("G0:");
  3092. X      AddCap("as=\\E(0:");
  3093. X      AddCap("ae=\\E(B:");
  3094. X    }
  3095. X      if (PO)
  3096. X    {
  3097. X      AddCap("po=\\E[5i:");
  3098. X      AddCap("pf=\\E[4i:");
  3099. X    }
  3100. X      if (CZ0)
  3101. X    {
  3102. X      AddCap("Z0=\\E[?3h:");
  3103. X      AddCap("Z1=\\E[?3l:");
  3104. X    }
  3105. X      if (CWS)
  3106. X    AddCap("WS=\\E[8;%d;%dt:");
  3107. X      for (i = T_CAPS; i < T_ECAPS; i++)
  3108. X    {
  3109. X      switch(term[i].type)
  3110. X        {
  3111. X        case T_STR:
  3112. X          if (d_tcs[i].str == 0)
  3113. X        break;
  3114. X          MakeString(term[i].tcname, buf, sizeof(buf), d_tcs[i].str);
  3115. X          AddCap(buf);
  3116. X          break;
  3117. X        case T_FLG:
  3118. X          if (d_tcs[i].flg == 0)
  3119. X        break;
  3120. X          sprintf(buf, "%s:", term[i].tcname);
  3121. X          AddCap(buf);
  3122. X          break;
  3123. X        default:
  3124. X          break;
  3125. X        }
  3126. X    }
  3127. X    }
  3128. X  debug("MakeTermcap: end\n");
  3129. X  return Termcap;
  3130. X}
  3131. X
  3132. Xstatic void
  3133. XMakeString(cap, buf, buflen, s)
  3134. Xchar *cap, *buf;
  3135. Xint buflen;
  3136. Xchar *s;
  3137. X{
  3138. X  register char *p, *pmax;
  3139. X  register unsigned int c;
  3140. X
  3141. X  p = buf;
  3142. X  pmax = p + buflen - (3+4+2);
  3143. X  *p++ = *cap++;
  3144. X  *p++ = *cap;
  3145. X  *p++ = '=';
  3146. X  while ((c = *s++) && (p < pmax))
  3147. X    {
  3148. X      switch (c)
  3149. X    {
  3150. X    case '\033':
  3151. X      *p++ = '\\';
  3152. X      *p++ = 'E';
  3153. X      break;
  3154. X    case ':':
  3155. X      sprintf(p, "\\072");
  3156. X      p += 4;
  3157. X      break;
  3158. X    case '^':
  3159. X    case '\\':
  3160. X      *p++ = '\\';
  3161. X      *p++ = c;
  3162. X      break;
  3163. X    default:
  3164. X      if (c >= 200)
  3165. X        {
  3166. X          sprintf(p, "\\%03o", c & 0377);
  3167. X          p += 4;
  3168. X        }
  3169. X      else if (c < ' ')
  3170. X        {
  3171. X          *p++ = '^';
  3172. X          *p++ = c + '@';
  3173. X        }
  3174. X      else
  3175. X        *p++ = c;
  3176. X    }
  3177. X    }
  3178. X  *p++ = ':';
  3179. X  *p = '\0';
  3180. X}
  3181. X
  3182. X
  3183. X/*
  3184. X**
  3185. X**  Termcap routines that use our extra_incap
  3186. X**
  3187. X*/
  3188. X
  3189. X
  3190. X/* findcap:
  3191. X *   cap = capability we are looking for
  3192. X *   tepp = pointer to bufferpointer
  3193. X *   n = size of buffer (0 = infinity)
  3194. X */
  3195. X
  3196. Xstatic char *
  3197. Xfindcap(cap, tepp, n)
  3198. Xchar *cap;
  3199. Xchar **tepp;
  3200. Xint n;
  3201. X{
  3202. X  char *tep;
  3203. X  char c, *p, *cp;
  3204. X  int mode;    /* mode: 0=LIT  1=^  2=\x  3,4,5=\nnn */
  3205. X  int num = 0, capl;
  3206. X
  3207. X  if (!extra_incap)
  3208. X    return (0);
  3209. X  tep = *tepp;
  3210. X  capl = strlen(cap);
  3211. X  cp = 0;
  3212. X  mode = 0;
  3213. X  for (p = extra_incap; *p; )
  3214. X    {
  3215. X      if (strncmp(p, cap, capl) == 0)
  3216. X    {
  3217. X      p += capl;
  3218. X      c = *p;
  3219. X      if (c && c != ':' && c != '@')
  3220. X        p++;
  3221. X      if (c == 0 || c == '@' || c == '=' || c == ':' || c == '#')
  3222. X        cp = tep;
  3223. X    }
  3224. X      while ((c = *p))
  3225. X    {
  3226. X      p++;
  3227. X      if (mode == 0)
  3228. X        {
  3229. X          if (c == ':')
  3230. X            break;
  3231. X          if (c == '^')
  3232. X        mode = 1;
  3233. X          if (c == '\\')
  3234. X        mode = 2;
  3235. X        }
  3236. X      else if (mode == 1)
  3237. X        {
  3238. X          mode = 0;
  3239. X          c = c & 0x1f;
  3240. X        }
  3241. X      else if (mode == 2)
  3242. X        {
  3243. X          mode = 0;
  3244. X          switch(c)
  3245. X        {
  3246. X        case '0':
  3247. X        case '1':
  3248. X        case '2':
  3249. X        case '3':
  3250. X        case '4':
  3251. X        case '5':
  3252. X        case '6':
  3253. X        case '7':
  3254. X        case '8':
  3255. X        case '9':
  3256. X          mode = 3;
  3257. X          num = 0;
  3258. X          break;
  3259. X        case 'E':
  3260. X          c = 27;
  3261. X          break;
  3262. X        case 'n':
  3263. X          c = '\n';
  3264. X          break;
  3265. X        case 'r':
  3266. X          c = '\r';
  3267. X          break;
  3268. X        case 't':
  3269. X          c = '\t';
  3270. X          break;
  3271. X        case 'b':
  3272. X          c = '\b';
  3273. X          break;
  3274. X        case 'f':
  3275. X          c = '\f';
  3276. X          break;
  3277. X        }
  3278. X        }
  3279. X      if (mode > 2)
  3280. X        {
  3281. X          num = num * 8 + (c - '0');
  3282. X          if (mode++ == 5 || (*p < '0' || *p > '9'))
  3283. X        {
  3284. X          c = num;
  3285. X          mode = 0;
  3286. X        }
  3287. X        }
  3288. X      if (mode)
  3289. X        continue;
  3290. X
  3291. X      if (cp && n != 1)
  3292. X        {
  3293. X          *cp++ = c;
  3294. X          n--;
  3295. X        }
  3296. X    }
  3297. X      if (cp)
  3298. X    {
  3299. X      *cp++ = 0;
  3300. X      *tepp = cp;
  3301. X      debug2("'%s' found in extra_incap -> %s\n", cap, tep);
  3302. X      return(tep);
  3303. X    }
  3304. X    }
  3305. X  return(0);
  3306. X}
  3307. X
  3308. Xstatic char *
  3309. Xe_tgetstr(cap, tepp)
  3310. Xchar *cap;
  3311. Xchar **tepp;
  3312. X{
  3313. X  char *tep, *tgetstr();
  3314. X  if ((tep = findcap(cap, tepp, 0)))
  3315. X    return((*tep == '@') ? 0 : tep);
  3316. X  return (tgetstr(cap, tepp));
  3317. X}
  3318. X
  3319. Xstatic int
  3320. Xe_tgetflag(cap)
  3321. Xchar *cap;
  3322. X{
  3323. X  char buf[2], *bufp;
  3324. X  char *tep;
  3325. X  bufp = buf;
  3326. X  if ((tep = findcap(cap, &bufp, 2)))
  3327. X    return((*tep == '@') ? 0 : 1);
  3328. X  return (tgetflag(cap));
  3329. X}
  3330. X
  3331. Xstatic int
  3332. Xe_tgetnum(cap)
  3333. Xchar *cap;
  3334. X{
  3335. X  char buf[20], *bufp;
  3336. X  char *tep, c;
  3337. X  int res, base = 10;
  3338. X
  3339. X  bufp = buf;
  3340. X  if ((tep = findcap(cap, &bufp, 20)))
  3341. X    {
  3342. X      c = *tep;
  3343. X      if (c == '@')
  3344. X    return(-1);
  3345. X      if (c == '0')
  3346. X    base = 8;
  3347. X      res = 0;
  3348. X      while ((c = *tep++) >= '0' && c <= '9')
  3349. X    res = res * base + (c - '0');
  3350. X      return(res);
  3351. X    }
  3352. X  return (tgetnum(cap));
  3353. X}
  3354. END_OF_FILE
  3355. if test 14829 -ne `wc -c <'termcap.c'`; then
  3356.     echo shar: \"'termcap.c'\" unpacked with wrong size!
  3357. fi
  3358. # end of 'termcap.c'
  3359. fi
  3360. if test -f 'utmp.c' -a "${1}" != "-c" ; then 
  3361.   echo shar: Will not clobber existing file \"'utmp.c'\"
  3362. else
  3363. echo shar: Extracting \"'utmp.c'\" \(18794 characters\)
  3364. sed "s/^X//" >'utmp.c' <<'END_OF_FILE'
  3365. X/* Copyright (c) 1993
  3366. X *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3367. X *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  3368. X * Copyright (c) 1987 Oliver Laumann
  3369. X *
  3370. X * This program is free software; you can redistribute it and/or modify
  3371. X * it under the terms of the GNU General Public License as published by
  3372. X * the Free Software Foundation; either version 2, or (at your option)
  3373. X * any later version.
  3374. X *
  3375. X * This program is distributed in the hope that it will be useful,
  3376. X * but WITHOUT ANY WARRANTY; without even the implied warranty of
  3377. X * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  3378. X * GNU General Public License for more details.
  3379. X *
  3380. X * You should have received a copy of the GNU General Public License
  3381. X * along with this program (see the file COPYING); if not, write to the
  3382. X * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  3383. X *
  3384. X ****************************************************************
  3385. X */
  3386. X
  3387. X#include "rcs.h"
  3388. XRCS_ID("$Id: utmp.c,v 1.3 1993/07/21 15:43:38 mlschroe Exp $ FAU")
  3389. X
  3390. X
  3391. X/*
  3392. X * An explanation of some weird things:
  3393. X *
  3394. X *  linux should have GETUTENT, but their pututline() doesn't have
  3395. X *  a return value.
  3396. X * 
  3397. X *  UTNOKEEP: A (ugly) hack for apollo, that does two things:
  3398. X *    1) Always close and reopen the utmp file descriptor. (I don't know
  3399. X *       for what reason this is done...)
  3400. X *    2) Implement an unsortet utmp file much like GETUTENT.
  3401. X *  (IMHO these two features should be split!)
  3402. X */
  3403. X
  3404. X
  3405. X#include <sys/types.h>
  3406. X#include <sys/stat.h>
  3407. X#include <fcntl.h>
  3408. X
  3409. X#include "config.h"
  3410. X#include "screen.h"
  3411. X#include "extern.h"
  3412. X
  3413. X
  3414. Xextern struct display *display;
  3415. Xextern struct win *fore;
  3416. Xextern char *LoginName;
  3417. X#ifdef NETHACK
  3418. Xextern nethackflag;
  3419. X#endif
  3420. X
  3421. X#ifdef UTMPOK
  3422. X
  3423. Xstatic slot_t TtyNameSlot __P((char *));
  3424. Xstatic int utmpok, utmpfd = -1;
  3425. Xstatic char UtmpName[] = UTMPFILE;
  3426. X
  3427. X
  3428. X# if defined(GETUTENT) && !defined(SVR4)
  3429. X#  if defined(hpux) /* cruel hpux release 8.0 */
  3430. X#   define pututline _pututline
  3431. X#  endif /* hpux */
  3432. Xextern struct utmp *getutline(), *pututline();
  3433. X#  if defined(_SEQUENT_)
  3434. Xextern struct utmp *ut_add_user(), *ut_delete_user();
  3435. Xextern char *ut_find_host();
  3436. X#   define UTHOST        /* _SEQUENT_ has got ut_find_host() */
  3437. X#  endif /* _SEQUENT_ */
  3438. X# endif /* GETUTENT && !SVR4 */
  3439. X
  3440. X# if defined (GETTTYENT) && !defined(GETUTENT)
  3441. X#   include <ttyent.h>
  3442. X# endif /* GETUTENT */
  3443. X
  3444. X# if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UTNOKEEP)
  3445. Xstruct ttyent
  3446. X{
  3447. X  char *ty_name;
  3448. X};
  3449. Xstatic void setttyent __P((void));
  3450. Xstatic struct ttyent *getttyent __P((void));
  3451. Xstatic char *tt, *ttnext;
  3452. Xstatic char ttys[] = "/etc/ttys";
  3453. X# endif /* !GETTTYENT && !GETUTENT && !UTNOKEEP */
  3454. X
  3455. X#endif /* UTMPOK */
  3456. X
  3457. X
  3458. X
  3459. X/*
  3460. X * SlotToggle - modify the utmp slot of the fore window.
  3461. X *
  3462. X * how > 0    do try to set a utmp slot.
  3463. X * how = 0    try to withdraw a utmp slot.
  3464. X *
  3465. X * w_slot = -1  window not logged in.
  3466. X * w_slot = 0   window not logged in, but should be logged in. 
  3467. X *              (unable to write utmp, or detached).
  3468. X */
  3469. Xvoid
  3470. XSlotToggle(how)
  3471. Xint how;
  3472. X{
  3473. X  debug1("SlotToggle %d\n", how);
  3474. X#ifdef UTMPOK
  3475. X  if (how)
  3476. X    {
  3477. X      debug(" try to log in\n");
  3478. X      if ((fore->w_slot == (slot_t) -1) || (fore->w_slot == (slot_t) 0))
  3479. X    {
  3480. X# ifdef USRLIMIT
  3481. X          if (CountUsers() >= USRLIMIT)
  3482. X            Msg(0, "User limit reached.");
  3483. X          else
  3484. X# endif
  3485. X            {
  3486. X              if (SetUtmp(fore) == 0)
  3487. X                Msg(0, "This window is now logged in.");
  3488. X              else
  3489. X                Msg(0, "This window should now be logged in.");
  3490. X            }
  3491. X    }
  3492. X      else
  3493. X    Msg(0, "This window is already logged in.");
  3494. X    }
  3495. X  else
  3496. X    {
  3497. X      debug(" try to log out\n");
  3498. X      if (fore->w_slot == (slot_t) -1)
  3499. X    Msg(0, "This window is already logged out\n");
  3500. X      else if (fore->w_slot == (slot_t) 0)
  3501. X    {
  3502. X      debug("What a relief! In fact, it was not logged in\n");
  3503. X      Msg(0, "This window is not logged in.");
  3504. X      fore->w_slot = (slot_t) -1;
  3505. X    }
  3506. X      else
  3507. X    {
  3508. X      RemoveUtmp(fore);
  3509. X      if (fore->w_slot != (slot_t) -1)
  3510. X        Msg(0, "What? Cannot remove Utmp slot?");
  3511. X      else
  3512. X        Msg(0, "This window is no longer logged in.");
  3513. X    }
  3514. X    }
  3515. X#else    /* !UTMPOK */
  3516. X  Msg(0, "Unable to modify %s.\n", UTMPFILE);
  3517. X#endif
  3518. X}
  3519. X
  3520. X
  3521. X#ifdef UTMPOK
  3522. X
  3523. X
  3524. Xvoid
  3525. XInitUtmp()
  3526. X{
  3527. X  debug1("InitUtmp testing '%s'...\n", UtmpName);
  3528. X  if ((utmpfd = open(UtmpName, O_RDWR)) == -1)
  3529. X    {
  3530. X      if (errno != EACCES)
  3531. X    Msg(errno, UtmpName);
  3532. X      debug("InitUtmp failed.\n");
  3533. X      utmpok = 0;
  3534. X      return;
  3535. X    }
  3536. X# ifdef GETUTENT
  3537. X  close(utmpfd);    /* it was just a test */
  3538. X  utmpfd = -1;
  3539. X# endif /* GETUTENT */
  3540. X  utmpok = 1;
  3541. X}
  3542. X
  3543. X
  3544. X#ifdef USRLIMIT
  3545. Xint
  3546. XCountUsers()
  3547. X{
  3548. X# ifdef GETUTENT
  3549. X  struct utmp *ut, *getutent();
  3550. X# else /* GETUTENT */
  3551. X  struct utmp utmpbuf;
  3552. X# endif /* GETUTENT */
  3553. X  int UserCount;
  3554. X
  3555. X# ifdef UTNOKEEP
  3556. X  InitUtmp();
  3557. X# endif /* UTNOKEEP */
  3558. X  debug1("CountUsers() - utmpok=%d\n", utmpok);
  3559. X  if (!utmpok)
  3560. X    return(0);
  3561. X  UserCount = 0;
  3562. X# ifdef GETUTENT
  3563. X  setutent();
  3564. X  while (ut = getutent())
  3565. X    if (ut->ut_type == USER_PROCESS)
  3566. X      UserCount++;
  3567. X# else /* GETUTENT */
  3568. X  (void) lseek(utmpfd, (off_t) 0, 0);
  3569. X  while (read(utmpfd, &utmpbuf, sizeof(struct utmp)) > 0)
  3570. X    {
  3571. X      if (utmpbuf.ut_name[0] != '\0')
  3572. X       UserCount++;
  3573. X    }
  3574. X# endif /* GETUTENT */
  3575. X# ifdef UTNOKEEP
  3576. X  close(utmpfd);
  3577. X# endif /* UTNOKEEP */
  3578. X  return(UserCount);
  3579. X}
  3580. X#endif /* USRLIMIT */
  3581. X
  3582. X
  3583. X
  3584. X/*
  3585. X * the utmp entry for tty is located and removed.
  3586. X * it is stored in d_utmp_logintty.
  3587. X */
  3588. Xvoid
  3589. XRemoveLoginSlot()
  3590. X{
  3591. X# ifdef GETUTENT
  3592. X  struct utmp *uu;
  3593. X# endif /* GETUTENT */
  3594. X  struct utmp u;    /* 'empty' slot that we write back */
  3595. X# ifdef _SEQUENT_
  3596. X  char *p;
  3597. X# endif /* _SEQUENT_ */
  3598. X
  3599. X  ASSERT(display);
  3600. X  debug("RemoveLoginSlot: removing your logintty\n");
  3601. X  d_loginslot = TtyNameSlot(d_usertty);
  3602. X# ifdef UTNOKEEP
  3603. X  InitUtmp();
  3604. X# endif /* UTNOKEEP */
  3605. X  if (!utmpok)
  3606. X    {
  3607. X      debug("RemoveLoginSlot: utmpok == 0\n");
  3608. X      return;
  3609. X    }
  3610. X  if (d_loginslot == (slot_t)0 || d_loginslot == (slot_t)-1)
  3611. X    {
  3612. X      return;
  3613. X    }
  3614. X# ifdef _SEQUENT_
  3615. X  if (p = ut_find_host(d_loginslot))
  3616. X    strncpy(d_loginhost, p, sizeof(d_loginhost) - 1);
  3617. X  d_loginhost[sizeof(d_loginhost) - 1] = 0;
  3618. X# endif /* _SEQUENT_ */
  3619. X
  3620. X  bzero((char *) &u, sizeof u);
  3621. X
  3622. X# ifdef GETUTENT
  3623. X  setutent();
  3624. X  strncpy(u.ut_line, d_loginslot, sizeof(u.ut_line));
  3625. X  if ((uu = getutline(&u)) == 0)
  3626. X    {
  3627. X      Msg(0, "Utmp slot not found -> not removed");
  3628. X      return;
  3629. X    }
  3630. X  d_utmp_logintty = *uu;
  3631. X#  ifdef _SEQUENT_
  3632. X  if (ut_delete_user(d_loginslot, uu->ut_pid, 0, 0) == 0)
  3633. X#  else /* _SEQUENT_ */
  3634. X  u = *uu;
  3635. X  u.ut_type = DEAD_PROCESS;
  3636. X  u.ut_exit.e_termination = 0;
  3637. X  u.ut_exit.e_exit= 0;
  3638. X  if (pututline(&u) == 0)
  3639. X#  endif /* _SEQUENT_ */
  3640. X
  3641. X# else /* GETUTENT */
  3642. X
  3643. X  (void) lseek(utmpfd, (off_t) (d_loginslot * sizeof u), 0);
  3644. X  bzero((char *)&d_utmp_logintty, sizeof u);
  3645. X  if (read(utmpfd, (char *) &d_utmp_logintty, sizeof u) != sizeof u)
  3646. X    {
  3647. X      Msg(errno, "cannot read %s ??", UTMPFILE);
  3648. X      sleep(1);
  3649. X    }
  3650. X  (void) lseek(utmpfd, (off_t) (d_loginslot * sizeof u), 0);
  3651. X#  ifdef UTNOKEEP
  3652. X  /* 
  3653. X   * as the utmp file is not sorted, we want to mark this slot occupied,
  3654. X   * as RestoreLoginSlot() will write exactly here.
  3655. X   */
  3656. X  bcopy((char *)&d_utmp_logintty, (char *)&u, sizeof u);
  3657. X  bzero(u.ut_name, sizeof(u.ut_name));
  3658. X  bzero(u.ut_host, sizeof(u.ut_host));
  3659. X#  endif /* UTNOKEEP */
  3660. X  if (write(utmpfd, (char *) &u, sizeof u) != sizeof u)
  3661. X
  3662. X# endif /* GETUTENT */
  3663. X
  3664. X    {
  3665. X# ifdef NETHACK
  3666. X      if (nethackflag)
  3667. X    {
  3668. X      Msg(errno, "%s is too hard to dig in", UTMPFILE); 
  3669. X    }
  3670. X      else
  3671. X# endif /* NETHACK */
  3672. X    {
  3673. X      Msg(errno, "Could not write %s", UTMPFILE);
  3674. X    }
  3675. X    }
  3676. X# ifdef UTNOKEEP
  3677. X  close(utmpfd);
  3678. X# endif /* UTNOKEEP */
  3679. X  debug1(" slot %d zapped\n", (int)d_loginslot);
  3680. X}
  3681. X
  3682. X/*
  3683. X * d_utmp_logintty is reinserted into utmp
  3684. X */
  3685. Xvoid
  3686. XRestoreLoginSlot()
  3687. X{
  3688. X  debug("RestoreLoginSlot()\n");
  3689. X  ASSERT(display);
  3690. X# ifdef UTNOKEEP
  3691. X  InitUtmp();
  3692. X# endif /* UTNOKEEP */
  3693. X  if (utmpok && d_loginslot != (slot_t)0 && d_loginslot != (slot_t)-1)
  3694. X    {
  3695. X# ifdef GETUTENT
  3696. X#  ifdef _SEQUENT_
  3697. X      int fail;
  3698. X      debug1(" logging you in again (slot %s)\n", d_loginslot);
  3699. X/*
  3700. X * We have problems if we add the console and use ut_add_user()
  3701. X * because the id will be 'scon' instead of 'co'. So we
  3702. X * restore it with pututline(). The reason why we don't use
  3703. X * pututline all the time is that we want to set the host field.
  3704. X * Unfortunatelly this can only be done with ut_add_user().
  3705. X */
  3706. X      if (*d_loginhost)
  3707. X        {
  3708. X          fail = (ut_add_user(d_utmp_logintty.ut_name, d_loginslot, d_utmp_logintty.ut_pid,
  3709. X                              *d_loginhost ? d_loginhost : (char *)0) == 0);
  3710. X        }
  3711. X      else
  3712. X        {
  3713. X          setutent();
  3714. X          fail = (pututline(&d_utmp_logintty) == 0);
  3715. X        }
  3716. X      if (fail)
  3717. X#  else    /* _SEQUENT_ */
  3718. X      debug1(" logging you in again (slot %s)\n", d_loginslot);
  3719. X      setutent();
  3720. X      if (pututline(&d_utmp_logintty)==0)
  3721. X#  endif    /* _SEQUENT */
  3722. X# else    /* GETUTENT */
  3723. X      debug1(" logging you in again (slot %d)\n", d_loginslot);
  3724. X#  ifdef sequent
  3725. X      /* 
  3726. X       * call sequent undocumented routine to count logins 
  3727. X       * and add utmp entry if possible 
  3728. X       */
  3729. X      if (add_utmp(d_loginslot, &d_utmp_logintty) == -1)
  3730. X#  else /* sequent */
  3731. X      (void) lseek(utmpfd, (off_t) (d_loginslot * sizeof(struct utmp)), 0);
  3732. X      if (write(utmpfd, (char *) &d_utmp_logintty, sizeof(struct utmp))
  3733. X      != sizeof(struct utmp))
  3734. X#  endif /* sequent */
  3735. X# endif    /* GETUTENT */
  3736. X        {
  3737. X# ifdef NETHACK
  3738. X          if (nethackflag)
  3739. X            Msg(errno, "%s is too hard to dig in", UTMPFILE);
  3740. X      else
  3741. X# endif /* NETHACK */
  3742. X          Msg(errno,"Could not write %s", UTMPFILE);
  3743. X        }
  3744. X    }
  3745. X# ifdef UTNOKEEP
  3746. X  close(utmpfd);
  3747. X# endif /* UTNOKEEP */
  3748. X  d_loginslot = (slot_t) 0;
  3749. X}
  3750. X
  3751. X
  3752. X
  3753. X/*
  3754. X * Construct a utmp entry for window wi.
  3755. X * the hostname field reflects what we know about the d_user (i.e. display)
  3756. X * location. If d_loginhost is not set, then he is local and we write
  3757. X * down the name of his terminal line; else he is remote and we keep
  3758. X * the hostname here. The letter S and the window id will be appended.
  3759. X * A saved utmp entry in wi->w_savut serves as a template, usually.
  3760. X */ 
  3761. X
  3762. Xint
  3763. XSetUtmp(wi)
  3764. Xstruct win *wi;
  3765. X{
  3766. X  register char *p;
  3767. X  register slot_t slot;
  3768. X# ifndef _SEQUENT_
  3769. X  char *line;
  3770. X# endif
  3771. X  struct utmp u;
  3772. X  int saved_ut;
  3773. X# ifdef UTHOST
  3774. X#  ifdef _SEQUENT_
  3775. X  char host[100+5];
  3776. X#  else /* _SEQUENT_ */
  3777. X  char host[sizeof(d_utmp_logintty.ut_host)+5];
  3778. X#  endif /* _SEQUENT_ */
  3779. X# endif /* UTHOST */
  3780. X
  3781. X  wi->w_slot = (slot_t) 0;
  3782. X  if (!utmpok)
  3783. X    return -1;
  3784. X  if ((slot = TtyNameSlot(wi->w_tty)) == (slot_t) NULL)
  3785. X    {
  3786. X      debug1("SetUtmp failed (tty %s).\n",wi->w_tty);
  3787. X      return -1;
  3788. X    }
  3789. X  debug2("SetUtmp %d will get slot %d...\n", wi->w_number, (int)slot);
  3790. X# ifdef UTNOKEEP
  3791. X  /* open here, as TtyNameSlot used (and closed) our filedescriptor */
  3792. X  InitUtmp();
  3793. X# endif /* UTNOKEEP */
  3794. X
  3795. X  bzero((char *) &u, sizeof u);
  3796. X  if ((saved_ut = bcmp((char *) &wi->w_savut, (char *) &u, sizeof u)))
  3797. X    /* restore original, of which we will adopt all fields but ut_host */
  3798. X    bcopy((char *) &wi->w_savut, (char *) &u, sizeof u);
  3799. X
  3800. X# ifdef UTHOST
  3801. X  host[sizeof(host)-5] = '\0';
  3802. X  if (display)
  3803. X    {
  3804. X#  ifdef _SEQUENT_
  3805. X      strncpy(host, d_loginhost, sizeof(host) - 5);
  3806. X#  else /* _SEQUENT */
  3807. X      strncpy(host, d_utmp_logintty.ut_host, sizeof(host) - 5);
  3808. X#  endif /* _SEQUENT */
  3809. X      if (d_loginslot != (slot_t)0 && d_loginslot != (slot_t)-1 && host[0] != '\0')
  3810. X    {
  3811. X      /*
  3812. X       * we want to set our ut_host field to something like
  3813. X       * ":ttyhf:s.0" or
  3814. X       * "faui45:s.0" or
  3815. X       * "132.199.81.4:s.0" (even this may hurt..), but not
  3816. X       * "faui45.informati"......:s.0
  3817. X       */
  3818. X      for (p = host; *p; p++)
  3819. X        if ((*p < '0' || *p > '9') && (*p != '.'))
  3820. X          break;
  3821. X      if (*p)
  3822. X        {
  3823. X          for (p = host; *p; p++)
  3824. X        if (*p == '.')
  3825. X          {
  3826. X            *p = '\0';
  3827. X            break;
  3828. X          }
  3829. X        }
  3830. X    }
  3831. X      else
  3832. X    {
  3833. X      strncpy(host + 1, stripdev(d_usertty), sizeof(host) - 6);
  3834. X      host[0] = ':';
  3835. X    }
  3836. X    }
  3837. X  else
  3838. X    strncpy(host, "local", sizeof(host) - 5);
  3839. X  sprintf(host + strlen(host), ":S.%c", '0' + wi->w_number);
  3840. X  debug1("rlogin hostname: '%s'\n", host);
  3841. X#  if !defined(_SEQUENT_) && !defined(sequent)
  3842. X  strncpy(u.ut_host, host, sizeof(u.ut_host));
  3843. X#  endif
  3844. X# endif /* UTHOST */
  3845. X
  3846. X# ifdef _SEQUENT_
  3847. X  if (ut_add_user(saved_ut ? u.ut_user : LoginName, slot, saved_ut ? u.ut_pid : wi->w_pid, host) == 0)
  3848. X# else /* _SEQUENT_ */
  3849. X  if (!saved_ut)
  3850. X    { /* make new utmp from scratch */
  3851. X      line = stripdev(wi->w_tty);
  3852. X#  ifdef GETUTENT
  3853. X      strncpy(u.ut_user, LoginName, sizeof(u.ut_user));
  3854. X#   ifdef sgi
  3855. X      strncpy(u.ut_id, line + 3, sizeof(u.ut_id));
  3856. X#   else /* sgi */
  3857. X      strncpy(u.ut_id, line + strlen(line) - 2, sizeof(u.ut_id));
  3858. X#   endif /* sgi */
  3859. X      strncpy(u.ut_line, line, sizeof(u.ut_line));
  3860. X      u.ut_pid = wi->w_pid;
  3861. X      u.ut_type = USER_PROCESS;
  3862. X      (void) time((time_t *)&u.ut_time);
  3863. X    } /* !saved_ut {-: */
  3864. X  setutent();
  3865. X  if (pututline(&u) == 0)
  3866. X#  else    /* GETUTENT */
  3867. X      strncpy(u.ut_line, line, sizeof(u.ut_line));
  3868. X      strncpy(u.ut_name, LoginName, sizeof(u.ut_name));
  3869. X#   if defined(linux)    /* should have GETUTENT */
  3870. X      u.ut_type = USER_PROCESS;
  3871. X      u.ut_pid = wi->w_pid;
  3872. X      strncpy(u.ut_id, line + 3, sizeof(u.ut_id));
  3873. X#   endif /* linux */
  3874. X      (void) time((time_t *)&u.ut_time);
  3875. X    } /* !saved_ut */
  3876. X#   ifdef sequent
  3877. X  /*
  3878. X   * call sequent undocumented routine to count logins and 
  3879. X   * add utmp entry if possible 
  3880. X   */
  3881. X  if (add_utmp(slot, &u) == -1)
  3882. X#   else /* sequent */
  3883. X  (void) lseek(utmpfd, (off_t) (slot * sizeof u), 0);
  3884. X  if (write(utmpfd, (char *) &u, sizeof u) != sizeof u)
  3885. X#   endif /* sequent */
  3886. X#  endif /* GETUTENT */
  3887. X# endif /* _SEQUENT_ */
  3888. X
  3889. X    {
  3890. X# ifdef NETHACK
  3891. X      if (nethackflag)
  3892. X        Msg(errno, "%s is too hard to dig in", UTMPFILE);
  3893. X      else
  3894. X# endif /* NETHACK */
  3895. X      Msg(errno,"Could not write %s", UTMPFILE);
  3896. X# ifdef UTNOKEEP
  3897. X      close(utmpfd);
  3898. X# endif /* UTNOKEEP */
  3899. X      return -1;
  3900. X    }
  3901. X  debug("SetUtmp successful\n");
  3902. X  wi->w_slot = slot;
  3903. X# ifdef UTNOKEEP
  3904. X  close(utmpfd);
  3905. X# endif /* UTNOKEEP */
  3906. X  return 0;
  3907. X}
  3908. X
  3909. X
  3910. X
  3911. X/*
  3912. X * if slot could be removed or was 0,  wi->w_slot = -1;
  3913. X * else not changed.
  3914. X */
  3915. X
  3916. Xint
  3917. XRemoveUtmp(wi)
  3918. Xstruct win *wi;
  3919. X{
  3920. X# ifdef GETUTENT
  3921. X  struct utmp *uu;
  3922. X# endif /* GETUTENT */
  3923. X  struct utmp u;
  3924. X  slot_t slot;
  3925. X
  3926. X  slot = wi->w_slot;
  3927. X# ifdef GETUTENT
  3928. X  debug1("RemoveUtmp(%s)\n", (slot == (slot_t) 0) ?
  3929. X         "no slot (0)":((slot == (slot_t) -1) ? "no slot (-1)" : slot));
  3930. X# else /* GETUTENT */
  3931. X  debug1("RemoveUtmp(wi.slot: %d)\n", slot);
  3932. X# endif /* GETUTENT */
  3933. X# ifdef UTNOKEEP
  3934. X  InitUtmp();
  3935. X# endif /* UTNOKEEP */
  3936. X  if (!utmpok)
  3937. X    return -1;
  3938. X  if (slot == (slot_t) 0 || slot == (slot_t) -1)
  3939. X    {
  3940. X      debug1("There is no utmp-slot to be removed(%d)\n", (int)slot);
  3941. X      wi->w_slot = (slot_t) -1;
  3942. X      return 0;
  3943. X    }
  3944. X  bzero((char *) &u, sizeof u);
  3945. X# ifdef GETUTENT
  3946. X  setutent();
  3947. X  strncpy(u.ut_line, slot, sizeof(u.ut_line));
  3948. X  if ((uu = getutline(&u)) == 0)
  3949. X    {
  3950. X      Msg(0, "Utmp slot not found -> not removed");
  3951. X      return -1;
  3952. X    }
  3953. X  bcopy((char *)uu, (char *)&wi->w_savut, sizeof(wi->w_savut));
  3954. X#  ifdef _SEQUENT_
  3955. X  if (ut_delete_user(slot, uu->ut_pid, 0, 0) == 0)
  3956. X#  else /* _SEQUENT_ */
  3957. X  u = *uu;
  3958. X  u.ut_type = DEAD_PROCESS;
  3959. X  u.ut_exit.e_termination = 0;
  3960. X  u.ut_exit.e_exit= 0;
  3961. X  if (pututline(&u) == 0)
  3962. X#  endif /* _SEQUENT_ */
  3963. X# else /* GETUTENT */
  3964. X  (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
  3965. X  if (read(utmpfd, (char *) &wi->w_savut, sizeof(wi->w_savut)) != sizeof u)
  3966. X    {
  3967. X      bzero((char *)&wi->w_savut, sizeof(wi->w_savut));
  3968. X      Msg(errno, "cannot read %s?", UTMPFILE);
  3969. X      sleep(1);
  3970. X    }
  3971. X  (void) lseek(utmpfd, (off_t) (slot * sizeof(u)), 0);
  3972. X#  ifdef UTNOKEEP
  3973. X  bcopy((char *)&wi->w_savut, (char *)&u, sizeof(u));
  3974. X  bzero(u.ut_name, sizeof(u.ut_name));
  3975. X  bzero(u.ut_host, sizeof(u.ut_host));
  3976. X#  endif /* UTNOKEEP */
  3977. X  if (write(utmpfd, (char *) &u, sizeof(u)) != sizeof(u))
  3978. X# endif /* GETUTENT */
  3979. X    {
  3980. X# ifdef NETHACK
  3981. X      if (nethackflag)
  3982. X        Msg(errno, "%s is too hard to dig in", UTMPFILE);
  3983. X      else
  3984. X# endif /* NETHACK */
  3985. X      Msg(errno,"Could not write %s", UTMPFILE);
  3986. X# ifdef UTNOKEEP
  3987. X      close(utmpfd);
  3988. X# endif /* UTNOKEEP */
  3989. X      return -1;
  3990. X    }
  3991. X  debug("RemoveUtmp successfull\n");
  3992. X  wi->w_slot = (slot_t) -1;
  3993. X# ifdef UTNOKEEP
  3994. X  close(utmpfd);
  3995. X# endif /* UTNOKEEP */
  3996. X  return 0;
  3997. X}
  3998. X
  3999. X
  4000. X
  4001. X/*
  4002. X * TtyNameSlot:
  4003. X * return an index, where the named tty is found in utmp.
  4004. X */
  4005. X
  4006. Xstatic slot_t 
  4007. XTtyNameSlot(nam)
  4008. Xchar *nam;
  4009. X{
  4010. X  char *name;
  4011. X  register slot_t slot;
  4012. X# ifdef UTNOKEEP
  4013. X  struct utmp u;
  4014. X# else
  4015. X#  ifndef GETUTENT
  4016. X  register struct ttyent *tp;
  4017. X#  endif /* GETUTENT */
  4018. X# endif /* UTNOKEEP */
  4019. X
  4020. X  debug1("TtyNameSlot(%s)\n", nam);
  4021. X# ifdef UTNOKEEP
  4022. X  InitUtmp();
  4023. X# endif /* UTNOKEEP */
  4024. X  if (!utmpok || nam == NULL)
  4025. X    return (slot_t)0;
  4026. X  name = stripdev(nam);
  4027. X# ifdef GETUTENT
  4028. X  slot = name;
  4029. X# else /* GETUTENT */
  4030. X#  ifdef UTNOKEEP
  4031. X  slot = 0;
  4032. X  while ((read(utmpfd, (char *)&u, sizeof(u)) == sizeof(u))
  4033. X         && (strcmp(u.ut_line, name)))
  4034. X    slot++;
  4035. X  close(utmpfd);
  4036. X#  else /* UTNOKEEP */
  4037. X  slot = 1;
  4038. X  setttyent();
  4039. X  while ((tp = getttyent()) != NULL && strcmp(name, tp->ty_name) != 0)
  4040. X    slot++;
  4041. X#  endif /* UTNOKEEP */
  4042. X# endif /* GETUTENT */
  4043. X  return slot;
  4044. X}
  4045. X
  4046. X
  4047. X
  4048. X# if !defined(GETTTYENT) && !defined(GETUTENT) && !defined(UTNOKEEP)
  4049. X
  4050. Xstatic void
  4051. Xsetttyent()
  4052. X{
  4053. X  struct stat s;
  4054. X  register int f;
  4055. X  register char *p, *ep;
  4056. X
  4057. X  if (ttnext)
  4058. X    {
  4059. X      ttnext = tt;
  4060. X      return;
  4061. X    }
  4062. X  if ((f = open(ttys, O_RDONLY)) == -1 || fstat(f, &s) == -1)
  4063. X    Panic(errno, ttys);
  4064. X  if ((tt = malloc((unsigned) s.st_size + 1)) == 0)
  4065. X    Panic(0, strnomem);
  4066. X  if (read(f, tt, s.st_size) != s.st_size)
  4067. X    Panic(errno, ttys);
  4068. X  close(f);
  4069. X  for (p = tt, ep = p + s.st_size; p < ep; ++p)
  4070. X    if (*p == '\n')
  4071. X      *p = '\0';
  4072. X  *p = '\0';
  4073. X  ttnext = tt;
  4074. X}
  4075. X
  4076. Xstatic struct ttyent *
  4077. Xgetttyent()
  4078. X{
  4079. X  static struct ttyent t;
  4080. X
  4081. X  if (*ttnext == '\0')
  4082. X    return NULL;
  4083. X  t.ty_name = ttnext + 2;
  4084. X  ttnext += strlen(ttnext) + 1;
  4085. X  return &t;
  4086. X}
  4087. X
  4088. X# endif    /* !GETTTYENT && !GETUTENT && !UTNOKEEP */
  4089. X
  4090. X
  4091. X#endif /* UTMPOK */
  4092. X
  4093. X
  4094. X
  4095. X/*********************************************************************
  4096. X *
  4097. X *  getlogin() replacement (for SVR4 machines)
  4098. X */
  4099. X
  4100. X# if defined(BUGGYGETLOGIN)
  4101. Xchar *
  4102. Xgetlogin()
  4103. X{
  4104. X  char *tty;
  4105. X#ifdef utmp
  4106. X# undef utmp
  4107. X#endif
  4108. X  struct utmp u;
  4109. X  static char retbuf[sizeof(u.ut_user)+1];
  4110. X  int fd;
  4111. X
  4112. X  for (fd = 0; fd <= 2 && (tty = ttyname(fd)) == NULL; fd++)
  4113. X    ;
  4114. X  if ((tty == NULL) || ((fd = open(UTMP_FILE, O_RDONLY)) < 0))
  4115. X    return NULL;
  4116. X  tty = stripdev(tty);
  4117. X  retbuf[0] = '\0';
  4118. X  while (read(fd, (char *)&u, sizeof(struct utmp)) == sizeof(struct utmp))
  4119. X    {
  4120. X      if (!strncmp(tty, u.ut_line, sizeof(u.ut_line)))
  4121. X    {
  4122. X      strncpy(retbuf, u.ut_user, sizeof(u.ut_user));
  4123. X      retbuf[sizeof(u.ut_user)] = '\0';
  4124. X      if (u.ut_type == USER_PROCESS)
  4125. X        break;
  4126. X    }
  4127. X    }
  4128. X  close(fd);
  4129. X
  4130. X  return *retbuf ? retbuf : NULL;
  4131. X}
  4132. X# endif /* BUGGYGETLOGIN */
  4133. X
  4134. END_OF_FILE
  4135. if test 18794 -ne `wc -c <'utmp.c'`; then
  4136.     echo shar: \"'utmp.c'\" unpacked with wrong size!
  4137. fi
  4138. # end of 'utmp.c'
  4139. fi
  4140. echo shar: End of archive 3 \(of 10\).
  4141. cp /dev/null ark3isdone
  4142. MISSING=""
  4143. for I in 1 2 3 4 5 6 7 8 9 10 ; do
  4144.     if test ! -f ark${I}isdone ; then
  4145.     MISSING="${MISSING} ${I}"
  4146.     fi
  4147. done
  4148. if test "${MISSING}" = "" ; then
  4149.     echo You have unpacked all 10 archives.
  4150.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  4151. else
  4152.     echo You still need to unpack the following archives:
  4153.     echo "        " ${MISSING}
  4154. fi
  4155. ##  End of shell archive.
  4156. exit 0
  4157.