mirror of
https://github.com/QubesOS/qubes-doc.git
synced 2025-05-03 07:15:04 -04:00
Fix over indented code blocks
This commit is contained in:
parent
0824b2d196
commit
752f1d4ddc
16 changed files with 530 additions and 492 deletions
|
@ -47,70 +47,70 @@ Our test runner runs mostly the same as the standard one, but it has some nice a
|
|||
You can use `python3 -m qubes.tests.run -h` to get usage information:
|
||||
|
||||
```
|
||||
[user@dom0 ~]$ python3 -m qubes.tests.run -h
|
||||
usage: run.py [-h] [--verbose] [--quiet] [--list] [--failfast] [--no-failfast]
|
||||
[--do-not-clean] [--do-clean] [--loglevel LEVEL]
|
||||
[--logfile FILE] [--syslog] [--no-syslog] [--kmsg] [--no-kmsg]
|
||||
[TESTNAME [TESTNAME ...]]
|
||||
[user@dom0 ~]$ python3 -m qubes.tests.run -h
|
||||
usage: run.py [-h] [--verbose] [--quiet] [--list] [--failfast] [--no-failfast]
|
||||
[--do-not-clean] [--do-clean] [--loglevel LEVEL]
|
||||
[--logfile FILE] [--syslog] [--no-syslog] [--kmsg] [--no-kmsg]
|
||||
[TESTNAME [TESTNAME ...]]
|
||||
|
||||
positional arguments:
|
||||
TESTNAME list of tests to run named like in description
|
||||
(default: run all tests)
|
||||
positional arguments:
|
||||
TESTNAME list of tests to run named like in description
|
||||
(default: run all tests)
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--verbose, -v increase console verbosity level
|
||||
--quiet, -q decrease console verbosity level
|
||||
--list, -l list all available tests and exit
|
||||
--failfast, -f stop on the first fail, error or unexpected success
|
||||
--no-failfast disable --failfast
|
||||
--loglevel LEVEL, -L LEVEL
|
||||
logging level for file and syslog forwarding (one of:
|
||||
NOTSET, DEBUG, INFO, WARN, WARNING, ERROR, CRITICAL;
|
||||
default: DEBUG)
|
||||
--logfile FILE, -o FILE
|
||||
if set, test run will be also logged to file
|
||||
--syslog reenable logging to syslog
|
||||
--no-syslog disable logging to syslog
|
||||
--kmsg, --very-brave-or-very-stupid
|
||||
log most important things to kernel ring-buffer
|
||||
--no-kmsg, --i-am-smarter-than-kay-sievers
|
||||
do not abuse kernel ring-buffer
|
||||
--allow-running-along-qubesd
|
||||
allow running in parallel with qubesd; this is
|
||||
DANGEROUS and WILL RESULT IN INCONSISTENT SYSTEM STATE
|
||||
--break-to-repl break to REPL after tests
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--verbose, -v increase console verbosity level
|
||||
--quiet, -q decrease console verbosity level
|
||||
--list, -l list all available tests and exit
|
||||
--failfast, -f stop on the first fail, error or unexpected success
|
||||
--no-failfast disable --failfast
|
||||
--loglevel LEVEL, -L LEVEL
|
||||
logging level for file and syslog forwarding (one of:
|
||||
NOTSET, DEBUG, INFO, WARN, WARNING, ERROR, CRITICAL;
|
||||
default: DEBUG)
|
||||
--logfile FILE, -o FILE
|
||||
if set, test run will be also logged to file
|
||||
--syslog reenable logging to syslog
|
||||
--no-syslog disable logging to syslog
|
||||
--kmsg, --very-brave-or-very-stupid
|
||||
log most important things to kernel ring-buffer
|
||||
--no-kmsg, --i-am-smarter-than-kay-sievers
|
||||
do not abuse kernel ring-buffer
|
||||
--allow-running-along-qubesd
|
||||
allow running in parallel with qubesd; this is
|
||||
DANGEROUS and WILL RESULT IN INCONSISTENT SYSTEM STATE
|
||||
--break-to-repl break to REPL after tests
|
||||
|
||||
When running only specific tests, write their names like in log, in format:
|
||||
MODULE+"/"+CLASS+"/"+FUNCTION. MODULE should omit initial "qubes.tests.".
|
||||
Example: basic/TC_00_Basic/test_000_create
|
||||
When running only specific tests, write their names like in log, in format:
|
||||
MODULE+"/"+CLASS+"/"+FUNCTION. MODULE should omit initial "qubes.tests.".
|
||||
Example: basic/TC_00_Basic/test_000_create
|
||||
```
|
||||
|
||||
For instance, to run only the tests for the fedora-21 template, you can use the `-l` option, then filter the list:
|
||||
|
||||
```
|
||||
[user@dom0 ~]$ python3 -m qubes.tests.run -l | grep fedora-21
|
||||
network/VmNetworking_fedora-21/test_000_simple_networking
|
||||
network/VmNetworking_fedora-21/test_010_simple_proxyvm
|
||||
network/VmNetworking_fedora-21/test_020_simple_proxyvm_nm
|
||||
network/VmNetworking_fedora-21/test_030_firewallvm_firewall
|
||||
network/VmNetworking_fedora-21/test_040_inter_vm
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_000_start_shutdown
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_010_run_gui_app
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_050_qrexec_simple_eof
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_051_qrexec_simple_eof_reverse
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_052_qrexec_vm_service_eof
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_053_qrexec_vm_service_eof_reverse
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_060_qrexec_exit_code_dom0
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_065_qrexec_exit_code_vm
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_100_qrexec_filecopy
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_110_qrexec_filecopy_deny
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_120_qrexec_filecopy_self
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_000_prepare_dvm
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_010_simple_dvm_run
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_020_gui_app
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_030_edit_file
|
||||
[user@dom0 ~]$ sudo -E python3 -m qubes.tests.run -v `python3 -m qubes.tests.run -l | grep fedora-21`
|
||||
[user@dom0 ~]$ python3 -m qubes.tests.run -l | grep fedora-21
|
||||
network/VmNetworking_fedora-21/test_000_simple_networking
|
||||
network/VmNetworking_fedora-21/test_010_simple_proxyvm
|
||||
network/VmNetworking_fedora-21/test_020_simple_proxyvm_nm
|
||||
network/VmNetworking_fedora-21/test_030_firewallvm_firewall
|
||||
network/VmNetworking_fedora-21/test_040_inter_vm
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_000_start_shutdown
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_010_run_gui_app
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_050_qrexec_simple_eof
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_051_qrexec_simple_eof_reverse
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_052_qrexec_vm_service_eof
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_053_qrexec_vm_service_eof_reverse
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_060_qrexec_exit_code_dom0
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_065_qrexec_exit_code_vm
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_100_qrexec_filecopy
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_110_qrexec_filecopy_deny
|
||||
vm_qrexec_gui/TC_00_AppVM_fedora-21/test_120_qrexec_filecopy_self
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_000_prepare_dvm
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_010_simple_dvm_run
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_020_gui_app
|
||||
vm_qrexec_gui/TC_20_DispVM_fedora-21/test_030_edit_file
|
||||
[user@dom0 ~]$ sudo -E python3 -m qubes.tests.run -v `python3 -m qubes.tests.run -l | grep fedora-21`
|
||||
```
|
||||
|
||||
Example test run:
|
||||
|
@ -120,7 +120,7 @@ Example test run:
|
|||
Tests are also compatible with nose2 test runner, so you can use this instead:
|
||||
|
||||
```bash
|
||||
sudo systemctl stop qubesd; sudo -E nose2 -v --plugin nose2.plugins.loader.loadtests qubes.tests; sudo systemctl start qubesd
|
||||
sudo systemctl stop qubesd; sudo -E nose2 -v --plugin nose2.plugins.loader.loadtests qubes.tests; sudo systemctl start qubesd
|
||||
```
|
||||
|
||||
This may be especially useful together with various nose2 plugins to store tests results (for example `nose2.plugins.junitxml`), to ease presenting results. This is what we use on [OpenQA].
|
||||
|
@ -179,16 +179,16 @@ You'll also need to add your test at the bottom of the `__init__.py` file, in th
|
|||
Again, given the hypothetical `example.py` test:
|
||||
|
||||
~~~python
|
||||
for modname in (
|
||||
'qubes.tests.basic',
|
||||
'qubes.tests.dom0_update',
|
||||
'qubes.tests.network',
|
||||
'qubes.tests.vm_qrexec_gui',
|
||||
'qubes.tests.backup',
|
||||
'qubes.tests.backupcompatibility',
|
||||
'qubes.tests.regressions',
|
||||
'qubes.tests.example', # This is our newly added test
|
||||
):
|
||||
for modname in (
|
||||
'qubes.tests.basic',
|
||||
'qubes.tests.dom0_update',
|
||||
'qubes.tests.network',
|
||||
'qubes.tests.vm_qrexec_gui',
|
||||
'qubes.tests.backup',
|
||||
'qubes.tests.backupcompatibility',
|
||||
'qubes.tests.regressions',
|
||||
'qubes.tests.example', # This is our newly added test
|
||||
):
|
||||
~~~
|
||||
|
||||
### Testing PyQt applications
|
||||
|
|
|
@ -43,19 +43,19 @@ You have to select the area in which you suspect less than optimal performance.
|
|||
Replace
|
||||
|
||||
```python
|
||||
def foo(self, bar):
|
||||
# function content
|
||||
def foo(self, bar):
|
||||
# function content
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```python
|
||||
def foo(self, *args, **kwargs):
|
||||
profile.runctx('self.real_foo(*args, **kwargs)', globals(), locals(),
|
||||
time.strftime('/home/user/profiling/foo-%Y%m%d-%H%M%S.pstats'))
|
||||
def foo(self, *args, **kwargs):
|
||||
profile.runctx('self.real_foo(*args, **kwargs)', globals(), locals(),
|
||||
time.strftime('/home/user/profiling/foo-%Y%m%d-%H%M%S.pstats'))
|
||||
|
||||
def real_foo(self, bar):
|
||||
# function content
|
||||
def real_foo(self, bar):
|
||||
# function content
|
||||
```
|
||||
|
||||
### Run application
|
||||
|
|
|
@ -23,37 +23,37 @@ First, do a clean install from ISO you built or grabbed elsewhere.
|
|||
You have to fix network, because it is intentionally broken. This script should reenable your network card without depending on anything else.
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
# adjust this for your NIC (run lspci)
|
||||
BDF=0000:02:00.0
|
||||
# adjust this for your NIC (run lspci)
|
||||
BDF=0000:02:00.0
|
||||
|
||||
prog=$(basename $0)
|
||||
prog=$(basename $0)
|
||||
|
||||
pciunbind() {
|
||||
local path
|
||||
path=/sys/bus/pci/devices/${1}/driver/unbind
|
||||
if ! [ -w ${path} ]; then
|
||||
echo "${prog}: Device ${1} not bound"
|
||||
return 1
|
||||
fi
|
||||
echo -n ${1} >${path}
|
||||
}
|
||||
pciunbind() {
|
||||
local path
|
||||
path=/sys/bus/pci/devices/${1}/driver/unbind
|
||||
if ! [ -w ${path} ]; then
|
||||
echo "${prog}: Device ${1} not bound"
|
||||
return 1
|
||||
fi
|
||||
echo -n ${1} >${path}
|
||||
}
|
||||
|
||||
pcibind() {
|
||||
local path
|
||||
path=/sys/bus/pci/drivers/${2}/bind
|
||||
if ! [ -w ${path} ]; then
|
||||
echo "${prog}: Driver ${2} not found"
|
||||
return 1
|
||||
fi
|
||||
echo ${1} >${path}
|
||||
}
|
||||
pcibind() {
|
||||
local path
|
||||
path=/sys/bus/pci/drivers/${2}/bind
|
||||
if ! [ -w ${path} ]; then
|
||||
echo "${prog}: Driver ${2} not found"
|
||||
return 1
|
||||
fi
|
||||
echo ${1} >${path}
|
||||
}
|
||||
|
||||
pciunbind ${BDF}
|
||||
pcibind ${BDF} e1000e
|
||||
pciunbind ${BDF}
|
||||
pcibind ${BDF} e1000e
|
||||
|
||||
dhclient
|
||||
dhclient
|
||||
```
|
||||
|
||||
TODO: describe how to run this at every startup
|
||||
|
@ -97,51 +97,51 @@ This step is optional, but very helpful. Put these scripts somewhere in your `${
|
|||
`qtb-runtests`:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
ssh testbench python -m qubes.tests.run
|
||||
ssh testbench python -m qubes.tests.run
|
||||
```
|
||||
|
||||
`qtb-install`:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
TMPDIR=/tmp/qtb-rpms
|
||||
TMPDIR=/tmp/qtb-rpms
|
||||
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "usage: $(basename $0) <rpmfile> ..."
|
||||
exit 2
|
||||
fi
|
||||
if [ $# -eq 0 ]; then
|
||||
echo "usage: $(basename $0) <rpmfile> ..."
|
||||
exit 2
|
||||
fi
|
||||
|
||||
set -e
|
||||
set -e
|
||||
|
||||
ssh testbench mkdir -p "${TMPDIR}"
|
||||
scp "${@}" testbench:"${TMPDIR}"
|
||||
ssh testbench mkdir -p "${TMPDIR}"
|
||||
scp "${@}" testbench:"${TMPDIR}"
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
ssh testbench sudo rpm -i --replacepkgs --replacefiles "${TMPDIR}/$(basename ${1})"
|
||||
shift
|
||||
done
|
||||
while [ $# -gt 0 ]; do
|
||||
ssh testbench sudo rpm -i --replacepkgs --replacefiles "${TMPDIR}/$(basename ${1})"
|
||||
shift
|
||||
done
|
||||
```
|
||||
|
||||
`qtb-iterate`:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -e
|
||||
|
||||
# substitute path to your builder installation
|
||||
pushd ${HOME}/builder >/dev/null
|
||||
# substitute path to your builder installation
|
||||
pushd ${HOME}/builder >/dev/null
|
||||
|
||||
# the following are needed only if you have sources outside builder
|
||||
#rm -rf qubes-src/core-admin
|
||||
#make COMPONENTS=core-admin get-sources
|
||||
# the following are needed only if you have sources outside builder
|
||||
#rm -rf qubes-src/core-admin
|
||||
#make COMPONENTS=core-admin get-sources
|
||||
|
||||
make core-admin
|
||||
qtb-install qubes-src/core-admin/rpm/x86_64/qubes-core-dom0-*.rpm
|
||||
qtb-runtests
|
||||
make core-admin
|
||||
qtb-install qubes-src/core-admin/rpm/x86_64/qubes-core-dom0-*.rpm
|
||||
qtb-runtests
|
||||
```
|
||||
|
||||
### Hooking git
|
||||
|
@ -151,17 +151,17 @@ I (woju) have those two git hooks. They ensure tests are passing (or are marked
|
|||
`core-admin/.git/hooks/pre-commit`: (you may retain also the default hook, here omitted for readability)
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
set -e
|
||||
|
||||
python -c "import sys, qubes.tests.run; sys.exit(not qubes.tests.run.main())"
|
||||
python -c "import sys, qubes.tests.run; sys.exit(not qubes.tests.run.main())"
|
||||
```
|
||||
|
||||
`core-admin/.git/hooks/pre-push`:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
exec qtb-iterate
|
||||
exec qtb-iterate
|
||||
```
|
||||
|
|
|
@ -25,11 +25,11 @@ Things get complicated if you need to perform kernel debugging or troubleshoot p
|
|||
- To determine which dom0 pty corresponds to VM's serial port you need to read xenstore, example script below:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
id1=$(xl domid "$1-dm")
|
||||
tty1=$(xenstore-read /local/domain/${id1}/device/console/3/tty)
|
||||
echo $tty1
|
||||
id1=$(xl domid "$1-dm")
|
||||
tty1=$(xenstore-read /local/domain/${id1}/device/console/3/tty)
|
||||
echo $tty1
|
||||
```
|
||||
|
||||
Pass it a running VM name and it will output the corresponding pty name.
|
||||
|
@ -37,13 +37,13 @@ Pass it a running VM name and it will output the corresponding pty name.
|
|||
- To connect both ptys you can use [socat](http://www.dest-unreach.org/socat/) like that:
|
||||
|
||||
```bash
|
||||
#!/bin/sh
|
||||
#!/bin/sh
|
||||
|
||||
id1=$(xl domid "$1-dm")
|
||||
id2=$(xl domid "$2-dm")
|
||||
tty1=$(xenstore-read /local/domain/${id1}/device/console/3/tty)
|
||||
tty2=$(xenstore-read /local/domain/${id2}/device/console/3/tty)
|
||||
socat $tty1,raw $tty2,raw
|
||||
id1=$(xl domid "$1-dm")
|
||||
id2=$(xl domid "$2-dm")
|
||||
tty1=$(xenstore-read /local/domain/${id1}/device/console/3/tty)
|
||||
tty2=$(xenstore-read /local/domain/${id2}/device/console/3/tty)
|
||||
socat $tty1,raw $tty2,raw
|
||||
```
|
||||
|
||||
...but there is a catch. Xen seems to process the traffic that goes through serial ports and changes all **0x0a** bytes into **0x0d, 0x0a** pairs (newline conversion). I didn't find a way to turn that off (setting ptys to raw mode didn't change anything) and it's not mentioned anywhere on the Internet, so maybe it's something on my system. If the above script works for you then you don't need anything more in dom0.
|
||||
|
@ -79,115 +79,115 @@ Pass it a running VM name and it will output the corresponding pty name.
|
|||
...then you're most likely a victim of the CRLF issue mentioned above. To get around it I wrote a small utility that basically does what socat would do and additionally corrects those replaced bytes in the stream. It's not pretty but it works:
|
||||
|
||||
```c
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
int fd1, fd2;
|
||||
char mark = ' ';
|
||||
int fd1, fd2;
|
||||
char mark = ' ';
|
||||
|
||||
void out(unsigned char c)
|
||||
void out(unsigned char c)
|
||||
{
|
||||
static int count = 0;
|
||||
static unsigned char buf[17] = {0};
|
||||
|
||||
// relay to ouptput port
|
||||
write(fd2, &c, 1);
|
||||
fprintf(stderr, "%c", mark);
|
||||
|
||||
/* dump all data going over the line
|
||||
if (count == 0)
|
||||
fprintf(stderr, "%c", mark);
|
||||
fprintf(stderr, "%02x ", c);
|
||||
if (c >= 0x20 && c < 0x80)
|
||||
buf[count] = c;
|
||||
else
|
||||
buf[count] = '.';
|
||||
count++;
|
||||
if (count == 0x10)
|
||||
{
|
||||
count = 0;
|
||||
fprintf(stderr, " %s\n", buf);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
unsigned char c = 0;
|
||||
struct termios tio;
|
||||
ssize_t size;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s pty1 pty2 [mark character]\n", argv[0]);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
fd1 = open(argv[1], O_RDONLY | O_NOCTTY);
|
||||
if (fd1 <= 0)
|
||||
{
|
||||
perror("open fd1");
|
||||
return errno;
|
||||
}
|
||||
fd2 = open(argv[2], O_WRONLY | O_NOCTTY);
|
||||
if (fd2 <= 0)
|
||||
{
|
||||
perror("open fd2");
|
||||
return errno;
|
||||
}
|
||||
/*
|
||||
// This doesn't make any difference which supports the theory
|
||||
// that it's Xen who corrupts the byte stream.
|
||||
cfmakeraw(&tio);
|
||||
if (tcsetattr(fd1, TCSANOW, &tio) < 0)
|
||||
{
|
||||
perror("tcsetattr 1");
|
||||
return errno;
|
||||
}
|
||||
if (tcsetattr(fd2, TCSANOW, &tio) < 0)
|
||||
{
|
||||
perror("tcsetattr 2");
|
||||
return errno;
|
||||
}
|
||||
*/
|
||||
if (argc == 4)
|
||||
mark = argv[3][0];
|
||||
|
||||
while (1)
|
||||
{
|
||||
size = read(fd1, &c, 1);
|
||||
if (size <= 0)
|
||||
break;
|
||||
|
||||
parse:
|
||||
if (c == 0x0d)
|
||||
{
|
||||
static int count = 0;
|
||||
static unsigned char buf[17] = {0};
|
||||
|
||||
// relay to ouptput port
|
||||
write(fd2, &c, 1);
|
||||
fprintf(stderr, "%c", mark);
|
||||
|
||||
/* dump all data going over the line
|
||||
if (count == 0)
|
||||
fprintf(stderr, "%c", mark);
|
||||
fprintf(stderr, "%02x ", c);
|
||||
if (c >= 0x20 && c < 0x80)
|
||||
buf[count] = c;
|
||||
size = read(fd1, &c, 1);
|
||||
if (size <= 0)
|
||||
{
|
||||
out(0x0d);
|
||||
break;
|
||||
}
|
||||
if (c == 0x0a)
|
||||
{
|
||||
out(0x0a);
|
||||
}
|
||||
else
|
||||
buf[count] = '.';
|
||||
count++;
|
||||
if (count == 0x10)
|
||||
{
|
||||
count = 0;
|
||||
fprintf(stderr, " %s\n", buf);
|
||||
out(0x0d);
|
||||
goto parse;
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
out(c);
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
unsigned char c = 0;
|
||||
struct termios tio;
|
||||
ssize_t size;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s pty1 pty2 [mark character]\n", argv[0]);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
fd1 = open(argv[1], O_RDONLY | O_NOCTTY);
|
||||
if (fd1 <= 0)
|
||||
{
|
||||
perror("open fd1");
|
||||
return errno;
|
||||
}
|
||||
fd2 = open(argv[2], O_WRONLY | O_NOCTTY);
|
||||
if (fd2 <= 0)
|
||||
{
|
||||
perror("open fd2");
|
||||
return errno;
|
||||
}
|
||||
/*
|
||||
// This doesn't make any difference which supports the theory
|
||||
// that it's Xen who corrupts the byte stream.
|
||||
cfmakeraw(&tio);
|
||||
if (tcsetattr(fd1, TCSANOW, &tio) < 0)
|
||||
{
|
||||
perror("tcsetattr 1");
|
||||
return errno;
|
||||
}
|
||||
if (tcsetattr(fd2, TCSANOW, &tio) < 0)
|
||||
{
|
||||
perror("tcsetattr 2");
|
||||
return errno;
|
||||
}
|
||||
*/
|
||||
if (argc == 4)
|
||||
mark = argv[3][0];
|
||||
|
||||
while (1)
|
||||
{
|
||||
size = read(fd1, &c, 1);
|
||||
if (size <= 0)
|
||||
break;
|
||||
|
||||
parse:
|
||||
if (c == 0x0d)
|
||||
{
|
||||
size = read(fd1, &c, 1);
|
||||
if (size <= 0)
|
||||
{
|
||||
out(0x0d);
|
||||
break;
|
||||
}
|
||||
if (c == 0x0a)
|
||||
{
|
||||
out(0x0a);
|
||||
}
|
||||
else
|
||||
{
|
||||
out(0x0d);
|
||||
goto parse;
|
||||
}
|
||||
}
|
||||
else
|
||||
out(c);
|
||||
}
|
||||
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return 0;
|
||||
}
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
> This utility is a unidirectional relay so you need to run two instances to get duplex communication, like:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue