dterm-nuc

changeset 0:ad098a33fd34

initial commit of my fork of dterm
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 07 Apr 2017 23:43:06 +0300
parents
children 5a80b73208dd
files .hgignore LICENCE.txt Makefile README.txt dterm.c
diffstat 5 files changed, 1535 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Fri Apr 07 23:43:06 2017 +0300
     1.3 @@ -0,0 +1,4 @@
     1.4 +\.o$
     1.5 +\.d$
     1.6 +\.swp$
     1.7 +^dterm$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/LICENCE.txt	Fri Apr 07 23:43:06 2017 +0300
     2.3 @@ -0,0 +1,339 @@
     2.4 +		    GNU GENERAL PUBLIC LICENSE
     2.5 +		       Version 2, June 1991
     2.6 +
     2.7 + Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
     2.8 + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     2.9 + Everyone is permitted to copy and distribute verbatim copies
    2.10 + of this license document, but changing it is not allowed.
    2.11 +
    2.12 +			    Preamble
    2.13 +
    2.14 +  The licenses for most software are designed to take away your
    2.15 +freedom to share and change it.  By contrast, the GNU General Public
    2.16 +License is intended to guarantee your freedom to share and change free
    2.17 +software--to make sure the software is free for all its users.  This
    2.18 +General Public License applies to most of the Free Software
    2.19 +Foundation's software and to any other program whose authors commit to
    2.20 +using it.  (Some other Free Software Foundation software is covered by
    2.21 +the GNU Lesser General Public License instead.)  You can apply it to
    2.22 +your programs, too.
    2.23 +
    2.24 +  When we speak of free software, we are referring to freedom, not
    2.25 +price.  Our General Public Licenses are designed to make sure that you
    2.26 +have the freedom to distribute copies of free software (and charge for
    2.27 +this service if you wish), that you receive source code or can get it
    2.28 +if you want it, that you can change the software or use pieces of it
    2.29 +in new free programs; and that you know you can do these things.
    2.30 +
    2.31 +  To protect your rights, we need to make restrictions that forbid
    2.32 +anyone to deny you these rights or to ask you to surrender the rights.
    2.33 +These restrictions translate to certain responsibilities for you if you
    2.34 +distribute copies of the software, or if you modify it.
    2.35 +
    2.36 +  For example, if you distribute copies of such a program, whether
    2.37 +gratis or for a fee, you must give the recipients all the rights that
    2.38 +you have.  You must make sure that they, too, receive or can get the
    2.39 +source code.  And you must show them these terms so they know their
    2.40 +rights.
    2.41 +
    2.42 +  We protect your rights with two steps: (1) copyright the software, and
    2.43 +(2) offer you this license which gives you legal permission to copy,
    2.44 +distribute and/or modify the software.
    2.45 +
    2.46 +  Also, for each author's protection and ours, we want to make certain
    2.47 +that everyone understands that there is no warranty for this free
    2.48 +software.  If the software is modified by someone else and passed on, we
    2.49 +want its recipients to know that what they have is not the original, so
    2.50 +that any problems introduced by others will not reflect on the original
    2.51 +authors' reputations.
    2.52 +
    2.53 +  Finally, any free program is threatened constantly by software
    2.54 +patents.  We wish to avoid the danger that redistributors of a free
    2.55 +program will individually obtain patent licenses, in effect making the
    2.56 +program proprietary.  To prevent this, we have made it clear that any
    2.57 +patent must be licensed for everyone's free use or not licensed at all.
    2.58 +
    2.59 +  The precise terms and conditions for copying, distribution and
    2.60 +modification follow.
    2.61 +
    2.62 +		    GNU GENERAL PUBLIC LICENSE
    2.63 +   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
    2.64 +
    2.65 +  0. This License applies to any program or other work which contains
    2.66 +a notice placed by the copyright holder saying it may be distributed
    2.67 +under the terms of this General Public License.  The "Program", below,
    2.68 +refers to any such program or work, and a "work based on the Program"
    2.69 +means either the Program or any derivative work under copyright law:
    2.70 +that is to say, a work containing the Program or a portion of it,
    2.71 +either verbatim or with modifications and/or translated into another
    2.72 +language.  (Hereinafter, translation is included without limitation in
    2.73 +the term "modification".)  Each licensee is addressed as "you".
    2.74 +
    2.75 +Activities other than copying, distribution and modification are not
    2.76 +covered by this License; they are outside its scope.  The act of
    2.77 +running the Program is not restricted, and the output from the Program
    2.78 +is covered only if its contents constitute a work based on the
    2.79 +Program (independent of having been made by running the Program).
    2.80 +Whether that is true depends on what the Program does.
    2.81 +
    2.82 +  1. You may copy and distribute verbatim copies of the Program's
    2.83 +source code as you receive it, in any medium, provided that you
    2.84 +conspicuously and appropriately publish on each copy an appropriate
    2.85 +copyright notice and disclaimer of warranty; keep intact all the
    2.86 +notices that refer to this License and to the absence of any warranty;
    2.87 +and give any other recipients of the Program a copy of this License
    2.88 +along with the Program.
    2.89 +
    2.90 +You may charge a fee for the physical act of transferring a copy, and
    2.91 +you may at your option offer warranty protection in exchange for a fee.
    2.92 +
    2.93 +  2. You may modify your copy or copies of the Program or any portion
    2.94 +of it, thus forming a work based on the Program, and copy and
    2.95 +distribute such modifications or work under the terms of Section 1
    2.96 +above, provided that you also meet all of these conditions:
    2.97 +
    2.98 +    a) You must cause the modified files to carry prominent notices
    2.99 +    stating that you changed the files and the date of any change.
   2.100 +
   2.101 +    b) You must cause any work that you distribute or publish, that in
   2.102 +    whole or in part contains or is derived from the Program or any
   2.103 +    part thereof, to be licensed as a whole at no charge to all third
   2.104 +    parties under the terms of this License.
   2.105 +
   2.106 +    c) If the modified program normally reads commands interactively
   2.107 +    when run, you must cause it, when started running for such
   2.108 +    interactive use in the most ordinary way, to print or display an
   2.109 +    announcement including an appropriate copyright notice and a
   2.110 +    notice that there is no warranty (or else, saying that you provide
   2.111 +    a warranty) and that users may redistribute the program under
   2.112 +    these conditions, and telling the user how to view a copy of this
   2.113 +    License.  (Exception: if the Program itself is interactive but
   2.114 +    does not normally print such an announcement, your work based on
   2.115 +    the Program is not required to print an announcement.)
   2.116 +
   2.117 +These requirements apply to the modified work as a whole.  If
   2.118 +identifiable sections of that work are not derived from the Program,
   2.119 +and can be reasonably considered independent and separate works in
   2.120 +themselves, then this License, and its terms, do not apply to those
   2.121 +sections when you distribute them as separate works.  But when you
   2.122 +distribute the same sections as part of a whole which is a work based
   2.123 +on the Program, the distribution of the whole must be on the terms of
   2.124 +this License, whose permissions for other licensees extend to the
   2.125 +entire whole, and thus to each and every part regardless of who wrote it.
   2.126 +
   2.127 +Thus, it is not the intent of this section to claim rights or contest
   2.128 +your rights to work written entirely by you; rather, the intent is to
   2.129 +exercise the right to control the distribution of derivative or
   2.130 +collective works based on the Program.
   2.131 +
   2.132 +In addition, mere aggregation of another work not based on the Program
   2.133 +with the Program (or with a work based on the Program) on a volume of
   2.134 +a storage or distribution medium does not bring the other work under
   2.135 +the scope of this License.
   2.136 +
   2.137 +  3. You may copy and distribute the Program (or a work based on it,
   2.138 +under Section 2) in object code or executable form under the terms of
   2.139 +Sections 1 and 2 above provided that you also do one of the following:
   2.140 +
   2.141 +    a) Accompany it with the complete corresponding machine-readable
   2.142 +    source code, which must be distributed under the terms of Sections
   2.143 +    1 and 2 above on a medium customarily used for software interchange; or,
   2.144 +
   2.145 +    b) Accompany it with a written offer, valid for at least three
   2.146 +    years, to give any third party, for a charge no more than your
   2.147 +    cost of physically performing source distribution, a complete
   2.148 +    machine-readable copy of the corresponding source code, to be
   2.149 +    distributed under the terms of Sections 1 and 2 above on a medium
   2.150 +    customarily used for software interchange; or,
   2.151 +
   2.152 +    c) Accompany it with the information you received as to the offer
   2.153 +    to distribute corresponding source code.  (This alternative is
   2.154 +    allowed only for noncommercial distribution and only if you
   2.155 +    received the program in object code or executable form with such
   2.156 +    an offer, in accord with Subsection b above.)
   2.157 +
   2.158 +The source code for a work means the preferred form of the work for
   2.159 +making modifications to it.  For an executable work, complete source
   2.160 +code means all the source code for all modules it contains, plus any
   2.161 +associated interface definition files, plus the scripts used to
   2.162 +control compilation and installation of the executable.  However, as a
   2.163 +special exception, the source code distributed need not include
   2.164 +anything that is normally distributed (in either source or binary
   2.165 +form) with the major components (compiler, kernel, and so on) of the
   2.166 +operating system on which the executable runs, unless that component
   2.167 +itself accompanies the executable.
   2.168 +
   2.169 +If distribution of executable or object code is made by offering
   2.170 +access to copy from a designated place, then offering equivalent
   2.171 +access to copy the source code from the same place counts as
   2.172 +distribution of the source code, even though third parties are not
   2.173 +compelled to copy the source along with the object code.
   2.174 +
   2.175 +  4. You may not copy, modify, sublicense, or distribute the Program
   2.176 +except as expressly provided under this License.  Any attempt
   2.177 +otherwise to copy, modify, sublicense or distribute the Program is
   2.178 +void, and will automatically terminate your rights under this License.
   2.179 +However, parties who have received copies, or rights, from you under
   2.180 +this License will not have their licenses terminated so long as such
   2.181 +parties remain in full compliance.
   2.182 +
   2.183 +  5. You are not required to accept this License, since you have not
   2.184 +signed it.  However, nothing else grants you permission to modify or
   2.185 +distribute the Program or its derivative works.  These actions are
   2.186 +prohibited by law if you do not accept this License.  Therefore, by
   2.187 +modifying or distributing the Program (or any work based on the
   2.188 +Program), you indicate your acceptance of this License to do so, and
   2.189 +all its terms and conditions for copying, distributing or modifying
   2.190 +the Program or works based on it.
   2.191 +
   2.192 +  6. Each time you redistribute the Program (or any work based on the
   2.193 +Program), the recipient automatically receives a license from the
   2.194 +original licensor to copy, distribute or modify the Program subject to
   2.195 +these terms and conditions.  You may not impose any further
   2.196 +restrictions on the recipients' exercise of the rights granted herein.
   2.197 +You are not responsible for enforcing compliance by third parties to
   2.198 +this License.
   2.199 +
   2.200 +  7. If, as a consequence of a court judgment or allegation of patent
   2.201 +infringement or for any other reason (not limited to patent issues),
   2.202 +conditions are imposed on you (whether by court order, agreement or
   2.203 +otherwise) that contradict the conditions of this License, they do not
   2.204 +excuse you from the conditions of this License.  If you cannot
   2.205 +distribute so as to satisfy simultaneously your obligations under this
   2.206 +License and any other pertinent obligations, then as a consequence you
   2.207 +may not distribute the Program at all.  For example, if a patent
   2.208 +license would not permit royalty-free redistribution of the Program by
   2.209 +all those who receive copies directly or indirectly through you, then
   2.210 +the only way you could satisfy both it and this License would be to
   2.211 +refrain entirely from distribution of the Program.
   2.212 +
   2.213 +If any portion of this section is held invalid or unenforceable under
   2.214 +any particular circumstance, the balance of the section is intended to
   2.215 +apply and the section as a whole is intended to apply in other
   2.216 +circumstances.
   2.217 +
   2.218 +It is not the purpose of this section to induce you to infringe any
   2.219 +patents or other property right claims or to contest validity of any
   2.220 +such claims; this section has the sole purpose of protecting the
   2.221 +integrity of the free software distribution system, which is
   2.222 +implemented by public license practices.  Many people have made
   2.223 +generous contributions to the wide range of software distributed
   2.224 +through that system in reliance on consistent application of that
   2.225 +system; it is up to the author/donor to decide if he or she is willing
   2.226 +to distribute software through any other system and a licensee cannot
   2.227 +impose that choice.
   2.228 +
   2.229 +This section is intended to make thoroughly clear what is believed to
   2.230 +be a consequence of the rest of this License.
   2.231 +
   2.232 +  8. If the distribution and/or use of the Program is restricted in
   2.233 +certain countries either by patents or by copyrighted interfaces, the
   2.234 +original copyright holder who places the Program under this License
   2.235 +may add an explicit geographical distribution limitation excluding
   2.236 +those countries, so that distribution is permitted only in or among
   2.237 +countries not thus excluded.  In such case, this License incorporates
   2.238 +the limitation as if written in the body of this License.
   2.239 +
   2.240 +  9. The Free Software Foundation may publish revised and/or new versions
   2.241 +of the General Public License from time to time.  Such new versions will
   2.242 +be similar in spirit to the present version, but may differ in detail to
   2.243 +address new problems or concerns.
   2.244 +
   2.245 +Each version is given a distinguishing version number.  If the Program
   2.246 +specifies a version number of this License which applies to it and "any
   2.247 +later version", you have the option of following the terms and conditions
   2.248 +either of that version or of any later version published by the Free
   2.249 +Software Foundation.  If the Program does not specify a version number of
   2.250 +this License, you may choose any version ever published by the Free Software
   2.251 +Foundation.
   2.252 +
   2.253 +  10. If you wish to incorporate parts of the Program into other free
   2.254 +programs whose distribution conditions are different, write to the author
   2.255 +to ask for permission.  For software which is copyrighted by the Free
   2.256 +Software Foundation, write to the Free Software Foundation; we sometimes
   2.257 +make exceptions for this.  Our decision will be guided by the two goals
   2.258 +of preserving the free status of all derivatives of our free software and
   2.259 +of promoting the sharing and reuse of software generally.
   2.260 +
   2.261 +			    NO WARRANTY
   2.262 +
   2.263 +  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
   2.264 +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
   2.265 +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
   2.266 +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
   2.267 +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   2.268 +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
   2.269 +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
   2.270 +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
   2.271 +REPAIR OR CORRECTION.
   2.272 +
   2.273 +  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
   2.274 +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
   2.275 +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
   2.276 +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
   2.277 +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
   2.278 +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
   2.279 +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
   2.280 +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
   2.281 +POSSIBILITY OF SUCH DAMAGES.
   2.282 +
   2.283 +		     END OF TERMS AND CONDITIONS
   2.284 +
   2.285 +	    How to Apply These Terms to Your New Programs
   2.286 +
   2.287 +  If you develop a new program, and you want it to be of the greatest
   2.288 +possible use to the public, the best way to achieve this is to make it
   2.289 +free software which everyone can redistribute and change under these terms.
   2.290 +
   2.291 +  To do so, attach the following notices to the program.  It is safest
   2.292 +to attach them to the start of each source file to most effectively
   2.293 +convey the exclusion of warranty; and each file should have at least
   2.294 +the "copyright" line and a pointer to where the full notice is found.
   2.295 +
   2.296 +    <one line to give the program's name and a brief idea of what it does.>
   2.297 +    Copyright (C) <year>  <name of author>
   2.298 +
   2.299 +    This program is free software; you can redistribute it and/or modify
   2.300 +    it under the terms of the GNU General Public License as published by
   2.301 +    the Free Software Foundation; either version 2 of the License, or
   2.302 +    (at your option) any later version.
   2.303 +
   2.304 +    This program is distributed in the hope that it will be useful,
   2.305 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   2.306 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   2.307 +    GNU General Public License for more details.
   2.308 +
   2.309 +    You should have received a copy of the GNU General Public License along
   2.310 +    with this program; if not, write to the Free Software Foundation, Inc.,
   2.311 +    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   2.312 +
   2.313 +Also add information on how to contact you by electronic and paper mail.
   2.314 +
   2.315 +If the program is interactive, make it output a short notice like this
   2.316 +when it starts in an interactive mode:
   2.317 +
   2.318 +    Gnomovision version 69, Copyright (C) year name of author
   2.319 +    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
   2.320 +    This is free software, and you are welcome to redistribute it
   2.321 +    under certain conditions; type `show c' for details.
   2.322 +
   2.323 +The hypothetical commands `show w' and `show c' should show the appropriate
   2.324 +parts of the General Public License.  Of course, the commands you use may
   2.325 +be called something other than `show w' and `show c'; they could even be
   2.326 +mouse-clicks or menu items--whatever suits your program.
   2.327 +
   2.328 +You should also get your employer (if you work as a programmer) or your
   2.329 +school, if any, to sign a "copyright disclaimer" for the program, if
   2.330 +necessary.  Here is a sample; alter the names:
   2.331 +
   2.332 +  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
   2.333 +  `Gnomovision' (which makes passes at compilers) written by James Hacker.
   2.334 +
   2.335 +  <signature of Ty Coon>, 1 April 1989
   2.336 +  Ty Coon, President of Vice
   2.337 +
   2.338 +This General Public License does not permit incorporating your program into
   2.339 +proprietary programs.  If your program is a subroutine library, you may
   2.340 +consider it more useful to permit linking proprietary applications with the
   2.341 +library.  If this is what you want to do, use the GNU Lesser General
   2.342 +Public License instead of this License.
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/Makefile	Fri Apr 07 23:43:06 2017 +0300
     3.3 @@ -0,0 +1,18 @@
     3.4 +COPT		= -O3 -Wall -Werror
     3.5 +BIN		= /usr/local/bin
     3.6 +VERSION		= 0.3
     3.7 +
     3.8 +dterm:		dterm.c
     3.9 +		gcc ${COPT} -o dterm dterm.c -DVERSION='"$(VERSION)"'
    3.10 +
    3.11 +install:
    3.12 +		install dterm ${BIN}
    3.13 +
    3.14 +clean:
    3.15 +		rm -f dterm *.o *.bak
    3.16 +
    3.17 +package:	dterm.c LICENCE.txt README.txt Makefile
    3.18 +		mkdir -p dterm-$(VERSION)
    3.19 +		cp dterm.c LICENCE.txt README.txt Makefile dterm-$(VERSION)
    3.20 +		tar cfvz dterm-$(VERSION).tgz dterm-$(VERSION)
    3.21 +		rm -rf dterm-$(VERSION)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/README.txt	Fri Apr 07 23:43:06 2017 +0300
     4.3 @@ -0,0 +1,129 @@
     4.4 +dterm: A simple terminal program
     4.5 +
     4.6 +
     4.7 +dterm is a simple terminal emulator, which doesn't actually emulate
     4.8 +any particular terminal.  Mainly, it is designed for use with xterm
     4.9 +and friends, which already do a perfectly good emulation, and therefore
    4.10 +don't need any special help; dterm simply provides a means by which 
    4.11 +keystrokes are forwarded to the serial line, and data forwarded from
    4.12 +the serial line appears on the terminal.
    4.13 +
    4.14 +
    4.15 +Running dterm
    4.16 +
    4.17 +dterm is invoked thusly:
    4.18 +
    4.19 +	dterm [options|device ...] 
    4.20 +
    4.21 +dterm attempts to read the file ~/.dtermrc for options; if this doesn't
    4.22 +exist, it tries /etc/dtermrc.  Then it parses the options passed on the
    4.23 +command line.
    4.24 +
    4.25 +The options read should include a device name, e.g "ttyS0" or "ttyd0"
    4.26 +for the first serial port on a Linux or FreeBSD system respectively.  If
    4.27 +no device is specified, dterm tries /dev/ttyS0, /dev/ttyd0, /dev/ttyUSB0
    4.28 +and /dev/ttyU0.
    4.29 +
    4.30 +Once started, dterm can be got into command mode using Ctrl/].  Press
    4.31 +enter once from command mode to get back into conversational mode.  (The
    4.32 +command character can be changed with the esc= option, e.g. esc=p to 
    4.33 +use Ctrl/P instead of Ctrl/].)
    4.34 +
    4.35 +
    4.36 +Options
    4.37 +
    4.38 +The following options can be used from command mode
    4.39 +
    4.40 +- 300, 1200, 9600 etc: Set speed, default 9600.
    4.41 +- 5, 6, 7, 8: Set bits per character, default 8.
    4.42 +- 1, 2: Set number of stop bits, default 1.
    4.43 +- e, o, n, m, s: Set parity to even, odd, none, mark or space, default none.
    4.44 +- cts, nocts:  Enable / disable CTS flow control, default nocts.
    4.45 +- xon, noxon: Enable / disable XON/XOFF flow control, default noxon.
    4.46 +- modem: Enable / disable modem control (hang up modem on exit, exit if
    4.47 +modem hangs up), default nomodem.
    4.48 +- bs, nobs: Enable / disable mapping of Delete to Backspace, default nobs.
    4.49 +- del, nodel: Enable / disable mapping of Backspace to Delete, default nodel.
    4.50 +- maplf, nomaplf: Enable / disable mapping of LF to CR, default nomaplf.
    4.51 +- igncr, noigncr: Ignore / output carriage returns, default noigncr.
    4.52 +- crlf, nocrlf: Enable / disable sending LF after each CR, default nocrlf.
    4.53 +- ctrl, noctrl: Enable / disable control character display mode.  In this
    4.54 +mode, non-printable characters are displayed as ^c for the codes 0-31 (except
    4.55 +CR, LF & TAB), [DEL] for 127, or [xx] for non-printing characters >= 128.
    4.56 +- hex, nohex: As for ctrl, but prints [xx] for all characters except 7-bit
    4.57 +printable ASCII, CR and LF.
    4.58 +- b: Send a 500 ms break.
    4.59 +- dtr, nodtr: Raise / lower DTR, default dtr.
    4.60 +- rts, norts: Raise / lower RTS, default rts.
    4.61 +- d, r: Toggle DTR / RTS.
    4.62 +- esc=<c>: Set command mode character to Ctrl/<c> (default ']') 
    4.63 +- @<filename>: Read and process configuration from <filename>.
    4.64 +- !<command>: Execute shell command
    4.65 +- sx <filename>: Send a file using XMODEM.
    4.66 +- rx <filename>: Receive a file using XMODEM.
    4.67 +- sz <filename>: Send a file using ZMODEM.
    4.68 +- rz: Receive file(s) using ZMODEM.
    4.69 +- show: Display current configuration and modem status.
    4.70 +- help, h, ?: Display a summary of commands.
    4.71 +- version: Display version, copyright and warranty information.
    4.72 +- quit, q: Exit
    4.73 +
    4.74 +
    4.75 +File Transfer
    4.76 +
    4.77 +If the rzsz package (or lrzsz) package is installed, the sx, sz, rx & rz
    4.78 +commands can be used to initiate file transfers using the reliable
    4.79 +XMODEM and ZMODEM file transfer protocols.  Note that the program files
    4.80 +for rzsz must be in /usr/bin or /usr/local/bin for dterm to find them.
    4.81 +
    4.82 +Note that rx, sx and rz require that the transfer be initiated at the
    4.83 +remote end before escaping back to the dterm command prompt.  sz will send 
    4.84 +an "rz" command down the serial link in start-up to initiate the transfer.
    4.85 +
    4.86 +
    4.87 +Examples
    4.88 +
    4.89 +Connect via ttyS1 to a system running at 2400 bps, 7 bits even parity:
    4.90 +
    4.91 +	dterm ttyS1 2400 7 e
    4.92 +
    4.93 +Send a break in a running session:
    4.94 +
    4.95 +	^]
    4.96 +	dterm> b
    4.97 +	dterm>
    4.98 +
    4.99 +Transmit a file using ZMODEM:
   4.100 +
   4.101 +	^]
   4.102 +	dterm> sz file.txt
   4.103 +	rz waiting to receive.Sending: file.txt
   4.104 +	Bytes Sent:  22943   BPS:645                             
   4.105 +	Transfer complete
   4.106 +	dterm>
   4.107 +
   4.108 +
   4.109 +Copyright
   4.110 +
   4.111 +dterm is Copyright 2007 Knossos Networks Ltd.
   4.112 +
   4.113 +This program is free software; you can redistribute it and/or
   4.114 +modify it under the terms of the GNU General Public License version 2
   4.115 +as published by the Free Software Foundation.
   4.116 +
   4.117 +This program is distributed in the hope that it will be useful,
   4.118 +but WITHOUT ANY WARRANTY; without even the implied warranty of
   4.119 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   4.120 +GNU General Public License for more details.
   4.121 +
   4.122 +A copy of the GNU General Public License version 2 is available at
   4.123 +http://www.knossos.net.nz/gpl.html or can be obtained from the Free
   4.124 +Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
   4.125 +02110-1301 USA.
   4.126 +
   4.127 +
   4.128 +Source Code
   4.129 +
   4.130 +dterm source code is located at 
   4.131 +http://www.knossos.net.nz/downloads/dterm-0.3.tgz
   4.132 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/dterm.c	Fri Apr 07 23:43:06 2017 +0300
     5.3 @@ -0,0 +1,1045 @@
     5.4 +/* dterm.c	Dumb terminal program				19/11/2004/dcs
     5.5 + */
     5.6 +
     5.7 +/*
     5.8 + * Copyright 2007 Knossos Networks Ltd.
     5.9 + * Copyright 2017 John Tsiombikas <nuclear@member.fsf.org>
    5.10 + *
    5.11 + * This program is free software; you can redistribute it and/or
    5.12 + * modify it under the terms of the GNU General Public License version 2
    5.13 + * as published by the Free Software Foundation.
    5.14 + *
    5.15 + * This program is distributed in the hope that it will be useful,
    5.16 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.17 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.18 + * GNU General Public License
    5.19 + *
    5.20 + * You should have received a copy of the GNU General Public License
    5.21 + * along with this program; if not, write to the Free Software
    5.22 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    5.23 + * 02110-1301, USA.
    5.24 + */
    5.25 +
    5.26 +#ifndef VERSION
    5.27 +#define VERSION "unknown"
    5.28 +#endif
    5.29 +#define COPYRIGHT \
    5.30 +"dterm version " VERSION " Copyright 2007 Knossos Networks Ltd.\n" \
    5.31 +" Copyright 2017 John Tsiombikas <nuclear@member.fsf.org>\n" \
    5.32 +"\n" \
    5.33 +"This program is free software; you can redistribute it and/or\n" \
    5.34 +"modify it under the terms of the GNU General Public License version 2\n" \
    5.35 +"as published by the Free Software Foundation.\n" \
    5.36 +"\n" \
    5.37 +"This program is distributed in the hope that it will be useful,\n" \
    5.38 +"but WITHOUT ANY WARRANTY; without even the implied warranty of\n" \
    5.39 +"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n" \
    5.40 +"GNU General Public License for more details.\n" \
    5.41 +"\n" \
    5.42 +"You should have received a copy of the GNU General Public License\n" \
    5.43 +"along with this program; if not, write to the Free Software\n" \
    5.44 +"Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA\n" \
    5.45 +"02110-1301, USA.\n"
    5.46 +
    5.47 +
    5.48 +#include <stdio.h>
    5.49 +#include <ctype.h>
    5.50 +#include <sys/types.h>
    5.51 +#include <sys/signal.h>
    5.52 +#include <sys/stat.h>
    5.53 +#include <sys/wait.h>
    5.54 +#include <fcntl.h>
    5.55 +#include <termios.h>
    5.56 +#include <string.h>
    5.57 +#include <unistd.h>
    5.58 +#include <stdlib.h>
    5.59 +#include <time.h>
    5.60 +#include <signal.h>
    5.61 +#include <sys/select.h>
    5.62 +#include <sys/stat.h>
    5.63 +#include <sys/ioctl.h>
    5.64 +#include <errno.h>
    5.65 +
    5.66 +#define FIXTTY	if(istty) tcsetattr(0, TCSADRAIN, &savetio)
    5.67 +#define DIEP(s)  { FIXTTY; perror(s); exit(1); }
    5.68 +#define DIE(s,m) { FIXTTY; fprintf(stderr, "%s: %s\n", s, m); exit(1); }
    5.69 +
    5.70 +/*
    5.71 + Sigh
    5.72 + */
    5.73 +#ifndef CCTS_OFLOW
    5.74 +#ifdef CRTSCTS
    5.75 +#define CCTS_OFLOW CRTSCTS
    5.76 +#endif /* CRTSCTS */
    5.77 +#endif /* ! CCTS_OFLOW */
    5.78 +
    5.79 +
    5.80 +/*
    5.81 + Valid speed settings. 
    5.82 + */
    5.83 +static struct { int s, c; } speeds[] = {
    5.84 +	{ 50, 		B50 	},
    5.85 +	{ 75,		B75 	},
    5.86 +	{ 110,		B110	},
    5.87 +	{ 134,		B134	},
    5.88 +	{ 150,		B150	},
    5.89 +	{ 200,		B200	},
    5.90 +	{ 300,		B300	},
    5.91 +	{ 600,		B600	},
    5.92 +	{ 1200,		B1200	},
    5.93 +	{ 1800,		B1800	},
    5.94 +	{ 2400,		B2400	},
    5.95 +	{ 4800,		B4800	},
    5.96 +	{ 9600,		B9600	},
    5.97 +	{ 19200,	B19200	},
    5.98 +	{ 38400,	B38400	},
    5.99 +#ifdef B7200
   5.100 +	{ 7200,		B7200	},
   5.101 +#endif
   5.102 +#ifdef B14400
   5.103 +	{ 14400,	B14400	},
   5.104 +#endif
   5.105 +#ifdef B28800
   5.106 +	{ 28800,	B28800	},
   5.107 +#endif
   5.108 +#ifdef B57600
   5.109 +	{ 57600,	B57600	},
   5.110 +#endif
   5.111 +#ifdef B76800
   5.112 +	{ 76800,	B76800	},
   5.113 +#endif
   5.114 +#ifdef B115200
   5.115 +	{ 115200,	B115200	},
   5.116 +#endif
   5.117 +#ifdef B230400
   5.118 +	{ 230400,	B230400	},
   5.119 +#endif
   5.120 +#ifdef B460800
   5.121 +	{ 460800,	B460800	},
   5.122 +#endif
   5.123 +#ifdef B921600
   5.124 +	{ 921600,	B921600	},
   5.125 +#endif
   5.126 +	{ 0,		0	}};
   5.127 +
   5.128 +
   5.129 +/*
   5.130 + Save the terminal settings here
   5.131 + */
   5.132 +static struct termios intio, savetio;
   5.133 +
   5.134 +static int fd = -1;		/* Channel to port			*/
   5.135 +static int cmdchar = 035;	/* Command character, default ^]	*/
   5.136 +static char *device = 0;	/* Device, no default			*/
   5.137 +static int ispeed = B9600;	/* Input speed, default 9600 bps	*/
   5.138 +static int ospeed = B9600;	/* Output speed, default 9600 bps	*/
   5.139 +static int twostop = 0;		/* Stop bits, if set to CSTOPB, use two	*/
   5.140 +static int parity = 0;		/* Parity, -1 = mark, -2 = space 0=none */
   5.141 +				/* PARENB enables parity, PARODD = odd	*/
   5.142 +static int bits = CS8;		/* CS5-CS8 for 5-8 bits per character	*/
   5.143 +static int ctsflow = 0;		/* CCTS_OFLOW enables CTS flow control	*/
   5.144 +static int xonflow = 0;		/* IXON | IXOFF for in & out soft F/c	*/
   5.145 +static int modemcontrol = 0;	/* Set to HUPCLto enable modem control	*/
   5.146 +static int markparity = 0;	/* Mark parity -- set high bit on out	*/
   5.147 +static int backspace = 0;	/* Backspace char, send on BS or DEL 	*/
   5.148 +static int maplf = 0;		/* If set, map LF to CR 		*/
   5.149 +static int ignorecr = 0;	/* Ignore carriage returns		*/
   5.150 +static int crlf = 0;		/* Send CRLF on CR			*/
   5.151 +static int istty;		/* Result of isatty()			*/
   5.152 +static char *connname = 0;	/* Connection name found in config	*/
   5.153 +static int sendbreak = 0;	/* Break requested			*/
   5.154 +static int modem = 0;		/* Current modem status			*/
   5.155 +static int setmodem = 0;	/* Set modem status to this		*/
   5.156 +static int delay = 0;		/* Millisecond delay after each key	*/
   5.157 +static int linedelay = 0;	/* Millisecond delay after each CR	*/
   5.158 +static int showspecial = 0;	/* Show special chars as [xx]		*/
   5.159 +
   5.160 +static void
   5.161 +help() {
   5.162 +	fprintf(stderr, 
   5.163 +"dterm commands:\n"
   5.164 +"^%c		Enter command mode	quit, q		Exit\n"
   5.165 +"show		Display configuration	help, h, ?	Display this message\n"
   5.166 +"!<command>	Execute shell command	version		Display version\n"
   5.167 +"@<filename>	Get configuration from <filename>\n"
   5.168 +"<device>	Connect to <device>	300,1200,9600	Set speed\n"
   5.169 +"5, 6, 7, 8	Set bits per character	1, 2		Set stop bits\n"
   5.170 +"e, o, n, m, s	Set parity"	
   5.171 +#ifdef CCTS_OFLOW
   5.172 +"		cts,nocts	Enable / disable CTS\n"
   5.173 +#else
   5.174 +"\n"
   5.175 +#endif
   5.176 +"dtr, nodtr	Raise / lower DTR	b		Send a 500ms break\n"
   5.177 +"rts, norts	Raise / lower RTS	d, r		Toggle DTR, RTS\n"
   5.178 +"rx <filename>	Receive file (XMODEM)	sx <filename>	Send file (XMODEM)\n"
   5.179 +"rz		Receive file (ZMODEM)	sz <filename>	Send file (ZMODEM)\n"
   5.180 +"xon,noxon	Enable / disable XON/XOFF flow control\n"
   5.181 +"modem		Hang up modem on exit, exit if modem hangs up\n"
   5.182 +"nomodem 	Do not do modem control\n"
   5.183 +"bs, nobs	Enable / disable mapping of Delete to Backspace\n"
   5.184 +"del, nodel	Enable / disable mapping of Backspace to Delete\n"
   5.185 +"maplf, nomaplf	Enable / disable mapping of LF to CR\n"
   5.186 +"igncr, noigncr	Ignore / output carriage returns\n"
   5.187 +"crlf, nocrlf	Enable / disable sending LF after each CR\n"
   5.188 +"delay=<n>	Add delay of <n> ms after each charachter sent\n"
   5.189 +"crwait=<n>	Add delay of <n> ms after each line sent\n"
   5.190 +"esc=<c> 	Set command mode character to Ctrl/<c>\n"
   5.191 +"ctrl,hex,noctrl	Show control characters as ^n (except tab, CR, LF)\n"
   5.192 +
   5.193 +
   5.194 +
   5.195 +	, cmdchar + '@');
   5.196 +}
   5.197 +
   5.198 +
   5.199 +
   5.200 +
   5.201 +/*
   5.202 + Show current setup
   5.203 + */
   5.204 +static void
   5.205 +showsetup() {
   5.206 +	int i;
   5.207 +	fprintf(stderr, "Port: %s\n", device);
   5.208 +	fprintf(stderr, "Communications parameters: ");
   5.209 +	for(i = 0; speeds[i].s && speeds[i].c != ispeed; )
   5.210 +		i++;
   5.211 +	fprintf(stderr, "%d", speeds[i].s);
   5.212 +	if(ospeed != ispeed) {
   5.213 +		for(i = 0; speeds[i].s && speeds[i].c != ospeed; )
   5.214 +			i++;
   5.215 +		fprintf(stderr, "/%d", speeds[i].s);
   5.216 +	}
   5.217 +	if(bits == CS5) fprintf(stderr, " 5");
   5.218 +	if(bits == CS6) fprintf(stderr, " 6");
   5.219 +	if(bits == CS7) fprintf(stderr, " 7");
   5.220 +	if(bits == CS8) fprintf(stderr, " 8");
   5.221 +	if(parity == 0) 		fprintf(stderr, " n");
   5.222 +	if(parity == PARENB)		fprintf(stderr, " e");
   5.223 +	if(parity == (PARENB|PARODD))	fprintf(stderr, " o");
   5.224 +	if(parity == -1)		fprintf(stderr, " m");
   5.225 +	if(parity == -2)		fprintf(stderr, " s");
   5.226 +	if(twostop)	fprintf(stderr, " 2\n");
   5.227 +	else		fprintf(stderr, " 1\n");
   5.228 +	fprintf(stderr, "Flow/modem control:");
   5.229 +	if(xonflow)	fprintf(stderr, " xon");
   5.230 +	if(ctsflow)	fprintf(stderr, " cts");
   5.231 +	if(modemcontrol)fprintf(stderr, " modem"); 
   5.232 +	putc('\n', stderr);
   5.233 +	fprintf(stderr, "Character mappings:");
   5.234 +	if(backspace == 8)	fprintf(stderr, " bs");
   5.235 +	if(backspace == 127)	fprintf(stderr, " del");
   5.236 +	if(maplf)		fprintf(stderr, " maplf");
   5.237 +	if(ignorecr)		fprintf(stderr, " igncr");
   5.238 +	if(crlf)		fprintf(stderr, " crlf");
   5.239 +	if(showspecial == 1)	fprintf(stderr, " ctrl");
   5.240 +	if(showspecial == 2)	fprintf(stderr, " hex");
   5.241 +	putc('\n', stderr);
   5.242 +	printf("Modem control: DTR: %s RTS: %s CTS: %s DSR: %s DCD: %s\n",
   5.243 +			setmodem & TIOCM_DTR ? "on" : "off",
   5.244 +			setmodem & TIOCM_RTS ? "on" : "off",
   5.245 +			   modem & TIOCM_CTS ? "on" : "off",
   5.246 +			   modem & TIOCM_DSR ? "on" : "off",
   5.247 +			   modem & TIOCM_CD  ? "on" : "off");
   5.248 +	fprintf(stderr, "Escape character: ^%c\n", cmdchar + '@');
   5.249 +	fflush(stderr);
   5.250 +}
   5.251 +
   5.252 +
   5.253 +/*
   5.254 + Use the rzsz or lrzsz package to do file transfer
   5.255 + Mode should be "rx", "rb" or "rz" to receive a file, "sx", "sb" or "sz"
   5.256 + to send.  "rz" & "rb" don't require a file name; the others do.
   5.257 + */
   5.258 +static int
   5.259 +rzsz(char *mode, char *file) {
   5.260 +	static char *loc[] = {	"/usr/bin/",  "/usr/local/bin/l",
   5.261 +				"/usr/bin/l", "/usr/local/bin/", 0 };
   5.262 +	char path[128];
   5.263 +	char *cmd;
   5.264 +	int i;
   5.265 +	struct stat sb;
   5.266 +	pid_t pid;
   5.267 +
   5.268 +	/*
   5.269 +	 Check file name
   5.270 +	 */
   5.271 +	if(*file == 0 && (mode[0] != 'r' || mode[1] == 'x')) {
   5.272 +		fprintf(stderr, "File name required for %c%c\n", 
   5.273 +						mode[0], mode[1]);
   5.274 +		return -1;
   5.275 +	}
   5.276 +
   5.277 +	/*
   5.278 +	 Find the appropriate command
   5.279 +	 */
   5.280 +	for(i = 0; loc[i]; i++) {
   5.281 +		if(mode[1] == 'a') {
   5.282 +			sprintf(path, "%sascii-xfr", loc[i]);
   5.283 +		} else {
   5.284 +			sprintf(path, "%s%c%c", loc[i], mode[0], mode[1]);
   5.285 +		}
   5.286 +		if(!stat(path, &sb) && (sb.st_mode & S_IXUSR))
   5.287 +			break;
   5.288 +	}
   5.289 +	if(!loc[i]) {
   5.290 +		fprintf(stderr, "RZ/SZ/ascii-xfr not installed\n");
   5.291 +		return -1;
   5.292 +	}
   5.293 +
   5.294 +	/*
   5.295 +	 Get the command name
   5.296 +	 */
   5.297 +	cmd = strrchr(path, '/');
   5.298 +	if(cmd)	cmd++;
   5.299 +	else	cmd = path;
   5.300 +
   5.301 +	/*
   5.302 +	 Fork subprocess.  Set stdin & stdout to the serial line
   5.303 +	 stderr remains on the console for progress messages
   5.304 +	 */
   5.305 +	pid = fork();
   5.306 +	if(pid == 0) {
   5.307 +		dup2(fd, 0);
   5.308 +		dup2(fd, 1);
   5.309 +		if(mode[1] == 'a') {
   5.310 +			char delay_str[64];
   5.311 +			sprintf(delay_str, "%d", linedelay);
   5.312 +			if(*file) execl(path, cmd, "-s", "-l", delay_str, file, NULL);
   5.313 +			else      execl(path, cmd, "-r", NULL);
   5.314 +		} else {
   5.315 +			if(*file) execl(path, cmd, file, NULL);
   5.316 +			else	  execl(path, cmd, NULL);
   5.317 +		}
   5.318 +		_exit(127);
   5.319 +	}
   5.320 +	else if(pid == -1) {
   5.321 +		perror("fork");
   5.322 +		return -1;
   5.323 +	}
   5.324 +
   5.325 +	/*
   5.326 +	 Wait for the process to complete and give a meaningful
   5.327 +	 response
   5.328 +	 */
   5.329 +	signal(SIGINT,  SIG_IGN);
   5.330 +	signal(SIGQUIT, SIG_IGN);
   5.331 +	signal(SIGTERM, SIG_IGN);
   5.332 +	while(waitpid(pid, &i, 0) != pid) {}
   5.333 +	signal(SIGINT,  SIG_DFL);
   5.334 +	signal(SIGQUIT, SIG_DFL);
   5.335 +	signal(SIGTERM, SIG_DFL);
   5.336 +
   5.337 +	if(WIFSIGNALED(i)) {
   5.338 +		fprintf(stderr, "Terminated on signal %d%s\n", WTERMSIG(i), 
   5.339 +				WCOREDUMP(i) ? " (core dumped)" : "");
   5.340 +		return -1;
   5.341 +	}
   5.342 +	if(WTERMSIG(i))
   5.343 +		return -1;
   5.344 +	return 0;
   5.345 +}
   5.346 +
   5.347 +
   5.348 +
   5.349 +static int readconfig(char *, char *);
   5.350 +
   5.351 +/*
   5.352 + Process commands passed as strings, may be several commands on a line
   5.353 + Allow ugliness like 8n1 -- treat as 8, n, 1
   5.354 + */
   5.355 +static int
   5.356 +setup(char *s, char *cffile, int cfline) {
   5.357 +	char *t, *d;
   5.358 +	int j,k;
   5.359 +	int ret = 0;
   5.360 +	struct stat sb;
   5.361 +	char ttybuf[128];
   5.362 +	int justospeed = 0;
   5.363 +
   5.364 +	while(*s) {
   5.365 +		/*
   5.366 +		 Skip whitespace, commas
   5.367 +		 */
   5.368 +		while(isspace(*s) || *s == ',') 
   5.369 +			s++;
   5.370 +		if(!*s) break;
   5.371 +
   5.372 +		/*
   5.373 +		 '?' = help
   5.374 +		 */
   5.375 +		if(*s == '?') {
   5.376 +			help();
   5.377 +			return -4;
   5.378 +		}
   5.379 +
   5.380 +		/*
   5.381 +		 '!' = shell command
   5.382 +		 */
   5.383 +		if(*s == '!') {
   5.384 +			if((t = strchr(s, '\n')))
   5.385 +				*t = 0;
   5.386 +			system(++s);
   5.387 +			break;
   5.388 +		}
   5.389 +
   5.390 +		/*
   5.391 +		 File transfer (sx, sz, rx, rz, sa, ra)
   5.392 +		 Run rzsz or ascii-xfr to perform the actual file transfer
   5.393 +		 Allow "sxfilename", "sx filename" or just "rz"
   5.394 +		 */
   5.395 +		if((s[0] == 's' || s[0] == 'r') && 
   5.396 +		   (s[1] == 'x' || s[1] == 'z' || s[1] == 'a')) {
   5.397 +			if((t = strchr(s, '\n')))
   5.398 +				*t = 0;
   5.399 +			for(t = s + 2; isspace(*t); ) t++;
   5.400 +			return rzsz(s, t);
   5.401 +		}
   5.402 +
   5.403 +		/*
   5.404 +		 If a number, process it.
   5.405 +		 If it's a valid speed, use that -- if nnn/mmm, set both to nnn 
   5.406 +		 for the first time, and flag things so mmm just sets ospeed
   5.407 +		 5-8 = data bits, 1,2 sets stops
   5.408 +		 Anything else is error
   5.409 +		 */
   5.410 +		if(isdigit(*s)) {
   5.411 +			j = strtol(s, &s, 10);
   5.412 +			for(k = 1; speeds[k].s; k++)
   5.413 +				if(speeds[k].s == j)
   5.414 +					break;
   5.415 +			if(speeds[k].s) {
   5.416 +				ospeed = speeds[k].c;
   5.417 +				if(!justospeed)
   5.418 +					ispeed = ospeed;
   5.419 +				if(*s == '/') {
   5.420 +					s++;
   5.421 +					justospeed = 1;
   5.422 +				}
   5.423 +				else	justospeed = 0;
   5.424 +			}
   5.425 +			else if(j == 5)	bits = CS5;
   5.426 +			else if(j == 6)	bits = CS6;
   5.427 +			else if(j == 7)	bits = CS7;
   5.428 +			else if(j == 8)	bits = CS8;
   5.429 +			else if(j == 1) twostop = 0;
   5.430 +			else if(j == 2) twostop = CSTOPB;
   5.431 +			else {
   5.432 +				if(cffile)
   5.433 +					fprintf(stderr, "in %s:%d: ",
   5.434 +						cffile, cfline);
   5.435 +				fprintf(stderr, "%d: invalid speed/bits\n", j);
   5.436 +				ret = -1;
   5.437 +			}
   5.438 +		}
   5.439 +
   5.440 +		/*
   5.441 +		 Otherwise, get the alpha-only keyword, see if it matches anything 
   5.442 +		 useful.
   5.443 +		 */
   5.444 +		else {
   5.445 +			t = s;
   5.446 +			while(isalpha(*t)) t++;
   5.447 +			j = *t;
   5.448 +			*t = 0;
   5.449 +			if(	!strcasecmp(s, "xon"))
   5.450 +				xonflow = IXON | IXOFF;
   5.451 +			else if(!strcasecmp(s, "noxon"))
   5.452 +				xonflow = 0;
   5.453 +
   5.454 +#ifdef CCTS_OFLOW
   5.455 +			else if(!strcasecmp(s, "cts"))
   5.456 +				ctsflow = CCTS_OFLOW;
   5.457 +			else if(!strcasecmp(s, "nocts"))
   5.458 +				ctsflow = 0;
   5.459 +#endif
   5.460 +			else if(!strcasecmp(s, "modem"))
   5.461 +				modemcontrol = HUPCL;
   5.462 +			else if(!strcasecmp(s, "nomodem"))
   5.463 +				modemcontrol = 0;
   5.464 +			else if(!strcasecmp(s, "E"))
   5.465 +				parity = PARENB;
   5.466 +			else if(!strcasecmp(s, "O"))
   5.467 +				parity = PARENB | PARODD;
   5.468 +			else if(!strcasecmp(s, "M"))
   5.469 +				parity = -1;
   5.470 +			else if(!strcasecmp(s, "S"))
   5.471 +				parity = -2;
   5.472 +			else if(!strcasecmp(s, "N"))
   5.473 +				parity = 0;
   5.474 +			else if(!strcasecmp(s, "q") || !strcasecmp(s, "quit"))
   5.475 +				ret = -3;
   5.476 +			else if(!strcasecmp(s, "h") || !strcasecmp(s, "help"))
   5.477 +				help();
   5.478 +			else if(!strcasecmp(s, "del"))
   5.479 +				backspace = 127;
   5.480 +			else if(!strcasecmp(s, "bs"))
   5.481 +				backspace = 8;
   5.482 +			else if(!strcasecmp(s,"nobs") || !strcasecmp(s,"nodel"))
   5.483 +				backspace = 0;
   5.484 +			else if(!strcasecmp(s, "noesc"))
   5.485 +				cmdchar = 0;
   5.486 +			else if(!strcasecmp(s, "maplf"))
   5.487 +				maplf = 1;
   5.488 +			else if(!strcasecmp(s, "nomaplf"))
   5.489 +				maplf = 0;
   5.490 +			else if(!strcasecmp(s, "igncr"))
   5.491 +				ignorecr = 1;
   5.492 +			else if(!strcasecmp(s, "noigncr"))
   5.493 +				ignorecr = 0;
   5.494 +			else if(!strcasecmp(s, "crlf"))
   5.495 +				crlf = 1;
   5.496 +			else if(!strcasecmp(s, "nocrlf"))
   5.497 +				crlf = 0;
   5.498 +			else if(!strcasecmp(s, "b")) 
   5.499 +				sendbreak = 1;
   5.500 +			else if(!strcasecmp(s, "d"))
   5.501 +				setmodem ^= TIOCM_DTR;
   5.502 +			else if(!strcasecmp(s, "r"))
   5.503 +				setmodem ^= TIOCM_RTS;
   5.504 +			else if(!strcasecmp(s, "dtr"))
   5.505 +				setmodem |= TIOCM_DTR;
   5.506 +			else if(!strcasecmp(s, "rts"))
   5.507 +				setmodem |= TIOCM_RTS;
   5.508 +			else if(!strcasecmp(s, "nodtr"))
   5.509 +				setmodem &= ~TIOCM_DTR;
   5.510 +			else if(!strcasecmp(s, "norts"))
   5.511 +				setmodem &= ~TIOCM_RTS;
   5.512 +			else if(!strcasecmp(s, "show"))
   5.513 +				showsetup();
   5.514 +			else if(!strcasecmp(s, "version"))
   5.515 +				fputs(COPYRIGHT, stderr);
   5.516 +			else if(!strcasecmp(s, "ctrl"))
   5.517 +				showspecial = 1;
   5.518 +			else if(!strcasecmp(s, "hex"))
   5.519 +				showspecial = 2;
   5.520 +			else if(!strcasecmp(s, "noctrl") ||
   5.521 +				!strcasecmp(s, "noctrl"))
   5.522 +				showspecial = 0;
   5.523 +
   5.524 +			/*
   5.525 +			 No?
   5.526 +			 @<filename>	includes a file
   5.527 +			 !cmd		Run a command
   5.528 +			 esc=c		sets escape char
   5.529 +			 <device>	select device
   5.530 +			 */
   5.531 +			else {
   5.532 +				*t = j;
   5.533 +				while(*t && !isspace(*t) && *t != ',')
   5.534 +					t++;
   5.535 +				j = *t;
   5.536 +				*t = 0;
   5.537 +				if(*s == '@') {
   5.538 +					k = readconfig(++s, 0);
   5.539 +					if(k == -2) {
   5.540 +						if(cffile)
   5.541 +							fprintf(stderr,
   5.542 +								"in %s:%d: ",
   5.543 +								cffile, cfline);
   5.544 +						fprintf(stderr, "%s: %s\n",
   5.545 +							s, strerror(errno));
   5.546 +						ret = -1;
   5.547 +					}
   5.548 +					goto next;
   5.549 +				}
   5.550 +				if(!strncasecmp(s, "esc=", 4)) {
   5.551 +					cmdchar = s[4] & 0x1f;
   5.552 +					goto next;
   5.553 +				}
   5.554 +				else if(!strncasecmp(s, "delay=", 6)) {
   5.555 +					delay = atoi(s+6);
   5.556 +					goto next;
   5.557 +				}
   5.558 +				else if(!strncasecmp(s, "crwait=", 7)) {
   5.559 +					linedelay = atoi(s+7);
   5.560 +					goto next;
   5.561 +				}
   5.562 +				d = s;	
   5.563 +				k = stat(d, &sb);
   5.564 +				if(k && *d != '/') {
   5.565 +					sprintf(ttybuf, "/dev/%.100s", d);
   5.566 +					d = ttybuf;
   5.567 +					k = stat(d, &sb);
   5.568 +				}
   5.569 +				if(!k) {
   5.570 +					if((sb.st_mode & S_IFMT) == S_IFCHR) {
   5.571 +						ret = 1;
   5.572 +						device = strdup(d);
   5.573 +						goto next;
   5.574 +					}
   5.575 +				}
   5.576 +				if(cffile)
   5.577 +					fprintf(stderr, "in %s:%d: ",
   5.578 +						cffile, cfline);
   5.579 +				fprintf(stderr,
   5.580 +					"%s: unrecognised keyword/device\n", s);
   5.581 +				ret = -1;
   5.582 +			}
   5.583 +		next:	*t = j;
   5.584 +			s = t;
   5.585 +		}
   5.586 +	}
   5.587 +	return ret;
   5.588 +}
   5.589 +
   5.590 +
   5.591 +/*
   5.592 + Read a config file
   5.593 + Input lines can be lists of config words, or in the form
   5.594 + name: words
   5.595 + If name: form, only lines matching passed name are used
   5.596 + */
   5.597 +static int
   5.598 +readconfig(char *file, char *name) {
   5.599 +	char buf[1024];
   5.600 +	FILE *f;
   5.601 +	char *s, *t;
   5.602 +	int lineno = 0;
   5.603 +	int ret = 0, r;
   5.604 +
   5.605 +	/*
   5.606 +	 ~/file = get file from $HOME/file
   5.607 +	 */
   5.608 +	if(*file == '~' && file[1] == '/' && (s = getenv("HOME"))) {
   5.609 +		snprintf(buf, sizeof(buf), "%s/%s", s, file+2);
   5.610 +		file = buf;
   5.611 +	}
   5.612 +
   5.613 +	/*
   5.614 +	 Return -2 if can't open
   5.615 +	 */
   5.616 +	f = fopen(file, "r");
   5.617 +	if(!f)	return -2;
   5.618 +
   5.619 +	/*
   5.620 +	 Read input, strip # commends
   5.621 +	 Count lines
   5.622 +	 Keep track of return code
   5.623 +	 */
   5.624 +	while(fgets(buf, sizeof(buf), f)) {
   5.625 +		lineno++;
   5.626 +		if((s = strchr(buf, '#')))
   5.627 +			*s = 0;
   5.628 +		for(s = buf; isspace(*s);)
   5.629 +			s++;
   5.630 +		if(!*s) continue;
   5.631 +		for(t = s; *t && *t != ':' && *t != ',' && !isspace(*t); )
   5.632 +			t++;
   5.633 +		if(*t == ':') {
   5.634 +			*t++ = 0;
   5.635 +			if(!name)
   5.636 +				continue;
   5.637 +			if(strcmp(name, s))
   5.638 +				continue;
   5.639 +			s = t;
   5.640 +			connname = name;
   5.641 +		}
   5.642 +
   5.643 +		r = setup(s, file, lineno);
   5.644 +		if(r < 0)
   5.645 +			ret = r;
   5.646 +		if(r > 0 && !ret)
   5.647 +			ret = 1;
   5.648 +	}
   5.649 +
   5.650 +	fclose(f);
   5.651 +	return ret;
   5.652 +}
   5.653 +
   5.654 +
   5.655 +/*
   5.656 + Sleep n milliseconds
   5.657 + */
   5.658 +static void
   5.659 +millisleep(int n) {
   5.660 +	struct timespec t;
   5.661 +	t.tv_sec = n / 1000;
   5.662 +	t.tv_nsec = (n % 1000) * 1000000;
   5.663 +	nanosleep(&t, 0);
   5.664 +}
   5.665 +
   5.666 +
   5.667 +/*
   5.668 + Set up the port
   5.669 + */
   5.670 +static int
   5.671 +setupport(int fd) {
   5.672 +	int parityflags;
   5.673 +	int modemflags;
   5.674 +	int spaceparity = 0;
   5.675 +	struct termios tio;
   5.676 +	int m;
   5.677 +
   5.678 +	/*
   5.679 +	 See what to do with parity
   5.680 +	 */
   5.681 +	markparity = 0;
   5.682 +	parityflags = parity;
   5.683 +	if(parity == -1) {
   5.684 +		parityflags = 0;
   5.685 +		markparity = ISTRIP;
   5.686 +	}
   5.687 +	else if(parity == -2) {
   5.688 +		parityflags = 0;
   5.689 +		spaceparity = ISTRIP;
   5.690 +	}
   5.691 +
   5.692 +	/*
   5.693 +	 If no modem control, use local mode
   5.694 +	 */
   5.695 +	modemflags = ctsflow | modemcontrol;
   5.696 +	if(!modemflags)
   5.697 +		modemflags = CLOCAL;
   5.698 +
   5.699 +	/*
   5.700 +	 Set the speed and params
   5.701 +	 */
   5.702 +	tcgetattr(fd, &tio);
   5.703 +	tio.c_iflag = IGNBRK | IGNPAR | xonflow | spaceparity | markparity;
   5.704 +	tio.c_cflag = CREAD | HUPCL | modemflags | bits | parityflags;
   5.705 +	tio.c_oflag = 0;
   5.706 +	tio.c_lflag = 0;
   5.707 +	cfsetispeed(&tio, ispeed);
   5.708 +	cfsetospeed(&tio, ospeed);
   5.709 +	if(tcsetattr(fd, TCSAFLUSH, &tio) == -1)
   5.710 +		return -1;
   5.711 +
   5.712 +	/*
   5.713 +	 Set up the modem lines
   5.714 +	 */
   5.715 +	ioctl(fd, TIOCMGET, &modem);
   5.716 +	if((modem & (TIOCM_RTS | TIOCM_DTR)) != (setmodem & (TIOCM_RTS |
   5.717 +							     TIOCM_DTR))) {
   5.718 +		m = setmodem 	& (TIOCM_RTS | TIOCM_DTR);
   5.719 +		ioctl(fd, TIOCMBIS, &m);
   5.720 +		m = (~setmodem) & (TIOCM_RTS | TIOCM_DTR);
   5.721 +		ioctl(fd, TIOCMBIC, &m);
   5.722 +	}
   5.723 +
   5.724 +	/*
   5.725 +	 Send a break if requested
   5.726 +	 */
   5.727 +	if(sendbreak) {
   5.728 +		ioctl(fd, TIOCSBRK, 0);
   5.729 +		millisleep(500);
   5.730 +		ioctl(fd, TIOCCBRK, 0);
   5.731 +		sendbreak = 0;
   5.732 +	}
   5.733 +
   5.734 +	/*
   5.735 +	 Get the current modem status
   5.736 +	 */
   5.737 +	ioctl(fd, TIOCMGET, &modem);
   5.738 +	setmodem = modem;
   5.739 +
   5.740 +	return 0;
   5.741 +}
   5.742 +
   5.743 +
   5.744 +/*
   5.745 + Set up the modem.  This is a little tricky due to the need to
   5.746 + ensure the modem does not block before we set it up.
   5.747 + */
   5.748 +static int
   5.749 +openport(char *device) {
   5.750 +	int fd;
   5.751 +
   5.752 +	if((fd = open(device, O_RDWR|O_NONBLOCK, 0)) < 0)
   5.753 +		DIEP(device)
   5.754 +	if(setupport(fd) < 0)
   5.755 +		DIEP(device)
   5.756 +	millisleep(10);
   5.757 +	fcntl(fd, F_SETFL, 0);
   5.758 +
   5.759 +	ioctl(fd, TIOCMGET, &modem);
   5.760 +	setmodem = modem;
   5.761 +
   5.762 +	setenv("DTERM_PORT", device, 1);
   5.763 +	return fd;
   5.764 +}
   5.765 +
   5.766 +
   5.767 +/*
   5.768 + Usage
   5.769 + */
   5.770 +static void
   5.771 +usage(char *this) {
   5.772 +	fprintf(stderr, "Usage: %s port/setup\n"
   5.773 +			"	'%s help' for help\n", this, this);
   5.774 +	exit(1);
   5.775 +}
   5.776 +
   5.777 +
   5.778 +int
   5.779 +main(int argc, char **argv) {
   5.780 +	int nfd;
   5.781 +	int i, j, c;
   5.782 +	unsigned char inbuf;
   5.783 +	char buf[256];
   5.784 +	char cbuf[8];
   5.785 +	char *s;
   5.786 +	int done;
   5.787 +	fd_set fds;
   5.788 +	struct timeval delay_tv, *readdelay;
   5.789 +	struct stat sb;
   5.790 +
   5.791 +	/*
   5.792 +	 Do the right things depending on whether stdin & stdout are TTYs
   5.793 +	 If the input is a TTY, we need to put it into non-canonical mode
   5.794 +	 (which we'll actually do later); otherwise, default to turning
   5.795 +	 LFs from a file into CRs.  (See [no]maplf setup command.)
   5.796 +	 If the output is a TTY, default to passing CR transparently; 
   5.797 +	 otherwise default to ignoring CR so that output is logged to a
   5.798 +	 files etc nicely.  (See [no]igncr.)
   5.799 +	 */
   5.800 +	istty = isatty(0);
   5.801 +	if(istty) {
   5.802 +		tcgetattr(0, &savetio);
   5.803 +		maplf = 0;
   5.804 +	}
   5.805 +	else 	maplf = 1;
   5.806 +	if(isatty(1))
   5.807 +		ignorecr = 0;
   5.808 +	else	ignorecr = 1;
   5.809 +
   5.810 +	/*
   5.811 +	 Read default config, if no private .dtermrc, use /etc/dtermrc
   5.812 +	 */
   5.813 +	setmodem = modem = TIOCM_DTR | TIOCM_RTS;
   5.814 +	if(readconfig("~/.dtermrc", argv[1]) == -2)
   5.815 +		readconfig("/etc/dtermrc", argv[1]);
   5.816 +
   5.817 +	/*
   5.818 +	 Parse args
   5.819 +	 If only arg is "help", exit
   5.820 +	 */
   5.821 +	i = 1;
   5.822 +	if(connname) i = 2;
   5.823 +	for(; i < argc; i++) 
   5.824 +		if(setup(argv[i], 0, 0) < 0)
   5.825 +			usage(argv[0]);
   5.826 +	if(argc == 2 && !strcasecmp(argv[1], "help"))
   5.827 +		exit(0);
   5.828 +
   5.829 +	/*
   5.830 +	 If no device specified, have a crack at finding a default device
   5.831 +	 Look for the first on-board device first; failing that look for
   5.832 +	 the first USB device.  For Linux & BSD these are:
   5.833 +		OS	Onboard	USB
   5.834 +		Linux	ttyS0	ttyUSB0
   5.835 +		BSD	ttyd0	ttyU0
   5.836 +	 Note that this rather assumes that the existence of a device
   5.837 +	 name in /dev indicates the actual existence of a device.  Mostly
   5.838 +	 this is the case on modern systems.  Mostly.
   5.839 +	 */
   5.840 +	if(!device) {
   5.841 +		if(     !stat("/dev/ttyS0",   &sb))  device = "/dev/ttyS0";
   5.842 +		else if(!stat("/dev/ttyd0",   &sb))  device = "/dev/ttyd0";
   5.843 +		else if(!stat("/dev/ttyUSB0", &sb))  device = "/dev/ttyUSB0";
   5.844 +		else if(!stat("/dev/ttyU0",   &sb))  device = "/dev/ttyU0";
   5.845 +		else {
   5.846 +			fprintf(stderr, "Could not find default device\n");
   5.847 +			usage(argv[0]);
   5.848 +		}
   5.849 +	}
   5.850 +
   5.851 +	/*
   5.852 +	 If the controlling TTY is in fact a TTY, set it up
   5.853 +	 */
   5.854 +	if(istty) {
   5.855 +		intio = savetio;
   5.856 +		intio.c_oflag = 0;
   5.857 +		intio.c_lflag = 0;
   5.858 +		intio.c_iflag = savetio.c_iflag & ~(INLCR|IGNCR|ICRNL);
   5.859 +
   5.860 +		intio.c_cc[VEOF]	= _POSIX_VDISABLE;
   5.861 +		intio.c_cc[VEOL]	= _POSIX_VDISABLE;
   5.862 +		intio.c_cc[VEOL2]	= _POSIX_VDISABLE;
   5.863 +		intio.c_cc[VERASE]	= _POSIX_VDISABLE;
   5.864 +		intio.c_cc[VWERASE]	= _POSIX_VDISABLE;
   5.865 +		intio.c_cc[VKILL]	= _POSIX_VDISABLE;
   5.866 +		intio.c_cc[VREPRINT]	= _POSIX_VDISABLE;
   5.867 +		intio.c_cc[VINTR]	= _POSIX_VDISABLE;
   5.868 +		intio.c_cc[VQUIT]	= _POSIX_VDISABLE;
   5.869 +		intio.c_cc[VSUSP]	= _POSIX_VDISABLE;
   5.870 +#ifdef VDSUSP
   5.871 +		intio.c_cc[VDSUSP]	= _POSIX_VDISABLE;
   5.872 +#endif
   5.873 +		intio.c_cc[VLNEXT]	= _POSIX_VDISABLE;
   5.874 +		intio.c_cc[VDISCARD]	= _POSIX_VDISABLE;
   5.875 +#ifdef VSTATUS
   5.876 +		intio.c_cc[VSTATUS]	= _POSIX_VDISABLE;
   5.877 +#endif
   5.878 +		tcsetattr(0, TCSADRAIN, &intio);
   5.879 +	}
   5.880 +
   5.881 +	/*
   5.882 +	 Connect to serial port
   5.883 +	 */
   5.884 +	fd = openport(device);
   5.885 +	if(fd < 0) exit(1);
   5.886 +
   5.887 +	/*
   5.888 +	 Main loop
   5.889 +	 */
   5.890 +	readdelay = 0;
   5.891 +	done = 0;
   5.892 +	while(!done) {
   5.893 +
   5.894 +		/*
   5.895 +		 Set up the select() call
   5.896 +		 If readdelay is not 0, we're waiting for things to go quiet so we
   5.897 +		 can exit.
   5.898 +		 Errors kill us, execpt for interrupted calls
   5.899 +		 0 return only happens if readdelay is set, so we exit then
   5.900 +		 */
   5.901 +		FD_ZERO(&fds);
   5.902 +		if(!readdelay) 
   5.903 +			FD_SET(0, &fds);
   5.904 +		FD_SET(fd, &fds);
   5.905 +		i = select(fd + 1, &fds, 0,0, readdelay);
   5.906 +		if(i == -1 && errno != EINTR)
   5.907 +			DIEP("select");
   5.908 +		if(i == 0 && readdelay)
   5.909 +			break;
   5.910 +
   5.911 +		/*
   5.912 +		 If input from line, read a full buffer in
   5.913 +		 IgnoreCR means sucking CRs out of the buffer (yuck)
   5.914 +		 If EOF (e.g. hangup), exit nicely.
   5.915 +		 */
   5.916 +		if(FD_ISSET(fd, &fds)) {
   5.917 +			i = read(fd, buf, sizeof(buf));
   5.918 +			if(i < 0) 
   5.919 +				DIEP(device);
   5.920 +			if(!i)	break;
   5.921 +			if(showspecial) {
   5.922 +				s = buf;
   5.923 +				do {
   5.924 +					c = 0;
   5.925 +					for(j = 0; j < i; j++) {
   5.926 +						c = (unsigned char) s[j];
   5.927 +						if(showspecial == 2 && (
   5.928 +						   c == '\t' || c > '~'))
   5.929 +							break;
   5.930 +						if(c == '\r' && ignorecr)
   5.931 +							break;
   5.932 +						if((  c < ' '    && c != '\t' 
   5.933 +						   && c != '\r'  && c != '\n') 
   5.934 +						   || (c > '~' && c < 160))
   5.935 +							break;
   5.936 +					}
   5.937 +					if(j) write(1, s, j);
   5.938 +					if(j >= i)
   5.939 +						break;
   5.940 +					if(c == '\r' && ignorecr) {
   5.941 +						/* Do nothing */
   5.942 +					}
   5.943 +					else if(c < 32 && showspecial != 2) {
   5.944 +						cbuf[0] = '^';
   5.945 +						cbuf[1] = c + '@';
   5.946 +						write(1, cbuf, 2);
   5.947 +					}
   5.948 +					else if(c == 127 && showspecial != 2)
   5.949 +						write(1, "[DEL]", 5);
   5.950 +					else {
   5.951 +						sprintf(cbuf, "[%02x]", c);
   5.952 +						write(1, cbuf, 4);
   5.953 +					}
   5.954 +					j++;
   5.955 +					s += j;
   5.956 +					i -= j;
   5.957 +				} while(i > 0);					
   5.958 +			}
   5.959 +			else {
   5.960 +				if(ignorecr) {
   5.961 +					j = 0;
   5.962 +					for(s = buf; s < buf + i; s++) 
   5.963 +						if(*s != '\r')
   5.964 +							buf[j++] = *s;
   5.965 +					i = j;
   5.966 +				}			
   5.967 +				write(1, buf, i);
   5.968 +			}
   5.969 +		}
   5.970 +
   5.971 +		/*
   5.972 +		 Input on stdin
   5.973 +		 Read a character
   5.974 +		 If EOF, set readdelay to 1 second
   5.975 +		 */
   5.976 +		if(FD_ISSET(0, &fds)) {
   5.977 +			if(read(0, &inbuf, 1) < 1) {
   5.978 +				delay_tv.tv_sec = 1;
   5.979 +				delay_tv.tv_usec = 0;
   5.980 +				readdelay = &delay_tv;
   5.981 +				continue;
   5.982 +			}
   5.983 +			/*
   5.984 +			 If command character received, read commands 
   5.985 +			 */
   5.986 +			if(inbuf == cmdchar && istty) {
   5.987 +				FIXTTY;
   5.988 +				putchar('\n');
   5.989 +				for(;;) {
   5.990 +					fprintf(stderr, "dterm> ");
   5.991 +					if(!fgets(buf, sizeof(buf), stdin)) 
   5.992 +						return 0;
   5.993 +					if((s = strchr(buf, '#')))
   5.994 +						*s = 0;
   5.995 +					for(s = buf; *s; s++)
   5.996 +						if(!isspace(*s)) break;
   5.997 +					if(!*s) break;
   5.998 +					ioctl(fd, TIOCMGET, &modem);
   5.999 +					i = setup(buf, 0, 0);
  5.1000 +					if(i == -3) 
  5.1001 +						return 0;
  5.1002 +					if(i == 1) {
  5.1003 +						nfd = openport(device);
  5.1004 +						if(nfd >= 0) {
  5.1005 +							close(fd);
  5.1006 +							fd = nfd;
  5.1007 +						}
  5.1008 +					}
  5.1009 +					else if(setupport(fd))
  5.1010 +						fprintf(stderr,
  5.1011 +						      "invalid parameters\n");
  5.1012 +				}
  5.1013 +				if(istty) tcsetattr(0, TCSADRAIN, &intio);
  5.1014 +			}
  5.1015 +			/*
  5.1016 +			 Otherwise do any processing on the character
  5.1017 +			 Add dread high bit disease if mark parity
  5.1018 +			 BS <-> DEL mapping
  5.1019 +			 LF -> CR mapping for files
  5.1020 +			 CR -> CRLF mapping for TTYs
  5.1021 +			 */
  5.1022 +			else {
  5.1023 +				if(markparity)
  5.1024 +					inbuf |= 0x80;
  5.1025 +				if(backspace && (inbuf == 8 || inbuf == 127))
  5.1026 +					inbuf = backspace;
  5.1027 +				if(maplf && inbuf == '\n')
  5.1028 +					inbuf = '\r';
  5.1029 +				write(fd, &inbuf, 1);
  5.1030 +				if(crlf && inbuf == '\r') {
  5.1031 +					inbuf = '\n';
  5.1032 +					write(fd, &inbuf, 1);
  5.1033 +				}
  5.1034 +				if(linedelay && inbuf == '\r')
  5.1035 +					millisleep(linedelay);
  5.1036 +				else if(delay)
  5.1037 +					millisleep(delay);
  5.1038 +			}
  5.1039 +		}
  5.1040 +
  5.1041 +	}
  5.1042 +
  5.1043 +	/*
  5.1044 +	 Fall out the bottom, cleaning up
  5.1045 +	 */
  5.1046 +	FIXTTY;
  5.1047 +	return 0;
  5.1048 +}