Devc-ditto, the principle, the usage
Ever since I get my hands on QNET, the question “where is ditto” seems following me. At some point, I decided to give it a try, to see what’s the problem. Turns out the ditto functionality on QNX4, is mostly built into the console device. The character devices on QNX6 has a different architecture, to do the samething, I would have to “port” those functionality into, right, libio-char; Not only libio-char is owned by Dan Dodge at the time (I am not kidding :D), at the time it already built into a whole lot character devices, including those non-x86s. So basically I am stuck.
One day I realized all “ditto” doing (or need to do), is to “sniff” characters between applications and the character device. Just like a network packet sniffer. Applications are going to write() into, for example, /dev/con1; All Ineed to do, is to find out what has benn written in, buffer them, for someone else to read out.
So how do I do this? QNX6 resource manager allow you register already exist path name, to, un, hijack it. So all I need to do, is write my own resrouce manager (called devc-ditto :D), it also attach to /dev/con1; The default behavior of resource manager pathname attach, is the “latest attched got message first”, which works very well. So once devc-ditto attached to /dev/con1, any one open(“/dev/con1”, ..) it will end up with a connection from application to devc-ditto. All the applications write() would comes to me, I buffer those data it is written, then relay it to the resource manager who is really managing /dev/con1 (devc-con); Done!
Well almost done, this only allow me to sniff out the datas, how do I pass it to another application? This is easy, if I take over /dev/con1 for example, I would then create a /dev/con1.ditto, read from this device, you got all it buffered.
So here is how you use it:
On a console 2, try
# devc-ditto /dev/con1
# cat /dev/con1.ditto
Then go back to console 1, do “ls >/dev/con1“, and come back, you should see all the “ls” output (from cat).
Wait, this is not what ditto doing right? Why is the 2 character “ls” not showing up in “cat” ? Think what happened, you hit “l” key, devc-con got it, give it to your shell, youe shell will echo it, by sending it to /dev/con1… but hey devc-ditto doesn’t see this “l”, why?
Because, the shell made a connection directly to devc-con, not to me. OK, so if I exit the shell, and re-login, that would do it, right? Sorry, no, because “login” spawned “sh”, the shell inherite stdin, stdout, stderr from “login”, in other words, the shell never open() the /dev/con1 device. Hm, so I have to run devc-ditto before “login” running? Yes, you can do that, by put devc-ditto in /etc/rc.d/rc.local, it actually works….
But, but I don’t like that. I want to be able to start/stop/restart devc-ditto freely. After talk to some expert, I have put this in my .kshrc.
alias reopen ‘exec 0<$TTY 1>$TTY 2>$TTY’
Now, exit and login again on console 1, and type
Wohoo, after that, anything you type in concole 1, you should be able to see it in “cat”.
“But that’s now all ‘ditto’ doing, I also want to type in from ‘the other window'”, yes, I hear you. To allow inject key, I made it so any character write() into /dev/con1.ditto device, would be read() out from the /dev/con1. So what do you need to inject key? Yes, use “qtalk”. Now there are a few gocha of “qtalk”, first of all, you need a qtalk support “-O” option, which ignores file open count; Also qtalk tend to open a character device in “edit” mode, we want “raw” mode. So here is what you do, (assume you are on /dev/con2)
# qtalk -O -m /dev/con1.ditto
# stty raw </dev/con2
After this, whatever you type in qtalk, would show up in /dev/con1, and processed by the shell running there. This ultimatlly gives you the same “ditto” experence. And of cause, all these are standard utilities (cat, qtalk), so they work over QNET just fine.
But this is not all of it. Since the principle is just hijack a device name, devc-ditto not limited to only console, you can use it against any character device, /dev/ser1, or maybe /dev/ttypX. Wait, “/dev/ttypX”, isn’t that means I can “ditto” into a telnet session? Exactly. I will leave the practice for you, to figure out how to “ditto” into a telnet session.
That’s all I have to say. come to ostech forum if you want to discuss more, enhance it if you have more idea. Oh, one more thing, I made the devc-ditto also handle mount/umount, so you don’t need to start a lot of them if you want to monitor multiple interfaces.
# mount -Tditto /dev/ttyp5
Now you can tap into /dev/ttyp5.ditto, after you done:
# umount /dev/ttyp5.ditto