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 +}