<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3176851032969559855</id><updated>2011-11-01T03:32:01.503-07:00</updated><category term='apprentice'/><category term='GPL'/><category term='infrastructure'/><category term='c/cpp'/><category term='fs-dev'/><category term='GPLv3'/><category term='translation'/><category term='for fun'/><category term='linuxfb'/><category term='Nokia'/><category term='BSFS'/><category term='CLFS'/><category term='name card ocr'/><category term='cas'/><category term='debian-handbook'/><category term='kernel hacking'/><title type='text'>Tech rider</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>37</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-4875397753854172894</id><published>2011-11-01T03:04:00.000-07:00</published><updated>2011-11-01T03:32:01.540-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='CLFS'/><title type='text'>CLSF 2011 - Day 2</title><content type='html'>The second day of &lt;a href="http://www.china-lsf.org/2011/"&gt;CLSF 2011&lt;/a&gt; started with Wu Fengguang's IO-less throttling. It is a continuous work from last year. Fengguang has done great work in improving Linux kernel read-ahead. And in the last two years, he is working on improving writeback.&lt;br /&gt;&lt;br /&gt;There are many dirty page writeback path in Linux kernel: fsync(), sync(), periodic writeback, backgroud writeback, balance_dirty_pages() and page reclaim path. Among them, balance_dirty_pages() and page reclaim path are worst for performance because they tend to writeback random single page. The purpose of balance_dirty_pages() is to balance page dirtying and page writeback, so that task doesn't cause too much memory pressure. Currently, balance_dirty_pages() calls writeback_inodes_wb() to writeback dirty pages. What Fengguang does is to adjust balance_dirty_pages() to:&lt;br /&gt;1. let dirtier task sleep instead of initiate writeback in balance_dirty_pages(), so flusher can start writeback when necessary;&lt;br /&gt;2. make page dirtying and writeback speed matching smoothly so that page reclaim is avoided as much as possible;&lt;br /&gt;3. balance the dirty speed of each memory dirtier so that large writer don't eat all memory causing smaller writers stall for a long time.&lt;br /&gt;&lt;br /&gt;There are a few parameters to tune and the most important one is how long dirtier should task sleep, which takes into account current disk write bandwidth, system memory pressure and task dirtying speed.&lt;br /&gt;&lt;br /&gt;The whole patchsets are referred as IO-less throttling and are getting merged in 3.2 merge window as decided in Kernel Summit last week. It is really a time-consuming critical work that needs brilliant and patient mind. Fengguang said he draw more than 10K performance graphs and read even more in the past year.&lt;br /&gt;&lt;br /&gt;While the IO-less throttling patches help improving writeback performance, Coly and Ma Tao said they are more interested in a side effect of the patches, per-task buffer writer bandwidth control. The problem comes with current implementation of blkio cgroup, which calculates IO bandwidth on the task that submitted bio. However, for buffer write, the pages are most likely written back by flusher thread. So the blkio controller does not work for buffer write. But Fengguang's IO-less throttling gives another way -- control write speed at balance_dirty_pages(). Fengguang said it should be possible and easy for balance_dirty_pages().&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-1jVhLR7o74I/Tq-z1KYJs5I/AAAAAAAABfw/EI2NefMD3cM/s1600/medium.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="400" src="http://3.bp.blogspot.com/-1jVhLR7o74I/Tq-z1KYJs5I/AAAAAAAABfw/EI2NefMD3cM/s400/medium.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;The second topic is memory management discussion led by Li Shaohua. We mainly discussed some issues found in Taobao's/Baidu's data centers. The first issue Coly presented is whether swap-off on all-in-memory service servers. When swap on, performance may get hurt when pages are swapping out, while swap off, oom-killer is easy to trigger when applications uses too many memory. The real problem is that application doesn't know about system memory pressure (malloc doesn't fail at all) until oom. A possible solution would be to send sigfault to application when system reaching memory high watermark. &lt;a href="http://weibo.com/hd8003"&gt;Xie Guangjun&lt;/a&gt; from Baidu, commented that swap is on in their deployment. Only small databases are all-in-memory. For file data, they use auto tiering, and their search engine applications are not allowed to allocate memory dynamically...&lt;br /&gt;&lt;br /&gt;Another issue in Taobao is about SSD+HD auto tiering. HD data cache hit ratio is very low. As a result, when there is a cache miss in SSD, reading from HD is very slow (avg 3 IO per file, dentry, inode, data). Possible solutions:&lt;br /&gt;1. Use cgroups to control memory for SSD and HD, to keep HD buffers cache in memory.&lt;br /&gt;2. Use DIO to read these small data, to avoid wasting page cache for HD data.&lt;br /&gt;3. create a new zone, use bdi-&gt;mapping flag to specify which zone to alloc memoroy for device, for the same reason as 1.&lt;br /&gt;&lt;br /&gt;Also it is mentioned that memcg count buffer cache to first users but it is unfair. Possible solution would be to create a task struct for each bdi and count these pages to bdi task.&lt;br /&gt;&lt;br /&gt;In the afternoon, first I led a session on pNFS discussion. The first issue is how much layout client should be asking for IO. Current pNFS client only asks 4KB length of layout in writepages, even if the wbc requires much more. Fengguang agreed that client has the information of how much to writeback and it is a pity to drop the information letting server do a wild guess. Then I presented the idea of making pNFS Linux a full POSIX client. It is technically do-able but the main reason (for EMC) would be business need.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-4L3rG9Mvjlc/Tq-6FGBK-AI/AAAAAAAABf8/FUpnlr3ozRA/s1600/769847c7gw1dm3lgono6sj.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="400" src="http://4.bp.blogspot.com/-4L3rG9Mvjlc/Tq-6FGBK-AI/AAAAAAAABf8/FUpnlr3ozRA/s400/769847c7gw1dm3lgono6sj.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;After that, Xie Guangjun led a session about Baidu's work in their data centers. The first change is to use memcg to guild oom-killer. They make mapreduce jobtracker send down memory limit per task, then task tracker creates new task with memory limit (now use cgroups) and oom-killer kills all processes in the same cgroup.&lt;br /&gt;&lt;br /&gt;Another interesting thing is that, Baidu is building a global resource manager in their data center. The idea is similar to Hadoop's new resource manager in MDS will be a general purpose one. Guangjun mentioned that Google has a similar implementation in their data center as well. &lt;br /&gt;&lt;br /&gt;The most interesting thing from Baidu is their work on flash. In current deployment, they build SSD from NAND with MTD+UBI+LVM. It is a joint work together with Huawei and fully implemented the functionality of mysterious FTL. In the future,they will build the SSD such that it bypasses whole VFS layer and uses ioctl API to do read/write/trim. It seems that even with some of Nick Pidgin's scalability patches merged, Linux VFS is still a hot pot of lock contention for high speed storage. In our previous training from Whamcloud, they came to the same conclusion and are planning to drop VFS interface in the future.&lt;br /&gt;&lt;br /&gt;After Baidu, Intel performance team let a discussion about the impact of emerging new hardware on current system architecture, namingly SSD and PCM. SSD is already changing system architecture in Baidu. PCM is likely to be even more evolutionary, even removing the need for current complex implemented file systems. However, it is still way far in the future. We need to focus on what we have at hand.&lt;br /&gt;&lt;br /&gt;That's all for the two days event. I didn't mean to write so long stories but all the above are worth documenting. So I can't drop any of them...&lt;br /&gt;&lt;br /&gt;In the end, thanks Baidu and Fujitsu for their generous sponsorship. Thank you all CLSF committees for making this happen. And thanks EMC for sending me there. It is really a valuable experience and will benefit me for quite a long time.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-QxZuZV7xC38/Tq-aMX-tHQI/AAAAAAAABfY/R8Vc9YxgzdI/s1600/769847c7gw1dm44p807hzj.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="auto" width="400" src="http://4.bp.blogspot.com/-QxZuZV7xC38/Tq-aMX-tHQI/AAAAAAAABfY/R8Vc9YxgzdI/s400/769847c7gw1dm44p807hzj.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-4875397753854172894?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/4875397753854172894/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/11/clsf-2011-day-2.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4875397753854172894'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4875397753854172894'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/11/clsf-2011-day-2.html' title='CLSF 2011 - Day 2'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-1jVhLR7o74I/Tq-z1KYJs5I/AAAAAAAABfw/EI2NefMD3cM/s72-c/medium.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-1185630833897616163</id><published>2011-11-01T03:03:00.000-07:00</published><updated>2011-11-01T03:03:51.367-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='CLFS'/><title type='text'>CLSF 2011 - Day 1</title><content type='html'>One year passed since last &lt;a href="http://bardofschool.blogspot.com/2011/09/clfs-2010.html"&gt;CLSF2010 &lt;/a&gt; in Shanghai. This year, CLSF is held in Nanjing and sponsored by Baidu and Fujitsu. And &lt;a href="http://www.weibo.com/colyli"&gt;Coly &lt;/a&gt;has kindly built &lt;a href="http://www.china-lsf.org/"&gt;an official website&lt;/a&gt; for the event.&lt;br /&gt;&lt;br /&gt;The workshop started with Btrfs updates given by Fujitsu's Zefan Li. Fujitsu has been contributing a lot to btrfs development this year. The first important feature Fujitsu developed for btrfs is LZO transparent compression. Before, btrfs only uses Zlib but the infrastructure allows adding more compression algorithms. LZO consumes less CPU and is faster than Zlib. The current compression unit is extent (at most 160KB) and every RW needs to read/write whole extent. So the feature seems to be more suitable for SRSW use case.&lt;br /&gt;&lt;br /&gt;Another interesting feature added to btrfs is auto-defragment. Copy-on-write filesystems like btrfs/WAFL all suffer from file fragmentation. So btrfs tries to (sort of) solve it in a nice and easy way. When a page is written, btrfs tries to read in the extent around current page and mark pages dirty in memory. So later writeback can write continuous blocks and ondisk extents tend to be less fragmented. However, a side effect is that it causes more IO than necessary and may hurt random write performance. While the idea of auto-defrag is cool, defragmentation consumes resources and thus timing is very important. What is the best time for starting auto-defrag and how far it should go (e.g., 5 frags into 4 may not be worth doing at all) remains still a open question.&lt;br /&gt;&lt;br /&gt;Miao Xie also introduced btrfs tree log and sub-transaction feature. Before tree log, btrfs maintains a big transaction (default 30sec) and if user fsync one file, the whole transaction has to be committed, hurting very much the performance of other writers. With tree log, btrfs maintains a write-ahead on-disk log for each of such fsync operations. And when transaction commits, it discards all these logs. As a result, fsync one file will only result in writing back the file's dirty data in tree log and other writers can continue writing to the same transaction, which improves performance in many writers with fsync use case.&lt;br /&gt;&lt;br /&gt;One defect of tree log is that, when writing new logs, it also writes all old logs (again and again). The solution is to assign a sub-transaction id to each log and use it to avoid writing old logs. And it improves performance in large file many fsync use case.&lt;br /&gt;&lt;br /&gt;One question that we are all interested is when btrfs will be suitable for production. Currently the most concern is about btrfsck, which has been delayed for years. Although btrfs has built-in RAID and scrub (which rebuilds broken RAID block automatically), people still think fsck a must. Zefan explained that &lt;a href="https://plus.google.com/105274031445877094012/about"&gt;Chris Mason &lt;/a&gt; will demo btrfsck at LinuxCon later this month. The reason he (Chris) didn't release btrfsck for so long is that he was trying different designs/implementations and do not want to corrupt user data with half-done btrfsck. Good news is that Chris is pushing btrfs into Oracle's next release UBL.&lt;br /&gt;&lt;br /&gt;The last but most important question for btrfs is performance. According to Intel guys' tests, btrfs is slower than ext4 in many cases. Some argued that btrfs presents many fancy features ext4 don't. But these features are more attractive to desktop users than to server users, and server users are the real force to push Linux kernel going forward these days.&lt;br /&gt;&lt;br /&gt;The second topic is Distributed/cluster storage and cloud, led by Novell's Zhang Jiaju. This is a general talk about open source cloud infrastructure. Distributed systems put a lot of pressure on DLM and sometimes make DLM itself too heavy. We also discussed why Lustre isn't wildly used outside of HPC market. Jiaju thought the most important reason is Lustre is not merged in Linux kernel thus enterprise users do not trust them as much as Kernel filesystems even like ceph.&lt;br /&gt;&lt;br /&gt;Jiaju maintains corosync in SUSE Linux and made an implementation of &lt;a href="https://github.com/jjzhang/booth"&gt;Paxos&lt;/a&gt;. Paxos came into people's eye because of Google &lt;a href="http://labs.google.com/papers/chubby-osdi06.pdf"&gt;Chubby&lt;/a&gt;. He also introduced a little about corosync's Totem. Totem performs better than Paxos when cluster membership doesn't change. But we all agree that quorum is not the best way to solve large cluster synchronization problem and that's why common Chubby cluster only have several machines.&lt;br /&gt;&lt;br /&gt;That's all for the morning. Bellow is we are continuing discussion during lunch break.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-jpkJ77EWyL8/Tq5T_yPyQDI/AAAAAAAABe8/lHz8JrxVtF8/s1600/769847c7tw1dm2dtaq238j.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="300" src="http://2.bp.blogspot.com/-jpkJ77EWyL8/Tq5T_yPyQDI/AAAAAAAABe8/lHz8JrxVtF8/s400/769847c7tw1dm2dtaq238j.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Taobao holds first two sessions in the afternoon.Taobao is using ext4 heavily in many of their servers and they are particularly interested in some features. First is Ted's bigalloc, which tries to allocate larger chunk of data and is useful for large sequential write applications like HDFS. One issue with bigalloc is directory. With bigalloc, minimal 1MB block for each directory is certainly a waste. &lt;a href="http://www.weibo.com/pagefault"&gt;Ma Tao&lt;/a&gt; has sent out &lt;a href="http://lwn.net/Articles/464510/"&gt;preview patches &lt;/a&gt;, the main idea is to make use of the inode xattr space to store the inline data.&lt;br /&gt;&lt;br /&gt;Metadata checksum, snapshot and compression are also in Taobao's eyes. Meta checksum is mainly for debug purpose. When file system corrupts, people can first check meta checksum. If checksum doesn't agree, it is very likely a disk problem instead of file system bug. However, it doesn't help no journal mode. For snapshot, &lt;a href="http://weibo.com/xiaoqiangnk"&gt;Yang Yongqiang&lt;/a&gt; is actively working on it.&lt;br /&gt;&lt;br /&gt;The third topic in the afternoon is block layer updates, led by Li Shaohua. The most important change in block layer is the dropping of IO barriers, in favor of FLUSH/FUA. IO barrier has been there for a very long time. They are a concept in the block layer, implemented via FLUSH/FUA and serve two purposes: request ordering and forced flushing to physcial medium. Both block layer and disk cache may queue/reorder io requests. IO barriers ensure preceding requests are processed before the barrier and following requests after. Also they ensure that all data in disk write cache are flushed before returning.&lt;br /&gt;&lt;br /&gt;IO barriers are well-known as performance killers. However, enforcing ordering with IO barriers at block layer is more than enough. Filesystems just want to ensure some important requests to get to disk, instead of EVERYTHING sent to block layer privier to IO barriers. Filesystems should concern themselves with ordering, since that's where the information is, and not dump that problem into the block layer. A filesystem which wants operations to happen in a specific order will simply need to issue them in the proper order, waiting for completion when necessary. The block layer can then reorder requests at will.&lt;br /&gt;&lt;br /&gt;The resolution is to export FLUSH/FUA and let filesystems decide. Therefore REQ_HARDBARRIER no longer exists, while REQ_FLUSH and REQ_FUA are added. REQ_FLUSH request forces the write cache to be flushed before beginning the operation, and REQ_FUA means the data associated with the request itself must be committed to persistent media by the time the request completes.&lt;br /&gt;&lt;br /&gt;So the procedure of write has changed from:&lt;br /&gt;submit_bio(WRITE_BARRIER)&lt;br /&gt;other reqs -&gt; (wait)preflush -&gt; (wait)bio reqs-&gt; (wait)postflush -&gt; other reqs&lt;br /&gt;to:&lt;br /&gt;submit_bio(WRITE_FLUSH_FUA)&lt;br /&gt;other reqs -&gt; preflush -&gt; other reqs -&gt; (preflush finishes) bio reqs -&gt; other reqs -&gt; (bio reqs finish) postflush&lt;br /&gt;&lt;br /&gt;For both cases, if device supports FUA, the bio reqs are issued with REQ_FUA flag and the postflush is omitted. Apparently, the performance gain comes from the fact that one transaction on longer need to wait for IO requests of other transactions, at the cost of letting file systems maintain the dependency of different io requests.&lt;br /&gt;&lt;br /&gt;The last session is a from industry session led by Huawei's chief scientist Hu Ziang. Ziang asked some questions for their engineers and then introduced Huawei's Linux strategy. Huawei used to be a very closed company but now they are seeking to get open and embrace Linux and open source. They will build a very large Linux developer team in near future. Good news for China Linux community.&lt;br /&gt;&lt;br /&gt;That's all for the first day of excitement.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-n9WID4KXKUo/Tq-cQuLmlnI/AAAAAAAABfk/AVCi7tSxih0/s1600/769847c7tw1dm2as83ok9j.jpg" imageanchor="1" style="margin-left:1em; margin-right:1em"&gt;&lt;img border="0" height="300" width="400" src="http://2.bp.blogspot.com/-n9WID4KXKUo/Tq-cQuLmlnI/AAAAAAAABfk/AVCi7tSxih0/s400/769847c7tw1dm2as83ok9j.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-1185630833897616163?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/1185630833897616163/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/11/clsf-2011-day-1.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1185630833897616163'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1185630833897616163'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/11/clsf-2011-day-1.html' title='CLSF 2011 - Day 1'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-jpkJ77EWyL8/Tq5T_yPyQDI/AAAAAAAABe8/lHz8JrxVtF8/s72-c/769847c7tw1dm2dtaq238j.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-1164205197537042180</id><published>2011-09-02T21:54:00.000-07:00</published><updated>2011-09-02T21:54:07.095-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='c/cpp'/><title type='text'>X86 Calling Conversion</title><content type='html'>Wikipedian has some &lt;a href="http://en.wikipedia.org/wiki/Calling_convention"&gt;definition&lt;/a&gt;: a calling convention is a scheme for how functions receive parameters from their caller and how they return a results.&lt;br /&gt;&lt;br /&gt;Basically, it is a compiler ABI and varies on different platforms (like Windows and Linux). This is interesting and useful for debugging (at least for understanding how debuggers work...).&lt;br /&gt;&lt;br /&gt;For example, a simple piece of code:&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset; height: auto; margin: 1px; overflow: auto; padding: 6px; text-align: left; width: auto;"&gt;&lt;span style="color: #aa00ff;"&gt;  1 void f(int arg1, int arg2, int arg3, int arg4, float arg5, int arg6, float arg7,&lt;br /&gt;  2         float arg8, int arg9, int arg10, int arg11, int arg12)&lt;br /&gt;  3 {&lt;br /&gt;  4         printf("%d %d %d %d %f %d %f %f %d %d %d %d\n",&lt;br /&gt;  5                 arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9,&lt;br /&gt;  6                 arg10, arg11, arg12);&lt;br /&gt;  7 }&lt;br /&gt;  8&lt;br /&gt;  9 void main()&lt;br /&gt; 10 {&lt;br /&gt; 11         f(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);&lt;br /&gt; 12 }&lt;/span&gt;&lt;/pre&gt;&lt;span style="font-size: x-large;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size: x-large;"&gt;&lt;b&gt;On Linux i386&lt;/b&gt;&lt;/span&gt;, above compiles to assembly:&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset; height: auto; margin: 1px; overflow: auto; padding: 6px; text-align: left; width: auto;"&gt;&lt;span style="color: #aa00ff;"&gt;[SID@test]$cc a.c -o a&lt;br /&gt;a.c: In function ‘f’:&lt;br /&gt;a.c:4: warning: incompatible implicit declaration of built-in function ‘printf’&lt;br /&gt;[SID@test]$objdump -d a &amp;gt; a.s&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;In a.s, we can see the main function calls f function by passing every argument through the stack.&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset; height: auto; margin: 1px; overflow: auto; padding: 6px; text-align: left; width: auto;"&gt;&lt;span style="color: #aa00ff;"&gt;160 0804842e &lt;main&gt;:&lt;br /&gt;161  804842e:       55                      push   %ebp&lt;br /&gt;162  804842f:       89 e5                   mov    %esp,%ebp&lt;br /&gt;163  8048431:       83 e4 f0                and    $0xfffffff0,%esp&lt;br /&gt;164  8048434:       83 ec 30                sub    $0x30,%esp&lt;br /&gt;165  8048437:       c7 44 24 2c 0c 00 00    movl   $0xc,0x2c(%esp)&lt;br /&gt;166  804843e:       00&lt;br /&gt;167  804843f:       c7 44 24 28 0b 00 00    movl   $0xb,0x28(%esp)&lt;br /&gt;168  8048446:       00&lt;br /&gt;169  8048447:       c7 44 24 24 0a 00 00    movl   $0xa,0x24(%esp)&lt;br /&gt;170  804844e:       00&lt;br /&gt;171  804844f:       c7 44 24 20 09 00 00    movl   $0x9,0x20(%esp)&lt;br /&gt;172  8048456:       00&lt;br /&gt;173  8048457:       b8 00 00 00 41          mov    $0x41000000,%eax&lt;br /&gt;174  804845c:       89 44 24 1c             mov    %eax,0x1c(%esp)&lt;br /&gt;175  8048460:       b8 00 00 e0 40          mov    $0x40e00000,%eax&lt;br /&gt;176  8048465:       89 44 24 18             mov    %eax,0x18(%esp)&lt;br /&gt;177  8048469:       c7 44 24 14 06 00 00    movl   $0x6,0x14(%esp)&lt;br /&gt;178  8048470:       00&lt;br /&gt;179  8048471:       b8 00 00 a0 40          mov    $0x40a00000,%eax&lt;br /&gt;180  8048476:       89 44 24 10             mov    %eax,0x10(%esp)&lt;br /&gt;181  804847a:       c7 44 24 0c 04 00 00    movl   $0x4,0xc(%esp)&lt;br /&gt;182  8048481:       00&lt;br /&gt;183  8048482:       c7 44 24 08 03 00 00    movl   $0x3,0x8(%esp)&lt;br /&gt;184  8048489:       00&lt;br /&gt;185  804848a:       c7 44 24 04 02 00 00    movl   $0x2,0x4(%esp)&lt;br /&gt;186  8048491:       00&lt;br /&gt;187  8048492:       c7 04 24 01 00 00 00    movl   $0x1,(%esp)&lt;br /&gt;188  8048499:       e8 26 ff ff ff          call   80483c4 &lt;f&gt;&lt;br /&gt;189  804849e:       c9                      leave&lt;br /&gt;190  804849f:       c3                      ret&lt;/f&gt;&lt;/main&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;Then &lt;span style="font-size: x-large;"&gt;&lt;b&gt;on X86_64 Linux&lt;/b&gt;&lt;/span&gt;, the code compiles into following, where parameters are passed to f function through three ways: general purpose registers (di, si, dx, cx, r8d, r9d), xmm registers (xmm0~xmm2), and function stack.&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset; height: auto; margin: 1px; overflow: auto; padding: 6px; text-align: left; width: auto;"&gt;&lt;span style="color: #aa00ff;"&gt;159 000000000040054b &lt;main&gt;:&lt;br /&gt;160   40054b:       55                      push   %rbp&lt;br /&gt;161   40054c:       48 89 e5                mov    %rsp,%rbp&lt;br /&gt;162   40054f:       48 83 ec 20             sub    $0x20,%rsp&lt;br /&gt;163   400553:       c7 44 24 10 0c 00 00    movl   $0xc,0x10(%rsp)&lt;br /&gt;164   40055a:       00&lt;br /&gt;165   40055b:       c7 44 24 08 0b 00 00    movl   $0xb,0x8(%rsp)&lt;br /&gt;166   400562:       00&lt;br /&gt;167   400563:       c7 04 24 0a 00 00 00    movl   $0xa,(%rsp)&lt;br /&gt;168   40056a:       41 b9 09 00 00 00       mov    $0x9,%r9d&lt;br /&gt;169   400570:       f3 0f 10 15 60 01 00    movss  0x160(%rip),%xmm2        # 4006d8 &amp;lt;__dso_handle+0    x30&amp;gt;&lt;br /&gt;170   400577:       00&lt;br /&gt;171   400578:       f3 0f 10 0d 5c 01 00    movss  0x15c(%rip),%xmm1        # 4006dc &amp;lt;__dso_handle+0    x34&amp;gt;&lt;br /&gt;172   40057f:       00&lt;br /&gt;173   400580:       41 b8 06 00 00 00       mov    $0x6,%r8d&lt;br /&gt;174   400586:       f3 0f 10 05 52 01 00    movss  0x152(%rip),%xmm0        # 4006e0 &amp;lt;__dso_handle+0    x38&amp;gt;&lt;br /&gt;175   40058d:       00&lt;br /&gt;176   40058e:       b9 04 00 00 00          mov    $0x4,%ecx&lt;br /&gt;177   400593:       ba 03 00 00 00          mov    $0x3,%edx&lt;br /&gt;178   400598:       be 02 00 00 00          mov    $0x2,%esi&lt;br /&gt;179   40059d:       bf 01 00 00 00          mov    $0x1,%edi&lt;br /&gt;180   4005a2:       e8 1d ff ff ff          callq  4004c4 &lt;f&gt;&lt;br /&gt;181   4005a7:       c9                      leaveq&lt;br /&gt;182   4005a8:       c3                      retq&lt;br /&gt;183   4005a9:       90                      nop&lt;br /&gt;184   4005aa:       90                      nop&lt;br /&gt;185   4005ab:       90                      nop&lt;br /&gt;186   4005ac:       90                      nop&lt;br /&gt;187   4005ad:       90                      nop&lt;br /&gt;188   4005ae:       90                      nop&lt;br /&gt;189   4005af:       90                      nop&lt;/f&gt;&lt;/main&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;So why the difference? Basically this is part of System V AMD64 ABI convention which GCC and ICC (Intel compiler) implements on Linux, BSD and Mac and which defines that rdi, rsi, rdx, rcx, r8, r9 can be used to pass down integer parameters and xmm0-7 can be used to pass down float point parameters.&lt;br /&gt;&lt;br /&gt;This leads to another question, why not other registers? On X86_64, there are 16 general purpose registers that can save integers (rax, rbx, rcx, rdx, rsi, rdi, rbp, rsp r8~r15), and 16 xmm registers that can save float points (xmm0~xmm15). They are divided by compiler ABI into volatile and non-volatile registers. Volatile registers are scratch registers presumed by the caller to be destroyed across a call. Nonvolatile registers are required to retain their values across a function call and must be saved by the callee if used. So volatile registers are naturally suitable for function arguments while there is overhead of using non-volatile registers (must be saved).&lt;br /&gt;&lt;br /&gt;The calling conversion ABI is basically about which register is volatile/non-volatile, which is reserved for specially purpose (parameter passing, frame pointer, stack pointer, etc.), what is the order of arguments on stack, who (caller or callee) is responsible for cleaning up the stack, as well as stack layout/alignness.&lt;br /&gt;&lt;br /&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;Architecture&lt;/th&gt;&lt;th&gt;Calling convention name&lt;/th&gt;&lt;th&gt;Operating system, Compiler&lt;/th&gt;&lt;th&gt;Parameters in registers&lt;/th&gt;&lt;th&gt;Parameter order on stack&lt;/th&gt;&lt;th&gt;Stack cleanup by&lt;/th&gt;&lt;th&gt;Notes&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td rowspan="2"&gt;64bit&lt;/td&gt;&lt;td&gt;Microsoft x64 calling convention&lt;/td&gt;&lt;td&gt;Windows (Microsoft compiler, Intel compiler)&lt;/td&gt;&lt;td&gt;rcx/xmm0, rdx/xmm1, r8/xmm2, r9/xmm3&lt;/td&gt;&lt;td&gt;RTL (C)&lt;/td&gt;&lt;td&gt;caller&lt;/td&gt;&lt;td&gt;Stack aligned on 16 bytes. 32 bytes shadow space on stack. The specified 8 registers can only be used for parameter number 1,2,3 and 4.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;System V AMD64 ABI convention&lt;/td&gt;&lt;td&gt;Linux, BSD, Mac (GCC, Intel compiler)&lt;/td&gt;&lt;td&gt;rdi, rsi, rdx, rcx, r8, r9, xmm0-7&lt;/td&gt;&lt;td&gt;RTL (C)&lt;/td&gt;&lt;td&gt;caller&lt;/td&gt;&lt;td&gt;Stack aligned on 16 bytes. Red zone below stack.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;br /&gt;The above table is only for either user space application or kernel space functions. Likewise, there is always an exception. Here the exception is system calls. System calls trap user space context into kernel space and have specially &lt;a href="http://x86-64.org/documentation/abi.pdf"&gt;requirement &lt;/a&gt;for parameter passing:&lt;br /&gt;1. User-level applications use as integer registers for passing the sequence %rdi, %rsi, %rdx, %rcx, %r8 and %r9. The kernel interface uses %rdi, %rsi, %rdx, %r10, %r8 and %r9.&lt;br /&gt;&lt;br /&gt;2. A system-call is done via the syscall instruction. The kernel destroys registers %rcx and %r11.&lt;br /&gt;&lt;br /&gt;3. The number of the syscall has to be passed in register %rax.&lt;br /&gt;&lt;br /&gt;4. System-calls are limited to six arguments, no argument is passed directly on&lt;br /&gt;the stack.&lt;br /&gt;&lt;br /&gt;5. Returning from the syscall, register %rax contains the result of the system-call. A value in the range between -4095 and -1 indicates an error, it is -errno.&lt;br /&gt;&lt;br /&gt;6. Only values of class INTEGER or class MEMORY are passed to the kernel.&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-1164205197537042180?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/1164205197537042180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/09/x86-calling-conversion.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1164205197537042180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1164205197537042180'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/09/x86-calling-conversion.html' title='X86 Calling Conversion'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-2407735631455934296</id><published>2011-09-01T04:05:00.001-07:00</published><updated>2011-09-01T04:05:46.946-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fs-dev'/><category scheme='http://www.blogger.com/atom/ns#' term='CLFS'/><title type='text'>CLFS 2010</title><content type='html'>I wasn't able to write down the details about CLFS (China Linux Filesystem and Storage workshop) last year (too busy at that time...). But luckily, I have written this slide to recode the major events in it. Here it is...&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px" id="__ss_9042863"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/bergwolf/clfs-2010" title="CLFS 2010" target="_blank"&gt;CLFS 2010&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/9042863" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/bergwolf" target="_blank"&gt;bergwolf&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-2407735631455934296?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/2407735631455934296/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/09/clfs-2010.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2407735631455934296'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2407735631455934296'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/09/clfs-2010.html' title='CLFS 2010'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-3909078912250477066</id><published>2011-09-01T04:02:00.000-07:00</published><updated>2011-09-01T04:02:43.558-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fs-dev'/><category scheme='http://www.blogger.com/atom/ns#' term='linuxfb'/><title type='text'>Virtual Machine File System</title><content type='html'>&lt;a href="http://dl.acm.org/citation.cfm?id=1899935"&gt;VMFS&lt;/a&gt; is an interesting paper. It tells us how VMware builds its high performance SAN file system. Since I was writing file system in ESX kernel in the passed year, I feel I got a good position in understand VMFS's designs and intentions. Here is the summary slides about it. I did my best to make sure no confidential information are leaked. All sentences and pictures are either from the paper or from Internet.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px" id="__ss_9033163"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/bergwolf/vmfs-intro" title="vmfs intro" target="_blank"&gt;vmfs intro&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/9033163" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/bergwolf" target="_blank"&gt;bergwolf&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-3909078912250477066?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/3909078912250477066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/09/virtual-machine-file-system.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/3909078912250477066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/3909078912250477066'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/09/virtual-machine-file-system.html' title='Virtual Machine File System'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-298432310453669832</id><published>2011-09-01T03:52:00.000-07:00</published><updated>2011-09-01T03:52:51.749-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='infrastructure'/><category scheme='http://www.blogger.com/atom/ns#' term='linuxfb'/><title type='text'>Google Megastore</title><content type='html'>Reading google's infrastructure paper is always joy, of which I have just had one recently. Google's &lt;a href="http://www.cidrdb.org/cidr2011/Papers/CIDR11_Paper32.pdf"&gt;megastore&lt;/a&gt; presents how Google builds transactional service on top of bigtable. Here is the slide I wrote about it...&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px" id="__ss_9042861"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/bergwolf/google-megastore-9042861" title="Google Megastore" target="_blank"&gt;Google Megastore&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/9042861" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/bergwolf" target="_blank"&gt;bergwolf&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-298432310453669832?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/298432310453669832/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/09/google-megastore.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/298432310453669832'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/298432310453669832'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/09/google-megastore.html' title='Google Megastore'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-2712416029900512991</id><published>2011-09-01T03:47:00.000-07:00</published><updated>2011-09-01T03:47:20.178-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='linuxfb'/><title type='text'>RCU</title><content type='html'>RCU had been a mystery to me for quite a long time. I finally had sometime to walk it through and understand what happened and why. Here is the slide I presented to guys on Auguest's linuxfb.net (&lt;a href="http://twitter.com/linuxfb"&gt;@linuxfb&lt;/a&gt;) seminar...&lt;br /&gt;&lt;br /&gt;&lt;div style="width:425px" id="__ss_9042891"&gt;&lt;strong style="display:block;margin:12px 0 4px"&gt;&lt;a href="http://www.slideshare.net/bergwolf/rcu" title="RCU" target="_blank"&gt;RCU&lt;/a&gt;&lt;/strong&gt; &lt;iframe src="http://www.slideshare.net/slideshow/embed_code/9042891" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"&gt;&lt;/iframe&gt; &lt;div style="padding:5px 0 12px"&gt;View more &lt;a href="http://www.slideshare.net/" target="_blank"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/bergwolf" target="_blank"&gt;bergwolf&lt;/a&gt; &lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-2712416029900512991?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/2712416029900512991/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2011/09/rcu.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2712416029900512991'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2712416029900512991'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2011/09/rcu.html' title='RCU'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-8996850320945265394</id><published>2009-12-04T05:11:00.000-08:00</published><updated>2009-12-04T08:13:17.586-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='fs-dev'/><category scheme='http://www.blogger.com/atom/ns#' term='for fun'/><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>Several filesystem related trees (0)</title><content type='html'>Coly has given an intro to the B_tree algorithm in Nov.'s linuxfb.org seminar. Here I'm going to extend his introduction to a brief overview of several file system related trees.&lt;br /&gt;&lt;br /&gt;Following is a list of trees I plan to write about(might be extended). I hope I can finish the list before the end of 2009 :)&lt;br /&gt;&lt;br /&gt;1. B_tree&lt;br /&gt;2. b+tree&lt;br /&gt;3. Htree&lt;br /&gt;4. Dancing tree&lt;br /&gt;5. Hash tree&lt;br /&gt;6. Tiger tree&lt;br /&gt;7. rb-tree&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-8996850320945265394?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/8996850320945265394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/12/several-filesystem-related-trees-0.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8996850320945265394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8996850320945265394'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/12/several-filesystem-related-trees-0.html' title='Several filesystem related trees (0)'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-4841191679117981462</id><published>2009-09-18T20:31:00.000-07:00</published><updated>2009-12-04T06:18:30.515-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='for fun'/><category scheme='http://www.blogger.com/atom/ns#' term='c/cpp'/><title type='text'>glibc malloc implementation</title><content type='html'>I've been asked several time in interviews how libc implements malloc function. So here I give the a simple summary.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;First&lt;/span&gt;, I'd like to copy some simple malloc implementation found from Internet.&lt;br /&gt;simple explaintion of malloc:&lt;pre&gt;struct mem_control_block {&lt;br /&gt; int is_available;&lt;br /&gt; int size;&lt;br /&gt;}; &lt;/pre&gt;1. If our allocator has not been initialized, initialize it.&lt;br /&gt;2. Add sizeof(struct mem_control_block) to the size requested.&lt;br /&gt;3. start at managed_memory_start.&lt;br /&gt;4. Are we at last_valid address?&lt;br /&gt;5. If we are:&lt;br /&gt;A. We didn't find any existing space that was large enough&lt;br /&gt;-- ask the operating system for more and return that.&lt;br /&gt;6. Otherwise:&lt;br /&gt;A. Is the current space available (check is_available from&lt;br /&gt;  the mem_control_block)?&lt;br /&gt;B. If it is:&lt;br /&gt;i) Is it large enough (check "size" from the mem_control_block)?&lt;br /&gt;ii) If so:&lt;br /&gt;a. Mark it as unavailable&lt;br /&gt;b. Move past mem_control_block and return the pointer&lt;br /&gt;iii) Otherwise:&lt;br /&gt;a. Move forward "size" bytes&lt;br /&gt;b. Go back go step 4&lt;br /&gt;C. Otherwise:&lt;br /&gt;i) Move forward "size" bytes&lt;br /&gt;ii) Go back to step 4&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;However&lt;/span&gt;, the real-world in libc in much more complicated and thus much more efficient.&lt;br /&gt;&lt;a href="http://en.wikipedia.org/wiki/Malloc#dlmalloc_.28the_glibc_allocator.29"&gt;Since &lt;/a&gt;2.3 release GNU C library (glibc) uses a modified ptmalloc2, based on "Doug Lea's Malloc" (&lt;a href="http://gee.cs.oswego.edu/dl/html/malloc.html"&gt;dlmalloc&lt;/a&gt;), which is a lock free implementation.&lt;br /&gt;&lt;br /&gt;Quoting glibc/malloc/malloc.c:&lt;pre&gt;  The main properties of the algorithms are:&lt;br /&gt;  * For large (&gt;= 512 bytes) requests, it is a pure best-fit allocator,&lt;br /&gt;    with ties normally decided via FIFO (i.e. least recently used).&lt;br /&gt;  * For small (&lt;= 64 bytes by default) requests, it is a caching&lt;br /&gt;    allocator, that maintains pools of quickly recycled chunks.&lt;br /&gt;  * In between, and for combinations of large and small requests, it does&lt;br /&gt;    the best it can trying to meet both goals at once.&lt;br /&gt;  * For very large requests (&gt;= 128KB by default), it relies on system&lt;br /&gt;    memory mapping facilities, if supported&lt;/pre&gt;The differences between memory allocated by sbrk() and mmap() are: 1). A released memory map does not create any "hole" that would need to be managed. 2). mmaped regions must be page-aligned. 3). invoking mmap and mfree is much slower than carving out an existing chunk of memory, because mmap will force kernel to zero out the memory it returns, which eats a lot of cache and memory bandwidth.&lt;br /&gt;&lt;br /&gt;The basic memory structure in glibc malloc is:&lt;pre&gt;struct malloc_chunk {&lt;br /&gt;&lt;br /&gt;  INTERNAL_SIZE_T      prev_size;  /* Size of previous chunk (if free).  */&lt;br /&gt;  INTERNAL_SIZE_T      size;       /* Size in bytes, including overhead. */&lt;br /&gt;&lt;br /&gt;  struct malloc_chunk* fd;         /* double links -- used only if free. */&lt;br /&gt;  struct malloc_chunk* bk;&lt;br /&gt;&lt;br /&gt;  /* Only used for large blocks: pointer to next larger size.  */&lt;br /&gt;  struct malloc_chunk* fd_nextsize; /* double links -- used only if free.  */&lt;br /&gt;  struct malloc_chunk* bk_nextsize;&lt;br /&gt;}; &lt;/pre&gt;There are two core elements in dlmalloc: &lt;span style="font-style:italic;"&gt;Boundary tags&lt;/span&gt; and &lt;span style="font-style:italic;"&gt;bins&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;Basically, boundary tags are how memory chunks look like, and bins are how memory chunks are managed.&lt;br /&gt;&lt;pre&gt;An allocated chunk looks like this (boundary tags):&lt;br /&gt;&lt;br /&gt;    chunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Size of previous chunk, if allocated            | |&lt;br /&gt;            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Size of chunk, in bytes                       |M|P|&lt;br /&gt;      mem-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             User data starts here...                          .&lt;br /&gt;            .                                                               .&lt;br /&gt;            .             (malloc_usable_size() bytes)                      .&lt;br /&gt;            .                                                               |&lt;br /&gt;nextchunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Size of chunk                                     |&lt;br /&gt;            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    chunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Size of previous chunk                            |&lt;br /&gt;            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;    `head:' |             Size of chunk, in bytes                         |P|&lt;br /&gt;      mem-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Forward pointer to next chunk in list             |&lt;br /&gt;            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Back pointer to previous chunk in list            |&lt;br /&gt;            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;            |             Unused space (may be 0 bytes long)                .&lt;br /&gt;            .                                                               .&lt;br /&gt;            .                                                               |&lt;br /&gt;nextchunk-&gt; +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;br /&gt;    `foot:' |             Size of chunk, in bytes                           |&lt;br /&gt;            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+&lt;/pre&gt;&lt;pre&gt;Bins&lt;br /&gt;    chunk in a list is known to be preceeded and followed by either&lt;br /&gt;    inuse chunks or the ends of memory.&lt;br /&gt;&lt;br /&gt;Fastbins&lt;br /&gt;    A single-linked LIFO array of lists holding recently freed small chunks.&lt;br /&gt;    Chunks in fastbins keep their inuse bit set. malloc_consolidate&lt;br /&gt;    releases all chunks in fastbins and consolidates them with&lt;br /&gt;    other free chunks.&lt;br /&gt;&lt;br /&gt;the "unsorted" bin&lt;br /&gt;    chunks being placed on it in free (and malloc_consolidate),&lt;br /&gt;    and taken off (to be either used or placed in bins) in malloc.&lt;br /&gt;&lt;br /&gt;Binmap&lt;br /&gt;    a bitvector recording whether bins are definitely empty so they can&lt;br /&gt;    be skipped over during during traversal&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-4841191679117981462?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/4841191679117981462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/09/glibc-malloc-implementation.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4841191679117981462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4841191679117981462'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/09/glibc-malloc-implementation.html' title='glibc malloc implementation'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-7837144920667999197</id><published>2009-07-16T09:12:00.001-07:00</published><updated>2009-07-16T09:19:51.585-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>First kernel patch</title><content type='html'>My real first kernel patch. I am quite exciting about it. Finally I got a Signed-off-by in the kernel commit log :)&lt;br /&gt;&lt;br /&gt;Luckily enough, the patch got merged just before 2.6.30-rc3 was released.&lt;br /&gt;&lt;br /&gt;commit ac046f1d6121ccdda6db66bd88acd52418f489b2&lt;br /&gt;Author: Peng Tao&lt;br /&gt;Date: Mon Jul 13 09:30:17 2009 -0400&lt;br /&gt;&lt;br /&gt;ext4: fix null handler of ioctls in no journal mode&lt;br /&gt;&lt;br /&gt;The EXT4_IOC_GROUP_ADD and EXT4_IOC_GROUP_EXTEND ioctls should not&lt;br /&gt;flush the journal in no_journal mode. Otherwise, running resize2fs on&lt;br /&gt;a mounted no_journal partition triggers the following error messages:&lt;br /&gt;&lt;br /&gt;BUG: unable to handle kernel NULL pointer dereference at 00000014&lt;br /&gt;IP: [] _spin_lock+0x8/0x19&lt;br /&gt;*pde = 00000000&lt;br /&gt;Oops: 0002 [#1] SMP&lt;br /&gt;&lt;br /&gt;Signed-off-by: Peng Tao&lt;br /&gt;Signed-off-by: "Theodore Ts'o"&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-7837144920667999197?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/7837144920667999197/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/07/first-kernel-patch.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/7837144920667999197'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/7837144920667999197'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/07/first-kernel-patch.html' title='First kernel patch'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-3570294454208202313</id><published>2009-07-15T08:24:00.000-07:00</published><updated>2009-07-15T08:27:47.898-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>Valerie's Advice to FS Developpers</title><content type='html'>From an interview from &lt;a href="http://www.linux-mag.com/id/7416/1/"&gt;Linux journal&lt;/a&gt;.&lt;br /&gt;Keep it in mind...&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;Keep talking to other file system developers face to face, keep experimenting with new file systems, keep talking to people in research and academia, keep paying attention to hardware trends. The way to avoid the “file systems are a solved problem” echo chamber is to stay in touch with both each other and the outside world.&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-3570294454208202313?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/3570294454208202313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/07/valeries-advice-to-fs-developpers.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/3570294454208202313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/3570294454208202313'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/07/valeries-advice-to-fs-developpers.html' title='Valerie&apos;s Advice to FS Developpers'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-1636563642093335250</id><published>2009-07-13T01:34:00.000-07:00</published><updated>2009-07-13T02:32:50.291-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='for fun'/><category scheme='http://www.blogger.com/atom/ns#' term='cas'/><title type='text'>Content Addressable Storage -- The Next Step</title><content type='html'>Recently, I was writing an slightly modified version of implementation of Content Addressable Storage (CAS) for our on-line image servers. I found it a perfect choice to apply CAS to image servers, where images are uploaded once and never changed, and where disk access throughput is a main bottleneck to many large-scale on-line image service providers.&lt;br /&gt;&lt;br /&gt;As explained on &lt;a href="http://en.wikipedia.org/wiki/Content_addressable_storage"&gt;wikipedia&lt;/a&gt;, CAS is a mechanism for storing information that can be retrieved based on its content, not its storage location. It is typically used for high-speed storage and retrieval of fixed content.&lt;br /&gt;&lt;br /&gt;CAS Characteristics:&lt;br /&gt;1. Storage is identified by its content&lt;br /&gt;2. Designed to make the searching for a given document content very quick&lt;br /&gt;3. Works most efficiently on data that does not change often&lt;br /&gt;&lt;br /&gt;Currently, most servers store images as common files and rely on filesystem's mechanism to optimize reading speed. However, filesystems are limited by POSIX standards and are optimized only for everyday usage. For large-scale image servers (or any application storing large amount of images), CAS will be a better choice (for the following reasons).&lt;br /&gt;&lt;br /&gt;1. deduplication: both block-level CAS and file-level CAS achieve efficient storage utilization by storing same data only once.&lt;br /&gt;2. Aggregation: log-structured extent-based on-disk object-stores, storing many images continuously in a single large file, resulting only one disk seek if index files are saved/managed in-memory (verses 2~3 disk seeks per read for common files).&lt;br /&gt;&lt;br /&gt;My CAS implementation is written by the fact that most images are small files (~10MB) and there are huge amount of them on image servers. The implementation should speed up accessing of these image files. I am planing some benchmarks this week and hope to post them here soon.&lt;br /&gt;&lt;br /&gt;After that, I will be writing a paper illustrating the opportunistic of applying CAS system to large-scale image servers. Then, I also want to explore the possibility of changing the interface (to, maybe dbus?) and make it runnable on common desktop, because current gnome/kde also read a lot of thumbnails. Maybe I can make it quicker somehow. Who knows :)&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-1636563642093335250?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/1636563642093335250/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/07/content-addressable-storage-next-step.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1636563642093335250'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1636563642093335250'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/07/content-addressable-storage-next-step.html' title='Content Addressable Storage -- The Next Step'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-4334098198064662423</id><published>2009-06-29T18:50:00.000-07:00</published><updated>2009-06-30T09:25:03.275-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='for fun'/><title type='text'>Easter egg in opensuse grub</title><content type='html'>Yesterday I booted my laptop while shaking it. First I saw some error messages saying something like "not enough memory". Then amazing things happened. A beautiful grub boot screen came into my eye. It's a snowy background with several penguins running around. I'm impressed! After booting into my system, I decided to find out what actually happened.&lt;br /&gt;&lt;br /&gt;opensuse grub uses a gfxmenu option in menu.list to set the colorful boot menus. In my case,&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 1px; padding: 6px; overflow: auto; width: auto; height: auto; text-align: left;"&gt;&lt;span style="color: rgb(170, 0, 255);"&gt;gfxmenu (hd0,2)/message&lt;/span&gt;&lt;/pre&gt;So I need to open (hd0,2)/message to see what's inside.&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 1px; padding: 6px; overflow: auto; width: auto; height: auto; text-align: left;"&gt;&lt;span style="color: rgb(170, 0, 255);"&gt;$cp /boot/message ~/test/grub/&lt;br /&gt;$cpio -i &lt;&gt;&lt;/span&gt;&lt;/pre&gt;Good, let's first see the about file&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 1px; padding: 6px; overflow: auto; width: auto; height: auto; text-align: left;"&gt;&lt;span style="color: rgb(170, 0, 255);"&gt;$cat pabout.txt&lt;br /&gt;Penguin theme originally made by Raphael Quinet&lt;br /&gt;(http://www.gamers.org/~quinet/lilo/).&lt;br /&gt;Modernized for openSUSE by Steffen Winterfeldt.&lt;br /&gt;&lt;br /&gt;Like it or hate it? Edit gfxboot.cfg in /boot/message&lt;br /&gt;to have it always or to get rid of it.&lt;/span&gt;&lt;/pre&gt;So gfxboot.cfg next. I found an option setting penguin theme there.&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 1px; padding: 6px; overflow: auto; width: auto; height: auto; text-align: left;"&gt;&lt;span style="color: rgb(170, 0, 255);"&gt;; penguin theme likelihood (in percent, -1 = auto)&lt;br /&gt;penguin=0&lt;/span&gt;&lt;/pre&gt;Wow, the likelihood is set 0, which explains why I didn't see the theme before. I must be so lucky that my shaking hands made grub to read the bit wrongly and presented the penguin theme to me. What a lucky dog I am!&lt;br /&gt;I really like the penguin grub theme. So I decided to have it always by setting penguin likelihood to 100. and then reinstall the picture. Of course don't forget to delete the original message before archiving the new one.&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 1px; padding: 6px; overflow: auto; width: auto; height: auto; text-align: left;"&gt;&lt;span style="color: rgb(170, 0, 255);"&gt;penguin=100&lt;br /&gt;$rm message&lt;br /&gt;$find ./ -print | cpio -ov &gt; message&lt;br /&gt;./&lt;br /&gt;./message&lt;br /&gt;./16x16.fnt&lt;br /&gt;./back.jpg&lt;br /&gt;./en.hlp&lt;br /&gt;./en.tr&lt;br /&gt;./gfxboot.cfg&lt;br /&gt;./init&lt;br /&gt;./lang&lt;br /&gt;./languages&lt;br /&gt;./pabout.txt&lt;br /&gt;./panim_a.jpg&lt;br /&gt;./panim.jpg&lt;br /&gt;./pback.jpg&lt;br /&gt;./phead.jpg&lt;br /&gt;./timer_a.jpg&lt;br /&gt;./translations.en&lt;br /&gt;835 blocks&lt;br /&gt;$mv message /boot/&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;OK, let me reboot to see the new grub theme.&lt;br /&gt;&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/vdmcEoydaqY7rTXkxNaYyg?authkey=Gv1sRgCOjqko3-19OTaw&amp;feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_U1COWsHt8EM/Sko6Y4lq8SI/AAAAAAAAA74/VK0cWHXDmCU/s400/DSC00469.JPG" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br /&gt;For those who want to try opensuse grub, please download from the official repository (look for grub &lt;a href="http://download.opensuse.org/factory/repo/src-oss/suse/src/"&gt;here&lt;/a&gt;). To install grub in command line, see &lt;a href="http://en.opensuse.org/SDB:The_Boot_Manager_Grub#Manual_installation_of_GRUB"&gt;here&lt;/a&gt;. Of course root privilege is needed.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-4334098198064662423?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/4334098198064662423/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/06/easter-egg-in-opensuse-grub.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4334098198064662423'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4334098198064662423'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/06/easter-egg-in-opensuse-grub.html' title='Easter egg in opensuse grub'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_U1COWsHt8EM/Sko6Y4lq8SI/AAAAAAAAA74/VK0cWHXDmCU/s72-c/DSC00469.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-15566654287554050</id><published>2009-06-19T02:57:00.000-07:00</published><updated>2009-06-19T03:04:21.178-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='name card ocr'/><title type='text'>tesseract-ocr: jpeg support added</title><content type='html'>I just pushed some patches to the &lt;a href="https://github.com/bergwolf/tesseract-ocr-copy/tree"&gt;github host&lt;/a&gt; to add jpeg image support with libjpeg.&lt;br /&gt;&lt;br /&gt;One drawback is that, because the image operation infrastructure in tesseract doesn't allow passing libjpeg private structures between open and read operations, I have to open the file stream twice in opening and reading jpeg images.&lt;br /&gt;&lt;br /&gt;To test the patch, pull from git://github.com/bergwolf/tesseract-ocr-copy.git and build tesseract-ocr. Then run some tests, this time against jpeg images :)&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-15566654287554050?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/15566654287554050/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/06/tesseract-ocr-jpeg-support-added.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/15566654287554050'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/15566654287554050'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/06/tesseract-ocr-jpeg-support-added.html' title='tesseract-ocr: jpeg support added'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-859514111050027690</id><published>2009-06-19T02:51:00.000-07:00</published><updated>2009-06-19T02:57:44.312-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='name card ocr'/><title type='text'>github copy of tesseract-ocr</title><content type='html'>We need to modify tesseract-ocr to support more image formats. So I set up a project host at &lt;a href="http://github.com"&gt;github&lt;/a&gt; and pulled the source code from tesseract-ocr's &lt;a href="http://code.google.com/p/tesseract-ocr/"&gt;googlecode host&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;So, to get the new code base, just type the following commands:&lt;br /&gt;1. git clone git://github.com/bergwolf/tesseract-ocr-copy.git&lt;br /&gt;2. cd tesseract-ocr-copy&lt;br /&gt;3. ./configure&lt;br /&gt;4. make&lt;br /&gt;5. make install&lt;br /&gt;&lt;br /&gt;works perfect :)&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-859514111050027690?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/859514111050027690/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/06/github-copy-of-tesseract-ocr.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/859514111050027690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/859514111050027690'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/06/github-copy-of-tesseract-ocr.html' title='github copy of tesseract-ocr'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-2293657729432573932</id><published>2009-06-19T02:37:00.000-07:00</published><updated>2009-06-19T02:51:07.413-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nokia'/><category scheme='http://www.blogger.com/atom/ns#' term='name card ocr'/><title type='text'>Great news: we have passed 1st round evaluation</title><content type='html'>Just got a notification email saying that our online namecard ocr project has passed the first round of Nokia Innovation Contest.&lt;br /&gt;&lt;br /&gt;Nokia is very generous to plan to sponsor us with a N95. Cool!&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-2293657729432573932?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/2293657729432573932/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/06/great-news-we-have-passed-1st-round.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2293657729432573932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2293657729432573932'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/06/great-news-we-have-passed-1st-round.html' title='Great news: we have passed 1st round evaluation'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-8017312659253234652</id><published>2009-05-12T02:00:00.000-07:00</published><updated>2009-05-12T03:37:05.717-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apprentice'/><category scheme='http://www.blogger.com/atom/ns#' term='name card ocr'/><title type='text'>libevent and so on</title><content type='html'>Since we need a HTTP server to provide efficient service to all kinds of clients, I started to look into some lightweight open source solutions. The first item that jumps into my eyes is &lt;a href="http://monkey.org/%7Eprovos/libevent/"&gt;libevent&lt;/a&gt;, because I happen to read a &lt;a href="http://www.facebook.com/note.php?note_id=76191543919"&gt;blog&lt;/a&gt; of a facebook developer's, stating that facebook is using libevent as a HTTP server in their haystack photo storage service.&lt;br /&gt;&lt;br /&gt;Libevent is a lightweight event driven library wildly used in many applications, such as memcached and tor. Libevent has simple but efficient HTTP support. Here is a sample code building a simple HTTP server with evhttp:&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 1px; padding: 6px; overflow: auto; width: 550px; height: 400px; text-align: left;"&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;sys/queue.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;sys/types.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;sys/socket.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;netdb.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;string.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;#include &lt;span style="color:#008000;"&gt;&amp;lt;evhttp.h&amp;gt;&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;ocr_handler&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;evhttp_request&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;req&lt;/span&gt;, &lt;strong&gt;void&lt;/strong&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;arg&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;evbuffer&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;buf&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;evkeyval&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;header&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;TAILQ_FOREACH&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;header&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;req&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;-&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;input_headers&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;next&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#2040a0;"&gt;fprintf&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;stdout&lt;/span&gt;, &lt;span style="color:#008000;"&gt;"key:%s&lt;span style="color:#77dd77;"&gt;\t&lt;/span&gt;value:%s&lt;span style="color:#77dd77;"&gt;\n&lt;/span&gt;"&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;header&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;-&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;key&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;header&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;-&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;value&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#4444ff;"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;main&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;strong&gt;int&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;argc&lt;/span&gt;, &lt;strong&gt;char&lt;/strong&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;argv&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;err&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;evhttp&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;httpd&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;event_base&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;*&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;evbase&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;span style="color:#2040a0;"&gt;port&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;=&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;1234&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;evbase&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;=&lt;/span&gt; &lt;span style="color:#2040a0;"&gt;event_init&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;fprintf&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;stderr&lt;/span&gt;, &lt;span style="color:#008000;"&gt;"event method: %s&lt;span style="color:#77dd77;"&gt;\n&lt;/span&gt;"&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;event_base_get_method&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;evbase&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;httpd&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;=&lt;/span&gt; &lt;span style="color:#2040a0;"&gt;evhttp_new&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;evbase&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;if&lt;/strong&gt; &lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;err&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;=&lt;/span&gt; &lt;span style="color:#2040a0;"&gt;evhttp_bind_socket&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;httpd&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;NULL&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;port&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;&amp;lt;&lt;/span&gt; &lt;span style="color:#ff0000;"&gt;0&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt; &lt;span style="color:#4444ff;"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:#2040a0;"&gt;fprintf&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;stderr&lt;/span&gt;, &lt;span style="color:#008000;"&gt;"error binding http server to port %d&lt;span style="color:#77dd77;"&gt;\n&lt;/span&gt;"&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;port&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;strong&gt;return&lt;/strong&gt; &lt;span style="color:#4444ff;"&gt;-&lt;/span&gt;&lt;span style="color:#ff0000;"&gt;1&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#4444ff;"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#444444;"&gt;/* set callback for "/" */&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;evhttp_set_cb&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;httpd&lt;/span&gt;, &lt;span style="color:#008000;"&gt;"/"&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;ocr_handler&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;NULL&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#444444;"&gt;/* Set a send callback for all other requests. */&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;evhttp_set_gencb&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;httpd&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;NULL&lt;/span&gt;, &lt;span style="color:#2040a0;"&gt;NULL&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;event_base_dispatch&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;evbase&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;evhttp_free&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;httpd&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;span style="color:#2040a0;"&gt;event_base_free&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;(&lt;/span&gt;&lt;span style="color:#2040a0;"&gt;evbase&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;)&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt; &lt;strong&gt;return&lt;/strong&gt; &lt;span style="color:#ff0000;"&gt;0&lt;/span&gt;&lt;span style="color:#4444ff;"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color:#4444ff;"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;However, as I looked into the library in details and wrote some test programs, it turns out that life is not that easy. I tried to dynamically create threads to serve incoming HTTP requests, but the code didn't work as I thought. After searching for a while, I found the problem:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://monkeymail.org/archives/libevent-users/2007-January/000450.html"&gt;Steven Grimm&lt;/a&gt;:&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;What libevent doesn't support is sharing a libevent instance across threads. It works just fine to use libevent in a multithreaded process where only one thread is making libevent calls.&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;Therefore, to use libevent in a multi-threaded program, we should create each thread a event base when initialising the program and call ev_set_base() after ev_set() but before ev_add(). Then we will have a thread pool to serve HTTP requests. There will a main thread listening to all incoming HTTP requests. When a request comes, it passes the request to some thread from the thread pool and wakes it up to handle the request.&lt;br /&gt;&lt;br /&gt;Although this will work, we somehow end up with a master/worker thread architecture, where the main thread handles all reads from netwrok. This will certainly be a bottleneck when there are thousands of clients(think the &lt;a href="http://www.kegel.com/c10k.html"&gt;C10K&lt;/a&gt; problem). I don't know how the facebook guys deal with this problem(maybe they patched libevent?:), But IMO, using an evhttp dispacher in a multi-threaded process, we'll end up this way.&lt;br /&gt;&lt;br /&gt;So, currently, I'm  planning to look at other solutions like lighttpd before making any decision on the server architecture.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-8017312659253234652?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/8017312659253234652/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/05/libevent-and-so-on.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8017312659253234652'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8017312659253234652'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/05/libevent-and-so-on.html' title='libevent and so on'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-2015472531823292310</id><published>2009-04-28T08:49:00.000-07:00</published><updated>2009-04-28T09:17:20.747-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apprentice'/><category scheme='http://www.blogger.com/atom/ns#' term='name card ocr'/><title type='text'>A first glance at tesseract-ocr</title><content type='html'>So, I start to look into the name card OCR project. As suggested by Alex, I'd first look at the OCR engine developed by Google, &lt;a href="http://code.google.com/p/tesseract-ocr/"&gt;tesseract-ocr&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;From wikipedia:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;Tesseract is a free optical character recognition engine. It was originally developed as proprietary software at Hewlett-Packard between 1985 until 1995. After ten years without any development taking place, Hewlett Packard and UNLV released it as open source in 2005. Tesseract is currently developed by Google and released under the Apache License, Version 2.0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It's a little strange that the featured tar balls listed on the project home page have compile errors. After modifying the source code, I successfully got the program binaries, but the language charsets aren't built. Then I change to the svn HEAD version, and it works.&lt;br /&gt;&lt;br /&gt;To use tesseract, I simply type:&lt;br /&gt;&lt;span style="font-style:italic;"&gt;[bergwolf@bin]$./tesseract phototest.tif result&lt;br /&gt;Tesseract Open Source OCR Engine&lt;br /&gt;[bergwolf@bin]$cat result.txt &lt;br /&gt;This is a lot of 12 point text to test the&lt;br /&gt;ocr code and see if it works on all types&lt;br /&gt;of file format.&lt;br /&gt;The quick brown dog jumped over the&lt;br /&gt;lazy fox. The quick brown dog jumped&lt;br /&gt;over the lazy fox. The quick brown dog&lt;br /&gt;jumped over the lazy fox. The quick&lt;br /&gt;brown dog jumped over the lazy fox.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tesseract OCR engine is very accurate, and is very suitable for our name card OCR service, because usually we only have white background and black letters in our images. &lt;br /&gt;&lt;br /&gt;However, the drawback is that it doesn't support many image formats. Most mobile device save camera photos in jpeg format. Currently, only tiff and bmp formats are recognizable by tesseract. If we want to use it as our OCR engine, two options are available: either patch tesseract with other image formats support, or use other tools like imagemagick to convert other image formats to tiff or bmp format, both of which shouldn't be very hard.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-2015472531823292310?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/2015472531823292310/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/04/first-glance-at-tesseract-ocr.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2015472531823292310'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2015472531823292310'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/04/first-glance-at-tesseract-ocr.html' title='A first glance at tesseract-ocr'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-8755302335802796307</id><published>2009-04-18T08:07:00.000-07:00</published><updated>2009-04-28T08:48:41.340-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='apprentice'/><title type='text'>Being one of opensource apprentices</title><content type='html'>A few days ago, I applied to be one of Alex Lau's 12 open source apprentices. After several conversations via email with Alex, I finally got a chance to see him face to face.&lt;br /&gt;&lt;br /&gt;It was a wonderful and pleasant talk. Alex gave me a lot of advices, on my tech path and on my future plans. We talked about many open source projects, like name card OCR, SyncML, Ifolder, Logfs(and FTL), as well as p2p file systems. At this point, I'm planning to first look at the on-line name card OCR project. It is most related to the Maemo project in my laboratory, and maybe, I can find someone in the lab to implement it together with me.&lt;br /&gt;&lt;br /&gt;My problem is that I applied for this year's GSoC program. But the GSoC slots allocation is not decided yet. So I don't know how much time I can devote to this program. Nevertheless, let's see the GSoC results first, which is due soon.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-8755302335802796307?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/8755302335802796307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/04/being-one-of-opensource-apprentices.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8755302335802796307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8755302335802796307'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/04/being-one-of-opensource-apprentices.html' title='Being one of opensource apprentices'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-7775992822609132487</id><published>2009-01-05T03:57:00.000-08:00</published><updated>2009-01-11T08:35:20.390-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>Kernel basis(2): radix trees</title><content type='html'>Abstract: this article talks about the data structure radix trees and its usage in Linux kernel.&lt;br /&gt;&lt;br /&gt;1. What is a radix tree?&lt;br /&gt;As described by &lt;a href="http://en.wikipedia.org/wiki/Radix_tree"&gt;wikipedia&lt;/a&gt;, A radix tree, Patricia trie/tree, or crit bit tree is a specialized set data structure based on the trie that is used to store a set of strings.&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lh3.ggpht.com/_U1COWsHt8EM/SWoKnoRqfMI/AAAAAAAAAgo/dX6mzBxSSUY/radix-tree-2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 602px; height: 332px;" src="http://lh3.ggpht.com/_U1COWsHt8EM/SWoKnoRqfMI/AAAAAAAAAgo/dX6mzBxSSUY/radix-tree-2.png" border="0" alt="" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;2. Linux kernel radix tree internals&lt;br /&gt;&lt;pre&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;radix_tree_root&lt;/span&gt; &lt;span style="color: rgb(68, 68, 255);"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;unsigned&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt;  &lt;span style="color: rgb(32, 64, 160);"&gt;height&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(32, 64, 160);"&gt;gfp_t&lt;/span&gt;   &lt;span style="color: rgb(32, 64, 160);"&gt;gfp_mask&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;radix_tree_node&lt;/span&gt; &lt;span style="color: rgb(68, 68, 255);"&gt;*&lt;/span&gt;&lt;span style="color: rgb(32, 64, 160);"&gt;rnode&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;radix_tree_node&lt;/span&gt; &lt;span style="color: rgb(68, 68, 255);"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;unsigned&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;height&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;  &lt;span style="color: rgb(68, 68, 68);"&gt;/* Height from the bottom */&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;unsigned&lt;/strong&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;count&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;rcu_head&lt;/span&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;rcu_head&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;span style="color: rgb(68, 68, 255);"&gt;*&lt;/span&gt;&lt;span style="color: rgb(32, 64, 160);"&gt;slots&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(32, 64, 160);"&gt;RADIX_TREE_MAP_SIZE&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;unsigned&lt;/strong&gt; &lt;strong&gt;long&lt;/strong&gt; &lt;span style="color: rgb(32, 64, 160);"&gt;tags&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(32, 64, 160);"&gt;RADIX_TREE_MAX_TAGS&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;[&lt;/span&gt;&lt;span style="color: rgb(32, 64, 160);"&gt;RADIX_TREE_TAG_LONGS&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;]&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/span&gt;&lt;span style="color: rgb(68, 68, 255);"&gt;;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&lt;strong&gt;#ifdef __KERNEL__&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&lt;strong&gt;#define RADIX_TREE_MAP_SHIFT (CONFIG_BASE_SMALL ? 4 : 6)&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&lt;strong&gt;#else&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&lt;strong&gt;#define RADIX_TREE_MAP_SHIFT 3&lt;span style="color: rgb(68, 68, 68);"&gt; /* For more stressful testing */&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 255);"&gt;&lt;strong&gt;#endif&lt;/strong&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;In Linux kernel, each radix tree node has 16/64 slots and can be indexed by a portion of the integer key. The leaf node points to the content. Empty slots contain a NULL pointer. For example, each node of the above three levels radix tree is indexed by 6 bits of the key. Nodes that have no children are not presented. Thus radix tree can be used to store sparse files.&lt;br /&gt;&lt;br /&gt;3. Usage&lt;br /&gt;In vanilla kernel, the PowPC architecture uses a radix tree to map real and virtual IRQ numbers. The NFS code uses a radix tree to index inode structures to keep track of outstanding requests. The address_space structure used to keep track of backing store contains a radix tree which tracks in-core pages tied to that mapping. Among other things, this tree allows the memory management code to quickly find pages which are dirty or under writeback.&lt;br /&gt;&lt;br /&gt;4. How to use radix trees?&lt;br /&gt;There are two ways to initialize a radix tree:&lt;pre&gt;&lt;strong&gt;#include linux/radix-tree.h&lt;br /&gt;then&lt;br /&gt; RADIX_TREE(name, gfp_mask);  /* Declare and initialize */&lt;br /&gt;or&lt;br /&gt; struct radix_tree_root my_tree;&lt;br /&gt; INIT_RADIX_TREE(my_tree, gfp_mask);&lt;/strong&gt;&lt;/pre&gt;&lt;br /&gt;The first approach is simply a wrapper of combination of the latter one.&lt;br /&gt;Then all functions defined in linux/radix-tree.h can be used to manipulate the tree.&lt;br /&gt;&lt;br /&gt;5. Notes&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;(1)Synchronization&lt;/span&gt;&lt;br /&gt;The radix-tree API requires users to provide all synchronizations(with some specific exceptions).&lt;br /&gt;For API usage, in general,&lt;br /&gt; - any function _modifying_ the tree or tags (inserting or deleting&lt;br /&gt;   items, setting or clearing tags) must exclude other modifications, and&lt;br /&gt;   exclude any functions reading the tree.&lt;br /&gt; - any function _reading_ the tree or tags (looking up items or tags,&lt;br /&gt;   gang lookups) must exclude modifications to the tree, but may occur&lt;br /&gt;   concurrently with other readers.&lt;br /&gt;&lt;br /&gt; The notable exceptions to this rule are the following functions:&lt;br /&gt; radix_tree_lookup&lt;br /&gt; radix_tree_lookup_slot&lt;br /&gt; radix_tree_tag_get&lt;br /&gt; radix_tree_gang_lookup&lt;br /&gt; radix_tree_gang_lookup_slot&lt;br /&gt; radix_tree_gang_lookup_tag&lt;br /&gt; radix_tree_gang_lookup_tag_slot&lt;br /&gt; radix_tree_tagged&lt;br /&gt;&lt;span style="color: rgb(255, 0, 0);"&gt;(1)Destroying a radix tree.&lt;/span&gt;&lt;br /&gt;There is no function for destroying a radix tree. It is, evidently, assumed that radix trees will last forever. In practice, deleting all items from a radix tree will free all memory associated with it other than the root node, which can then be disposed of normally.&lt;br /&gt;&lt;br /&gt;6. Reference:&lt;br /&gt;http://lwn.net/Articles/175432/&lt;br /&gt;http://en.wikipedia.org/wiki/Radix_tree&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-7775992822609132487?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/7775992822609132487/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/01/kernel-basis2-radix-trees.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/7775992822609132487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/7775992822609132487'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/01/kernel-basis2-radix-trees.html' title='Kernel basis(2): radix trees'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_U1COWsHt8EM/SWoKnoRqfMI/AAAAAAAAAgo/dX6mzBxSSUY/s72-c/radix-tree-2.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-2709438114511120904</id><published>2009-01-01T19:45:00.000-08:00</published><updated>2009-01-05T03:59:01.200-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='c/cpp'/><title type='text'>Kernel basis(1): the container_of macro</title><content type='html'>Short version:&lt;br /&gt;The following article explains how container_of macro works and how to use&lt;br /&gt;it(based on http://www.kroah.com/log/linux/container_of.html).&lt;br /&gt;&lt;br /&gt;Long version:&lt;br /&gt;The container_of macro is defined in linux/kernel.h&lt;br /&gt;/**&lt;br /&gt;* container_of - cast a member of a structure out to the containing structure&lt;br /&gt;* @ptr:        the pointer to the member.&lt;br /&gt;* @type:       the type of the container struct this is embedded in.&lt;br /&gt;* @member:     the name of the member within the struct.&lt;br /&gt;*&lt;br /&gt;*/&lt;br /&gt;#define container_of(ptr, type, member) ({                      \&lt;br /&gt;   const typeof( ((type *)0)-&gt;member ) *__mptr = (ptr);    \&lt;br /&gt;   (type *)( (char *)__mptr - offsetof(type,member) );})&lt;br /&gt;&lt;br /&gt;Some fundamentals:&lt;br /&gt;1. typeof:&lt;br /&gt;This is one of GNU C extensions. In ANSI C and ISO C, this should be&lt;br /&gt;__typeof__. The macro takes in two types of arguments: an expression or&lt;br /&gt;a type.&lt;br /&gt;&lt;br /&gt;Expression:    typeof(x[0](1))&lt;br /&gt;where x is an array of pointers to functions. The macro returns the value&lt;br /&gt;of the function.&lt;br /&gt;&lt;br /&gt;Type:        typeof(int *)&lt;br /&gt;This is the type of pointers to int.&lt;br /&gt;&lt;br /&gt;2. offsetof(TYPE, MEMBER)&lt;br /&gt;This is an ANSI C library feature defined in stddef.h. It evaluates to&lt;br /&gt;offset(in bytes) of a given member within a struct or union type.&lt;br /&gt;Typical implementations:&lt;br /&gt;#define offsetof(TYPE, MEMBER) ((site_t) &amp;amp;((TYPE*)0)-&gt;MEMBER)&lt;br /&gt;&lt;br /&gt;#define offsetof(TYPE, MEMBER) \&lt;br /&gt;   ((size_t) ((char *)&amp;amp;((TYPE*)(0))-&gt;MEMBER - (char *)0))&lt;br /&gt;&lt;br /&gt;gcc has buitin offsetof. To use it, do&lt;br /&gt;#undef offsetof&lt;br /&gt;#ifdef __compiler_offsetof&lt;br /&gt;#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)&lt;br /&gt;#else&lt;br /&gt;#define offsetof(TYPE, MEMBER) ((size_t) &amp;amp;((TYPE *)0)-&gt;MEMBER)&lt;br /&gt;#endif&lt;br /&gt;&lt;br /&gt;Now, we come to the container_of macro at last. Really easy to understand.&lt;br /&gt;The first line defines a pointer(__mptr) that points to *ptr. So we have&lt;br /&gt;tow pointers(__mptr and ptr) both pointing to the same memory location.&lt;br /&gt;&lt;br /&gt;The second line finds the real location in memory of the containing&lt;br /&gt;structure that contains what ptr points to. The offsetof macro calculates&lt;br /&gt;the memory offset of member starting from type. Then it dismiss the offset&lt;br /&gt;from memory location __mptr and gives us the memory location of the&lt;br /&gt;containing structure, type.&lt;br /&gt;&lt;br /&gt;How to use it?&lt;br /&gt;This is useful for calling back functions between different software layers.&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 0px; padding: 6px; overflow: auto; width: 600px; height: 1000px; text-align: left;"&gt;&lt;span style="font-size:120;"&gt; container_of_sample.c&lt;pre&gt;&lt;font color="#444444"&gt;/* test code to illustrate use of Linux kernel container_of macro&lt;br /&gt; *&lt;br /&gt; * Copyright (c) 2008 Cliff Brake, BEC Systems LLC&lt;br /&gt; *&lt;br /&gt; * This program is free software; you can redistribute it and/or modify&lt;br /&gt; * it under the terms of the GNU General Public License version 2 as&lt;br /&gt; * published by the Free Software Foundation.&lt;br /&gt; *&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;stdio.h&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;string.h&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#include &lt;font color="#008000"&gt;&amp;lt;stdlib.h&amp;gt;&lt;/font&gt;&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/* This program illustrates how the container_of macro works.&lt;br /&gt; * The container of macro is very useful in multi layered&lt;br /&gt; * software systems where you have progressivly more detailed&lt;br /&gt; * software layers.  Below is an example of a bus layer,&lt;br /&gt; * and then a device layer where a number of different&lt;br /&gt; * devices might register with the bus.&lt;br /&gt; * The device registers itself with the bus subsystem, and&lt;br /&gt; * then the bus subsystem makes a callback into the device.&lt;br /&gt; * Normally if there are multiple devices registered, the &lt;br /&gt; * bus subsystem must store and pass a device structure&lt;br /&gt; * when making callbacks.  With the container_of macro, this is&lt;br /&gt; * no longer necessary, and the bus subsystem only has to&lt;br /&gt; * know about one generic device structure, and does not need visibility&lt;br /&gt; * into lots of different device structures, or do tricks&lt;br /&gt; * by casting void pointers, etc.  With the container_of macro&lt;br /&gt; * we can backcast from the generic data structure, to the containing&lt;br /&gt; * datastructure.  This forces good separation of code in that&lt;br /&gt; * that bus layer cannot modifiy data structures that are specific&lt;br /&gt; * to the device layer.&lt;br /&gt; *&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;&lt;i&gt;/**&lt;br /&gt; * (from Linux kernel source)&lt;br /&gt; * container_of - cast a member of a structure out to the containing structure&lt;br /&gt; * @ptr: the pointer to the member.&lt;br /&gt; * @type: the type of the container struct this is embedded in.&lt;br /&gt; * @member: the name of the member within the struct.&lt;br /&gt; *&lt;br /&gt; */&lt;/i&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#define container_of(ptr, type, member) ({   \&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;const&lt;/strong&gt; &lt;font color="#2040a0"&gt;typeof&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;type&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;member&lt;/font&gt; &lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;__mptr&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;ptr&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt; \&lt;br /&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;type&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;char&lt;/strong&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="#2040a0"&gt;__mptr&lt;/font&gt; &lt;font color="4444FF"&gt;-&lt;/font&gt; &lt;font color="#2040a0"&gt;offsetof&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;type&lt;/font&gt;,&lt;font color="#2040a0"&gt;member&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="0000ff"&gt;&lt;strong&gt;#define offsetof(TYPE, MEMBER) ((size_t) &amp;amp;((TYPE *)0)-&amp;gt;MEMBER)&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/*==========================================================&lt;br /&gt; * BUS layer code&lt;br /&gt; *==========================================================*/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/* generic bus device structure */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;font color="#2040a0"&gt;general_device_param_a&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;font color="#2040a0"&gt;general_device_param_b&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;void&lt;/strong&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;device_callback&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/* the following is a global list of&lt;br /&gt; * devices that have registered with the &lt;br /&gt; * bus subsystem.  Normally this would&lt;br /&gt; * be something like a dynamic linked list.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;bd_list&lt;/font&gt;&lt;font color="4444FF"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;5&lt;/font&gt;&lt;font color="4444FF"&gt;]&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/* function to register a device with the bus */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;register_with_bus&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* since this example only deals with one&lt;br /&gt;  * device, will put it in slot 0&lt;br /&gt;  */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;bd_list&lt;/font&gt;&lt;font color="4444FF"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;]&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;start_bus&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;font color="#2040a0"&gt;i&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* make callbacks to all devices on bus */&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;for&lt;/strong&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;i&lt;/font&gt;&lt;font color="4444FF"&gt;=&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;font color="#2040a0"&gt;i&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;lt;&lt;/font&gt;&lt;strong&gt;sizeof&lt;/strong&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;bd_list&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;/&lt;strong&gt;sizeof&lt;/strong&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;bd_list&lt;/font&gt;&lt;font color="4444FF"&gt;[&lt;/font&gt;&lt;font color="#FF0000"&gt;0&lt;/font&gt;&lt;font color="4444FF"&gt;]&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;font color="#2040a0"&gt;i&lt;/font&gt;&lt;font color="4444FF"&gt;+&lt;/font&gt;&lt;font color="4444FF"&gt;+&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;bd&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;bd_list&lt;/font&gt;&lt;font color="4444FF"&gt;[&lt;/font&gt;&lt;font color="#2040a0"&gt;i&lt;/font&gt;&lt;font color="4444FF"&gt;]&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;  &lt;strong&gt;if&lt;/strong&gt; &lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;!&lt;/font&gt;&lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt; &lt;strong&gt;continue&lt;/strong&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;  &lt;font color="#444444"&gt;/* call device callback with generic&lt;br /&gt;   * bus device structure&lt;br /&gt;   */&lt;/font&gt;&lt;br /&gt;  &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;device_callback&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/*==========================================================&lt;br /&gt; * device X specific code&lt;br /&gt; * this would normally be in a different module&lt;br /&gt; *==========================================================*/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/* structure that holds device X specific stuff, as well as&lt;br /&gt; * generic bus_device structure&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x_specific_param_a&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;int&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x_specific_param_b&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x_callback&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;bus_device&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* if we know the structure type that contains the bus_device structure,&lt;br /&gt;  * we can extract a pointer to the containing structure using the container_of&lt;br /&gt;  * macro&lt;br /&gt;  */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/*                                   ptr       type       member  */&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;devx&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;container_of&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;bd&lt;/font&gt;, &lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x&lt;/font&gt;, &lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* the above statement expands to&lt;br /&gt;  * struct device_x * devx = (&lt;br /&gt;  * { &lt;br /&gt;  *   const typeof( ((struct device_x *)0)-&amp;gt;bd ) *__mptr = (bd); &lt;br /&gt;  *   (struct device_x *)( (char *)__mptr - ((size_t) &amp;amp;((struct device_x *)0)-&amp;gt;bd) );&lt;br /&gt;  * }&lt;br /&gt;  * );&lt;br /&gt;  */&lt;/font&gt;  &lt;br /&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;printf&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#008000"&gt;&amp;quot;device_x_callback called!, device_x_specific_param_a = %i&lt;font color="#77dd77"&gt;\n&lt;/font&gt;&amp;quot;&lt;/font&gt;, &lt;br /&gt;   &lt;font color="#2040a0"&gt;devx&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;device_x_specific_param_a&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;void&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x_init&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* dynamically allocate structures */&lt;/font&gt;&lt;br /&gt; &lt;strong&gt;struct&lt;/strong&gt; &lt;font color="#2040a0"&gt;device_x&lt;/font&gt; &lt;font color="4444FF"&gt;*&lt;/font&gt; &lt;font color="#2040a0"&gt;devx&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;malloc&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;strong&gt;sizeof&lt;/strong&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;devx&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;memset&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="#2040a0"&gt;devx&lt;/font&gt;, &lt;font color="#FF0000"&gt;0&lt;/font&gt;, &lt;strong&gt;sizeof&lt;/strong&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;*&lt;/font&gt;&lt;font color="#2040a0"&gt;devx&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* set a parameter in the device_x structure so &lt;br /&gt;  * we can test for this in the callback&lt;br /&gt;  */&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;devx&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;device_x_specific_param_a&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#FF0000"&gt;1001&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* set up callback function */&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;devx&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;bd&lt;/font&gt;.&lt;font color="#2040a0"&gt;device_callback&lt;/font&gt; &lt;font color="4444FF"&gt;=&lt;/font&gt; &lt;font color="#2040a0"&gt;device_x_callback&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* we register the generic bus device structure&lt;br /&gt;  * as the bus layer does not need to know&lt;br /&gt;  * about the device_x stucture.  Note, the &lt;br /&gt;  * devx structure is not stored anywhere, yet&lt;br /&gt;  * its location is being preserved without&lt;br /&gt;  * specifically passing it to the bus &lt;br /&gt;  * layer.&lt;br /&gt;  */&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;register_with_bus&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;amp;&lt;/font&gt;&lt;font color="#2040a0"&gt;devx&lt;/font&gt;&lt;font color="4444FF"&gt;-&lt;/font&gt;&lt;font color="4444FF"&gt;&amp;gt;&lt;/font&gt;&lt;font color="#2040a0"&gt;bd&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;int&lt;/strong&gt; &lt;font color="#2040a0"&gt;main&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;{&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* test the above system */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* first, initialize device_x */&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;device_x_init&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt; &lt;font color="#444444"&gt;/* now, start the bus.  This should make&lt;br /&gt;  * a callback into the device_x&lt;br /&gt;  */&lt;/font&gt;&lt;br /&gt; &lt;font color="#2040a0"&gt;start_bus&lt;/font&gt;&lt;font color="4444FF"&gt;(&lt;/font&gt;&lt;font color="4444FF"&gt;)&lt;/font&gt;&lt;font color="4444FF"&gt;;&lt;/font&gt;&lt;br /&gt;&lt;font color="4444FF"&gt;&lt;strong&gt;}&lt;/strong&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#444444"&gt;/* when run, this program returns:&lt;br /&gt; * device_x_callback called!, device_x_specific_param_a = 1001&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;/span&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-2709438114511120904?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/2709438114511120904/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2009/01/containerof-macro-in-nutshell.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2709438114511120904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/2709438114511120904'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2009/01/containerof-macro-in-nutshell.html' title='Kernel basis(1): the container_of macro'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-4336864228885821049</id><published>2008-11-29T08:50:00.000-08:00</published><updated>2009-04-28T08:03:34.377-07:00</updated><title type='text'>Enable ext4 to run without a journal</title><content type='html'>This is really useful on flash devices.&lt;br /&gt;According to the kernel documents, there are three kind of journal mode in ext4: writeback, ordered, journal.&lt;br /&gt;(1) writeback mode: ext4 doesn't journal data at all. Only metadata journaling is provided. Data ordering is not preserved. Data may be written into the disk after its metadata has been committed to the journal. A crash-recovery may cause data corruption in files which written shortly before the crash.&lt;br /&gt;(2) ordered mode: ext4 only journals metadata, but logically groups metadata information related to data changes with the data blocks into a single unit called a transaction. When it's time to write the new metadata out to disk, the associated data blocks are written first.&lt;br /&gt;(3) journal mode: ext4 provides full metadata and data journaling. All new data is written to the journal first, and then to its final location. In the event of a crash, the journal can be replayed, bringing both data and metadata into a consistent state.&lt;br /&gt;&lt;br /&gt;Basically, the idea is to make use of data writeback mode. In writeback mode, data is written directly to disk, and when it comes to metadata, we need to write it out to disk once a dirty_metadata_buffer_head request is received. Superblock buffer head and inode buffer header are handled separately.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-4336864228885821049?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/4336864228885821049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/11/enable-ext4-to-run-without-journal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4336864228885821049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4336864228885821049'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/11/enable-ext4-to-run-without-journal.html' title='Enable ext4 to run without a journal'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-1543473577966074346</id><published>2008-11-27T06:50:00.000-08:00</published><updated>2008-11-27T07:11:10.338-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='c/cpp'/><title type='text'>Use git behind a proxy</title><content type='html'>Since someone is asking me to provide an English version about git proxy configuration in my former &lt;a href="http://bardofschool.blogspot.com/2008/10/get-lastest-version-of-ext4-code.html"&gt;blog&lt;/a&gt;. Here it is.&lt;br /&gt;Basically, I know two ways to use git behind a proxy.&lt;br /&gt;(1). Set the http_proxy environment if git repository supports http connections.&lt;br /&gt;(2). find a proxy command to bypass the connection:&lt;br /&gt;1. gcc -o connect connect.c&lt;br /&gt;mv connect ~/bin&lt;br /&gt;2. set up a wrapper&lt;br /&gt;echo "/home/gigi/bin/connect -H proxy.bupt.edu.cn:8080 $@" &gt;&gt; ~/bin/proxy&lt;br /&gt;chmod +x ~/bin/proxy&lt;br /&gt;Here I'm using a http proxy offered by my school, which uses port 8080&lt;br /&gt;The connect command also support socket proxy. Use -S host:port to indicate that.&lt;br /&gt;3. echo "export CONNECT_USER=bergwolf" &gt;&gt; .bashrc&lt;br /&gt;echo "export GIT_PROXY_COMMAND=proxy" &gt;&gt; .bashrc&lt;br /&gt;The connect command reads proxy username and password from CONNECT_USER and CONNECT_PASSWORD evironment. The default username is current login user if no CONNECT_USER is set. Password will be requested interactively if CONNECT_PASSWORD is empty.&lt;br /&gt;GIT_PROXY_COMMAND indicates that git should use the command "proxy"(the wrapper we setup at step 2) as its proxy_command. This can also be set in .git/config.&lt;br /&gt;&lt;br /&gt;Now, everything we need is done. Have a try:&lt;br /&gt;[gigi-Ubuntu:bin]$git clone git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git&lt;br /&gt;Initialized empty Git repository in /home/gigi/bin/e2fsprogs/.git/&lt;br /&gt;Enter proxy authentication password for bergwolf@proxy.bupt.edu.cn:&lt;br /&gt;remote: Counting objects: 24006, done.&lt;br /&gt;remote: Compressing objects: 100% (4701/4701), done.&lt;br /&gt;ceiving objects: 1% (241/24006), 43.99 KiB | 56 KiB/s&lt;br /&gt;&lt;br /&gt;connect.c:&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 0px; padding: 6px; overflow: auto; width: 600px; height: 1000px; text-align: left;"&gt;&lt;br /&gt;&lt;pre width="80"&gt;&lt;font color="#B22222"&gt;/***********************************************************************&lt;br /&gt; * connect.c -- Make socket connection using SOCKS4/5 and HTTP tunnel.&lt;br /&gt; *&lt;br /&gt; * Copyright (c) 2000-2006 Shun-ichi Goto&lt;br /&gt; * Copyright (c) 2002, J. Grant (English Corrections)&lt;br /&gt; *&lt;br /&gt; * This program is free software; you can redistribute it and/or&lt;br /&gt; * modify it under the terms of the GNU General Public License&lt;br /&gt; * as published by the Free Software Foundation; either version 2&lt;br /&gt; * of the License, or (at your option) any later version.&lt;br /&gt; *&lt;br /&gt; * This program is distributed in the hope that it will be useful,&lt;br /&gt; * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt; * GNU General Public License for more details.&lt;br /&gt; *&lt;br /&gt; * You should have received a copy of the GNU General Public License&lt;br /&gt; * along with this program; if not, write to the Free Software&lt;br /&gt; * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt; *&lt;br /&gt; * ---------------------------------------------------------&lt;br /&gt; * PROJECT:  My Test Program&lt;br /&gt; * AUTHOR:   Shun-ichi GOTO &amp;lt;gotoh@taiyo.co.jp&amp;gt;&lt;br /&gt; * CREATE:   Wed Jun 21, 2000&lt;br /&gt; * REVISION: $Revision: 100 $&lt;br /&gt; * ---------------------------------------------------------&lt;br /&gt; *&lt;br /&gt; * Getting Source&lt;br /&gt; * ==============&lt;br /&gt; *&lt;br /&gt; *   Recent version of 'connect.c' is available from&lt;br /&gt; *     http://www.taiyo.co.jp/~gotoh/ssh/connect.c&lt;br /&gt; *&lt;br /&gt; *   Related tool, ssh-askpass.exe (alternative ssh-askpass on UNIX)&lt;br /&gt; *   is available:&lt;br /&gt; *     http://www.taiyo.co.jp/~gotoh/ssh/ssh-askpass.exe.gz&lt;br /&gt; *&lt;br /&gt; *   See more detail:&lt;br /&gt; *     http://www.taiyo.co.jp/~gotoh/ssh/connect.html&lt;br /&gt; *&lt;br /&gt; * How To Compile&lt;br /&gt; * ==============&lt;br /&gt; *&lt;br /&gt; *  On UNIX environment:&lt;br /&gt; *      $ gcc connect.c -o connect&lt;br /&gt; *&lt;br /&gt; *  On SOLARIS:&lt;br /&gt; *      $ gcc -o connect -lresolv -lsocket -lnsl connect.c&lt;br /&gt; *&lt;br /&gt; *  on Win32 environment:&lt;br /&gt; *      $ cl connect.c wsock32.lib advapi32.lib&lt;br /&gt; *    or&lt;br /&gt; *      $ bcc32 connect.c wsock32.lib advapi32.lib&lt;br /&gt; *    or&lt;br /&gt; *      $ gcc connect.c -o connect&lt;br /&gt; *&lt;br /&gt; *  on Mac OS X environment:&lt;br /&gt; *      $ gcc connect.c -o connect -lresolv&lt;br /&gt; *    or&lt;br /&gt; *      $ gcc connect.c -o connect -DBIND_8_COMPAT=1&lt;br /&gt; *&lt;br /&gt; * How To Use&lt;br /&gt; * ==========&lt;br /&gt; *&lt;br /&gt; *   You can specify proxy method in an environment variable or in a&lt;br /&gt; *   command line option.&lt;br /&gt; *&lt;br /&gt; *   usage:  connect [-dnhst45] [-R resolve] [-p local-port] [-w sec]&lt;br /&gt; *                   [-H [user@]proxy-server[:port]]&lt;br /&gt; *                   [-S [user@]socks-server[:port]]&lt;br /&gt; *                   [-T proxy-server[:port]]&lt;br /&gt; *                   [-c telnet proxy command]&lt;br /&gt; *                   host port&lt;br /&gt; *&lt;br /&gt; *   "host" and "port" is for the target hostname and port-number to&lt;br /&gt; *   connect to.&lt;br /&gt; *&lt;br /&gt; *   The -H option specifys a hostname and port number of the http proxy&lt;br /&gt; *   server to relay. If port is omitted, 80 is used. You can specify this&lt;br /&gt; *   value in the environment variable HTTP_PROXY and pass the -h option&lt;br /&gt; *   to use it.&lt;br /&gt; *&lt;br /&gt; *   The -S option specifys the hostname and port number of the SOCKS&lt;br /&gt; *   server to relay.  Like -H, port number can be omitted and the default&lt;br /&gt; *   is 1080. You can also specify this value pair in the environment&lt;br /&gt; *   variable SOCKS5_SERVER and give the -s option to use it.&lt;br /&gt; *&lt;br /&gt; *   The '-4' and the '-5' options are for specifying SOCKS relaying and&lt;br /&gt; *   indicates protocol version to use. It is valid only when used with&lt;br /&gt; *   '-s' or '-S'. Default is '-5' (protocol version 5)&lt;br /&gt; *&lt;br /&gt; *   The '-R' option is for specifying method to resolve the&lt;br /&gt; *   hostname. Three keywords ("local", "remote", "both") or dot-notation&lt;br /&gt; *   IP address are acceptable.  The keyword "both" means, "Try local&lt;br /&gt; *   first, then remote". If a dot-notation IP address is specified, use&lt;br /&gt; *   this host as nameserver. The default is "remote" for SOCKS5 or&lt;br /&gt; *   "local" for others. On SOCKS4 protocol, remote resolving method&lt;br /&gt; *   ("remote" and "both") requires protocol 4a supported server.&lt;br /&gt; *&lt;br /&gt; *   The '-p' option will forward a local TCP port instead of using the&lt;br /&gt; *   standard input and output.&lt;br /&gt; *&lt;br /&gt; *   The '-P' option is same to '-p' except keep remote session. The&lt;br /&gt; *   program repeats waiting the port with holding remote session without&lt;br /&gt; *   disconnecting. To disconnect the remote session, send EOF to stdin or&lt;br /&gt; *   kill the program.&lt;br /&gt; *&lt;br /&gt; *   The '-w' option specifys timeout seconds for making connection with&lt;br /&gt; *   TARGET host.&lt;br /&gt; *&lt;br /&gt; *   The '-d' option is used for debug. If you fail to connect, use this&lt;br /&gt; *   and check request to and response from server.&lt;br /&gt; *&lt;br /&gt; *   You can omit the "port" argument when program name is special format&lt;br /&gt; *   containing port number itself. For example,&lt;br /&gt; *     $ ln -s connect connect-25&lt;br /&gt; *   means this connect-25 command is spcifying port number 25 already&lt;br /&gt; *   so you need not 2nd argument (and ignored if specified).&lt;br /&gt; *&lt;br /&gt; *   To use proxy, this example is for SOCKS5 connection to connect to&lt;br /&gt; *   'host' at port 25 via SOCKS5 server on 'firewall' host.&lt;br /&gt; *     $ connect -S firewall  host 25&lt;br /&gt; *   or&lt;br /&gt; *     $ SOCKS5_SERVER=firewall; export SOCKS5_SERVER&lt;br /&gt; *     $ connect -s host 25&lt;br /&gt; *&lt;br /&gt; *   For a HTTP-PROXY connection:&lt;br /&gt; *     $ connect -H proxy-server:8080  host 25&lt;br /&gt; *   or&lt;br /&gt; *     $ HTTP_PROXY=proxy-server:8080; export HTTP_PROXY&lt;br /&gt; *     $ connect -h host 25&lt;br /&gt; *   To forward a local port, for example to use ssh:&lt;br /&gt; *     $ connect -p 5550 -H proxy-server:8080  host 22&lt;br /&gt; *    ($ ssh -l user -p 5550 localhost )&lt;br /&gt; *&lt;br /&gt; * TIPS&lt;br /&gt; * ====&lt;br /&gt; *&lt;br /&gt; *   Connect.c doesn't have any configuration to specify the SOCKS server.&lt;br /&gt; *   If you are a mobile user, this limitation might bother you.  However,&lt;br /&gt; *   You can compile connect.c and link with other standard SOCKS library&lt;br /&gt; *   like the NEC SOCKS5 library or Dante. This means connect.c is&lt;br /&gt; *   socksified and uses a configration file like to other SOCKSified&lt;br /&gt; *   network commands and you can switch configuration file any time&lt;br /&gt; *   (ex. when ppp startup) that brings you switching of SOCKS server for&lt;br /&gt; *   connect.c in same way with other commands. For this case, you can&lt;br /&gt; *   write ~/.ssh/config like this:&lt;br /&gt; *&lt;br /&gt; *     ProxyCommand connect -n %h %p&lt;br /&gt; *&lt;br /&gt; * SOCKS5 authentication&lt;br /&gt; * =====================&lt;br /&gt; *&lt;br /&gt; *   Only USER/PASS authentication is supported.&lt;br /&gt; *&lt;br /&gt; * Proxy authentication&lt;br /&gt; * ====================&lt;br /&gt; *&lt;br /&gt; *   Only BASIC scheme is supported.&lt;br /&gt; *&lt;br /&gt; * Authentication informations&lt;br /&gt; * ===========================&lt;br /&gt; *&lt;br /&gt; *   User name for authentication is specifed by an environment variable&lt;br /&gt; *   or system login name.  And password is specified from environment&lt;br /&gt; *   variable or external program (specified in $SSH_ASKPASS) or tty.&lt;br /&gt; *&lt;br /&gt; *   Following environment variable is used for specifying user name.&lt;br /&gt; *     SOCKS: $SOCKS5_USER, $LOGNAME, $USER&lt;br /&gt; *     HTTP Proxy: $HTTP_PROXY_USER, $LOGNAME, $USER&lt;br /&gt; *&lt;br /&gt; * ssh-askpass support&lt;br /&gt; * ===================&lt;br /&gt;  *&lt;br /&gt; *   You can use ssh-askpass (came from OpenSSH or else) to specify&lt;br /&gt; *   password on graphical environment (X-Window or MS Windows). To use&lt;br /&gt; *   this, set program name to environment variable SSH_ASKPASS. On UNIX,&lt;br /&gt; *   X-Window must be required, so $DISPLAY environment variable is also&lt;br /&gt; *   needed.  On Win32 environment, $DISPLAY is not mentioned.&lt;br /&gt; *&lt;br /&gt; * Related Informations&lt;br /&gt; * ====================&lt;br /&gt; *&lt;br /&gt; *   SOCKS5 -- RFC 1928, RFC 1929, RFC 1961&lt;br /&gt; *             NEC SOCKS Reference Implementation is available from:&lt;br /&gt; *               http://www.socks.nec.com&lt;br /&gt; *             DeleGate version 5 or earlier can be SOCKS4 server,&lt;br /&gt; *             and version 6 can be SOCKS5 and SOCKS4 server.&lt;br /&gt; *             and version 7.7.0 or later can be SOCKS5 and SOCKS4a server.&lt;br /&gt; *               http://www.delegate.org/delegate/&lt;br /&gt; *&lt;br /&gt; *   HTTP-Proxy --&lt;br /&gt; *             Many http proxy servers supports this, but https should&lt;br /&gt; *             be allowed as configuration on your host.&lt;br /&gt; *             For example on DeleGate, you should add "https" to the&lt;br /&gt; *             "REMITTABLE" parameter to allow HTTP-Proxy like this:&lt;br /&gt; *               delegated -Pxxxx ...... REMITTABLE="+,https" ...&lt;br /&gt; *&lt;br /&gt; *  Hypertext Transfer Protocol -- HTTP/1.1  -- RFC 2616&lt;br /&gt; *  HTTP Authentication: Basic and Digest Access Authentication -- RFC 2617&lt;br /&gt; *             For proxy authentication, refer these documents.&lt;br /&gt; *&lt;br /&gt; ***********************************************************************/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;string.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;ctype.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;memory.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;errno.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;assert.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;stdarg.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;signal.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef __CYGWIN32__&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#undef _WIN32&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;windows.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;winsock.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/stat.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;io.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;conio.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;unistd.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;pwd.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;termios.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef __hpux&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/select.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* __hpux */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/socket.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;netinet/in.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;arpa/inet.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;netdb.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define WITH_RESOLVER 1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;arpa/nameser.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;resolv.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not ( not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__) */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#undef WITH_RESOLVER&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not ( not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__) */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ECONNRESET WSAECONNRESET&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WI32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef LINT&lt;/font&gt;&lt;br /&gt;static char *vcid = &lt;font color="#666666"&gt;"$Id: connect.c 100 2007-07-03 10:48:26Z gotoh $"&lt;/font&gt;;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Microsoft Visual C/C++ has _snprintf() and _vsnprintf() */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _MSC_VER&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define snprintf _snprintf&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define vsnprintf _vsnprintf&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* consider Borland C */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef __BORLANDC__&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define _kbhit kbhit&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define _setmode setmode&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* help message.&lt;br /&gt;   Win32 environment does not support -R option (vc and cygwin)&lt;br /&gt;   Win32 native compilers does not support -w option, yet (vc)&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;static char *usage = &lt;font color="#666666"&gt;"usage: %s [-dnhst45] [-p local-port]"&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef __CYGWIN32__&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"[-w timeout] \n"&lt;/font&gt;                               &lt;font color="#B22222"&gt;/* cygwin cannot -R */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;" \n"&lt;/font&gt;                                           &lt;font color="#B22222"&gt;/* VC cannot -w nor -R  */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* help message for UNIX */&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"[-R resolve] [-w timeout] \n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          [-H proxy-server[:port]] [-S [user@]socks-server[:port]] \n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          [-T proxy-server[:port]]\n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          [-c telnet-proxy-command]\n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          host port\n"&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* name of this program */&lt;/font&gt;&lt;br /&gt;char *progname = NULL;&lt;br /&gt;char *progdesc = &lt;font color="#666666"&gt;"connect --- simple relaying command via proxy."&lt;/font&gt;;&lt;br /&gt;char *rcs_revstr = &lt;font color="#666666"&gt;"$Revision: 100 $"&lt;/font&gt;;&lt;br /&gt;char *revstr = NULL;&lt;br /&gt;int major_version = 1;&lt;br /&gt;int minor_version = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* set of character for strspn() */&lt;/font&gt;&lt;br /&gt;const char *digits    = &lt;font color="#666666"&gt;"0123456789"&lt;/font&gt;;&lt;br /&gt;const char *dotdigits = &lt;font color="#666666"&gt;"0123456789."&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* options */&lt;/font&gt;&lt;br /&gt;int f_debug = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* report flag to hide secure information */&lt;/font&gt;&lt;br /&gt;int f_report = 1;&lt;br /&gt;&lt;br /&gt;int connect_timeout = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* local input type */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define LOCAL_STDIO     0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define LOCAL_SOCKET    1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;char *local_type_names[] = { &lt;font color="#666666"&gt;"stdio"&lt;/font&gt;, &lt;font color="#666666"&gt;"socket"&lt;/font&gt; };&lt;br /&gt;int   local_type = LOCAL_STDIO;&lt;br /&gt;u_short local_port = 0;                         &lt;font color="#B22222"&gt;/* option 'p' */&lt;/font&gt;&lt;br /&gt;int f_hold_session = 0;                         &lt;font color="#B22222"&gt;/* option 'P' */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;char *telnet_command = &lt;font color="#666666"&gt;"telnet %h %p"&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* utiity types, pair holder of number and string */&lt;/font&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;typedef&lt;/font&gt; &lt;font color="#4169E1"&gt;struct&lt;/font&gt; {&lt;br /&gt;    int num;&lt;br /&gt;    const char *str;&lt;br /&gt;} LOOKUP_ITEM;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* relay method, server and port */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_UNDECIDED 0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_DIRECT    1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_SOCKS     2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_HTTP      3&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_TELNET    4&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;char *method_names[] = { &lt;font color="#666666"&gt;"UNDECIDED"&lt;/font&gt;, &lt;font color="#666666"&gt;"DIRECT"&lt;/font&gt;, &lt;font color="#666666"&gt;"SOCKS"&lt;/font&gt;, &lt;font color="#666666"&gt;"HTTP"&lt;/font&gt;, &lt;font color="#666666"&gt;"TELNET"&lt;/font&gt; };&lt;br /&gt;&lt;br /&gt;int   relay_method = METHOD_UNDECIDED;          &lt;font color="#B22222"&gt;/* relaying method */&lt;/font&gt;&lt;br /&gt;char *relay_host = NULL;                        &lt;font color="#B22222"&gt;/* hostname of relay server */&lt;/font&gt;&lt;br /&gt;u_short relay_port = 0;                         &lt;font color="#B22222"&gt;/* port of relay server */&lt;/font&gt;&lt;br /&gt;char *relay_user = NULL;                        &lt;font color="#B22222"&gt;/* user name for auth */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* destination target host and port */&lt;/font&gt;&lt;br /&gt;char *dest_host = NULL;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="sockaddr_in"&gt;&lt;/a&gt;struct sockaddr_in &lt;/font&gt;dest_addr;&lt;br /&gt;u_short dest_port = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* informations for SOCKS */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_SUCCEEDED    0x00    &lt;/font&gt;&lt;font color="#B22222"&gt;/* succeeded */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_FAIL         0x01    &lt;/font&gt;&lt;font color="#B22222"&gt;/* general SOCKS serer failure */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_NALLOWED     0x02    &lt;/font&gt;&lt;font color="#B22222"&gt;/* connection not allowed by ruleset */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_NUNREACH     0x03    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Network unreachable */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_HUNREACH     0x04    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Host unreachable */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_REFUSED      0x05    &lt;/font&gt;&lt;font color="#B22222"&gt;/* connection refused */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_EXPIRED      0x06    &lt;/font&gt;&lt;font color="#B22222"&gt;/* TTL expired */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_CNOTSUP      0x07    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Command not supported */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_ANOTSUP      0x08    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Address not supported */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_INVADDR      0x09    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Inalid address */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;LOOKUP_ITEM socks5_rep_names[] = {&lt;br /&gt;    { SOCKS5_REP_SUCCEEDED, &lt;font color="#666666"&gt;"succeeded"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_FAIL,      &lt;font color="#666666"&gt;"general SOCKS server failure"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_NALLOWED,  &lt;font color="#666666"&gt;"connection not allowed by ruleset"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_NUNREACH,  &lt;font color="#666666"&gt;"Network unreachable"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_HUNREACH,  &lt;font color="#666666"&gt;"Host unreachable"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_REFUSED,   &lt;font color="#666666"&gt;"connection refused"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_EXPIRED,   &lt;font color="#666666"&gt;"TTL expired"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_CNOTSUP,   &lt;font color="#666666"&gt;"Command not supported"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_ANOTSUP,   &lt;font color="#666666"&gt;"Address not supported"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_INVADDR,   &lt;font color="#666666"&gt;"Invalid address"&lt;/font&gt;},&lt;br /&gt;    { -1, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* SOCKS5 authentication methods */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_REJECT      0xFF    &lt;/font&gt;&lt;font color="#B22222"&gt;/* No acceptable auth method */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_NOAUTH      0x00    &lt;/font&gt;&lt;font color="#B22222"&gt;/* without authentication */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_GSSAPI      0x01    &lt;/font&gt;&lt;font color="#B22222"&gt;/* GSSAPI */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_USERPASS    0x02    &lt;/font&gt;&lt;font color="#B22222"&gt;/* User/Password */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_CHAP        0x03    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Challenge-Handshake Auth Proto. */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_EAP         0x05    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Extensible Authentication Proto. */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_MAF         0x08    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Multi-Authentication Framework */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_SUCCEEDED    90      &lt;/font&gt;&lt;font color="#B22222"&gt;/* rquest granted (succeeded) */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_REJECTED     91      &lt;/font&gt;&lt;font color="#B22222"&gt;/* request rejected or failed */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_IDENT_FAIL   92      &lt;/font&gt;&lt;font color="#B22222"&gt;/* cannot connect identd */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_USERID       93      &lt;/font&gt;&lt;font color="#B22222"&gt;/* user id not matched */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;LOOKUP_ITEM socks4_rep_names[] = {&lt;br /&gt;    { SOCKS4_REP_SUCCEEDED,  &lt;font color="#666666"&gt;"request granted (succeeded)"&lt;/font&gt;},&lt;br /&gt;    { SOCKS4_REP_REJECTED,   &lt;font color="#666666"&gt;"request rejected or failed"&lt;/font&gt;},&lt;br /&gt;    { SOCKS4_REP_IDENT_FAIL, &lt;font color="#666666"&gt;"cannot connect identd"&lt;/font&gt;},&lt;br /&gt;    { SOCKS4_REP_USERID,     &lt;font color="#666666"&gt;"user id not matched"&lt;/font&gt;},&lt;br /&gt;    { -1, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_UNKNOWN 0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_LOCAL   1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_REMOTE  2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_BOTH    3&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;char *resolve_names[] = { &lt;font color="#666666"&gt;"UNKNOWN"&lt;/font&gt;, &lt;font color="#666666"&gt;"LOCAL"&lt;/font&gt;, &lt;font color="#666666"&gt;"REMOTE"&lt;/font&gt;, &lt;font color="#666666"&gt;"BOTH"&lt;/font&gt; };&lt;br /&gt;&lt;br /&gt;int socks_version = 5;                          &lt;font color="#B22222"&gt;/* SOCKS protocol version */&lt;/font&gt;&lt;br /&gt;int socks_resolve = RESOLVE_UNKNOWN;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="sockaddr_in"&gt;&lt;/a&gt;struct sockaddr_in &lt;/font&gt;socks_ns;&lt;br /&gt;char *socks5_auth = NULL;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Environment variable names */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_SERVER  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_SERVER"&lt;/font&gt;&lt;font color="#228B22"&gt;        &lt;/font&gt;&lt;font color="#B22222"&gt;/* SOCKS server */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_SERVER &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_SERVER"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_SERVER &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_SERVER"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_RESOLVE  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_RESOLVE"&lt;/font&gt;&lt;font color="#228B22"&gt;      &lt;/font&gt;&lt;font color="#B22222"&gt;/* resolve method */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_RESOLVE &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_RESOLVE"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_RESOLVE &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_RESOLVE"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;       &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user for SOCKS5 */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;       &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user for SOCKS4 */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_USER      &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;        &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user for SOCKS */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_PASSWD   &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_PASSWD"&lt;/font&gt;&lt;font color="#228B22"&gt;     &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth password for SOCKS5 */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_PASSWORD &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_PASSWORD"&lt;/font&gt;&lt;font color="#228B22"&gt;   &lt;/font&gt;&lt;font color="#B22222"&gt;/* old style */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_PROXY          &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_PROXY"&lt;/font&gt;&lt;font color="#228B22"&gt;    &lt;/font&gt;&lt;font color="#B22222"&gt;/* common env var */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_PROXY_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_PROXY_USER"&lt;/font&gt;&lt;font color="#228B22"&gt; &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_PROXY_PASSWORD &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_PROXY_PASSWORD"&lt;/font&gt;&lt;font color="#228B22"&gt; &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth password */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_TELNET_PROXY          &lt;/font&gt;&lt;font color="#666666"&gt;"TELNET_PROXY"&lt;/font&gt;&lt;font color="#228B22"&gt;    &lt;/font&gt;&lt;font color="#B22222"&gt;/* common env var */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_CONNECT_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"CONNECT_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;     &lt;/font&gt;&lt;font color="#B22222"&gt;/* default auth user name */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_CONNECT_PASSWORD &lt;/font&gt;&lt;font color="#666666"&gt;"CONNECT_PASSWORD"&lt;/font&gt;&lt;font color="#228B22"&gt; &lt;/font&gt;&lt;font color="#B22222"&gt;/* default auth password */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_DIRECT   &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;       &lt;/font&gt;&lt;font color="#B22222"&gt;/* addr-list for non-proxy */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_DIRECT  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_DIRECT  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_DIRECT    &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_CONNECT_DIRECT &lt;/font&gt;&lt;font color="#666666"&gt;"CONNECT_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_AUTH &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_AUTH"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SSH_ASKPASS &lt;/font&gt;&lt;font color="#666666"&gt;"SSH_ASKPASS"&lt;/font&gt;&lt;font color="#228B22"&gt;           &lt;/font&gt;&lt;font color="#B22222"&gt;/* askpass program */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Prefix string of HTTP_PROXY */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define HTTP_PROXY_PREFIX &lt;/font&gt;&lt;font color="#666666"&gt;"http://"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PROXY_AUTH_NONE 0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PROXY_AUTH_BASIC 1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PROXY_AUTH_DIGEST 2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;int proxy_auth_type = PROXY_AUTH_NONE;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* reason of end repeating */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_UNK              -2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_ERROR            -1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_CLOSED_BY_LOCAL  0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_CLOSED_BY_REMOTE 1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* return value of relay start function. */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define START_ERROR -1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define START_OK     0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define START_RETRY  1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* socket related definitions */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKET int&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef SOCKET_ERROR&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKET_ERROR -1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define socket_errno() WSAGetLastError()&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define closesocket close&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define socket_errno() (errno)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define popen _popen&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* packet operation macro */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* debug message output */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="debug"&gt;&lt;/a&gt;void&lt;br /&gt;debug( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( f_debug ) {&lt;br /&gt;        va_start( args, fmt );&lt;br /&gt;        fprintf(stderr, &lt;font color="#666666"&gt;"DEBUG: "&lt;/font&gt;);&lt;br /&gt;        vfprintf( stderr, fmt, args );&lt;br /&gt;        va_end( args );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="debug_"&gt;&lt;/a&gt;void&lt;br /&gt;debug_( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;                  &lt;font color="#B22222"&gt;/* without prefix */&lt;/font&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( f_debug ) {&lt;br /&gt;        va_start( args, fmt );&lt;br /&gt;        vfprintf( stderr, fmt, args );&lt;br /&gt;        va_end( args );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* error message output */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="error"&gt;&lt;/a&gt;void&lt;br /&gt;error( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start( args, fmt );&lt;br /&gt;    fprintf(stderr, &lt;font color="#666666"&gt;"ERROR: "&lt;/font&gt;);&lt;br /&gt;    vfprintf( stderr, fmt, args );&lt;br /&gt;    va_end( args );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="fatal"&gt;&lt;/a&gt;void&lt;br /&gt;fatal( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start( args, fmt );&lt;br /&gt;    fprintf(stderr, &lt;font color="#666666"&gt;"FATAL: "&lt;/font&gt;);&lt;br /&gt;    vfprintf( stderr, fmt, args );&lt;br /&gt;    va_end( args );&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="xmalloc"&gt;&lt;/a&gt;void *&lt;br /&gt;xmalloc (size_t size)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    void *ret = malloc(size);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (ret == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot allocate memory: %d bytes.\n"&lt;/font&gt;, size);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="downcase"&gt;&lt;/a&gt;char *&lt;br /&gt;downcase( char *str )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *buf = str;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *buf ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( isupper(*buf) )&lt;br /&gt;            *buf += 'a'-'A';&lt;br /&gt;        buf++;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; str;                                 &lt;font color="#B22222"&gt;/* return converted arg */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="expand_host_and_port"&gt;&lt;/a&gt;char *&lt;br /&gt;expand_host_and_port (const char *fmt, const char *host, int port)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    const char *src;&lt;br /&gt;    char *buf, *dst, *ptr;&lt;br /&gt;    size_t len = strlen(fmt) + strlen(host) + 20;&lt;br /&gt;    buf = xmalloc (len);&lt;br /&gt;    dst = buf;&lt;br /&gt;    src = fmt;&lt;br /&gt;    &lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (*src) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*src == '%') {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; (src[1]) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'h':&lt;br /&gt;                strcpy (dst, host);&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'p':&lt;br /&gt;                snprintf (dst, len, &lt;font color="#666666"&gt;"%d"&lt;/font&gt;, port);&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                src ++;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;            dst = buf + strlen (buf);&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*src == '\\') {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; (src[1]) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'r':                                &lt;font color="#B22222"&gt;/* CR */&lt;/font&gt;&lt;br /&gt;                *dst++ = '\r';&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'n':                                &lt;font color="#B22222"&gt;/* LF */&lt;/font&gt;&lt;br /&gt;                *dst++ = '\n';&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 't':                                &lt;font color="#B22222"&gt;/* TAB */&lt;/font&gt;&lt;br /&gt;                *dst++ = '\t';&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                src ++;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* usual */&lt;/font&gt;&lt;br /&gt;            *dst++ = *src++;&lt;br /&gt;        }&lt;br /&gt;        *dst = '\0';&lt;br /&gt;    }&lt;br /&gt;    assert (strlen(buf) &amp;lt; len);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="lookup_resolve"&gt;&lt;/a&gt;int&lt;br /&gt;lookup_resolve( const char *str )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *buf = strdup( str );&lt;br /&gt;    int ret;&lt;br /&gt;&lt;br /&gt;    downcase( buf );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp( buf, &lt;font color="#666666"&gt;"both"&lt;/font&gt; ) == 0 )&lt;br /&gt;        ret = RESOLVE_BOTH;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp( buf, &lt;font color="#666666"&gt;"remote"&lt;/font&gt; ) == 0 )&lt;br /&gt;        ret = RESOLVE_REMOTE;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp( buf, &lt;font color="#666666"&gt;"local"&lt;/font&gt; ) == 0 )&lt;br /&gt;        ret = RESOLVE_LOCAL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strspn(buf, dotdigits) == strlen(buf) ) {&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef WITH_RESOLVER&lt;/font&gt;&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Sorry, you can't specify to resolve the hostname with the -R option on Win32 environment."&lt;/font&gt;);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not WITH_RESOLVER */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;        ret = RESOLVE_LOCAL;                    &lt;font color="#B22222"&gt;/* this case is also 'local' */&lt;/font&gt;&lt;br /&gt;        socks_ns.sin_addr.s_addr = inet_addr(buf);&lt;br /&gt;        socks_ns.sin_family = AF_INET;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;        ret = RESOLVE_UNKNOWN;&lt;br /&gt;    free(buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="getusername"&gt;&lt;/a&gt;char *&lt;br /&gt;getusername(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;    static char buf[1024];&lt;br /&gt;    DWORD size = &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf);&lt;br /&gt;    buf[0] = '\0';&lt;br /&gt;    GetUserName( buf, &amp;amp;size);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct passwd&lt;/font&gt; *pw = getpwuid(getuid());&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( pw == NULL )&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"getpwuid() failed for uid: %d\n"&lt;/font&gt;, getuid());&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; pw-&amp;gt;pw_name;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* expect&lt;br /&gt;   check STR is begin with substr with case-ignored comparison.&lt;br /&gt;   Return 1 if matched, otherwise 0.&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="expect"&gt;&lt;/a&gt;int&lt;br /&gt;expect( char *str, char *substr)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int len = strlen(substr);&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; len-- ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( toupper(*str) != toupper(*substr) )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                           &lt;font color="#B22222"&gt;/* not matched */&lt;/font&gt;&lt;br /&gt;        str++, substr++;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                   &lt;font color="#B22222"&gt;/* good, matched */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** PARAMETER operation **/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PARAMETER_FILE &lt;/font&gt;&lt;font color="#666666"&gt;"/etc/connectrc"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PARAMETER_DOTFILE &lt;/font&gt;&lt;font color="#666666"&gt;".connectrc"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;typedef&lt;/font&gt; &lt;font color="#4169E1"&gt;struct&lt;/font&gt; {&lt;br /&gt;    char* name;&lt;br /&gt;    char* value;&lt;br /&gt;} PARAMETER_ITEM;&lt;br /&gt;PARAMETER_ITEM parameter_table[] = {&lt;br /&gt;    { ENV_SOCKS_SERVER, NULL },&lt;br /&gt;    { ENV_SOCKS5_SERVER, NULL },&lt;br /&gt;    { ENV_SOCKS4_SERVER, NULL },&lt;br /&gt;    { ENV_SOCKS_RESOLVE, NULL },&lt;br /&gt;    { ENV_SOCKS5_RESOLVE, NULL },&lt;br /&gt;    { ENV_SOCKS4_RESOLVE, NULL },&lt;br /&gt;    { ENV_SOCKS5_USER, NULL },&lt;br /&gt;    { ENV_SOCKS5_PASSWD, NULL },&lt;br /&gt;    { ENV_SOCKS5_PASSWORD, NULL },&lt;br /&gt;    { ENV_HTTP_PROXY, NULL },&lt;br /&gt;    { ENV_HTTP_PROXY_USER, NULL },&lt;br /&gt;    { ENV_HTTP_PROXY_PASSWORD, NULL },&lt;br /&gt;    { ENV_CONNECT_USER, NULL },&lt;br /&gt;    { ENV_CONNECT_PASSWORD, NULL },&lt;br /&gt;    { ENV_SSH_ASKPASS, NULL },&lt;br /&gt;    { ENV_SOCKS5_DIRECT, NULL },&lt;br /&gt;    { ENV_SOCKS4_DIRECT, NULL },&lt;br /&gt;    { ENV_SOCKS_DIRECT, NULL },&lt;br /&gt;    { ENV_HTTP_DIRECT, NULL },&lt;br /&gt;    { ENV_CONNECT_DIRECT, NULL },&lt;br /&gt;    { ENV_SOCKS5_AUTH, NULL },&lt;br /&gt;    { NULL, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="find_parameter_item"&gt;&lt;/a&gt;PARAMETER_ITEM*&lt;br /&gt;find_parameter_item(const char* name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int i;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt;( i = 0; parameter_table[i].name != NULL; i++ ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp(name, parameter_table[i].name) == 0 )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; &amp;amp;parameter_table[i];&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="read_parameter_file_1"&gt;&lt;/a&gt;void&lt;br /&gt;read_parameter_file_1(const char* name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    FILE* f;&lt;br /&gt;    int line;&lt;br /&gt;    char lbuf[1025];&lt;br /&gt;    f = fopen(name, &lt;font color="#666666"&gt;"r"&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt;( f ){&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"Reading parameter file(%s)\n"&lt;/font&gt;, name);&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( line = 1; fgets(lbuf, 1024, f); line++ ) {&lt;br /&gt;            char *p, *q, *param, *value;&lt;br /&gt;            p = strchr(lbuf, '\n');&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( p == NULL )&lt;br /&gt;                fatal(&lt;font color="#666666"&gt;"%s:%d: buffer overflow\n"&lt;/font&gt;, name, line);&lt;br /&gt;            *p = '\0';&lt;br /&gt;            p = strchr(lbuf, '#');&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( p )&lt;br /&gt;                *p = '\0';&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( p = lbuf; *p; p++ )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt;( *p != ' ' &amp;amp;&amp;amp; *p != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *p == '\0' ) &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;&lt;br /&gt;            param = p;&lt;br /&gt;            p = strchr(p, '=');&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( p == NULL ) {&lt;br /&gt;                error(&lt;font color="#666666"&gt;"%s:%d: missing equal sign\n"&lt;/font&gt;, name, line);&lt;br /&gt;                &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( q = p - 1; q &amp;gt;= lbuf; q-- )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *q != ' ' &amp;amp;&amp;amp; *q != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            *++q = '\0';&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( ++p; *p; p++ )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *p != ' ' &amp;amp;&amp;amp; *p != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            value = p;&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( ; *p; p++ );&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( p--; p &amp;gt;= lbuf; p-- )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *p != ' ' &amp;amp;&amp;amp; *p != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            *++p = '\0';&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( param &amp;amp;&amp;amp; value ) {&lt;br /&gt;                PARAMETER_ITEM *item;&lt;br /&gt;                item = find_parameter_item(param);&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( item == NULL ) {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"%s:%d: unknown parameter `%s'\n"&lt;/font&gt;, name, line, param);&lt;br /&gt;                    &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;&lt;br /&gt;                }&lt;br /&gt;                item-&amp;gt;value = strdup(value);&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"Parameter `%s' is set to `%s'\n"&lt;/font&gt;, param, value);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="read_parameter_file"&gt;&lt;/a&gt;void&lt;br /&gt;read_parameter_file(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) || defined(cygwin)&lt;/font&gt;&lt;br /&gt;    char *name;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct passwd&lt;/font&gt; *pw;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    read_parameter_file_1(PARAMETER_FILE);&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) || defined(cygwin)&lt;/font&gt;&lt;br /&gt;    pw = getpwuid(getuid());&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( pw == NULL )&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"getpwuid() failed for uid: %d\n"&lt;/font&gt;, getuid());&lt;br /&gt;    name = xmalloc(strlen(pw-&amp;gt;pw_dir) + strlen(PARAMETER_DOTFILE) + 2);&lt;br /&gt;    strcpy(name, pw-&amp;gt;pw_dir);&lt;br /&gt;    strcat(name, &lt;font color="#666666"&gt;"/"&lt;/font&gt; PARAMETER_DOTFILE);&lt;br /&gt;    read_parameter_file_1(name);&lt;br /&gt;    free(name);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="getparam"&gt;&lt;/a&gt;char*&lt;br /&gt;getparam(const char* name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *value = getenv(name);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( value == NULL ){&lt;br /&gt;        PARAMETER_ITEM *item = find_parameter_item(name);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( item != NULL )&lt;br /&gt;            value = item-&amp;gt;value;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; value;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** DIRECT connection **/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define MAX_DIRECT_ADDR_LIST 256&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="ADDRPAIR"&gt;&lt;/a&gt;struct ADDRPAIR &lt;/font&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; addr;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; mask;&lt;br /&gt;    char *name;&lt;br /&gt;    int negative;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="ADDRPAIR"&gt;&lt;/a&gt;struct ADDRPAIR &lt;/font&gt;direct_addr_list[MAX_DIRECT_ADDR_LIST];&lt;br /&gt;int n_direct_addr_list = 0;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="mask_addr"&gt;&lt;/a&gt;void&lt;br /&gt;mask_addr (void *addr, void *mask, int addrlen)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *a, *m;&lt;br /&gt;    a = addr;&lt;br /&gt;    m = mask;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; addrlen-- )&lt;br /&gt;        *a++ &amp;amp;= *m++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="add_direct_addr"&gt;&lt;/a&gt;int&lt;br /&gt;add_direct_addr (struct in_addr *addr, struct in_addr *mask, int negative)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; iaddr;&lt;br /&gt;    char *s;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( MAX_DIRECT_ADDR_LIST &amp;lt;= n_direct_addr_list ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"direct address table is full!\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    iaddr = *addr;&lt;br /&gt;    mask_addr(&amp;amp;iaddr, mask, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(iaddr));&lt;br /&gt;    s = strdup(inet_ntoa(iaddr));&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"adding direct addr entry: %s%s/%s\n"&lt;/font&gt;,&lt;br /&gt;          negative? &lt;font color="#666666"&gt;"!"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;, s, inet_ntoa(*mask));&lt;br /&gt;    free(s);&lt;br /&gt;    memcpy( &amp;amp;direct_addr_list[n_direct_addr_list].addr,&lt;br /&gt;            &amp;amp;iaddr, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(iaddr));&lt;br /&gt;    memcpy( &amp;amp;direct_addr_list[n_direct_addr_list].mask,&lt;br /&gt;            mask, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(*mask));&lt;br /&gt;    direct_addr_list[n_direct_addr_list].name = NULL;&lt;br /&gt;    direct_addr_list[n_direct_addr_list].negative = negative;&lt;br /&gt;    n_direct_addr_list++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* add domain/host name entry to direct name table */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="add_direct_host"&gt;&lt;/a&gt;int&lt;br /&gt;add_direct_host( const char *name, int negative)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( MAX_DIRECT_ADDR_LIST &amp;lt;= n_direct_addr_list ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"direct address table is full!\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*name == '*')&lt;br /&gt;        name++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*name == '.')&lt;br /&gt;        name++;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"adding direct name entry: %s%s\n"&lt;/font&gt;, negative? &lt;font color="#666666"&gt;"!"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;, name);&lt;br /&gt;    direct_addr_list[n_direct_addr_list].name = downcase(strdup(name));&lt;br /&gt;    direct_addr_list[n_direct_addr_list].negative = negative;&lt;br /&gt;    n_direct_addr_list++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="parse_addr_pair"&gt;&lt;/a&gt;int&lt;br /&gt;parse_addr_pair (const char *str, struct in_addr *addr, struct in_addr *mask)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#B22222"&gt;/* NOTE: */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Assume already be splitted by separator&lt;br /&gt;       and formatted as folowing:&lt;br /&gt;       1)  12.34.56.789/255.255.255.0&lt;br /&gt;       2)  12.34.56.789/24&lt;br /&gt;       3)  12.34.56.&lt;br /&gt;       All above generates same addr/mask pair 12.34.56.0 and 255.255.255.0&lt;br /&gt;    */&lt;/font&gt;&lt;br /&gt;    const char *ptr;&lt;br /&gt;    u_char *dsta, *dstm;&lt;br /&gt;    int i, n;&lt;br /&gt;&lt;br /&gt;    assert( str != NULL );&lt;br /&gt;    addr-&amp;gt;s_addr = 0;&lt;br /&gt;    mask-&amp;gt;s_addr = 0;&lt;br /&gt;    ptr = str;&lt;br /&gt;    dsta = (u_char*)&amp;amp;addr-&amp;gt;s_addr;&lt;br /&gt;    dstm = (u_char*)&amp;amp;mask-&amp;gt;s_addr;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;4; i++ ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '\0' )&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;              &lt;font color="#B22222"&gt;/* case of format #3 */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !isdigit(*ptr) )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;          &lt;font color="#B22222"&gt;/* format error: */&lt;/font&gt;&lt;br /&gt;        *dsta++ = atoi( ptr );&lt;br /&gt;        *dstm++ = 255;          &lt;font color="#B22222"&gt;/* automatic mask for format #3 */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( isdigit(*ptr) ) &lt;font color="#B22222"&gt;/* skip digits */&lt;/font&gt;&lt;br /&gt;            ptr++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '.' )&lt;br /&gt;            ptr++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* At this point, *ptr points '/' or EOS ('\0') */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '\0' )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                       &lt;font color="#B22222"&gt;/* complete as format #3 */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr != '/' )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                      &lt;font color="#B22222"&gt;/* format error */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Now parse mask for format #1 or #2 */&lt;/font&gt;&lt;br /&gt;    ptr++;&lt;br /&gt;    mask-&amp;gt;s_addr = 0;                   &lt;font color="#B22222"&gt;/* clear automatic mask */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strchr( ptr, '.') ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of format #1 */&lt;/font&gt;&lt;br /&gt;        dstm = (u_char*)&amp;amp;mask-&amp;gt;s_addr;&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;4; i++) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !isdigit(*ptr) )&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;              &lt;font color="#B22222"&gt;/* format error: */&lt;/font&gt;&lt;br /&gt;            *dstm++ = atoi(ptr);&lt;br /&gt;            &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( isdigit(*ptr) )     &lt;font color="#B22222"&gt;/* skip digits */&lt;/font&gt;&lt;br /&gt;                ptr++;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '.' )&lt;br /&gt;                ptr++;&lt;br /&gt;            &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;                  &lt;font color="#B22222"&gt;/* from for loop */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#B22222"&gt;/* complete as format #1 */&lt;/font&gt;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of format #2 */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !isdigit(*ptr) )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                  &lt;font color="#B22222"&gt;/* format error: */&lt;/font&gt;&lt;br /&gt;        n = atoi(ptr);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( n&amp;lt;0 || 32&amp;lt;n)&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                  &lt;font color="#B22222"&gt;/* format error */&lt;/font&gt;&lt;br /&gt;        mask-&amp;gt;s_addr = (n==0)? 0: htonl(((u_long)0xFFFFFFFF)&amp;lt;&amp;lt;(32-n));&lt;br /&gt;        &lt;font color="#B22222"&gt;/* complete as format #1 */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="initialize_direct_addr"&gt;&lt;/a&gt;void&lt;br /&gt;initialize_direct_addr (void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int negative;&lt;br /&gt;    int n_entries;&lt;br /&gt;    char *env = NULL, *beg, *next, *envkey = NULL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; addr, mask;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_SOCKS ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_version == 5 )&lt;br /&gt;            envkey = ENV_SOCKS5_DIRECT;&lt;br /&gt;        &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;            envkey = ENV_SOCKS4_DIRECT;&lt;br /&gt;        env = getparam(envkey);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;            env = getparam(ENV_SOCKS_DIRECT);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_HTTP ){&lt;br /&gt;        env = getparam(ENV_HTTP_DIRECT);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;        env = getparam(ENV_CONNECT_DIRECT);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;                 &lt;font color="#B22222"&gt;/* no entry */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"making direct addr list from: '%s'\n"&lt;/font&gt;, env);&lt;br /&gt;    env = strdup( env );        &lt;font color="#B22222"&gt;/* reallocate to modify */&lt;/font&gt;&lt;br /&gt;    beg = next = env;&lt;br /&gt;    n_entries = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;do&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( MAX_DIRECT_ADDR_LIST &amp;lt;= n_entries ) {&lt;br /&gt;            error(&lt;font color="#666666"&gt;"too many entries in %s"&lt;/font&gt;, envkey);&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;              &lt;font color="#B22222"&gt;/* from do loop */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;        next = strchr( beg, ',');&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( next != NULL )&lt;br /&gt;            *next++ = '\0';&lt;br /&gt;        addr.s_addr = 0;&lt;br /&gt;        mask.s_addr = 0;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*beg == '!') {&lt;br /&gt;            negative = 1;&lt;br /&gt;            beg++;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;            negative = 0;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !parse_addr_pair( beg, &amp;amp;addr, &amp;amp;mask ) ) {&lt;br /&gt;            add_direct_addr( &amp;amp;addr, &amp;amp;mask, negative );&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            add_direct_host( beg, negative );&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( next != NULL )&lt;br /&gt;            beg = next;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( next != NULL );&lt;br /&gt;&lt;br /&gt;    free( env );&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="cmp_addr"&gt;&lt;/a&gt;int&lt;br /&gt;cmp_addr (void *addr1, void *addr2, int addrlen)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; memcmp( addr1, addr2, addrlen );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="is_direct_address"&gt;&lt;/a&gt;int&lt;br /&gt;is_direct_address (const struct in_addr addr)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int i, neg;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; iaddr;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Note: assume IPV4 address !! */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;n_direct_addr_list; i++ ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (direct_addr_list[i].name != NULL)&lt;br /&gt;            &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;                           &lt;font color="#B22222"&gt;/* it's name entry */&lt;/font&gt;&lt;br /&gt;        neg = direct_addr_list[i].negative;&lt;br /&gt;        iaddr = addr;&lt;br /&gt;        mask_addr( &amp;amp;iaddr, &amp;amp;direct_addr_list[i].mask,&lt;br /&gt;                   &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(&lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt;));&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (cmp_addr(&amp;amp;iaddr, &amp;amp;direct_addr_list[i].addr,&lt;br /&gt;                     &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(&lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt;)) == 0) {&lt;br /&gt;            char *a, *m;&lt;br /&gt;            a = strdup(inet_ntoa(direct_addr_list[i].addr));&lt;br /&gt;            m = strdup(inet_ntoa(direct_addr_list[i].mask));&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"match with: %s/%s%s\n"&lt;/font&gt;, a, m, neg? &lt;font color="#666666"&gt;" (negative)"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;);&lt;br /&gt;            free(a);&lt;br /&gt;            free(m);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; !neg? 1: 0;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"not matched, addr to be relayed: %s\n"&lt;/font&gt;, inet_ntoa(addr));&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                   &lt;font color="#B22222"&gt;/* not direct */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* check s1 is ends with s2.&lt;br /&gt;   return 1 if exact match or domain part match.&lt;br /&gt;   return 0 if s1 is shorter than s2 or partial match.&lt;br /&gt;   For example, &lt;br /&gt;    ends_with("bar.com", "bar.com")        =&amp;gt; 1 (exact match)&lt;br /&gt;    ends_with("foo.bar.com", "bar.com")    =&amp;gt; 1 (domain match)&lt;br /&gt;    ends_with("foo.beebar.com", "bar.com") =&amp;gt; 0 (partial match)&lt;br /&gt;    ends_with("bar", "bar.com")            =&amp;gt; 0 (shorter)&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="omain_match"&gt;&lt;/a&gt;domain_match(const char *s1, const char *s2)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int len1, len2;&lt;br /&gt;    const char *tail1, *tail2;&lt;br /&gt;    len1 = strlen(s1);&lt;br /&gt;    len2 = strlen(s2);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (len1 &amp;lt; len2 || len1 == 0 || len2 == 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;    tail1 = s1 + len1;&lt;br /&gt;    tail2 = s2 + len2;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (0 &amp;lt; len1 &amp;amp;&amp;amp; 0 &amp;lt; len2) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*--tail1 != *--tail2)&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;                              &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;        len1--, len2--;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (len2 != 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Now exact match, domain match or partial match.&lt;br /&gt;       Return true if exact or domain match.&lt;br /&gt;       Or continue checking. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (tail1 == s1 || tail1[-1] == '.')&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                               &lt;font color="#B22222"&gt;/* match! */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                   &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Check given NAME is ends with one of &lt;br /&gt;   registered direct name entry.&lt;br /&gt;   Return 1 if matched, or 0.&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="is_direct_name"&gt;&lt;/a&gt;int&lt;br /&gt;is_direct_name (const char *name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int len, i;&lt;br /&gt;    const char *tail;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"checking %s is for direct?\n"&lt;/font&gt;, name);&lt;br /&gt;    name = downcase(strdup(name));&lt;br /&gt;    len = strlen(name);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (len &amp;lt; 1)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* false */&lt;/font&gt;&lt;br /&gt;    tail = &amp;amp;name[len];&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;n_direct_addr_list; i++ ) {&lt;br /&gt;        int dlen, neg;&lt;br /&gt;        const char *dname;&lt;br /&gt;        const char *n, *d;&lt;br /&gt;        dname = direct_addr_list[i].name;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (dname == NULL)&lt;br /&gt;            &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;                           &lt;font color="#B22222"&gt;/* it's addr/mask entry */&lt;/font&gt;&lt;br /&gt;        neg = direct_addr_list[i].negative;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (domain_match(name, dname)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"match with: %s%s\n"&lt;/font&gt;, dname, neg? &lt;font color="#666666"&gt;" (negative)"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (neg) {&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;       &lt;font color="#B22222"&gt;/* not direct */&lt;/font&gt;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;       &lt;font color="#B22222"&gt;/* direct*/&lt;/font&gt;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                   &lt;font color="#B22222"&gt;/* not matched */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* check to connect to HOST directyly?&lt;br /&gt;   return 1 if to be direct, 0 for else. */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="check_direct"&gt;&lt;/a&gt;int&lt;br /&gt;check_direct(const char *host)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; addr;&lt;br /&gt;    addr.s_addr = inet_addr(host);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (addr.s_addr != INADDR_NONE) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of IP address */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (is_direct_address(addr)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"%s is for direct.\n"&lt;/font&gt;, host);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                           &lt;font color="#B22222"&gt;/* true */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of hostname */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (is_direct_name(host)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"%s is for direct.\n"&lt;/font&gt;, host);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                           &lt;font color="#B22222"&gt;/* true */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"%s is for not direct.\n"&lt;/font&gt;, host);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                    &lt;font color="#B22222"&gt;/* false */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** TTY operation **/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;int intr_flag = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="intr_handler"&gt;&lt;/a&gt;void&lt;br /&gt;intr_handler(int sig)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    intr_flag = 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="tty_change_echo"&gt;&lt;/a&gt;void&lt;br /&gt;tty_change_echo(int fd, int enable)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static &lt;font color="#4169E1"&gt;struct termios&lt;/font&gt; ntio, otio;           &lt;font color="#B22222"&gt;/* new/old termios */&lt;/font&gt;&lt;br /&gt;    static sigset_t nset, oset;                 &lt;font color="#B22222"&gt;/* new/old sigset */&lt;/font&gt;&lt;br /&gt;    static &lt;font color="#4169E1"&gt;struct sigaction&lt;/font&gt; nsa, osa;           &lt;font color="#B22222"&gt;/* new/old sigaction */&lt;/font&gt;&lt;br /&gt;    static int disabled = 0;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( disabled &amp;amp;&amp;amp; enable ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* enable echo */&lt;/font&gt;&lt;br /&gt;        tcsetattr(fd, TCSANOW, &amp;amp;otio);&lt;br /&gt;        disabled = 0;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* resotore sigaction */&lt;/font&gt;&lt;br /&gt;        sigprocmask(SIG_SETMASK, &amp;amp;oset, NULL);&lt;br /&gt;        sigaction(SIGINT, &amp;amp;osa, NULL);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( intr_flag != 0 ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* re-generate signal  */&lt;/font&gt;&lt;br /&gt;            kill(getpid(), SIGINT);&lt;br /&gt;            sigemptyset(&amp;amp;nset);&lt;br /&gt;            sigsuspend(&amp;amp;nset);&lt;br /&gt;            intr_flag = 0;&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!disabled &amp;amp;&amp;amp; !enable) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* set SIGINTR handler and break syscall on singal */&lt;/font&gt;&lt;br /&gt;        sigemptyset(&amp;amp;nset);&lt;br /&gt;        sigaddset(&amp;amp;nset, SIGTSTP);&lt;br /&gt;        sigprocmask(SIG_BLOCK, &amp;amp;nset, &amp;amp;oset);&lt;br /&gt;        intr_flag = 0;&lt;br /&gt;        memset(&amp;amp;nsa, 0, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(nsa));&lt;br /&gt;        nsa.sa_handler = intr_handler;&lt;br /&gt;        sigaction(SIGINT, &amp;amp;nsa, &amp;amp;osa);&lt;br /&gt;        &lt;font color="#B22222"&gt;/* disable echo */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (tcgetattr(fd, &amp;amp;otio) == 0 &amp;amp;&amp;amp; (otio.c_lflag &amp;amp; ECHO)) {&lt;br /&gt;            disabled = 1;&lt;br /&gt;            ntio = otio;&lt;br /&gt;            ntio.c_lflag &amp;amp;= ~(ECHO | ECHOE | ECHOK | ECHONL);&lt;br /&gt;            (void) tcsetattr(fd, TCSANOW, &amp;amp;ntio);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define TTY_NAME &lt;/font&gt;&lt;font color="#666666"&gt;"/dev/tty"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="tty_readpass"&gt;&lt;/a&gt;int&lt;br /&gt;tty_readpass( const char *prompt, char *buf, size_t size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int tty, ret = 0;&lt;br /&gt;&lt;br /&gt;    tty = open(TTY_NAME, O_RDWR);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( tty &amp;lt; 0 ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Unable to open %s\n"&lt;/font&gt;, TTY_NAME);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* can't open tty */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( size &amp;lt;= 0 )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* no room */&lt;/font&gt;&lt;br /&gt;    write(tty, prompt, strlen(prompt));&lt;br /&gt;    buf[0] = '\0';&lt;br /&gt;    tty_change_echo(tty, 0);                    &lt;font color="#B22222"&gt;/* disable echo */&lt;/font&gt;&lt;br /&gt;    ret = read(tty,buf, size-1);&lt;br /&gt;    tty_change_echo(tty, 1);                    &lt;font color="#B22222"&gt;/* restore */&lt;/font&gt;&lt;br /&gt;    write(tty, &lt;font color="#666666"&gt;"\n"&lt;/font&gt;, 1);                        &lt;font color="#B22222"&gt;/* new line */&lt;/font&gt;&lt;br /&gt;    close(tty);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strchr(buf,'\n') == NULL  )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; ret )&lt;br /&gt;        buf[ret] = '\0';&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="w32_intr_handler"&gt;&lt;/a&gt;BOOL __stdcall&lt;br /&gt;w32_intr_handler(DWORD dwCtrlType)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dwCtrlType == CTRL_C_EVENT ) {&lt;br /&gt;        intr_flag = 1;&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; TRUE;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; FALSE;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define tty_readpass w32_tty_readpass&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="w32_tty_readpass"&gt;&lt;/a&gt;int&lt;br /&gt;w32_tty_readpass( const char *prompt, char *buf, size_t size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    HANDLE in = CreateFile(&lt;font color="#666666"&gt;"CONIN$"&lt;/font&gt;, GENERIC_READ|GENERIC_WRITE,&lt;br /&gt;                           0, NULL, OPEN_EXISTING, 0, NULL);&lt;br /&gt;    HANDLE out = CreateFile(&lt;font color="#666666"&gt;"CONOUT$"&lt;/font&gt;, GENERIC_WRITE,&lt;br /&gt;                            0, NULL, OPEN_EXISTING, 0, NULL);&lt;br /&gt;    DWORD mode;&lt;br /&gt;    DWORD ret, bytes;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (in == INVALID_HANDLE_VALUE || out == INVALID_HANDLE_VALUE)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot open console. (errno=%d)"&lt;/font&gt;, GetLastError());&lt;br /&gt;&lt;br /&gt;    WriteFile(out, prompt, strlen(prompt), &amp;amp;bytes, 0);&lt;br /&gt;    SetConsoleCtrlHandler(w32_intr_handler, TRUE ); &lt;font color="#B22222"&gt;/* add handler */&lt;/font&gt;&lt;br /&gt;    GetConsoleMode(in, &amp;amp;mode);&lt;br /&gt;    SetConsoleMode(in, mode&amp;amp;~ENABLE_ECHO_INPUT); &lt;font color="#B22222"&gt;/* disable echo */&lt;/font&gt;&lt;br /&gt;    ret = ReadFile(in, buf, size, &amp;amp;bytes, 0);&lt;br /&gt;    SetConsoleMode(in, mode);                   &lt;font color="#B22222"&gt;/* enable echo */&lt;/font&gt;&lt;br /&gt;    SetConsoleCtrlHandler( w32_intr_handler, FALSE ); &lt;font color="#B22222"&gt;/* remove handler */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( intr_flag )&lt;br /&gt;        GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); &lt;font color="#B22222"&gt;/* re-signal */&lt;/font&gt;&lt;br /&gt;    WriteFile(out,&lt;font color="#666666"&gt;"\n"&lt;/font&gt;, 1, &amp;amp;bytes, 0);&lt;br /&gt;    CloseHandle(in);&lt;br /&gt;    CloseHandle(out);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/*** User / Password ***/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* SOCKS5 and HTTP Proxy authentication may requires username and&lt;br /&gt;   password. We ll give it via environment variable or tty.&lt;br /&gt;   Username and password for authentication are decided by&lt;br /&gt;   following rules:&lt;br /&gt;&lt;br /&gt;   Username is taken from&lt;br /&gt;     1) server location spec (i.e. user@host:port)&lt;br /&gt;     2) environment variables (see tables.1)&lt;br /&gt;     3) system account name currently logged in.&lt;br /&gt;&lt;br /&gt;     Table.1 Order of environment variables for username&lt;br /&gt;&lt;br /&gt;        |  SOCKS v5   |  SOCKS v4   |   HTTP proxy    |&lt;br /&gt;      --+-------------+-------------+-----------------+&lt;br /&gt;      1 | SOCKS45_USER | SOCKS4_USER | HTTP_PROXY_USER |&lt;br /&gt;      --+-------------+-------------+                 |&lt;br /&gt;      2 |        SOCKS_USER         |                 |&lt;br /&gt;      --+---------------------------+-----------------+&lt;br /&gt;      3 |              CONNECT_USER                   |&lt;br /&gt;      --+---------------------------------------------+&lt;br /&gt;&lt;br /&gt;   Password is taken from&lt;br /&gt;     1) by environment variables (see table.2)&lt;br /&gt;     2) by entering from tty.&lt;br /&gt;&lt;br /&gt;     Table.2 Order of environment variables for password&lt;br /&gt;&lt;br /&gt;        |    SOCKS v5     |     HTTP proxy      |&lt;br /&gt;      --+-----------------+---------------------+&lt;br /&gt;      1 | SOCKS5_PASSWD   |                     |&lt;br /&gt;      --+-----------------+ HTTP_PROXY_PASSWORD |&lt;br /&gt;      2 | SOCKS5_PASSWORD |                     |&lt;br /&gt;      --+-----------------+---------------------+&lt;br /&gt;      3 |           CONNECT_PASSWORD            |&lt;br /&gt;      --+---------------------------------------+&lt;br /&gt;&lt;br /&gt;      Note: SOCKS5_PASSWD which is added in rev. 1.79&lt;br /&gt;            to share value with NEC SOCKS implementation.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="determine_relay_user"&gt;&lt;/a&gt;char *&lt;br /&gt;determine_relay_user ()&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *user = NULL;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* get username from environment variable, or system. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_method == METHOD_SOCKS) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL &amp;amp;&amp;amp; socks_version == 5)&lt;br /&gt;            user = getparam (ENV_SOCKS5_USER);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL &amp;amp;&amp;amp; socks_version == 4)&lt;br /&gt;            user = getparam (ENV_SOCKS4_USER);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;            user = getparam (ENV_SOCKS_USER);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_method == METHOD_HTTP) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;            user = getparam (ENV_HTTP_PROXY_USER);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;        user = getparam (ENV_CONNECT_USER);&lt;br /&gt;    &lt;font color="#B22222"&gt;/* determine relay user by system call if not yet. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;        user = getusername();&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; user;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="determine_relay_password"&gt;&lt;/a&gt;char *&lt;br /&gt;determine_relay_password ()&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *pass = NULL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL &amp;amp;&amp;amp; relay_method == METHOD_HTTP)&lt;br /&gt;        pass = getparam(ENV_HTTP_PROXY_PASSWORD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL &amp;amp;&amp;amp; relay_method == METHOD_SOCKS)&lt;br /&gt;        pass = getparam(ENV_SOCKS5_PASSWD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL &amp;amp;&amp;amp; relay_method == METHOD_SOCKS)&lt;br /&gt;        pass = getparam(ENV_SOCKS5_PASSWORD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL)&lt;br /&gt;        pass = getparam(ENV_CONNECT_PASSWORD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; pass;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/*** network operations ***/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* set_relay()&lt;br /&gt;   Determine relay informations:&lt;br /&gt;   method, host, port, and username.&lt;br /&gt;   1st arg, METHOD should be METHOD_xxx.&lt;br /&gt;   2nd arg, SPEC is hostname or hostname:port or user@hostame:port.&lt;br /&gt;   hostname is domain name or dot notation.&lt;br /&gt;   If port is omitted, use 80 for METHOD_HTTP method,&lt;br /&gt;   use 1080 for METHOD_SOCKS method.&lt;br /&gt;   Username is also able to given by 3rd. format.&lt;br /&gt;   2nd argument SPEC can be NULL. if NULL, use environment variable.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="set_relay"&gt;&lt;/a&gt;int&lt;br /&gt;set_relay( int method, char *spec )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *buf, *sep, *resolve;&lt;br /&gt;&lt;br /&gt;    relay_method = method;&lt;br /&gt;&lt;br /&gt;    read_parameter_file();&lt;br /&gt;    initialize_direct_addr();&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (n_direct_addr_list == 0) {&lt;br /&gt;        debug (&lt;font color="#666666"&gt;"No direct address are specified.\n"&lt;/font&gt;);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug (&lt;font color="#666666"&gt;"%d direct address entries.\n"&lt;/font&gt;, n_direct_addr_list);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( method ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_DIRECT:&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* nothing to do */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_SOCKS:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( socks_version ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 5:&lt;br /&gt;                spec = getparam(ENV_SOCKS5_SERVER);&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 4:&lt;br /&gt;                spec = getparam(ENV_SOCKS4_SERVER);&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            spec = getparam(ENV_SOCKS_SERVER);&lt;br /&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"Failed to determine SOCKS server.\n"&lt;/font&gt;);&lt;br /&gt;        relay_port = 1080;                      &lt;font color="#B22222"&gt;/* set default first */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* determine resolve method */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_resolve == RESOLVE_UNKNOWN ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ((socks_version == 5) &amp;amp;&amp;amp;&lt;br /&gt;                  ((resolve = getparam(ENV_SOCKS5_RESOLVE)) != NULL)) ||&lt;br /&gt;                 ((socks_version == 4) &amp;amp;&amp;amp;&lt;br /&gt;                  ((resolve = getparam(ENV_SOCKS4_RESOLVE)) != NULL)) ||&lt;br /&gt;                 ((resolve = getparam(ENV_SOCKS_RESOLVE)) != NULL) ) {&lt;br /&gt;                socks_resolve = lookup_resolve( resolve );&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_resolve == RESOLVE_UNKNOWN )&lt;br /&gt;                    fatal(&lt;font color="#666666"&gt;"Invalid resolve method: %s\n"&lt;/font&gt;, resolve);&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* default */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_version == 5 )&lt;br /&gt;                    socks_resolve = RESOLVE_REMOTE;&lt;br /&gt;                &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                    socks_resolve = RESOLVE_LOCAL;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_HTTP:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            spec = getparam(ENV_HTTP_PROXY);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"You must specify http proxy server\n"&lt;/font&gt;);&lt;br /&gt;        relay_port = 80;                        &lt;font color="#B22222"&gt;/* set default first */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_TELNET:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            spec = getparam(ENV_TELNET_PROXY);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"You must specify telnet proxy server\n"&lt;/font&gt;);&lt;br /&gt;        relay_port = 23;                        &lt;font color="#B22222"&gt;/* set default first */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (expect( spec, HTTP_PROXY_PREFIX)) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* URL format like: "http://server:port/" */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* extract server:port part */&lt;/font&gt;&lt;br /&gt;        buf = strdup( spec + strlen(HTTP_PROXY_PREFIX));&lt;br /&gt;        buf[strcspn(buf, &lt;font color="#666666"&gt;"/"&lt;/font&gt;)] = '\0';&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* assume spec is aready "server:port" format */&lt;/font&gt;&lt;br /&gt;        buf = strdup( spec );&lt;br /&gt;    }&lt;br /&gt;    spec = buf;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check username in spec */&lt;/font&gt;&lt;br /&gt;    sep = strchr( spec, '@' );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( sep != NULL ) {&lt;br /&gt;        *sep = '\0';&lt;br /&gt;        relay_user = strdup( spec );&lt;br /&gt;        spec = sep +1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_user == NULL)&lt;br /&gt;        relay_user = determine_relay_user();&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* split out hostname and port number from spec */&lt;/font&gt;&lt;br /&gt;    sep = strchr(spec,':');&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( sep == NULL ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* hostname only, port is already set as default */&lt;/font&gt;&lt;br /&gt;        relay_host = strdup( spec );&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* hostname and port */&lt;/font&gt;&lt;br /&gt;        relay_port = atoi(sep+1);&lt;br /&gt;        *sep = '\0';&lt;br /&gt;        relay_host = strdup( spec );&lt;br /&gt;    }&lt;br /&gt;    free(buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="resolve_port"&gt;&lt;/a&gt;u_short&lt;br /&gt;resolve_port( const char *service )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int port;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( service[strspn (service, digits)] == '\0'  ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* all digits, port number */&lt;/font&gt;&lt;br /&gt;        port = atoi(service);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* treat as service name */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;struct servent&lt;/font&gt; *ent;&lt;br /&gt;        ent = getservbyname( service, NULL );&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ent == NULL ) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"Unknown service, '%s'\n"&lt;/font&gt;, service);&lt;br /&gt;            port = 0;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            port = ntohs(ent-&amp;gt;s_port);&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"service: %s =&amp;gt; %d\n"&lt;/font&gt;, service, port);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; (u_short)port;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="make_revstr"&gt;&lt;/a&gt;void&lt;br /&gt;make_revstr(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *ptr;&lt;br /&gt;    size_t len;&lt;br /&gt;    ptr = strstr(rcs_revstr, &lt;font color="#666666"&gt;": "&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!ptr) {&lt;br /&gt;        revstr = strdup(&lt;font color="#666666"&gt;"unknown"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;    ptr += 2;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* assume subversion's keyword expansion like "Revision: 96". */&lt;/font&gt;&lt;br /&gt;    minor_version = atoi(ptr);&lt;br /&gt;    revstr = xmalloc(20);&lt;br /&gt;    snprintf(revstr, 20, &lt;font color="#666666"&gt;"%d.%d"&lt;/font&gt;, major_version, minor_version);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="getarg"&gt;&lt;/a&gt;int&lt;br /&gt;getarg( int argc, char **argv )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int err = 0;&lt;br /&gt;    char *ptr, *server = (char*)NULL;&lt;br /&gt;    int method = METHOD_DIRECT;&lt;br /&gt;&lt;br /&gt;    progname = *argv;&lt;br /&gt;    argc--, argv++;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check optinos */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( (0 &amp;lt; argc) &amp;amp;&amp;amp; (**argv == '-') ) {&lt;br /&gt;        ptr = *argv + 1;&lt;br /&gt;        &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *ptr ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( *ptr ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 's':                           &lt;font color="#B22222"&gt;/* use SOCKS */&lt;/font&gt;&lt;br /&gt;                method = METHOD_SOCKS;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'n':                           &lt;font color="#B22222"&gt;/* no proxy */&lt;/font&gt;&lt;br /&gt;                method = METHOD_DIRECT;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'h':                           &lt;font color="#B22222"&gt;/* use http-proxy */&lt;/font&gt;&lt;br /&gt;                method = METHOD_HTTP;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 't':&lt;br /&gt;                method = METHOD_TELNET;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'S':                           &lt;font color="#B22222"&gt;/* specify SOCKS server */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    method = METHOD_SOCKS;&lt;br /&gt;                    server = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'H':                           &lt;font color="#B22222"&gt;/* specify http-proxy server */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    method = METHOD_HTTP;&lt;br /&gt;                    server = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'T':                           &lt;font color="#B22222"&gt;/* specify telnet proxy server */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    method = METHOD_TELNET;&lt;br /&gt;                    server = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'c':&lt;br /&gt;                 &lt;font color="#4169E1"&gt;if&lt;/font&gt; (1 &amp;lt; argc) {&lt;br /&gt;                      argv++, argc--;&lt;br /&gt;                      telnet_command = *argv;&lt;br /&gt;                 } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                      error(&lt;font color="#666666"&gt;"option '%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                      err++;&lt;br /&gt;                 }&lt;br /&gt;                 &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'P':&lt;br /&gt;                f_hold_session = 1;&lt;br /&gt;                &lt;font color="#B22222"&gt;/* without break */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'p':                          &lt;font color="#B22222"&gt;/* specify port to forward */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    local_type = LOCAL_SOCKET;&lt;br /&gt;                    local_port = resolve_port(*argv);&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'w':&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    connect_timeout = atoi(*argv);&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '4':&lt;br /&gt;                socks_version = 4;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '5':&lt;br /&gt;                socks_version = 5;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'a':&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    socks5_auth = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'R':                           &lt;font color="#B22222"&gt;/* specify resolve method */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    socks_resolve = lookup_resolve( *argv );&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'V':                           &lt;font color="#B22222"&gt;/* print version */&lt;/font&gt;&lt;br /&gt;                fprintf(stderr, &lt;font color="#666666"&gt;"%s\nVersion %s\n"&lt;/font&gt;, progdesc, revstr);&lt;br /&gt;                exit(0);&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'd':                           &lt;font color="#B22222"&gt;/* debug mode */&lt;/font&gt;&lt;br /&gt;                f_debug++;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                error(&lt;font color="#666666"&gt;"unknown option '-%c'\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                err++;&lt;br /&gt;            }&lt;br /&gt;            ptr++;&lt;br /&gt;        }&lt;br /&gt;        argc--, argv++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check error */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; err )&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; quit;&lt;br /&gt;&lt;br /&gt;    set_relay( method, server );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check destination HOST (MUST) */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( argc == 0  ) {&lt;br /&gt;        fprintf(stderr, &lt;font color="#666666"&gt;"%s\nVersion %s\n"&lt;/font&gt;, progdesc, revstr);&lt;br /&gt;        fprintf(stderr, usage, progname);&lt;br /&gt;        exit(0);&lt;br /&gt;    }&lt;br /&gt;    dest_host = argv[0];&lt;br /&gt;    &lt;font color="#B22222"&gt;/* decide port or service name from programname or argument */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ((ptr=strrchr( progname, '/' )) != NULL) ||&lt;br /&gt;         ((ptr=strchr( progname, '\\')) != NULL) )&lt;br /&gt;        ptr++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;        ptr = progname;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dest_port == 0 ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* accept only if -P is not specified. */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* get port number from argument (prior to progname) */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#B22222"&gt;/* NOTE: This way is for cvs ext method. */&lt;/font&gt;&lt;br /&gt;            dest_port = resolve_port(argv[1]);&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strncmp( ptr, &lt;font color="#666666"&gt;"connect-"&lt;/font&gt;, 8) == 0 ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* decide port number from program name */&lt;/font&gt;&lt;br /&gt;            char *str = strdup( ptr+8 );&lt;br /&gt;            str[strcspn( str, &lt;font color="#666666"&gt;"."&lt;/font&gt; )] = '\0';&lt;br /&gt;            dest_port = resolve_port(str);&lt;br /&gt;            free(str);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check port number */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dest_port &amp;lt;= 0 ) {&lt;br /&gt;        error( &lt;font color="#666666"&gt;"You must specify the destination port correctly.\n"&lt;/font&gt;);&lt;br /&gt;        err++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; quit;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (relay_method != METHOD_DIRECT) &amp;amp;&amp;amp; (relay_port &amp;lt;= 0) ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Invalid relay port: %d\n"&lt;/font&gt;, dest_port);&lt;br /&gt;        err++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; quit;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;quit:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* report for debugging */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"relay_method = %s (%d)\n"&lt;/font&gt;,&lt;br /&gt;          method_names[relay_method], relay_method);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method != METHOD_DIRECT ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"relay_host=%s\n"&lt;/font&gt;, relay_host);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"relay_port=%d\n"&lt;/font&gt;, relay_port);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"relay_user=%s\n"&lt;/font&gt;, relay_user);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_SOCKS ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"socks_version=%d\n"&lt;/font&gt;, socks_version);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"socks_resolve=%s (%d)\n"&lt;/font&gt;,&lt;br /&gt;              resolve_names[socks_resolve], socks_resolve);&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"local_type=%s\n"&lt;/font&gt;, local_type_names[local_type]);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( local_type == LOCAL_SOCKET ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"local_port=%d\n"&lt;/font&gt;, local_port);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (f_hold_session)&lt;br /&gt;            debug (&lt;font color="#666666"&gt;"  with holding remote session.\n"&lt;/font&gt;);&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"dest_host=%s\n"&lt;/font&gt;, dest_host);&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"dest_port=%d\n"&lt;/font&gt;, dest_port);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; err ) {&lt;br /&gt;        fprintf(stderr, usage, progname);&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Time-out feature is not allowed for Win32 native compilers. */&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* MSVC and Borland C cannot but Cygwin and UNIXes can. */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* timeout signal hander */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="sig_timeout"&gt;&lt;/a&gt;void&lt;br /&gt;sig_timeout(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    signal( SIGALRM, SIG_IGN );&lt;br /&gt;    alarm( 0 );&lt;br /&gt;    error( &lt;font color="#666666"&gt;"timed out\n"&lt;/font&gt; );&lt;br /&gt;    exit(1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* set timeout param = seconds, 0 clears */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="set_timeout"&gt;&lt;/a&gt;void&lt;br /&gt;set_timeout(int timeout)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#B22222"&gt;/* This feature is allowed for UNIX or cygwin environments, currently */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( timeout == 0 ) {&lt;br /&gt;        debug( &lt;font color="#666666"&gt;"clearing timeout\n"&lt;/font&gt; );&lt;br /&gt;        signal( SIGALRM, SIG_IGN );&lt;br /&gt;        alarm( 0 );&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug( &lt;font color="#666666"&gt;"setting timeout: %d seconds\n"&lt;/font&gt;, timeout );&lt;br /&gt;        signal(SIGALRM, (void *)sig_timeout);&lt;br /&gt;        alarm( timeout );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="switch_ns"&gt;&lt;/a&gt;void&lt;br /&gt;switch_ns (struct sockaddr_in *ns)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    res_init();&lt;br /&gt;    memcpy (&amp;amp;_res.nsaddr_list[0], ns, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(*ns));&lt;br /&gt;    _res.nscount = 1;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"Using nameserver at %s\n"&lt;/font&gt;, inet_ntoa(ns-&amp;gt;sin_addr));&lt;br /&gt;}&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 &amp;amp;&amp;amp; !__CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* TODO: IPv6&lt;br /&gt;   TODO: fallback if askpass execution failed.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="local_resolve"&gt;&lt;/a&gt;int&lt;br /&gt;local_resolve (const char *host, struct sockaddr_in *addr)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct hostent&lt;/font&gt; *ent;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strspn(host, dotdigits) == strlen(host) ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* given by IPv4 address */&lt;/font&gt;&lt;br /&gt;        addr-&amp;gt;sin_family = AF_INET;&lt;br /&gt;        addr-&amp;gt;sin_addr.s_addr = inet_addr(host);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"resolving host by name: %s\n"&lt;/font&gt;, host);&lt;br /&gt;        ent = gethostbyname (host);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ent ) {&lt;br /&gt;            memcpy (&amp;amp;addr-&amp;gt;sin_addr, ent-&amp;gt;h_addr, ent-&amp;gt;h_length);&lt;br /&gt;            addr-&amp;gt;sin_family = ent-&amp;gt;h_addrtype;&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"resolved: %s (%s)\n"&lt;/font&gt;,&lt;br /&gt;                  host, inet_ntoa(addr-&amp;gt;sin_addr));&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"failed to resolve locally.\n"&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                          &lt;font color="#B22222"&gt;/* failed */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                   &lt;font color="#B22222"&gt;/* good */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="open_connection"&gt;&lt;/a&gt;int&lt;br /&gt;open_connection( const char *host, u_short port )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    SOCKET s;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct sockaddr_in&lt;/font&gt; saddr;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* resolve address of proxy or direct target */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (local_resolve (host, &amp;amp;saddr) &amp;lt; 0) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"can't resolve hostname: %s\n"&lt;/font&gt;, host);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; SOCKET_ERROR;&lt;br /&gt;    }&lt;br /&gt;    saddr.sin_port = htons(port);&lt;br /&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"connecting to %s:%u\n"&lt;/font&gt;, inet_ntoa(saddr.sin_addr), port);&lt;br /&gt;    s = socket( AF_INET, SOCK_STREAM, 0 );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( connect( s, (&lt;font color="#4169E1"&gt;struct sockaddr&lt;/font&gt; *)&amp;amp;saddr, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(saddr))&lt;br /&gt;         == SOCKET_ERROR) {&lt;br /&gt;        debug( &lt;font color="#666666"&gt;"connect() failed.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; SOCKET_ERROR;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; s;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="report_text"&gt;&lt;/a&gt;void&lt;br /&gt;report_text( char *prefix, char *buf )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static char work[1024];&lt;br /&gt;    char *tmp;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !f_debug )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !f_report )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;                                 &lt;font color="#B22222"&gt;/* don't report */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"%s \""&lt;/font&gt;, prefix);&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *buf ) {&lt;br /&gt;        memset( work, 0, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(work));&lt;br /&gt;        tmp = work;&lt;br /&gt;        &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *buf &amp;amp;&amp;amp; ((tmp-work) &amp;lt; (int)&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(work)-5) ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( *buf ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\t': *tmp++ = '\\'; *tmp++ = 't'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\r': *tmp++ = '\\'; *tmp++ = 'r'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\n': *tmp++ = '\\'; *tmp++ = 'n'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\\': *tmp++ = '\\'; *tmp++ = '\\'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( isprint(*buf) ) {&lt;br /&gt;                    *tmp++ = *buf;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    int consumed = tmp - work;&lt;br /&gt;                    snprintf( tmp, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(work)-consumed,&lt;br /&gt;                              &lt;font color="#666666"&gt;"\\x%02X"&lt;/font&gt;, (unsigned char)*buf);&lt;br /&gt;                    tmp += strlen(tmp);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            buf++;&lt;br /&gt;            *tmp = '\0';&lt;br /&gt;        }&lt;br /&gt;        debug_(&lt;font color="#666666"&gt;"%s"&lt;/font&gt;, work);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    debug_(&lt;font color="#666666"&gt;"\"\n"&lt;/font&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="report_bytes"&gt;&lt;/a&gt;void&lt;br /&gt;report_bytes( char *prefix, char *buf, int len )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ! f_debug )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;    debug( &lt;font color="#666666"&gt;"%s"&lt;/font&gt;, prefix );&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; len ) {&lt;br /&gt;        fprintf( stderr, &lt;font color="#666666"&gt;" %02x"&lt;/font&gt;, *(unsigned char *)buf);&lt;br /&gt;        buf++;&lt;br /&gt;        len--;&lt;br /&gt;    }&lt;br /&gt;    fprintf(stderr, &lt;font color="#666666"&gt;"\n"&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="atomic_out"&gt;&lt;/a&gt;int&lt;br /&gt;atomic_out( SOCKET s, char *buf, int size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int ret, len;&lt;br /&gt;&lt;br /&gt;    assert( buf != NULL );&lt;br /&gt;    assert( 0&amp;lt;=size );&lt;br /&gt;    &lt;font color="#B22222"&gt;/* do atomic out */&lt;/font&gt;&lt;br /&gt;    ret = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; size ) {&lt;br /&gt;        len = send( s, buf+ret, size, 0 );&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"atomic_out() failed to send(), %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;        ret += len;&lt;br /&gt;        size -= len;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!f_report) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_out()  [some bytes]\n"&lt;/font&gt;);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt; xx xx xx xx ...\n"&lt;/font&gt;);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_out()  [%d bytes]\n"&lt;/font&gt;, ret);&lt;br /&gt;        report_bytes(&lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt;"&lt;/font&gt;, buf, ret);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="atomic_in"&gt;&lt;/a&gt;int&lt;br /&gt;atomic_in( SOCKET s, char *buf, int size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int ret, len;&lt;br /&gt;&lt;br /&gt;    assert( buf != NULL );&lt;br /&gt;    assert( 0&amp;lt;=size );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* do atomic in */&lt;/font&gt;&lt;br /&gt;    ret = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; size ) {&lt;br /&gt;        len = recv( s, buf+ret, size, 0 );&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 ) {&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"atomic_in() failed to recv(), %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == 0 ) {&lt;br /&gt;            fatal( &lt;font color="#666666"&gt;"Connection closed by peer.\n"&lt;/font&gt;);&lt;br /&gt;        }&lt;br /&gt;        ret += len;&lt;br /&gt;        size -= len;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!f_report) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_in()  [some bytes]\n"&lt;/font&gt;);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt; xx xx xx xx ...\n"&lt;/font&gt;);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_in() [%d bytes]\n"&lt;/font&gt;, ret);&lt;br /&gt;        report_bytes(&lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt;"&lt;/font&gt;, buf, ret);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="line_input"&gt;&lt;/a&gt;int&lt;br /&gt;line_input( SOCKET s, char *buf, int size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *dst = buf;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( size == 0 )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* no error */&lt;/font&gt;&lt;br /&gt;    size--;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; size ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( recv( s, dst, 1, 0) ) {        &lt;font color="#B22222"&gt;/* recv one-by-one */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKET_ERROR:&lt;br /&gt;            error(&lt;font color="#666666"&gt;"recv() error\n"&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                          &lt;font color="#B22222"&gt;/* error */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; 0:&lt;br /&gt;            size = 0;                           &lt;font color="#B22222"&gt;/* end of stream */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;        default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;            &lt;font color="#B22222"&gt;/* continue reading until last 1 char is EOL? */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *dst == '\n' ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* finished */&lt;/font&gt;&lt;br /&gt;                size = 0;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* more... */&lt;/font&gt;&lt;br /&gt;                size--;&lt;br /&gt;            }&lt;br /&gt;            dst++;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    *dst = '\0';&lt;br /&gt;    report_text( &lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt;"&lt;/font&gt;, buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* cut_token()&lt;br /&gt;   Span token in given string STR until char in DELIM is appeared.&lt;br /&gt;   Then replace contiguous DELIMS with '\0' for string termination&lt;br /&gt;   and returns next pointer.&lt;br /&gt;   If no next token, return NULL.&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="cut_token"&gt;&lt;/a&gt;char *&lt;br /&gt;cut_token( char *str, char *delim)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *ptr = str + strcspn(str, delim);&lt;br /&gt;    char *end = ptr + strspn(ptr, delim);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ptr == str )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( ptr &amp;lt; end )&lt;br /&gt;        *ptr++ = '\0';&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ptr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="lookup"&gt;&lt;/a&gt;const char *&lt;br /&gt;lookup(int num, LOOKUP_ITEM *items)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int i = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (0 &amp;lt;= items[i].num) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (items[i].num == num)&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; items[i].str;&lt;br /&gt;        i++;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"(unknown)"&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* readpass()&lt;br /&gt;   password input routine&lt;br /&gt;   Use ssh-askpass (same mechanism to OpenSSH)&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="readpass"&gt;&lt;/a&gt;char *&lt;br /&gt;readpass( const char* prompt, ...)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static char buf[1000];                      &lt;font color="#B22222"&gt;/* XXX, don't be fix length */&lt;/font&gt;&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start(args, prompt);&lt;br /&gt;    vsnprintf(buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf), prompt, args);&lt;br /&gt;    va_end(args);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( getparam(ENV_SSH_ASKPASS)&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;         &amp;amp;&amp;amp; getenv(&lt;font color="#666666"&gt;"DISPLAY"&lt;/font&gt;)&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;        ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* use ssh-askpass to get password */&lt;/font&gt;&lt;br /&gt;        FILE *fp;&lt;br /&gt;        char *askpass = getparam(ENV_SSH_ASKPASS), *cmd;&lt;br /&gt;        int cmd_size = strlen(askpass) +1 +1 +strlen(buf) +1 +1;&lt;br /&gt;        cmd = xmalloc(cmd_size);&lt;br /&gt;        snprintf(cmd, cmd_size, &lt;font color="#666666"&gt;"%s \"%s\""&lt;/font&gt;, askpass, buf);&lt;br /&gt;        fp = popen(cmd, &lt;font color="#666666"&gt;"r"&lt;/font&gt;);&lt;br /&gt;        free(cmd);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( fp == NULL )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;                        &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;        buf[0] = '\0';&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (fgets(buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf), fp) == NULL)&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;                        &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;        fclose(fp);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        tty_readpass( buf, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf));&lt;br /&gt;    }&lt;br /&gt;    buf[strcspn(buf, &lt;font color="#666666"&gt;"\r\n"&lt;/font&gt;)] = '\0';&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_do_auth_userpass"&gt;&lt;/a&gt;static int&lt;br /&gt;socks5_do_auth_userpass( int s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    unsigned char buf[1024], *ptr;&lt;br /&gt;    char *pass = NULL;&lt;br /&gt;    int len;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* do User/Password authentication. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* This feature requires username and password from&lt;br /&gt;       command line argument or environment variable,&lt;br /&gt;       or terminal. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_user == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"cannot determine user name.\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* get password from environment variable if exists. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ((pass=determine_relay_password()) == NULL &amp;amp;&amp;amp;&lt;br /&gt;        (pass=readpass(&lt;font color="#666666"&gt;"Enter SOCKS5 password for %s@%s: "&lt;/font&gt;,&lt;br /&gt;                       relay_user, relay_host)) == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot get password for user: %s\n"&lt;/font&gt;, relay_user);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* make authentication packet */&lt;/font&gt;&lt;br /&gt;    ptr = buf;&lt;br /&gt;    PUT_BYTE( ptr++, 1 );                       &lt;font color="#B22222"&gt;/* subnegotiation ver.: 1 */&lt;/font&gt;&lt;br /&gt;    len = strlen( relay_user );                 &lt;font color="#B22222"&gt;/* ULEN and UNAME */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, len );&lt;br /&gt;    strcpy( ptr, relay_user );&lt;br /&gt;    ptr += len;&lt;br /&gt;    len = strlen( pass );                       &lt;font color="#B22222"&gt;/* PLEN and PASSWD */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, strlen(pass));&lt;br /&gt;    strcpy( ptr, pass );&lt;br /&gt;    ptr += len;&lt;br /&gt;    memset (pass, 0, strlen(pass));             &lt;font color="#B22222"&gt;/* erase password */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* send it and get answer */&lt;/font&gt;&lt;br /&gt;    f_report = 0;&lt;br /&gt;    atomic_out( s, buf, ptr-buf );&lt;br /&gt;    f_report = 1;&lt;br /&gt;    atomic_in( s, buf, 2 );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check status */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( buf[1] == 0 )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* success */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_getauthname"&gt;&lt;/a&gt;static const char *&lt;br /&gt;socks5_getauthname( int auth )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( auth ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_REJECT: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"REJECTED"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_NOAUTH: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"NO-AUTH"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_GSSAPI: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"GSSAPI"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_USERPASS: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"USERPASS"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_CHAP: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"CHAP"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_EAP: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"EAP"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_MAF: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"MAF"&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;    default:&lt;/font&gt;&lt;/strong&gt; &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"(unknown)"&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;typedef&lt;/font&gt; &lt;font color="#4169E1"&gt;struct&lt;/font&gt; {&lt;br /&gt;    char* name;&lt;br /&gt;    unsigned char auth;&lt;br /&gt;} AUTH_METHOD_ITEM;&lt;br /&gt;&lt;br /&gt;AUTH_METHOD_ITEM socks5_auth_table[] = {&lt;br /&gt;    { &lt;font color="#666666"&gt;"none"&lt;/font&gt;, SOCKS5_AUTH_NOAUTH },&lt;br /&gt;    { &lt;font color="#666666"&gt;"gssapi"&lt;/font&gt;, SOCKS5_AUTH_GSSAPI },&lt;br /&gt;    { &lt;font color="#666666"&gt;"userpass"&lt;/font&gt;, SOCKS5_AUTH_USERPASS },&lt;br /&gt;    { &lt;font color="#666666"&gt;"chap"&lt;/font&gt;, SOCKS5_AUTH_CHAP },&lt;br /&gt;    { NULL, -1 },&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_auth_parse_1"&gt;&lt;/a&gt;int&lt;br /&gt;socks5_auth_parse_1(char *start, char *end)&lt;/font&gt;&lt;/strong&gt;{&lt;br /&gt;    int i, len;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( ; *start; start++ )&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *start != ' ' &amp;amp;&amp;amp; *start != '\t') &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( end--; end &amp;gt;= start; end-- ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *end != ' ' &amp;amp;&amp;amp; *end != '\t'){&lt;br /&gt;            end++;&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    len = end - start;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( i = 0; socks5_auth_table[i].name != NULL; i++ ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strncmp(start, socks5_auth_table[i].name, len) == 0) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; socks5_auth_table[i].auth;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    fatal(&lt;font color="#666666"&gt;"Unknown auth method: %s\n"&lt;/font&gt;, start);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_auth_parse"&gt;&lt;/a&gt;int&lt;br /&gt;socks5_auth_parse(char *start, unsigned char *auth_list, int max_auth)&lt;/font&gt;&lt;/strong&gt;{&lt;br /&gt;    char *end;&lt;br /&gt;    int i = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( i &amp;lt; max_auth ) {&lt;br /&gt;        end = strchr(start, ',');&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*start &amp;amp;&amp;amp; end) {&lt;br /&gt;            auth_list[i++] = socks5_auth_parse_1(start, end);&lt;br /&gt;            start = ++end;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *start &amp;amp;&amp;amp; ( i &amp;lt; max_auth ) ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt;( end = start; *end; end++ );&lt;br /&gt;        auth_list[i++] = socks5_auth_parse_1(start, end);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Too much auth method.\n"&lt;/font&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; i;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* begin SOCKS5 relaying&lt;br /&gt;   And no authentication is supported.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="begin_socks5_relay"&gt;&lt;/a&gt;int&lt;br /&gt;begin_socks5_relay( SOCKET s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    unsigned char buf[256], *ptr, *env = socks5_auth;&lt;br /&gt;    unsigned char n_auth = 0; unsigned char auth_list[10], auth_method;&lt;br /&gt;    int len, auth_result, i;&lt;br /&gt;&lt;br /&gt;    debug( &lt;font color="#666666"&gt;"begin_socks_relay()\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* request authentication */&lt;/font&gt;&lt;br /&gt;    ptr = buf;&lt;br /&gt;    PUT_BYTE( ptr++, 5);                        &lt;font color="#B22222"&gt;/* SOCKS version (5) */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;        env = getparam(ENV_SOCKS5_AUTH);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* add no-auth authentication */&lt;/font&gt;&lt;br /&gt;        auth_list[n_auth++] = SOCKS5_AUTH_NOAUTH;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* add user/pass authentication */&lt;/font&gt;&lt;br /&gt;        auth_list[n_auth++] = SOCKS5_AUTH_USERPASS;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        n_auth = socks5_auth_parse(env, auth_list, 10);&lt;br /&gt;    }&lt;br /&gt;    PUT_BYTE( ptr++, n_auth);                   &lt;font color="#B22222"&gt;/* num auth */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;n_auth; i++) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"available auth method[%d] = %s (0x%02x)\n"&lt;/font&gt;,&lt;br /&gt;              i, socks5_getauthname(auth_list[i]), auth_list[i]);&lt;br /&gt;        PUT_BYTE( ptr++, auth_list[i]);         &lt;font color="#B22222"&gt;/* authentications */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    atomic_out( s, buf, ptr-buf );              &lt;font color="#B22222"&gt;/* send requst */&lt;/font&gt;&lt;br /&gt;    atomic_in( s, buf, 2 );                     &lt;font color="#B22222"&gt;/* recv response */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (buf[0] != 5) ||                       &lt;font color="#B22222"&gt;/* ver5 response */&lt;/font&gt;&lt;br /&gt;         (buf[1] == 0xFF) ) {                   &lt;font color="#B22222"&gt;/* check auth method */&lt;/font&gt;&lt;br /&gt;        error(&lt;font color="#666666"&gt;"No auth method accepted.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    auth_method = buf[1];&lt;br /&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"auth method: %s\n"&lt;/font&gt;, socks5_getauthname(auth_method));&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( auth_method ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_REJECT:&lt;br /&gt;        error(&lt;font color="#666666"&gt;"No acceptable authentication method\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_NOAUTH:&lt;br /&gt;        &lt;font color="#B22222"&gt;/* nothing to do */&lt;/font&gt;&lt;br /&gt;        auth_result = 0;&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_USERPASS:&lt;br /&gt;        auth_result = socks5_do_auth_userpass(s);&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;    default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Unsupported authentication method: %s\n"&lt;/font&gt;,&lt;br /&gt;              socks5_getauthname( auth_method ));&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( auth_result != 0 ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Authentication failed.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* request to connect */&lt;/font&gt;&lt;br /&gt;    ptr = buf;&lt;br /&gt;    PUT_BYTE( ptr++, 5);                        &lt;font color="#B22222"&gt;/* SOCKS version (5) */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, 1);                        &lt;font color="#B22222"&gt;/* CMD: CONNECT */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, 0);                        &lt;font color="#B22222"&gt;/* FLG: 0 */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dest_addr.sin_addr.s_addr == 0 ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* resolved by SOCKS server */&lt;/font&gt;&lt;br /&gt;        PUT_BYTE( ptr++, 3);                    &lt;font color="#B22222"&gt;/* ATYP: DOMAINNAME */&lt;/font&gt;&lt;br /&gt;        len = strlen(dest_host);&lt;br /&gt;        PUT_BYTE( ptr++, len);                  &lt;font color="#B22222"&gt;/* DST.ADDR (len) */&lt;/font&gt;&lt;br /&gt;        memcpy( ptr, dest_host, len );          &lt;font color="#B22222"&gt;/* (hostname) */&lt;/font&gt;&lt;br /&gt;        ptr += len;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* resolved localy */&lt;/font&gt;&lt;br /&gt;        PUT_BYTE( ptr++, 1 );                   &lt;font color="#B22222"&gt;/* ATYP: IPv4 */&lt;/font&gt;&lt;br /&gt;        memcpy( ptr, &amp;amp;dest_addr.sin_addr.s_addr, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(dest_addr.sin_addr));&lt;br /&gt;        ptr += &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(dest_addr.sin_addr);&lt;br /&gt;    }&lt;br /&gt;    PUT_BYTE( ptr++, dest_port&amp;gt;&amp;gt;8);     &lt;font color="#B22222"&gt;/* DST.PORT */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, dest_port&amp;amp;0xFF);&lt;br /&gt;    atomic_out( s, buf, ptr-buf);               &lt;font color="#B22222"&gt;/* send request */&lt;/font&gt;&lt;br /&gt;    atomic_in( s, buf, 4 );                     &lt;font color="#B22222"&gt;/* recv response */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (buf[1] != SOCKS5_REP_SUCCEEDED) ) {   &lt;font color="#B22222"&gt;/* check reply code */&lt;/font&gt;&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Got error response from SOCKS server: %d (%s).\n"&lt;/font&gt;,&lt;br /&gt;              buf[1], lookup(buf[1], socks5_rep_names));&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    ptr = buf + 4;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( buf[3] ) {                         &lt;font color="#B22222"&gt;/* case by ATYP */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 1:                                     &lt;font color="#B22222"&gt;/* IP v4 ADDR*/&lt;/font&gt;&lt;br /&gt;        atomic_in( s, ptr, 4+2 );               &lt;font color="#B22222"&gt;/* recv IPv4 addr and port */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 3:                                     &lt;font color="#B22222"&gt;/* DOMAINNAME */&lt;/font&gt;&lt;br /&gt;        atomic_in( s, ptr, 1 );                 &lt;font color="#B22222"&gt;/* recv name and port */&lt;/font&gt;&lt;br /&gt;        atomic_in( s, ptr+1, *(unsigned char*)ptr + 2);&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 4:                                     &lt;font color="#B22222"&gt;/* IP v6 ADDR */&lt;/font&gt;&lt;br /&gt;        atomic_in( s, ptr, 16+2 );              &lt;font color="#B22222"&gt;/* recv IPv6 addr and port */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Conguraturation, connected via SOCKS5 server! */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* begin SOCKS protocol 4 relaying&lt;br /&gt;   And no authentication is supported.&lt;br /&gt;&lt;br /&gt;   There's SOCKS protocol version 4 and 4a. Protocol version&lt;br /&gt;   4a has capability to resolve hostname by SOCKS server, so&lt;br /&gt;   we don't need resolving IP address of destination host on&lt;br /&gt;   local machine.&lt;br /&gt;&lt;br /&gt;   Environment variable SOCKS_RESOLVE directs how to resolve&lt;br /&gt;   IP addess. There's 3 keywords allowed; "local", "remote"&lt;br /&gt;   and "both" (case insensitive). Keyword "local" means taht&lt;br /&gt;   target host name is resolved by localhost resolver&lt;br /&gt;   (usualy with gethostbyname()), "remote" means by remote&lt;br /&gt;   SOCKS server, "both" means to try resolving by localhost&lt;br /&gt;   then remote.&lt;br /&gt;&lt;br /&gt;   SOCKS4 protocol and authentication of SOCKS5 protocol&lt;br /&gt;   requires user name on connect request.&lt;br /&gt;   User name is determined by following method.&lt;br /&gt;&lt;br /&gt;   1. If server spec has user@hostname:port format then&lt;br /&gt;      user part is used for this SOCKS server.&lt;br /&gt;&lt;br /&gt;   2. Get user name from environment variable LOGNAME, USER&lt;br /&gt;      (in this order).&lt;br /&gt;&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="begin_socks4_relay"&gt;&lt;/a&gt;int&lt;br /&gt;begin_socks4_relay( SOCKET s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    unsigned char buf[256], *ptr;&lt;br /&gt;&lt;br /&gt;    debug( &lt;font color="#666666"&gt;"begin_socks_relay()\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* make connect request packet&lt;br /&gt;       protocol v4:&lt;br /&gt;         VN:1, CD:1, PORT:2, ADDR:4, USER:n, NULL:1&lt;br /&gt;       protocol v4a:&lt;br /&gt;         VN:1, CD:1, PORT:2, DUMMY:4, USER:n, NULL:1, HOSTNAME:n, NULL:1&lt;br /&gt;    */&lt;/font&gt;&lt;br /&gt;    ptr = buf;&lt;br /&gt;    PUT_BYTE( ptr++, 4);                        &lt;font color="#B22222"&gt;/* protocol version (4) */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, 1);                        &lt;font color="#B22222"&gt;/* CONNECT command */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, dest_port&amp;gt;&amp;gt;8);     &lt;font color="#B22222"&gt;/* destination Port */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, dest_port&amp;amp;0xFF);&lt;br /&gt;    &lt;font color="#B22222"&gt;/* destination IP */&lt;/font&gt;&lt;br /&gt;    memcpy(ptr, &amp;amp;dest_addr.sin_addr, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(dest_addr.sin_addr));&lt;br /&gt;    ptr += &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(dest_addr.sin_addr);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dest_addr.sin_addr.s_addr == 0 )&lt;br /&gt;        *(ptr-1) = 1;                           &lt;font color="#B22222"&gt;/* fake, protocol 4a */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* username */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_user == NULL)&lt;br /&gt;        fatal( &lt;font color="#666666"&gt;"Cannot determine user name.\n"&lt;/font&gt;);&lt;br /&gt;    strcpy( ptr, relay_user );&lt;br /&gt;    ptr += strlen( relay_user ) +1;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* destination host name (for protocol 4a) */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (socks_version == 4) &amp;amp;&amp;amp; (dest_addr.sin_addr.s_addr == 0)) {&lt;br /&gt;        strcpy( ptr, dest_host );&lt;br /&gt;        ptr += strlen( dest_host ) +1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* send command and get response&lt;br /&gt;       response is: VN:1, CD:1, PORT:2, ADDR:4 */&lt;/font&gt;&lt;br /&gt;    atomic_out( s, buf, ptr-buf);               &lt;font color="#B22222"&gt;/* send request */&lt;/font&gt;&lt;br /&gt;    atomic_in( s, buf, 8 );                     &lt;font color="#B22222"&gt;/* recv response */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (buf[1] != SOCKS4_REP_SUCCEEDED) ) {   &lt;font color="#B22222"&gt;/* check reply code */&lt;/font&gt;&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Got error response: %d: '%s'.\n"&lt;/font&gt;,&lt;br /&gt;              buf[1], lookup(buf[1], socks4_rep_names));&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* failed */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Conguraturation, connected via SOCKS4 server! */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="sendf"&gt;&lt;/a&gt;int&lt;br /&gt;sendf(SOCKET s, const char *fmt,...)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static char buf[10240];                     &lt;font color="#B22222"&gt;/* xxx, enough? */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start( args, fmt );&lt;br /&gt;    vsnprintf( buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf), fmt, args );&lt;br /&gt;    va_end( args );&lt;br /&gt;&lt;br /&gt;    report_text(&lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt;"&lt;/font&gt;, buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( send(s, buf, strlen(buf), 0) == SOCKET_ERROR ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"failed to send http request. errno=%d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;const char *base64_table =&lt;br /&gt;&lt;font color="#666666"&gt;"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="make_base64_string"&gt;&lt;/a&gt;char *&lt;br /&gt;make_base64_string(const char *str)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static char *buf;&lt;br /&gt;    unsigned char *src;&lt;br /&gt;    char *dst;&lt;br /&gt;    int bits, data, src_len, dst_len;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* make base64 string */&lt;/font&gt;&lt;br /&gt;    src_len = strlen(str);&lt;br /&gt;    dst_len = (src_len+2)/3*4;&lt;br /&gt;    buf = xmalloc(dst_len+1);&lt;br /&gt;    bits = data = 0;&lt;br /&gt;    src = (unsigned char *)str;&lt;br /&gt;    dst = (unsigned char *)buf;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( dst_len-- ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( bits &amp;lt; 6 ) {&lt;br /&gt;            data = (data &amp;lt;&amp;lt; 8) | *src;&lt;br /&gt;            bits += 8;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *src != 0 )&lt;br /&gt;                src++;&lt;br /&gt;        }&lt;br /&gt;        *dst++ = base64_table[0x3F &amp;amp; (data &amp;gt;&amp;gt; (bits-6))];&lt;br /&gt;        bits -= 6;&lt;br /&gt;    }&lt;br /&gt;    *dst = '\0';&lt;br /&gt;    &lt;font color="#B22222"&gt;/* fix-up tail padding */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( src_len%3 ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 1:&lt;br /&gt;        *--dst = '=';&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 2:&lt;br /&gt;        *--dst = '=';&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="basic_auth"&gt;&lt;/a&gt;int&lt;br /&gt;basic_auth (SOCKET s)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *userpass;&lt;br /&gt;    char *cred;&lt;br /&gt;    const char *user = relay_user;&lt;br /&gt;    char *pass = NULL;&lt;br /&gt;    int len, ret;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Get username/password for authentication */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot decide username for proxy authentication."&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ((pass = determine_relay_password ()) == NULL &amp;amp;&amp;amp;&lt;br /&gt;        (pass = readpass(&lt;font color="#666666"&gt;"Enter proxy authentication password for %s@%s: "&lt;/font&gt;,&lt;br /&gt;                         relay_user, relay_host)) == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot decide password for proxy authentication."&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    len = strlen(user)+strlen(pass)+1;&lt;br /&gt;    userpass = xmalloc(len+1);&lt;br /&gt;    snprintf(userpass, len+1, &lt;font color="#666666"&gt;"%s:%s"&lt;/font&gt;, user, pass);&lt;br /&gt;    memset (pass, 0, strlen(pass));&lt;br /&gt;    cred = make_base64_string(userpass);&lt;br /&gt;    memset (userpass, 0, len);&lt;br /&gt;&lt;br /&gt;    f_report = 0;                               &lt;font color="#B22222"&gt;/* don't report for security */&lt;/font&gt;&lt;br /&gt;    ret = sendf(s, &lt;font color="#666666"&gt;"Proxy-Authorization: Basic %s\r\n"&lt;/font&gt;, cred);&lt;br /&gt;    f_report = 1;&lt;br /&gt;    report_text(&lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt;"&lt;/font&gt;, &lt;font color="#666666"&gt;"Proxy-Authorization: Basic xxxxx\r\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    memset(cred, 0, strlen(cred));&lt;br /&gt;    free(cred);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* begin relaying via HTTP proxy&lt;br /&gt;   Directs CONNECT method to proxy server to connect to&lt;br /&gt;   destination host (and port). It may not be allowed on your&lt;br /&gt;   proxy server.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="begin_http_relay"&gt;&lt;/a&gt;int&lt;br /&gt;begin_http_relay( SOCKET s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char buf[1024];&lt;br /&gt;    int result;&lt;br /&gt;    char *auth_what;&lt;br /&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"begin_http_relay()\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (sendf(s,&lt;font color="#666666"&gt;"CONNECT %s:%d HTTP/1.0\r\n"&lt;/font&gt;, dest_host, dest_port) &amp;lt; 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (proxy_auth_type == PROXY_AUTH_BASIC &amp;amp;&amp;amp; basic_auth (s) &amp;lt; 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (sendf(s,&lt;font color="#666666"&gt;"\r\n"&lt;/font&gt;) &amp;lt; 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* get response */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( line_input(s, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf)) &amp;lt; 0 ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"failed to read http response.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check status */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!strchr(buf, ' ')) {&lt;br /&gt;        error (&lt;font color="#666666"&gt;"Unexpected http response: '%s'.\n"&lt;/font&gt;, buf);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;    }&lt;br /&gt;    result = atoi(strchr(buf,' '));&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( result ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 200:&lt;br /&gt;        &lt;font color="#B22222"&gt;/* Conguraturation, connected via http proxy server! */&lt;/font&gt;&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"connected, start user session.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 302:                                   &lt;font color="#B22222"&gt;/* redirect */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;do&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (line_input(s, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf)))&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            downcase(buf);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (expect(buf, &lt;font color="#666666"&gt;"Location: "&lt;/font&gt;)) {&lt;br /&gt;                relay_host = cut_token(buf, &lt;font color="#666666"&gt;"//"&lt;/font&gt;);&lt;br /&gt;                cut_token(buf, &lt;font color="#666666"&gt;"/"&lt;/font&gt;);&lt;br /&gt;                relay_port = atoi(cut_token(buf, &lt;font color="#666666"&gt;":"&lt;/font&gt;));&lt;br /&gt;            }&lt;br /&gt;        } &lt;font color="#4169E1"&gt;while&lt;/font&gt; (strcmp(buf,&lt;font color="#666666"&gt;"\r\n"&lt;/font&gt;) != 0);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_RETRY;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* We handle both 401 and 407 codes here: 401 is WWW-Authenticate, which&lt;br /&gt;     * not strictly the correct response, but some proxies do send this (e.g.&lt;br /&gt;     * Symantec's Raptor firewall) */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 401:                                   &lt;font color="#B22222"&gt;/* WWW-Auth required */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; 407:                                   &lt;font color="#B22222"&gt;/* Proxy-Auth required */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/** NOTE: As easy implementation, we support only BASIC scheme&lt;br /&gt;            and ignore realm. */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* If proxy_auth_type is PROXY_AUTH_BASIC and get&lt;br /&gt;         this result code, authentication was failed. */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (proxy_auth_type != PROXY_AUTH_NONE) {&lt;br /&gt;            error(&lt;font color="#666666"&gt;"Authentication failed.\n"&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;        }&lt;br /&gt;        auth_what = (result == 401) ? &lt;font color="#666666"&gt;"WWW-Authenticate:"&lt;/font&gt; : &lt;font color="#666666"&gt;"Proxy-Authenticate:"&lt;/font&gt;;&lt;br /&gt;        &lt;font color="#4169E1"&gt;do&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( line_input(s, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf)) ) {&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;            downcase(buf);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (expect(buf, auth_what)) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* parse type and realm */&lt;/font&gt;&lt;br /&gt;                char *scheme, *realm;&lt;br /&gt;                scheme = cut_token(buf, &lt;font color="#666666"&gt;" "&lt;/font&gt;);&lt;br /&gt;                realm = cut_token(scheme, &lt;font color="#666666"&gt;" "&lt;/font&gt;);&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( scheme == NULL || realm == NULL ) {&lt;br /&gt;                    debug(&lt;font color="#666666"&gt;"Invalid format of %s field."&lt;/font&gt;, auth_what);&lt;br /&gt;                    &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;         &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#B22222"&gt;/* check supported auth type */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; (expect(scheme, &lt;font color="#666666"&gt;"basic"&lt;/font&gt;)) {&lt;br /&gt;                    proxy_auth_type = PROXY_AUTH_BASIC;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    debug(&lt;font color="#666666"&gt;"Unsupported authentication type: %s"&lt;/font&gt;, scheme);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        } &lt;font color="#4169E1"&gt;while&lt;/font&gt; (strcmp(buf,&lt;font color="#666666"&gt;"\r\n"&lt;/font&gt;) != 0);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( proxy_auth_type == PROXY_AUTH_NONE ) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"Can't find %s in response header."&lt;/font&gt;, auth_what);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_RETRY;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;    default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* Not allowed */&lt;/font&gt;&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"http proxy is not allowed.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* skip to end of response header */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;do&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( line_input(s, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf) ) ) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"Can't skip response headers\n"&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( strcmp(buf,&lt;font color="#666666"&gt;"\r\n"&lt;/font&gt;) != 0 );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_OK;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* begin relaying via TELNET proxy.&lt;br /&gt;   Sends string specified by telnet_command (-c option) with&lt;br /&gt;   replacing host name and port number to the socket.  */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="begin_telnet_relay"&gt;&lt;/a&gt;int&lt;br /&gt;begin_telnet_relay( SOCKET s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char buf[1024];&lt;br /&gt;    char *cmd;&lt;br /&gt;    char *good_phrase = &lt;font color="#666666"&gt;"connected to"&lt;/font&gt;;&lt;br /&gt;    char *bad_phrase_list[] = {&lt;br /&gt;        &lt;font color="#666666"&gt;" failed"&lt;/font&gt;, &lt;font color="#666666"&gt;" refused"&lt;/font&gt;, &lt;font color="#666666"&gt;" rejected"&lt;/font&gt;, &lt;font color="#666666"&gt;" closed"&lt;/font&gt;&lt;br /&gt;    };&lt;br /&gt;    char sep = ' ';&lt;br /&gt;    int i;&lt;br /&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"begin_telnet_relay()\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* report phrase */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"good phrase: '%s'\n"&lt;/font&gt;, good_phrase);&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"bad phrases"&lt;/font&gt;);&lt;br /&gt;    sep = ':';&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt; (&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(bad_phrase_list) / &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(char*)); i++) {&lt;br /&gt;        debug_(&lt;font color="#666666"&gt;"%c '%s'"&lt;/font&gt;, sep, bad_phrase_list[i]);&lt;br /&gt;        sep = ',';&lt;br /&gt;    }&lt;br /&gt;    debug_(&lt;font color="#666666"&gt;"\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* make request string with replacing %h by destination hostname&lt;br /&gt;       and %p by port number, etc. */&lt;/font&gt;&lt;br /&gt;    cmd = expand_host_and_port(telnet_command, dest_host, dest_port);&lt;br /&gt;    &lt;br /&gt;    &lt;font color="#B22222"&gt;/* Sorry, we send request string now without waiting a prompt. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (sendf(s, &lt;font color="#666666"&gt;"%s\r\n"&lt;/font&gt;, cmd) &amp;lt; 0) {&lt;br /&gt;        free(cmd);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;    }&lt;br /&gt;    free(cmd);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Process answer from proxy until good or bad phrase is detected.  We&lt;br /&gt;       assume that the good phrase should be appeared only in the final&lt;br /&gt;       line of proxy responses. Bad keywods in the line causes operation&lt;br /&gt;       fail. First checks a good phrase, then checks bad phrases.&lt;br /&gt;       If no match, continue reading line from proxy. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (!line_input(s, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf)) &amp;amp;&amp;amp; buf[0] != '\0') {&lt;br /&gt;        downcase(buf);&lt;br /&gt;        &lt;font color="#B22222"&gt;/* first, check good phrase */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (strstr(buf, good_phrase)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"good phrase is detected: '%s'\n"&lt;/font&gt;, good_phrase);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_OK;&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#B22222"&gt;/* then, check bad phrase */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;(&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(bad_phrase_list)/&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(char*)); i++) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (strstr(buf, bad_phrase_list[i]) != NULL) {&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"bad phrase is detected: '%s'\n"&lt;/font&gt;, bad_phrase_list[i]);&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"error reading from telnet proxy\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; START_ERROR;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* ddatalen()&lt;br /&gt;   Returns 1 if data is available, otherwise return 0&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="stdindatalen"&gt;&lt;/a&gt;int&lt;br /&gt;stdindatalen (void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    DWORD len = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct stat&lt;/font&gt; st;&lt;br /&gt;    fstat( 0, &amp;amp;st );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( st.st_mode &amp;amp; _S_IFIFO ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* in case of PIPE */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !PeekNamedPipe( GetStdHandle(STD_INPUT_HANDLE),&lt;br /&gt;                             NULL, 0, NULL, &amp;amp;len, NULL) ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( GetLastError() == ERROR_BROKEN_PIPE ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* PIPE source is closed */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#B22222"&gt;/* read() will detects EOF */&lt;/font&gt;&lt;br /&gt;                len = 1;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                fatal(&lt;font color="#666666"&gt;"PeekNamedPipe() failed, errno=%d\n"&lt;/font&gt;,&lt;br /&gt;                      GetLastError());&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( st.st_mode &amp;amp; _S_IFREG ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* in case of regular file (redirected) */&lt;/font&gt;&lt;br /&gt;        len = 1;                        &lt;font color="#B22222"&gt;/* always data ready */&lt;/font&gt;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( _kbhit() ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* in case of console */&lt;/font&gt;&lt;br /&gt;        len = 1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; len;&lt;br /&gt;}&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* relay byte from stdin to socket and fro socket to stdout.&lt;br /&gt;   returns reason of termination */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="do_repeater"&gt;&lt;/a&gt;int&lt;br /&gt;do_repeater( SOCKET local_in, SOCKET local_out, SOCKET remote )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#B22222"&gt;/** vars for local input data **/&lt;/font&gt;&lt;br /&gt;    char lbuf[1024];                            &lt;font color="#B22222"&gt;/* local input buffer */&lt;/font&gt;&lt;br /&gt;    int lbuf_len;                               &lt;font color="#B22222"&gt;/* available data in lbuf */&lt;/font&gt;&lt;br /&gt;    int f_local;                                &lt;font color="#B22222"&gt;/* read local input more? */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/** vars for remote input data **/&lt;/font&gt;&lt;br /&gt;    char rbuf[1024];                            &lt;font color="#B22222"&gt;/* remote input buffer */&lt;/font&gt;&lt;br /&gt;    int rbuf_len;                               &lt;font color="#B22222"&gt;/* available data in rbuf */&lt;/font&gt;&lt;br /&gt;    int f_remote;                               &lt;font color="#B22222"&gt;/* read remote input more? */&lt;/font&gt;&lt;br /&gt;    int close_reason = REASON_UNK;              &lt;font color="#B22222"&gt;/* reason of end repeating */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/** other variables **/&lt;/font&gt;&lt;br /&gt;    int nfds, len;&lt;br /&gt;    fd_set ifds, ofds;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct timeval&lt;/font&gt; *tmo;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct timeval&lt;/font&gt; win32_tmo;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* repeater between stdin/out and socket  */&lt;/font&gt;&lt;br /&gt;    nfds = ((local_in&amp;lt;remote)? remote: local_in) +1;&lt;br /&gt;    f_local = 1;                                &lt;font color="#B22222"&gt;/* yes, read from local */&lt;/font&gt;&lt;br /&gt;    f_remote = 1;                               &lt;font color="#B22222"&gt;/* yes, read from remote */&lt;/font&gt;&lt;br /&gt;    lbuf_len = 0;&lt;br /&gt;    rbuf_len = 0;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( f_local || f_remote ) {&lt;br /&gt;        FD_ZERO(&amp;amp;ifds );&lt;br /&gt;        FD_ZERO(&amp;amp;ofds );&lt;br /&gt;        tmo = NULL;&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/** prepare for reading local input **/&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( f_local &amp;amp;&amp;amp; (lbuf_len &amp;lt; (int)&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(lbuf)) ) {&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( local_type != LOCAL_SOCKET ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* select() on Winsock is not accept standard handle.&lt;br /&gt;                   So use select() with short timeout and checking data&lt;br /&gt;                   in stdin by another method. */&lt;/font&gt;&lt;br /&gt;                win32_tmo.tv_sec = 0;&lt;br /&gt;                win32_tmo.tv_usec = 10*1000;    &lt;font color="#B22222"&gt;/* 10 ms */&lt;/font&gt;&lt;br /&gt;                tmo = &amp;amp;win32_tmo;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;            FD_SET( local_in, &amp;amp;ifds );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/** prepare for reading remote input **/&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( f_remote &amp;amp;&amp;amp; (rbuf_len &amp;lt; (int)&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(rbuf)) ) {&lt;br /&gt;            FD_SET( remote, &amp;amp;ifds );&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* FD_SET( local_out, ofds ); */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* FD_SET( remote, ofds ); */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( select( nfds, &amp;amp;ifds, &amp;amp;ofds, (fd_set*)NULL, tmo ) == -1 ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* some error */&lt;/font&gt;&lt;br /&gt;            error( &lt;font color="#666666"&gt;"select() failed, %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; REASON_ERROR;&lt;br /&gt;        }&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* fake ifds if local is stdio handle because&lt;br /&gt;           select() of Winsock does not accept stdio&lt;br /&gt;           handle. */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (f_local &amp;amp;&amp;amp; (local_type!=LOCAL_SOCKET) &amp;amp;&amp;amp; (0&amp;lt;stdindatalen()))&lt;br /&gt;            FD_SET(0,&amp;amp;ifds);            &lt;font color="#B22222"&gt;/* data ready */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* remote =&amp;gt; local */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( FD_ISSET(remote, &amp;amp;ifds) &amp;amp;&amp;amp; (rbuf_len &amp;lt; (int)&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(rbuf)) ) {&lt;br /&gt;            len = recv( remote, rbuf + rbuf_len, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(rbuf)-rbuf_len, 0);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == 0 || (len == -1 &amp;amp;&amp;amp; socket_errno() == ECONNRESET)) {&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"connection %s by peer\n"&lt;/font&gt;,&lt;br /&gt;                      (len==0)? &lt;font color="#666666"&gt;"closed"&lt;/font&gt;: &lt;font color="#666666"&gt;"reset"&lt;/font&gt;);&lt;br /&gt;                close_reason = REASON_CLOSED_BY_REMOTE;&lt;br /&gt;                f_remote = 0;                   &lt;font color="#B22222"&gt;/* no more read from socket */&lt;/font&gt;&lt;br /&gt;                f_local = 0;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* error */&lt;/font&gt;&lt;br /&gt;                fatal(&lt;font color="#666666"&gt;"recv() failed, %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"recv %d bytes\n"&lt;/font&gt;, len);&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; f_debug )              &lt;font color="#B22222"&gt;/* more verbose */&lt;/font&gt;&lt;br /&gt;                    report_bytes( &lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt;"&lt;/font&gt;, rbuf+rbuf_len, len);&lt;br /&gt;                rbuf_len += len;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* local =&amp;gt; remote */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( FD_ISSET(local_in, &amp;amp;ifds) &amp;amp;&amp;amp; (lbuf_len &amp;lt; (int)&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(lbuf)) ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (local_type == LOCAL_SOCKET)&lt;br /&gt;                len = recv(local_in, lbuf + lbuf_len,&lt;br /&gt;                           &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(lbuf)-lbuf_len, 0);&lt;br /&gt;            &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                len = read(local_in, lbuf + lbuf_len, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(lbuf)-lbuf_len);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == 0 ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* stdin is EOF */&lt;/font&gt;&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"local input is EOF\n"&lt;/font&gt;);&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!f_hold_session)&lt;br /&gt;                    shutdown(remote, 1);        &lt;font color="#B22222"&gt;/* no-more writing */&lt;/font&gt;&lt;br /&gt;                f_local = 0;&lt;br /&gt;                close_reason = REASON_CLOSED_BY_LOCAL;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* error on reading from stdin */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; (f_hold_session) {&lt;br /&gt;                    debug (&lt;font color="#666666"&gt;"failed to read from local\n"&lt;/font&gt;);&lt;br /&gt;                    f_local = 0;&lt;br /&gt;                    close_reason = REASON_CLOSED_BY_LOCAL;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                    fatal(&lt;font color="#666666"&gt;"recv() failed, errno = %d\n"&lt;/font&gt;, errno);&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* repeat */&lt;/font&gt;&lt;br /&gt;                lbuf_len += len;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* flush data in buffer to socket */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; lbuf_len ) {&lt;br /&gt;            len = send(remote, lbuf, lbuf_len, 0);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 ) {&lt;br /&gt;                fatal(&lt;font color="#666666"&gt;"send() failed, %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; len ) {&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; f_debug )              &lt;font color="#B22222"&gt;/* more verbose */&lt;/font&gt;&lt;br /&gt;                    report_bytes( &lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt;"&lt;/font&gt;, lbuf, len);&lt;br /&gt;                &lt;font color="#B22222"&gt;/* move data on to top of buffer */&lt;/font&gt;&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"sent %d bytes\n"&lt;/font&gt;, len);&lt;br /&gt;                lbuf_len -= len;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; lbuf_len )&lt;br /&gt;                    memcpy( lbuf, lbuf+len, lbuf_len );&lt;br /&gt;                assert( 0 &amp;lt;= lbuf_len );&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* flush data in buffer to local output */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; rbuf_len ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (local_type == LOCAL_SOCKET)&lt;br /&gt;                len = send( local_out, rbuf, rbuf_len, 0);&lt;br /&gt;            &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                len = write( local_out, rbuf, rbuf_len);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 ) {&lt;br /&gt;                fatal(&lt;font color="#666666"&gt;"output (local) failed, errno=%d\n"&lt;/font&gt;, errno);&lt;br /&gt;            }&lt;br /&gt;            rbuf_len -= len;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len &amp;lt; rbuf_len )&lt;br /&gt;                memcpy( rbuf, rbuf+len, rbuf_len );&lt;br /&gt;            assert( 0 &amp;lt;= rbuf_len );&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (f_local == 0 &amp;amp;&amp;amp; f_hold_session) {&lt;br /&gt;            debug (&lt;font color="#666666"&gt;"closing local port without disconnecting from remote\n"&lt;/font&gt;);&lt;br /&gt;            f_remote = 0;&lt;br /&gt;            shutdown (local_out, 2);&lt;br /&gt;            close (local_out);&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; close_reason;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="accept_connection"&gt;&lt;/a&gt;int&lt;br /&gt;accept_connection (u_short port)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static int sock = -1;&lt;br /&gt;    int connection;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct sockaddr_in&lt;/font&gt; name;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct sockaddr&lt;/font&gt; client;&lt;br /&gt;    int socklen;&lt;br /&gt;    fd_set ifds;&lt;br /&gt;    int nfds;&lt;br /&gt;    int sockopt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Create the socket. */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"Creating source port to forward.\n"&lt;/font&gt;);&lt;br /&gt;    sock = socket (PF_INET, SOCK_STREAM, 0);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (sock &amp;lt; 0)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"socket() failed, errno=%d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;    sockopt = 1;&lt;br /&gt;    setsockopt (sock, SOL_SOCKET, SO_REUSEADDR,&lt;br /&gt;                (void*)&amp;amp;sockopt, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(sockopt));&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Give the socket a name. */&lt;/font&gt;&lt;br /&gt;    name.sin_family = AF_INET;&lt;br /&gt;    name.sin_port = htons (port);&lt;br /&gt;    name.sin_addr.s_addr = htonl (INADDR_ANY);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (bind (sock, (&lt;font color="#4169E1"&gt;struct sockaddr&lt;/font&gt; *) &amp;amp;name, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt; (name)) &amp;lt; 0)&lt;br /&gt;        fatal (&lt;font color="#666666"&gt;"bind() failed, errno=%d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (listen( sock, 1) &amp;lt; 0)&lt;br /&gt;        fatal (&lt;font color="#666666"&gt;"listen() failed, errno=%d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* wait for new connection with watching EOF of stdin. */&lt;/font&gt;&lt;br /&gt;    debug (&lt;font color="#666666"&gt;"waiting new connection at port %d (socket=%d)\n"&lt;/font&gt;, port, sock);&lt;br /&gt;    nfds = sock + 1;&lt;br /&gt;    &lt;font color="#4169E1"&gt;do&lt;/font&gt; {&lt;br /&gt;        int n;&lt;br /&gt;        &lt;font color="#4169E1"&gt;struct timeval&lt;/font&gt; *ptmo = NULL;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;struct timeval&lt;/font&gt; tmo;&lt;br /&gt;        tmo.tv_sec = 0;&lt;br /&gt;        tmo.tv_usec = 100*1000;                 &lt;font color="#B22222"&gt;/* On Windows, 100ms timeout */&lt;/font&gt;&lt;br /&gt;        ptmo = &amp;amp;tmo;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;        FD_ZERO (&amp;amp;ifds);&lt;br /&gt;        FD_SET ((SOCKET)sock, &amp;amp;ifds);&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;        FD_SET (0, &amp;amp;ifds);                      &lt;font color="#B22222"&gt;/* watch stdin */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;        n = select (nfds, &amp;amp;ifds, NULL, NULL, ptmo);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (n == -1) {&lt;br /&gt;            fatal (&lt;font color="#666666"&gt;"select() failed, %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;            exit (1);&lt;br /&gt;        }&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (0 &amp;lt; stdindatalen()) {&lt;br /&gt;            FD_SET (0, &amp;amp;ifds);          &lt;font color="#B22222"&gt;/* fake */&lt;/font&gt;&lt;br /&gt;            n++;&lt;br /&gt;        }&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (0 &amp;lt; n) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (FD_ISSET(0, &amp;amp;ifds) &amp;amp;&amp;amp; (getchar() &amp;lt;= 0)) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* EOF */&lt;/font&gt;&lt;br /&gt;                debug (&lt;font color="#666666"&gt;"Give-up waiting port because stdin is closed."&lt;/font&gt;);&lt;br /&gt;                exit(0);&lt;br /&gt;            }&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (FD_ISSET(sock, &amp;amp;ifds))&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;                          &lt;font color="#B22222"&gt;/* socket is stimulated */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;while&lt;/font&gt; (1);&lt;br /&gt;    socklen = &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(client);&lt;br /&gt;    connection = accept( sock, &amp;amp;client, &amp;amp;socklen);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( connection &amp;lt; 0 )&lt;br /&gt;        fatal (&lt;font color="#666666"&gt;"accept() failed, errno=%d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; connection;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** Main of program **/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="main"&gt;&lt;/a&gt;int&lt;br /&gt;main( int argc, char **argv )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int ret;&lt;br /&gt;    int remote;                                 &lt;font color="#B22222"&gt;/* socket */&lt;/font&gt;&lt;br /&gt;    int local_in;                               &lt;font color="#B22222"&gt;/* Local input */&lt;/font&gt;&lt;br /&gt;    int local_out;                              &lt;font color="#B22222"&gt;/* Local output */&lt;/font&gt;&lt;br /&gt;    int reason;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;    WSADATA wsadata;&lt;br /&gt;    WSAStartup( 0x101, &amp;amp;wsadata);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* initialization */&lt;/font&gt;&lt;br /&gt;    make_revstr();&lt;br /&gt;    getarg( argc, argv );&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"Program is $Revision: 100 $\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Open local_in and local_out if forwarding a port */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( local_type == LOCAL_SOCKET ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* Relay between local port and destination */&lt;/font&gt;&lt;br /&gt;        local_in = local_out = accept_connection( local_port );&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* Relay between stdin/stdout and desteination */&lt;/font&gt;&lt;br /&gt;        local_in = 0;&lt;br /&gt;        local_out = 1;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;        _setmode(local_in, O_BINARY);&lt;br /&gt;        _setmode(local_out, O_BINARY);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;retry:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (0 &amp;lt; connect_timeout)&lt;br /&gt;        set_timeout (connect_timeout);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (check_direct(dest_host))&lt;br /&gt;        relay_method = METHOD_DIRECT;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* make connection */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_DIRECT ) {&lt;br /&gt;        remote = open_connection (dest_host, dest_port);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( remote == SOCKET_ERROR )&lt;br /&gt;            fatal( &lt;font color="#666666"&gt;"Unable to connect to destination host, errno=%d\n"&lt;/font&gt;,&lt;br /&gt;                   socket_errno());&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        remote = open_connection (relay_host, relay_port);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( remote == SOCKET_ERROR )&lt;br /&gt;            fatal( &lt;font color="#666666"&gt;"Unable to connect to relay host, errno=%d\n"&lt;/font&gt;,&lt;br /&gt;                   socket_errno());&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/** resolve destination host (SOCKS) **/&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (socks_ns.sin_addr.s_addr != 0)&lt;br /&gt;        switch_ns (&amp;amp;socks_ns);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_method == METHOD_SOCKS &amp;amp;&amp;amp;&lt;br /&gt;        socks_resolve == RESOLVE_LOCAL &amp;amp;&amp;amp;&lt;br /&gt;        local_resolve (dest_host, &amp;amp;dest_addr) &amp;lt; 0) {&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Unknown host: %s"&lt;/font&gt;, dest_host);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/** relay negociation **/&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( relay_method ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_SOCKS:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ((socks_version == 5) &amp;amp;&amp;amp; (begin_socks5_relay(remote) &amp;lt; 0)) ||&lt;br /&gt;             ((socks_version == 4) &amp;amp;&amp;amp; (begin_socks4_relay(remote) &amp;lt; 0)) )&lt;br /&gt;            fatal( &lt;font color="#666666"&gt;"failed to begin relaying via SOCKS.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_HTTP:&lt;br /&gt;        ret = begin_http_relay(remote);&lt;br /&gt;        &lt;font color="#4169E1"&gt;switch&lt;/font&gt; (ret) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; START_ERROR:&lt;br /&gt;            close (remote);&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"failed to begin relaying via HTTP.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; START_OK:&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; START_RETRY:&lt;br /&gt;            &lt;font color="#B22222"&gt;/* retry with authentication */&lt;/font&gt;&lt;br /&gt;            close (remote);&lt;br /&gt;            &lt;font color="#4169E1"&gt;goto&lt;/font&gt; retry;&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_TELNET:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (begin_telnet_relay(remote) &amp;lt; 0)&lt;br /&gt;             fatal(&lt;font color="#666666"&gt;"failed to begin relaying via telnet.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"connected\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (0 &amp;lt; connect_timeout)&lt;br /&gt;        set_timeout (0);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* main loop */&lt;/font&gt;&lt;br /&gt;    debug (&lt;font color="#666666"&gt;"start relaying.\n"&lt;/font&gt;);&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;do_repeater:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;    reason = do_repeater(local_in, local_out, remote);&lt;br /&gt;    debug (&lt;font color="#666666"&gt;"relaying done.\n"&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (local_type == LOCAL_SOCKET &amp;amp;&amp;amp;&lt;br /&gt;        reason == REASON_CLOSED_BY_LOCAL &amp;amp;&amp;amp;&lt;br /&gt;        f_hold_session) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* re-wait at local port without closing remote session */&lt;/font&gt;&lt;br /&gt;        debug (&lt;font color="#666666"&gt;"re-waiting at local port %d\n"&lt;/font&gt;, local_port);&lt;br /&gt;        local_in = local_out = accept_connection( local_port );&lt;br /&gt;        debug (&lt;font color="#666666"&gt;"re-start relaying\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; do_repeater;&lt;br /&gt;    }&lt;br /&gt;    closesocket(remote);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( local_type == LOCAL_SOCKET)&lt;br /&gt;        closesocket(local_in);&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;    WSACleanup();&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;    debug (&lt;font color="#666666"&gt;"that's all, bye.\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* ------------------------------------------------------------&lt;br /&gt;   Local Variables:&lt;br /&gt;   compile-command: "cc connect.c -o connect"&lt;br /&gt;   tab-width: 8&lt;br /&gt;   fill-column: 74&lt;br /&gt;   comment-column: 48&lt;br /&gt;   End:&lt;br /&gt;   ------------------------------------------------------------ */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/*** end of connect.c ***/&lt;/font&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-1543473577966074346?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/1543473577966074346/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/11/use-git-behind-proxy.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1543473577966074346'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/1543473577966074346'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/11/use-git-behind-proxy.html' title='Use git behind a proxy'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-8100323022385389190</id><published>2008-11-17T23:37:00.000-08:00</published><updated>2009-04-28T08:06:30.294-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='BSFS'/><title type='text'>FTL</title><content type='html'>Most of the following conclusions are taken from Intel's "&lt;a href="http://www.embeddedfreebsd.org/Documents/Intel-FTL.pdf"&gt;Understanding the Flash Translation Layer (FTL) Specification&lt;/a&gt;".&lt;br /&gt;&lt;br /&gt;Note: the problem of FTL is that it has no idea about the contents that it handles. Thus when it stores something, it has to find a new place instead of appending to the original place.&lt;br /&gt;&lt;br /&gt;FTL is the driver that works in conjunction with an existing operating system (or, in some embedded applications, as the operating system) to make linear flash memory appear to the system like a disk drive. First, it creates “virtual” small blocks of data, or sectors, out of flash’s large erase blocks. Next, it manages data on the flash so that it appears to be “write in place” when in fact it is being stored in different spots in the flash. Finally, FTL manages the flash so there are clean/erased places to store data.&lt;br /&gt;&lt;br /&gt;Basically, FTL does one thing: read the block data from the file system, write it at a free/erased location on the flash media and invalidates the block that previously contained the block's data.&lt;br /&gt;&lt;br /&gt;For Intel NOR flash, Erased state is 1, programmed state is 0, a 0 cannot be changed back to a 1 except by an erase, and an erase must occur on a full erase block.&lt;br /&gt;&lt;br /&gt;The main weakness of a FTL is that it has no idea of what part of an erase block belong to the same file. Thus leads to massive obslated blocks and more often garbage collection. The introduction of SATA 3.0 interface can solve this problem, with the new TRIM command which tells the underlying FTL which blocks are no longer being used and can be erased in garbage collection.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-8100323022385389190?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/8100323022385389190/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/11/designing-and-writing-bsfs2-ftl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8100323022385389190'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/8100323022385389190'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/11/designing-and-writing-bsfs2-ftl.html' title='FTL'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-238436570314696921</id><published>2008-11-13T19:24:00.000-08:00</published><updated>2009-04-28T08:04:05.120-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><category scheme='http://www.blogger.com/atom/ns#' term='BSFS'/><title type='text'>Flash limitations</title><content type='html'>As stated in the &lt;a href="http://lazybastard.org/~joern/logfs1.pdf"&gt;paper&lt;/a&gt; of Jorn Engel's(author of logfs), flash device has some limitations to be a storage device.&lt;br /&gt;1. Flash requires out of place updates of existing data. Before being&lt;br /&gt;able to write to a specific location, that erase block has to be&lt;br /&gt;erased. After being erased, all bits are set to 1. An unclean&lt;br /&gt;unmount at this time will cause data loss, as neither the old nor&lt;br /&gt;the new data can be retrieved.&lt;br /&gt;Notes: which means, transaction writes is a must.&lt;br /&gt;&lt;br /&gt;2. Lifetime of flash erase blocks is limited by the number of erase cycles on them. Hardware manufacturers usually guarantee 100.000&lt;br /&gt;erase cycles. This number is per individual erase block.&lt;br /&gt;Notes: in-memory superblock or dynamic superblock? balanced writes.&lt;br /&gt;&lt;br /&gt;3. Erase blocks are significantly larger than hard disk sectors or&lt;br /&gt;filesystem blocks. Therefore, erase blocks must be shared by&lt;br /&gt;several filesystem blocks. During operation, erase blocks get par-&lt;br /&gt;tially obsoleted and require garbage collection to free space. &lt;br /&gt;Notes: GC is only one of the ways to solve this problem...&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-238436570314696921?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/238436570314696921/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/11/designing-and-writing-bsfs2-flash.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/238436570314696921'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/238436570314696921'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/11/designing-and-writing-bsfs2-flash.html' title='Flash limitations'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-5489690614387150172</id><published>2008-10-20T00:22:00.000-07:00</published><updated>2008-10-20T00:35:01.156-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>NGFS: From ext4 to btrfs</title><content type='html'>In a mail Ted sent to LKML, he described the core filesystem developers' plan for the future: ext4 as interim step to btrfs[1].&lt;br /&gt;&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 0px; padding: 6px; overflow: auto; width: 600px; height: 1000px; text-align: left;"&gt;From: &lt;span style="font-size:120%;"&gt;Theodore Tso&lt;br /&gt;Subject: Re: [RFC] Btrfs mainline plans&lt;br /&gt;Newsgroups: gmane.linux.file-systems, gmane.linux.kernel, gmane.comp.file-systems.ext4&lt;br /&gt;Date: 2008-10-10 03:01:31 GMT&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;As far as ext4 is concerned, being in the mainline was all upside, and&lt;br /&gt;I believe that having in the kernel *did* accelerate its progress.  It&lt;br /&gt;meant that kernel-wide API changes were applied automatically, and it&lt;br /&gt;meant that kernel developers who wanted to try out ext4 could do so&lt;br /&gt;quite easily.  Yes, in the past two releases I started maintaining&lt;br /&gt;patchsets against a stable kernel; this was mainly to support those&lt;br /&gt;users who didn't want to follow the latest git releases --- and that&lt;br /&gt;was a reflection that ext4 was mature enough that there were stable&lt;br /&gt;kernel users who were interested in using ext4.  I could have used the&lt;br /&gt;-stable infrastructure, but ext4 was changing so rapidly that it was&lt;br /&gt;easier just to maintain a full patchset.  As a matter of fact,&lt;br /&gt;starting with 2.6.27, given that we'll be renaming ext4dev to ext4 in&lt;br /&gt;the 2.6.28 mergeset, the plan is that we'll be submitting patches to&lt;br /&gt;the -stable series.&lt;br /&gt;&lt;br /&gt;Yes, ext4 didn't go as quickly as I would have liked, but part of the&lt;br /&gt;problem was I personally didn't have enough time to review the patches&lt;br /&gt;being created by the various ext4 developers, and I wasn't about to&lt;br /&gt;merge patches until they were ready.  We didn't have enough senior&lt;br /&gt;developers on ext4, and it took a while for some of the developers&lt;br /&gt;assigned to the project to get up to speed.  (I was the most senior&lt;br /&gt;developer, but I've never had time assigned by my employer to work on&lt;br /&gt;ext4; it has always something I did on my own time, often late at&lt;br /&gt;night (hint: check the time this mail was sent, and when the last ext4&lt;br /&gt;patchset was sent out last night).  Fortunately, at this point a&lt;br /&gt;number of developers like Aneesh have become comfortable with the&lt;br /&gt;code, and good at writing patches that don't require major review and&lt;br /&gt;changes, and the addition of engineers hired by Red Hat, such as Eric&lt;br /&gt;and Val, have also helped immensely.&lt;br /&gt;&lt;span style="color:#b22222;"&gt;&lt;br /&gt;As far as btrfs is concerned, one of the things that you may not know&lt;br /&gt;is that about a year ago (on November 12-13, 2007), a small group key&lt;br /&gt;filesystem developers, that included engineers employed by HP, Oracle,&lt;br /&gt;IBM, Intel, HP, and Red Hat, and whose experience included working&lt;br /&gt;with a large number of filesystems: ext2, ext4, ext4, ocfs2, lustre,&lt;br /&gt;btrfs, advfs, reiserfs, and xfs came together for a two day "next&lt;br /&gt;generation filesystem" (NGFS) workshop.  At the end of the that&lt;br /&gt;workshop, there was unaminous agreement (including from yours truly)&lt;br /&gt;that (a) Linux needed a next generation filesystem to be competitive,&lt;br /&gt;(b) Chris Mason's btrfs (with some changes/enhancements discussed&lt;br /&gt;during the workshop) was the best long-term solution for NGFS, and (c)&lt;br /&gt;because creating a new enterprise filesystem always takes longer than&lt;br /&gt;people expect, and even then, it takes a while for enterprise users to&lt;br /&gt;trust a new filesystem for their most critical data, ext4 in the next&lt;br /&gt;generation of filesystems was needed as the bridge to the NGFS.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;The reason why we made these recommendations was not to influence open&lt;br /&gt;source developers (which is why we haven't really talked about it a&lt;br /&gt;lot in venues like the LKML) but as recommendations to the management&lt;br /&gt;of the above-mentioned for assigning resources to the project.  (One&lt;br /&gt;of the recommendations we made was that a critical success factor was&lt;br /&gt;that knowledge about the filesystem must be spread throughout multiple&lt;br /&gt;vendors and distributions.)  But I think it is fair to say that btrfs&lt;br /&gt;isn't just a private a project of a single Linux kernel developer, but&lt;br /&gt;rather the design has been discussed and reviewed by a large number of&lt;br /&gt;experienced filesystem architects.  What *is* important is that Chris&lt;br /&gt;is a well-known kernel developer who is trusted to create and maintain&lt;br /&gt;quality kernel code, and his employer *has* apparently given him&lt;br /&gt;enough time that he can do a lot of personal, hands-on development.&lt;br /&gt;&lt;br /&gt;Given btrfs's current status, in terms of its functionality, even its&lt;br /&gt;format is not fully cast into stone yet, and given Chris's reputation&lt;br /&gt;and skills as a kernel devleoper, my personal opinion is that we would&lt;br /&gt;not be making a "special case exception" for btrfs to get it into&lt;br /&gt;mainline, but rather something which makes completely good sense.&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;references:&lt;br /&gt;[1] http://thread.gmane.org/gmane.linux.file-systems/26246/focus=26492&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-5489690614387150172?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/5489690614387150172/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/10/ngfs-from-ext4-to-btrfs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/5489690614387150172'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/5489690614387150172'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/10/ngfs-from-ext4-to-btrfs.html' title='NGFS: From ext4 to btrfs'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-4492626868949122950</id><published>2008-10-19T20:19:00.000-07:00</published><updated>2008-10-20T00:21:39.469-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>undelete still open files on ext2/3/4</title><content type='html'>As mentioned by Ted on linux-ext4 mailing list, there are some ways to get your files back if it is still open:&lt;br /&gt;&lt;br /&gt;Some background:&lt;br /&gt;On ext3/4, once deleted, the inode will be put to orphaned inode list. On recovery,on recovery this orphan list is traversed and iput will be called on each of the inodes to mark them as free.&lt;br /&gt;&lt;br /&gt;So, theoretically, we have out first solution:&lt;br /&gt;1. provoke a crash and manually remove the inode from the orphan list, then mount the partition as ext3.&lt;br /&gt;&lt;br /&gt;But another simple solution exists:&lt;br /&gt;2. kill -STOP the process that owns the file, copy it via "cat /proc/$pid/fd/$fd &gt; rescue-file". and then kill -9 the process if you don't want it to make any further changes.&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-4492626868949122950?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/4492626868949122950/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/10/undelete-still-open-files-on-ext234.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4492626868949122950'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/4492626868949122950'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/10/undelete-still-open-files-on-ext234.html' title='undelete still open files on ext2/3/4'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-6718803324486555829</id><published>2008-10-19T19:54:00.000-07:00</published><updated>2008-10-20T00:22:16.904-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Nokia'/><title type='text'>Gnome Asia Summit 2008</title><content type='html'>Gnome Asia Summit 2008于上周末在北航举行。会上有一些很有意思且与我们项目相关(主要是maemo相关)的topic，我总结了一下：&lt;br /&gt;&lt;br /&gt;1. Introduction of Gstreamer in maemo[1]&lt;br /&gt;这个topic的speaker是Nokia芬兰研发中心的工程师Huaming Wang。他主要介绍maemo中Gstreamer的应用。在maemo中多媒体数据除了real格式以外都是由Gstreamer来handle的。同时Nokia把一些视频和音频的解码程序固化到了DSP上，从而加强了N8*0上多媒体数据的处理能力。&lt;br /&gt;&lt;br /&gt;2. Qt maemo hildon port, making Qt and GTK+ working together in mobile devices&lt;br /&gt;这个topic的speaker是Forum Nokia的maemo首席工程师Kate Alhola，她主要讲strategy上的东东。hildon是Nokia开发并upstream的Linux上移动设备应用程序的framework，实验室之前项目的代码包括现在UI项目上的代码都是基于这个框架的。以前hildon只支持gtk+，现在在maemo Diablo版本中添加了Qt的支持。Kate并没有留下她的slides，比较可惜。。。&lt;br /&gt;这可以作为我们的一个alternative，夏双荣之前提到的gtk+中图形无法准确定位的问题也可以在Qt中很好的解决。但是Qt的一个问题就是lisense。社区版的Qt使用的是GPL，如果我们项目要用Qt的话只有两种办法，要么GPL发布我们的代码，要么向Trolltech购买商业授权。不过Trolltech已经被Nokia收购，估计让Nokia购买商业授权也不会有太大阻力。&lt;br /&gt;&lt;br /&gt;3. Out-of-memory management in a mobile GNOME device[2]&lt;br /&gt;这个topic的speaker是Nokia maemo的资深开发人员Kimmo Hamalainen。他主要介绍了如何编写内存受限的移动设备应用程序，以及当内存不足的时候Linux kernel会如何处理，在maemo中又做了哪些方面的改进。&lt;br /&gt;&lt;br /&gt;4. Cross-platform GUI Application Design In The View of a Mac Developer[3]&lt;br /&gt;这个topic的speaker是名叫Jiang Jiang的在读研究生。他专注于Mac和Linux平台上的程序开发。他从一个Mac开发人员的角度来介绍了如何设计和开发用户友好的GUI程序。&lt;br /&gt;&lt;br /&gt;5. Moblin Hugs Gnome[4]&lt;br /&gt;这个topic的speaker是Intel北京OTC的开源策略经理Xu Chen。moblin是maemo在市场上的主要竞争对手，二者有很多相似之处。比如都是采用Linux内核的开源平台，都有以自己公司为核心的community，都以Gnome mobile作为图形界面，应用程序都使用hildon作为应用程序的框架等。Intel刚刚在国内成立了moblin的team，估计要不了多久就会来学校宣传，北邮嵌入式协会也已经在和陈绪接触，可能用不了多久就会拿到一些moblin的项目。上周例会上王老师提到的３D的桌面效果在moblin上已经有支持，他们用基于openGL的Clutter实现了在3D以及动画效果。maemo方面也打算采用Clutter，他们正在working on it。。。让我比较惊奇的是，Nokia居然打算完全自己去做Clutter的maemo port，“与其指望与他们（指Clutter）合作，不如等着我们来提供给你们（指在座的developer）“。。。搞通信的人的想法到底还是和搞计算机的有本质的区别。。。&lt;br /&gt;&lt;br /&gt;6. Metadata management for the Desktop&lt;br /&gt;这个topic的speaker是Nokia芬兰研发中心负责maemo平台和hildon库研发的工程师Richard&lt;br /&gt;Sun。他主要介绍了基于metadata的文件索引和检索工具tracker。tracker是目前Linux平台上三大metadata检索工具（另外两个beagle, strigi）之一。tracker目前focus on的是桌面搜索，即对本地资源的快速索引和检索。目前在maemo中的本地检索也可以使用tracker，而且Nokia方面希望long term support这个项目，所以如果我们项目以后有桌面搜索需要的话，也可以选择通过D-bus直接与trackerd通信来使用tracker的高效检索服务。Richard也没有留下他的slides。。。&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;references:&lt;br /&gt;[1]http://www.gnome.asia/static/upload/event_file/GNOMEAisaSummit.odp&lt;br /&gt;[2]http://www.gnome.asia/static/upload/event_file/gnome-asia-low-memory-handling.odp&lt;br /&gt;[3]http://www.gnome.asia/static/upload/event_file/gui-app-design.pdf&lt;br /&gt;[4]http://www.gnome.asia/static/upload/event_file/MoblinHugsGnome.pdf&lt;div class="blogger-post-footer"&gt;--
No rights reserved except that of others.&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3176851032969559855-6718803324486555829?l=bardofschool.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bardofschool.blogspot.com/feeds/6718803324486555829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bardofschool.blogspot.com/2008/10/gnome-asia-summit-2008.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/6718803324486555829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3176851032969559855/posts/default/6718803324486555829'/><link rel='alternate' type='text/html' href='http://bardofschool.blogspot.com/2008/10/gnome-asia-summit-2008.html' title='Gnome Asia Summit 2008'/><author><name>Bergwolf</name><uri>http://www.blogger.com/profile/11192780434391294955</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='24' src='http://2.bp.blogspot.com/-vjF7IgtWJa8/TmGz7zOjttI/AAAAAAAABac/xBK9eIBkMds/s220/IMG_5340.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3176851032969559855.post-4693953267708816059</id><published>2008-10-15T22:26:00.000-07:00</published><updated>2008-10-16T00:40:31.898-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='kernel hacking'/><title type='text'>Get the lastest version of ext4 code</title><content type='html'>This is a general instruction of getting latest Linux kernel code.&lt;br /&gt;&lt;br /&gt;1. Get the laster version of ext4-patch-queue&lt;br /&gt;$&gt;git clone git://git.kernel.org/pub/scm/fs/ext2/ext4-patch-queue.git&lt;br /&gt;&lt;br /&gt;have a look at the series file in ext4-patch-queue folder. It has a kernel version number indicating which version of kernel this patch queue is based on(e.g. v2.6.26-rc9)&lt;br /&gt;&lt;br /&gt;2. Get the latest version of Linux kernel from ext4 git branch.&lt;br /&gt;$&gt;git clone git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4.git&lt;br /&gt;checkout to the targeted kernel version:&lt;br /&gt;$&gt;git checkout -b view v2.6.26-rc9&lt;br /&gt;which equals to&lt;br /&gt;$&gt;git branch view v2.6.26-rc9&lt;br /&gt;$&gt;git checkout view&lt;br /&gt;&lt;br /&gt;3. Apply the patch queue either by stgit or by quilt.&lt;br /&gt;The advantage of stgit over quilt is that stgit modifies git logs too, so you can see the changelog if you choose stgit to apply the patches. However, stgit doesn't handel fuzz patches, which is a grate weakness.&lt;br /&gt;&lt;br /&gt;stgit:&lt;br /&gt;$&gt;stgit init&lt;br /&gt;$&gt;stgit import --series ../ext4-patch-queue/series&lt;br /&gt;Or quilt:&lt;br /&gt;$&gt;ln -s ../ext4-patch-queue patches&lt;br /&gt;$&gt;quilt push -a&lt;br /&gt;&lt;br /&gt;Now, I have the latest version of ext4 code on hand.&lt;br /&gt;&lt;br /&gt;BTW, I have two ways to use git behind proxy:&lt;br /&gt;(1). Set the http_proxy environment if git repository supports http connections.&lt;br /&gt;(2). find a proxy command to bypass the connection:&lt;br /&gt;1. gcc -o connect connect.c&lt;br /&gt;   mv connect ~/bin&lt;br /&gt;2. 设置一个wrapper&lt;br /&gt;   echo "/home/gigi/bin/connect -H proxy.bupt.edu.cn:8080 $@" &gt;&gt; ~/bin/proxy&lt;br /&gt;   chmod +x ~/bin/proxy&lt;br /&gt;这里我使用的是学校的代理 proxy.bupt.edu.cn，端口是8080&lt;br /&gt;connect这个小程序还支持socket代理，用法是connect -S host:port&lt;br /&gt;3. echo "export CONNECT_USER=bergwolf" &gt;&gt; .bashrc&lt;br /&gt;   echo "export GIT_PROXY_COMMAND=proxy" &gt;&gt; .bashrc&lt;br /&gt;connect程序从环境变量CONNECT_USER和CONNECT_PASSWORD&lt;br /&gt;中读取用户名和密码,如果密码没有设置，在连接时会要求输入&lt;br /&gt;GIT_PROXY_COMMAND是git默认使用的代理程序，也可以在.git/config中设置&lt;br /&gt;&lt;br /&gt;到此git代理设置就完成了，试用一下：&lt;br /&gt;[gigi-Ubuntu:bin]$git clone git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git&lt;br /&gt;Initialized empty Git repository in /home/gigi/bin/e2fsprogs/.git/&lt;br /&gt;Enter proxy authentication password for bergwolf@proxy.bupt.edu.cn:&lt;br /&gt;remote: Counting objects: 24006, done.&lt;br /&gt;remote: Compressing objects: 100% (4701/4701), done.&lt;br /&gt;ceiving objects:   1% (241/24006), 43.99 KiB | 56 KiB/s&lt;br /&gt;&lt;br /&gt;connect.c:&lt;br /&gt;&lt;pre class="alt2" dir="ltr" style="border: 1px inset ; margin: 0px; padding: 6px; overflow: auto; width: 600px; height: 1000px; text-align: left;"&gt;&lt;br /&gt;&lt;pre width="80"&gt;&lt;font color="#B22222"&gt;/***********************************************************************&lt;br /&gt; * connect.c -- Make socket connection using SOCKS4/5 and HTTP tunnel.&lt;br /&gt; *&lt;br /&gt; * Copyright (c) 2000-2006 Shun-ichi Goto&lt;br /&gt; * Copyright (c) 2002, J. Grant (English Corrections)&lt;br /&gt; *&lt;br /&gt; * This program is free software; you can redistribute it and/or&lt;br /&gt; * modify it under the terms of the GNU General Public License&lt;br /&gt; * as published by the Free Software Foundation; either version 2&lt;br /&gt; * of the License, or (at your option) any later version.&lt;br /&gt; *&lt;br /&gt; * This program is distributed in the hope that it will be useful,&lt;br /&gt; * but WITHOUT ANY WARRANTY; without even the implied warranty of&lt;br /&gt; * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the&lt;br /&gt; * GNU General Public License for more details.&lt;br /&gt; *&lt;br /&gt; * You should have received a copy of the GNU General Public License&lt;br /&gt; * along with this program; if not, write to the Free Software&lt;br /&gt; * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.&lt;br /&gt; *&lt;br /&gt; * ---------------------------------------------------------&lt;br /&gt; * PROJECT:  My Test Program&lt;br /&gt; * AUTHOR:   Shun-ichi GOTO &amp;lt;gotoh@taiyo.co.jp&amp;gt;&lt;br /&gt; * CREATE:   Wed Jun 21, 2000&lt;br /&gt; * REVISION: $Revision: 100 $&lt;br /&gt; * ---------------------------------------------------------&lt;br /&gt; *&lt;br /&gt; * Getting Source&lt;br /&gt; * ==============&lt;br /&gt; *&lt;br /&gt; *   Recent version of 'connect.c' is available from&lt;br /&gt; *     http://www.taiyo.co.jp/~gotoh/ssh/connect.c&lt;br /&gt; *&lt;br /&gt; *   Related tool, ssh-askpass.exe (alternative ssh-askpass on UNIX)&lt;br /&gt; *   is available:&lt;br /&gt; *     http://www.taiyo.co.jp/~gotoh/ssh/ssh-askpass.exe.gz&lt;br /&gt; *&lt;br /&gt; *   See more detail:&lt;br /&gt; *     http://www.taiyo.co.jp/~gotoh/ssh/connect.html&lt;br /&gt; *&lt;br /&gt; * How To Compile&lt;br /&gt; * ==============&lt;br /&gt; *&lt;br /&gt; *  On UNIX environment:&lt;br /&gt; *      $ gcc connect.c -o connect&lt;br /&gt; *&lt;br /&gt; *  On SOLARIS:&lt;br /&gt; *      $ gcc -o connect -lresolv -lsocket -lnsl connect.c&lt;br /&gt; *&lt;br /&gt; *  on Win32 environment:&lt;br /&gt; *      $ cl connect.c wsock32.lib advapi32.lib&lt;br /&gt; *    or&lt;br /&gt; *      $ bcc32 connect.c wsock32.lib advapi32.lib&lt;br /&gt; *    or&lt;br /&gt; *      $ gcc connect.c -o connect&lt;br /&gt; *&lt;br /&gt; *  on Mac OS X environment:&lt;br /&gt; *      $ gcc connect.c -o connect -lresolv&lt;br /&gt; *    or&lt;br /&gt; *      $ gcc connect.c -o connect -DBIND_8_COMPAT=1&lt;br /&gt; *&lt;br /&gt; * How To Use&lt;br /&gt; * ==========&lt;br /&gt; *&lt;br /&gt; *   You can specify proxy method in an environment variable or in a&lt;br /&gt; *   command line option.&lt;br /&gt; *&lt;br /&gt; *   usage:  connect [-dnhst45] [-R resolve] [-p local-port] [-w sec]&lt;br /&gt; *                   [-H [user@]proxy-server[:port]]&lt;br /&gt; *                   [-S [user@]socks-server[:port]]&lt;br /&gt; *                   [-T proxy-server[:port]]&lt;br /&gt; *                   [-c telnet proxy command]&lt;br /&gt; *                   host port&lt;br /&gt; *&lt;br /&gt; *   "host" and "port" is for the target hostname and port-number to&lt;br /&gt; *   connect to.&lt;br /&gt; *&lt;br /&gt; *   The -H option specifys a hostname and port number of the http proxy&lt;br /&gt; *   server to relay. If port is omitted, 80 is used. You can specify this&lt;br /&gt; *   value in the environment variable HTTP_PROXY and pass the -h option&lt;br /&gt; *   to use it.&lt;br /&gt; *&lt;br /&gt; *   The -S option specifys the hostname and port number of the SOCKS&lt;br /&gt; *   server to relay.  Like -H, port number can be omitted and the default&lt;br /&gt; *   is 1080. You can also specify this value pair in the environment&lt;br /&gt; *   variable SOCKS5_SERVER and give the -s option to use it.&lt;br /&gt; *&lt;br /&gt; *   The '-4' and the '-5' options are for specifying SOCKS relaying and&lt;br /&gt; *   indicates protocol version to use. It is valid only when used with&lt;br /&gt; *   '-s' or '-S'. Default is '-5' (protocol version 5)&lt;br /&gt; *&lt;br /&gt; *   The '-R' option is for specifying method to resolve the&lt;br /&gt; *   hostname. Three keywords ("local", "remote", "both") or dot-notation&lt;br /&gt; *   IP address are acceptable.  The keyword "both" means, "Try local&lt;br /&gt; *   first, then remote". If a dot-notation IP address is specified, use&lt;br /&gt; *   this host as nameserver. The default is "remote" for SOCKS5 or&lt;br /&gt; *   "local" for others. On SOCKS4 protocol, remote resolving method&lt;br /&gt; *   ("remote" and "both") requires protocol 4a supported server.&lt;br /&gt; *&lt;br /&gt; *   The '-p' option will forward a local TCP port instead of using the&lt;br /&gt; *   standard input and output.&lt;br /&gt; *&lt;br /&gt; *   The '-P' option is same to '-p' except keep remote session. The&lt;br /&gt; *   program repeats waiting the port with holding remote session without&lt;br /&gt; *   disconnecting. To disconnect the remote session, send EOF to stdin or&lt;br /&gt; *   kill the program.&lt;br /&gt; *&lt;br /&gt; *   The '-w' option specifys timeout seconds for making connection with&lt;br /&gt; *   TARGET host.&lt;br /&gt; *&lt;br /&gt; *   The '-d' option is used for debug. If you fail to connect, use this&lt;br /&gt; *   and check request to and response from server.&lt;br /&gt; *&lt;br /&gt; *   You can omit the "port" argument when program name is special format&lt;br /&gt; *   containing port number itself. For example,&lt;br /&gt; *     $ ln -s connect connect-25&lt;br /&gt; *   means this connect-25 command is spcifying port number 25 already&lt;br /&gt; *   so you need not 2nd argument (and ignored if specified).&lt;br /&gt; *&lt;br /&gt; *   To use proxy, this example is for SOCKS5 connection to connect to&lt;br /&gt; *   'host' at port 25 via SOCKS5 server on 'firewall' host.&lt;br /&gt; *     $ connect -S firewall  host 25&lt;br /&gt; *   or&lt;br /&gt; *     $ SOCKS5_SERVER=firewall; export SOCKS5_SERVER&lt;br /&gt; *     $ connect -s host 25&lt;br /&gt; *&lt;br /&gt; *   For a HTTP-PROXY connection:&lt;br /&gt; *     $ connect -H proxy-server:8080  host 25&lt;br /&gt; *   or&lt;br /&gt; *     $ HTTP_PROXY=proxy-server:8080; export HTTP_PROXY&lt;br /&gt; *     $ connect -h host 25&lt;br /&gt; *   To forward a local port, for example to use ssh:&lt;br /&gt; *     $ connect -p 5550 -H proxy-server:8080  host 22&lt;br /&gt; *    ($ ssh -l user -p 5550 localhost )&lt;br /&gt; *&lt;br /&gt; * TIPS&lt;br /&gt; * ====&lt;br /&gt; *&lt;br /&gt; *   Connect.c doesn't have any configuration to specify the SOCKS server.&lt;br /&gt; *   If you are a mobile user, this limitation might bother you.  However,&lt;br /&gt; *   You can compile connect.c and link with other standard SOCKS library&lt;br /&gt; *   like the NEC SOCKS5 library or Dante. This means connect.c is&lt;br /&gt; *   socksified and uses a configration file like to other SOCKSified&lt;br /&gt; *   network commands and you can switch configuration file any time&lt;br /&gt; *   (ex. when ppp startup) that brings you switching of SOCKS server for&lt;br /&gt; *   connect.c in same way with other commands. For this case, you can&lt;br /&gt; *   write ~/.ssh/config like this:&lt;br /&gt; *&lt;br /&gt; *     ProxyCommand connect -n %h %p&lt;br /&gt; *&lt;br /&gt; * SOCKS5 authentication&lt;br /&gt; * =====================&lt;br /&gt; *&lt;br /&gt; *   Only USER/PASS authentication is supported.&lt;br /&gt; *&lt;br /&gt; * Proxy authentication&lt;br /&gt; * ====================&lt;br /&gt; *&lt;br /&gt; *   Only BASIC scheme is supported.&lt;br /&gt; *&lt;br /&gt; * Authentication informations&lt;br /&gt; * ===========================&lt;br /&gt; *&lt;br /&gt; *   User name for authentication is specifed by an environment variable&lt;br /&gt; *   or system login name.  And password is specified from environment&lt;br /&gt; *   variable or external program (specified in $SSH_ASKPASS) or tty.&lt;br /&gt; *&lt;br /&gt; *   Following environment variable is used for specifying user name.&lt;br /&gt; *     SOCKS: $SOCKS5_USER, $LOGNAME, $USER&lt;br /&gt; *     HTTP Proxy: $HTTP_PROXY_USER, $LOGNAME, $USER&lt;br /&gt; *&lt;br /&gt; * ssh-askpass support&lt;br /&gt; * ===================&lt;br /&gt;  *&lt;br /&gt; *   You can use ssh-askpass (came from OpenSSH or else) to specify&lt;br /&gt; *   password on graphical environment (X-Window or MS Windows). To use&lt;br /&gt; *   this, set program name to environment variable SSH_ASKPASS. On UNIX,&lt;br /&gt; *   X-Window must be required, so $DISPLAY environment variable is also&lt;br /&gt; *   needed.  On Win32 environment, $DISPLAY is not mentioned.&lt;br /&gt; *&lt;br /&gt; * Related Informations&lt;br /&gt; * ====================&lt;br /&gt; *&lt;br /&gt; *   SOCKS5 -- RFC 1928, RFC 1929, RFC 1961&lt;br /&gt; *             NEC SOCKS Reference Implementation is available from:&lt;br /&gt; *               http://www.socks.nec.com&lt;br /&gt; *             DeleGate version 5 or earlier can be SOCKS4 server,&lt;br /&gt; *             and version 6 can be SOCKS5 and SOCKS4 server.&lt;br /&gt; *             and version 7.7.0 or later can be SOCKS5 and SOCKS4a server.&lt;br /&gt; *               http://www.delegate.org/delegate/&lt;br /&gt; *&lt;br /&gt; *   HTTP-Proxy --&lt;br /&gt; *             Many http proxy servers supports this, but https should&lt;br /&gt; *             be allowed as configuration on your host.&lt;br /&gt; *             For example on DeleGate, you should add "https" to the&lt;br /&gt; *             "REMITTABLE" parameter to allow HTTP-Proxy like this:&lt;br /&gt; *               delegated -Pxxxx ...... REMITTABLE="+,https" ...&lt;br /&gt; *&lt;br /&gt; *  Hypertext Transfer Protocol -- HTTP/1.1  -- RFC 2616&lt;br /&gt; *  HTTP Authentication: Basic and Digest Access Authentication -- RFC 2617&lt;br /&gt; *             For proxy authentication, refer these documents.&lt;br /&gt; *&lt;br /&gt; ***********************************************************************/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;stdio.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;stdlib.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;string.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;ctype.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;memory.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;errno.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;assert.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/types.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;stdarg.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;fcntl.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;signal.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef __CYGWIN32__&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#undef _WIN32&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;windows.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;winsock.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/stat.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;io.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;conio.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;unistd.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;pwd.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;termios.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/time.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef __hpux&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/select.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* __hpux */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;sys/socket.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;netinet/in.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;arpa/inet.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;netdb.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define WITH_RESOLVER 1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;arpa/nameser.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#include &amp;lt;resolv.h&amp;gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not ( not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__) */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#undef WITH_RESOLVER&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not ( not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__) */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ECONNRESET WSAECONNRESET&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WI32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef LINT&lt;/font&gt;&lt;br /&gt;static char *vcid = &lt;font color="#666666"&gt;"$Id: connect.c 100 2007-07-03 10:48:26Z gotoh $"&lt;/font&gt;;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Microsoft Visual C/C++ has _snprintf() and _vsnprintf() */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _MSC_VER&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define snprintf _snprintf&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define vsnprintf _vsnprintf&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* consider Borland C */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef __BORLANDC__&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define _kbhit kbhit&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define _setmode setmode&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* help message.&lt;br /&gt;   Win32 environment does not support -R option (vc and cygwin)&lt;br /&gt;   Win32 native compilers does not support -w option, yet (vc)&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;static char *usage = &lt;font color="#666666"&gt;"usage: %s [-dnhst45] [-p local-port]"&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef __CYGWIN32__&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"[-w timeout] \n"&lt;/font&gt;                               &lt;font color="#B22222"&gt;/* cygwin cannot -R */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;" \n"&lt;/font&gt;                                           &lt;font color="#B22222"&gt;/* VC cannot -w nor -R  */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* help message for UNIX */&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"[-R resolve] [-w timeout] \n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          [-H proxy-server[:port]] [-S [user@]socks-server[:port]] \n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          [-T proxy-server[:port]]\n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          [-c telnet-proxy-command]\n"&lt;/font&gt;&lt;br /&gt;&lt;font color="#666666"&gt;"          host port\n"&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* name of this program */&lt;/font&gt;&lt;br /&gt;char *progname = NULL;&lt;br /&gt;char *progdesc = &lt;font color="#666666"&gt;"connect --- simple relaying command via proxy."&lt;/font&gt;;&lt;br /&gt;char *rcs_revstr = &lt;font color="#666666"&gt;"$Revision: 100 $"&lt;/font&gt;;&lt;br /&gt;char *revstr = NULL;&lt;br /&gt;int major_version = 1;&lt;br /&gt;int minor_version = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* set of character for strspn() */&lt;/font&gt;&lt;br /&gt;const char *digits    = &lt;font color="#666666"&gt;"0123456789"&lt;/font&gt;;&lt;br /&gt;const char *dotdigits = &lt;font color="#666666"&gt;"0123456789."&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* options */&lt;/font&gt;&lt;br /&gt;int f_debug = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* report flag to hide secure information */&lt;/font&gt;&lt;br /&gt;int f_report = 1;&lt;br /&gt;&lt;br /&gt;int connect_timeout = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* local input type */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define LOCAL_STDIO     0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define LOCAL_SOCKET    1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;char *local_type_names[] = { &lt;font color="#666666"&gt;"stdio"&lt;/font&gt;, &lt;font color="#666666"&gt;"socket"&lt;/font&gt; };&lt;br /&gt;int   local_type = LOCAL_STDIO;&lt;br /&gt;u_short local_port = 0;                         &lt;font color="#B22222"&gt;/* option 'p' */&lt;/font&gt;&lt;br /&gt;int f_hold_session = 0;                         &lt;font color="#B22222"&gt;/* option 'P' */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;char *telnet_command = &lt;font color="#666666"&gt;"telnet %h %p"&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* utiity types, pair holder of number and string */&lt;/font&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;typedef&lt;/font&gt; &lt;font color="#4169E1"&gt;struct&lt;/font&gt; {&lt;br /&gt;    int num;&lt;br /&gt;    const char *str;&lt;br /&gt;} LOOKUP_ITEM;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* relay method, server and port */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_UNDECIDED 0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_DIRECT    1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_SOCKS     2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_HTTP      3&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define METHOD_TELNET    4&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;char *method_names[] = { &lt;font color="#666666"&gt;"UNDECIDED"&lt;/font&gt;, &lt;font color="#666666"&gt;"DIRECT"&lt;/font&gt;, &lt;font color="#666666"&gt;"SOCKS"&lt;/font&gt;, &lt;font color="#666666"&gt;"HTTP"&lt;/font&gt;, &lt;font color="#666666"&gt;"TELNET"&lt;/font&gt; };&lt;br /&gt;&lt;br /&gt;int   relay_method = METHOD_UNDECIDED;          &lt;font color="#B22222"&gt;/* relaying method */&lt;/font&gt;&lt;br /&gt;char *relay_host = NULL;                        &lt;font color="#B22222"&gt;/* hostname of relay server */&lt;/font&gt;&lt;br /&gt;u_short relay_port = 0;                         &lt;font color="#B22222"&gt;/* port of relay server */&lt;/font&gt;&lt;br /&gt;char *relay_user = NULL;                        &lt;font color="#B22222"&gt;/* user name for auth */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* destination target host and port */&lt;/font&gt;&lt;br /&gt;char *dest_host = NULL;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="sockaddr_in"&gt;&lt;/a&gt;struct sockaddr_in &lt;/font&gt;dest_addr;&lt;br /&gt;u_short dest_port = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* informations for SOCKS */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_SUCCEEDED    0x00    &lt;/font&gt;&lt;font color="#B22222"&gt;/* succeeded */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_FAIL         0x01    &lt;/font&gt;&lt;font color="#B22222"&gt;/* general SOCKS serer failure */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_NALLOWED     0x02    &lt;/font&gt;&lt;font color="#B22222"&gt;/* connection not allowed by ruleset */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_NUNREACH     0x03    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Network unreachable */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_HUNREACH     0x04    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Host unreachable */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_REFUSED      0x05    &lt;/font&gt;&lt;font color="#B22222"&gt;/* connection refused */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_EXPIRED      0x06    &lt;/font&gt;&lt;font color="#B22222"&gt;/* TTL expired */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_CNOTSUP      0x07    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Command not supported */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_ANOTSUP      0x08    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Address not supported */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_REP_INVADDR      0x09    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Inalid address */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;LOOKUP_ITEM socks5_rep_names[] = {&lt;br /&gt;    { SOCKS5_REP_SUCCEEDED, &lt;font color="#666666"&gt;"succeeded"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_FAIL,      &lt;font color="#666666"&gt;"general SOCKS server failure"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_NALLOWED,  &lt;font color="#666666"&gt;"connection not allowed by ruleset"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_NUNREACH,  &lt;font color="#666666"&gt;"Network unreachable"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_HUNREACH,  &lt;font color="#666666"&gt;"Host unreachable"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_REFUSED,   &lt;font color="#666666"&gt;"connection refused"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_EXPIRED,   &lt;font color="#666666"&gt;"TTL expired"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_CNOTSUP,   &lt;font color="#666666"&gt;"Command not supported"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_ANOTSUP,   &lt;font color="#666666"&gt;"Address not supported"&lt;/font&gt;},&lt;br /&gt;    { SOCKS5_REP_INVADDR,   &lt;font color="#666666"&gt;"Invalid address"&lt;/font&gt;},&lt;br /&gt;    { -1, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* SOCKS5 authentication methods */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_REJECT      0xFF    &lt;/font&gt;&lt;font color="#B22222"&gt;/* No acceptable auth method */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_NOAUTH      0x00    &lt;/font&gt;&lt;font color="#B22222"&gt;/* without authentication */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_GSSAPI      0x01    &lt;/font&gt;&lt;font color="#B22222"&gt;/* GSSAPI */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_USERPASS    0x02    &lt;/font&gt;&lt;font color="#B22222"&gt;/* User/Password */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_CHAP        0x03    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Challenge-Handshake Auth Proto. */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_EAP         0x05    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Extensible Authentication Proto. */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS5_AUTH_MAF         0x08    &lt;/font&gt;&lt;font color="#B22222"&gt;/* Multi-Authentication Framework */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_SUCCEEDED    90      &lt;/font&gt;&lt;font color="#B22222"&gt;/* rquest granted (succeeded) */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_REJECTED     91      &lt;/font&gt;&lt;font color="#B22222"&gt;/* request rejected or failed */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_IDENT_FAIL   92      &lt;/font&gt;&lt;font color="#B22222"&gt;/* cannot connect identd */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKS4_REP_USERID       93      &lt;/font&gt;&lt;font color="#B22222"&gt;/* user id not matched */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;LOOKUP_ITEM socks4_rep_names[] = {&lt;br /&gt;    { SOCKS4_REP_SUCCEEDED,  &lt;font color="#666666"&gt;"request granted (succeeded)"&lt;/font&gt;},&lt;br /&gt;    { SOCKS4_REP_REJECTED,   &lt;font color="#666666"&gt;"request rejected or failed"&lt;/font&gt;},&lt;br /&gt;    { SOCKS4_REP_IDENT_FAIL, &lt;font color="#666666"&gt;"cannot connect identd"&lt;/font&gt;},&lt;br /&gt;    { SOCKS4_REP_USERID,     &lt;font color="#666666"&gt;"user id not matched"&lt;/font&gt;},&lt;br /&gt;    { -1, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_UNKNOWN 0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_LOCAL   1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_REMOTE  2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define RESOLVE_BOTH    3&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;char *resolve_names[] = { &lt;font color="#666666"&gt;"UNKNOWN"&lt;/font&gt;, &lt;font color="#666666"&gt;"LOCAL"&lt;/font&gt;, &lt;font color="#666666"&gt;"REMOTE"&lt;/font&gt;, &lt;font color="#666666"&gt;"BOTH"&lt;/font&gt; };&lt;br /&gt;&lt;br /&gt;int socks_version = 5;                          &lt;font color="#B22222"&gt;/* SOCKS protocol version */&lt;/font&gt;&lt;br /&gt;int socks_resolve = RESOLVE_UNKNOWN;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="sockaddr_in"&gt;&lt;/a&gt;struct sockaddr_in &lt;/font&gt;socks_ns;&lt;br /&gt;char *socks5_auth = NULL;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Environment variable names */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_SERVER  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_SERVER"&lt;/font&gt;&lt;font color="#228B22"&gt;        &lt;/font&gt;&lt;font color="#B22222"&gt;/* SOCKS server */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_SERVER &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_SERVER"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_SERVER &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_SERVER"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_RESOLVE  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_RESOLVE"&lt;/font&gt;&lt;font color="#228B22"&gt;      &lt;/font&gt;&lt;font color="#B22222"&gt;/* resolve method */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_RESOLVE &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_RESOLVE"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_RESOLVE &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_RESOLVE"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;       &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user for SOCKS5 */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;       &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user for SOCKS4 */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_USER      &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;        &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user for SOCKS */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_PASSWD   &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_PASSWD"&lt;/font&gt;&lt;font color="#228B22"&gt;     &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth password for SOCKS5 */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_PASSWORD &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_PASSWORD"&lt;/font&gt;&lt;font color="#228B22"&gt;   &lt;/font&gt;&lt;font color="#B22222"&gt;/* old style */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_PROXY          &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_PROXY"&lt;/font&gt;&lt;font color="#228B22"&gt;    &lt;/font&gt;&lt;font color="#B22222"&gt;/* common env var */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_PROXY_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_PROXY_USER"&lt;/font&gt;&lt;font color="#228B22"&gt; &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth user */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_PROXY_PASSWORD &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_PROXY_PASSWORD"&lt;/font&gt;&lt;font color="#228B22"&gt; &lt;/font&gt;&lt;font color="#B22222"&gt;/* auth password */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_TELNET_PROXY          &lt;/font&gt;&lt;font color="#666666"&gt;"TELNET_PROXY"&lt;/font&gt;&lt;font color="#228B22"&gt;    &lt;/font&gt;&lt;font color="#B22222"&gt;/* common env var */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_CONNECT_USER     &lt;/font&gt;&lt;font color="#666666"&gt;"CONNECT_USER"&lt;/font&gt;&lt;font color="#228B22"&gt;     &lt;/font&gt;&lt;font color="#B22222"&gt;/* default auth user name */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_CONNECT_PASSWORD &lt;/font&gt;&lt;font color="#666666"&gt;"CONNECT_PASSWORD"&lt;/font&gt;&lt;font color="#228B22"&gt; &lt;/font&gt;&lt;font color="#B22222"&gt;/* default auth password */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS_DIRECT   &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;       &lt;/font&gt;&lt;font color="#B22222"&gt;/* addr-list for non-proxy */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_DIRECT  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS4_DIRECT  &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS4_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_HTTP_DIRECT    &lt;/font&gt;&lt;font color="#666666"&gt;"HTTP_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_CONNECT_DIRECT &lt;/font&gt;&lt;font color="#666666"&gt;"CONNECT_DIRECT"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SOCKS5_AUTH &lt;/font&gt;&lt;font color="#666666"&gt;"SOCKS5_AUTH"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define ENV_SSH_ASKPASS &lt;/font&gt;&lt;font color="#666666"&gt;"SSH_ASKPASS"&lt;/font&gt;&lt;font color="#228B22"&gt;           &lt;/font&gt;&lt;font color="#B22222"&gt;/* askpass program */&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Prefix string of HTTP_PROXY */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define HTTP_PROXY_PREFIX &lt;/font&gt;&lt;font color="#666666"&gt;"http://"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PROXY_AUTH_NONE 0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PROXY_AUTH_BASIC 1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PROXY_AUTH_DIGEST 2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;int proxy_auth_type = PROXY_AUTH_NONE;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* reason of end repeating */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_UNK              -2&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_ERROR            -1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_CLOSED_BY_LOCAL  0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define REASON_CLOSED_BY_REMOTE 1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* return value of relay start function. */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define START_ERROR -1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define START_OK     0&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define START_RETRY  1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* socket related definitions */&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKET int&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef SOCKET_ERROR&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define SOCKET_ERROR -1&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define socket_errno() WSAGetLastError()&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define closesocket close&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define socket_errno() (errno)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define popen _popen&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* packet operation macro */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* debug message output */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="debug"&gt;&lt;/a&gt;void&lt;br /&gt;debug( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( f_debug ) {&lt;br /&gt;        va_start( args, fmt );&lt;br /&gt;        fprintf(stderr, &lt;font color="#666666"&gt;"DEBUG: "&lt;/font&gt;);&lt;br /&gt;        vfprintf( stderr, fmt, args );&lt;br /&gt;        va_end( args );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="debug_"&gt;&lt;/a&gt;void&lt;br /&gt;debug_( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;                  &lt;font color="#B22222"&gt;/* without prefix */&lt;/font&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( f_debug ) {&lt;br /&gt;        va_start( args, fmt );&lt;br /&gt;        vfprintf( stderr, fmt, args );&lt;br /&gt;        va_end( args );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* error message output */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="error"&gt;&lt;/a&gt;void&lt;br /&gt;error( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start( args, fmt );&lt;br /&gt;    fprintf(stderr, &lt;font color="#666666"&gt;"ERROR: "&lt;/font&gt;);&lt;br /&gt;    vfprintf( stderr, fmt, args );&lt;br /&gt;    va_end( args );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="fatal"&gt;&lt;/a&gt;void&lt;br /&gt;fatal( const char *fmt, ... )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start( args, fmt );&lt;br /&gt;    fprintf(stderr, &lt;font color="#666666"&gt;"FATAL: "&lt;/font&gt;);&lt;br /&gt;    vfprintf( stderr, fmt, args );&lt;br /&gt;    va_end( args );&lt;br /&gt;    exit (EXIT_FAILURE);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="xmalloc"&gt;&lt;/a&gt;void *&lt;br /&gt;xmalloc (size_t size)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    void *ret = malloc(size);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (ret == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot allocate memory: %d bytes.\n"&lt;/font&gt;, size);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="downcase"&gt;&lt;/a&gt;char *&lt;br /&gt;downcase( char *str )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *buf = str;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *buf ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( isupper(*buf) )&lt;br /&gt;            *buf += 'a'-'A';&lt;br /&gt;        buf++;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; str;                                 &lt;font color="#B22222"&gt;/* return converted arg */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="expand_host_and_port"&gt;&lt;/a&gt;char *&lt;br /&gt;expand_host_and_port (const char *fmt, const char *host, int port)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    const char *src;&lt;br /&gt;    char *buf, *dst, *ptr;&lt;br /&gt;    size_t len = strlen(fmt) + strlen(host) + 20;&lt;br /&gt;    buf = xmalloc (len);&lt;br /&gt;    dst = buf;&lt;br /&gt;    src = fmt;&lt;br /&gt;    &lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (*src) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*src == '%') {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; (src[1]) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'h':&lt;br /&gt;                strcpy (dst, host);&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'p':&lt;br /&gt;                snprintf (dst, len, &lt;font color="#666666"&gt;"%d"&lt;/font&gt;, port);&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                src ++;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;            dst = buf + strlen (buf);&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*src == '\\') {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; (src[1]) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'r':                                &lt;font color="#B22222"&gt;/* CR */&lt;/font&gt;&lt;br /&gt;                *dst++ = '\r';&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'n':                                &lt;font color="#B22222"&gt;/* LF */&lt;/font&gt;&lt;br /&gt;                *dst++ = '\n';&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 't':                                &lt;font color="#B22222"&gt;/* TAB */&lt;/font&gt;&lt;br /&gt;                *dst++ = '\t';&lt;br /&gt;                src += 2;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                src ++;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* usual */&lt;/font&gt;&lt;br /&gt;            *dst++ = *src++;&lt;br /&gt;        }&lt;br /&gt;        *dst = '\0';&lt;br /&gt;    }&lt;br /&gt;    assert (strlen(buf) &amp;lt; len);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="lookup_resolve"&gt;&lt;/a&gt;int&lt;br /&gt;lookup_resolve( const char *str )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *buf = strdup( str );&lt;br /&gt;    int ret;&lt;br /&gt;&lt;br /&gt;    downcase( buf );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp( buf, &lt;font color="#666666"&gt;"both"&lt;/font&gt; ) == 0 )&lt;br /&gt;        ret = RESOLVE_BOTH;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp( buf, &lt;font color="#666666"&gt;"remote"&lt;/font&gt; ) == 0 )&lt;br /&gt;        ret = RESOLVE_REMOTE;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp( buf, &lt;font color="#666666"&gt;"local"&lt;/font&gt; ) == 0 )&lt;br /&gt;        ret = RESOLVE_LOCAL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strspn(buf, dotdigits) == strlen(buf) ) {&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef WITH_RESOLVER&lt;/font&gt;&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Sorry, you can't specify to resolve the hostname with the -R option on Win32 environment."&lt;/font&gt;);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not WITH_RESOLVER */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;        ret = RESOLVE_LOCAL;                    &lt;font color="#B22222"&gt;/* this case is also 'local' */&lt;/font&gt;&lt;br /&gt;        socks_ns.sin_addr.s_addr = inet_addr(buf);&lt;br /&gt;        socks_ns.sin_family = AF_INET;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;        ret = RESOLVE_UNKNOWN;&lt;br /&gt;    free(buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="getusername"&gt;&lt;/a&gt;char *&lt;br /&gt;getusername(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifdef _WIN32&lt;/font&gt;&lt;br /&gt;    static char buf[1024];&lt;br /&gt;    DWORD size = &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf);&lt;br /&gt;    buf[0] = '\0';&lt;br /&gt;    GetUserName( buf, &amp;amp;size);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct passwd&lt;/font&gt; *pw = getpwuid(getuid());&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( pw == NULL )&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"getpwuid() failed for uid: %d\n"&lt;/font&gt;, getuid());&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; pw-&amp;gt;pw_name;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* expect&lt;br /&gt;   check STR is begin with substr with case-ignored comparison.&lt;br /&gt;   Return 1 if matched, otherwise 0.&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="expect"&gt;&lt;/a&gt;int&lt;br /&gt;expect( char *str, char *substr)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int len = strlen(substr);&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; len-- ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( toupper(*str) != toupper(*substr) )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                           &lt;font color="#B22222"&gt;/* not matched */&lt;/font&gt;&lt;br /&gt;        str++, substr++;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                   &lt;font color="#B22222"&gt;/* good, matched */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** PARAMETER operation **/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PARAMETER_FILE &lt;/font&gt;&lt;font color="#666666"&gt;"/etc/connectrc"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define PARAMETER_DOTFILE &lt;/font&gt;&lt;font color="#666666"&gt;".connectrc"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;typedef&lt;/font&gt; &lt;font color="#4169E1"&gt;struct&lt;/font&gt; {&lt;br /&gt;    char* name;&lt;br /&gt;    char* value;&lt;br /&gt;} PARAMETER_ITEM;&lt;br /&gt;PARAMETER_ITEM parameter_table[] = {&lt;br /&gt;    { ENV_SOCKS_SERVER, NULL },&lt;br /&gt;    { ENV_SOCKS5_SERVER, NULL },&lt;br /&gt;    { ENV_SOCKS4_SERVER, NULL },&lt;br /&gt;    { ENV_SOCKS_RESOLVE, NULL },&lt;br /&gt;    { ENV_SOCKS5_RESOLVE, NULL },&lt;br /&gt;    { ENV_SOCKS4_RESOLVE, NULL },&lt;br /&gt;    { ENV_SOCKS5_USER, NULL },&lt;br /&gt;    { ENV_SOCKS5_PASSWD, NULL },&lt;br /&gt;    { ENV_SOCKS5_PASSWORD, NULL },&lt;br /&gt;    { ENV_HTTP_PROXY, NULL },&lt;br /&gt;    { ENV_HTTP_PROXY_USER, NULL },&lt;br /&gt;    { ENV_HTTP_PROXY_PASSWORD, NULL },&lt;br /&gt;    { ENV_CONNECT_USER, NULL },&lt;br /&gt;    { ENV_CONNECT_PASSWORD, NULL },&lt;br /&gt;    { ENV_SSH_ASKPASS, NULL },&lt;br /&gt;    { ENV_SOCKS5_DIRECT, NULL },&lt;br /&gt;    { ENV_SOCKS4_DIRECT, NULL },&lt;br /&gt;    { ENV_SOCKS_DIRECT, NULL },&lt;br /&gt;    { ENV_HTTP_DIRECT, NULL },&lt;br /&gt;    { ENV_CONNECT_DIRECT, NULL },&lt;br /&gt;    { ENV_SOCKS5_AUTH, NULL },&lt;br /&gt;    { NULL, NULL }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="find_parameter_item"&gt;&lt;/a&gt;PARAMETER_ITEM*&lt;br /&gt;find_parameter_item(const char* name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int i;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt;( i = 0; parameter_table[i].name != NULL; i++ ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strcmp(name, parameter_table[i].name) == 0 )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; &amp;amp;parameter_table[i];&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="read_parameter_file_1"&gt;&lt;/a&gt;void&lt;br /&gt;read_parameter_file_1(const char* name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    FILE* f;&lt;br /&gt;    int line;&lt;br /&gt;    char lbuf[1025];&lt;br /&gt;    f = fopen(name, &lt;font color="#666666"&gt;"r"&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt;( f ){&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"Reading parameter file(%s)\n"&lt;/font&gt;, name);&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( line = 1; fgets(lbuf, 1024, f); line++ ) {&lt;br /&gt;            char *p, *q, *param, *value;&lt;br /&gt;            p = strchr(lbuf, '\n');&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( p == NULL )&lt;br /&gt;                fatal(&lt;font color="#666666"&gt;"%s:%d: buffer overflow\n"&lt;/font&gt;, name, line);&lt;br /&gt;            *p = '\0';&lt;br /&gt;            p = strchr(lbuf, '#');&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( p )&lt;br /&gt;                *p = '\0';&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( p = lbuf; *p; p++ )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt;( *p != ' ' &amp;amp;&amp;amp; *p != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *p == '\0' ) &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;&lt;br /&gt;            param = p;&lt;br /&gt;            p = strchr(p, '=');&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( p == NULL ) {&lt;br /&gt;                error(&lt;font color="#666666"&gt;"%s:%d: missing equal sign\n"&lt;/font&gt;, name, line);&lt;br /&gt;                &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( q = p - 1; q &amp;gt;= lbuf; q-- )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *q != ' ' &amp;amp;&amp;amp; *q != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            *++q = '\0';&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( ++p; *p; p++ )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *p != ' ' &amp;amp;&amp;amp; *p != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            value = p;&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( ; *p; p++ );&lt;br /&gt;            &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( p--; p &amp;gt;= lbuf; p-- )&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *p != ' ' &amp;amp;&amp;amp; *p != '\t' ) &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            *++p = '\0';&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( param &amp;amp;&amp;amp; value ) {&lt;br /&gt;                PARAMETER_ITEM *item;&lt;br /&gt;                item = find_parameter_item(param);&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( item == NULL ) {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"%s:%d: unknown parameter `%s'\n"&lt;/font&gt;, name, line, param);&lt;br /&gt;                    &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;&lt;br /&gt;                }&lt;br /&gt;                item-&amp;gt;value = strdup(value);&lt;br /&gt;                debug(&lt;font color="#666666"&gt;"Parameter `%s' is set to `%s'\n"&lt;/font&gt;, param, value);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="read_parameter_file"&gt;&lt;/a&gt;void&lt;br /&gt;read_parameter_file(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) || defined(cygwin)&lt;/font&gt;&lt;br /&gt;    char *name;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct passwd&lt;/font&gt; *pw;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    read_parameter_file_1(PARAMETER_FILE);&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) || defined(cygwin)&lt;/font&gt;&lt;br /&gt;    pw = getpwuid(getuid());&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( pw == NULL )&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"getpwuid() failed for uid: %d\n"&lt;/font&gt;, getuid());&lt;br /&gt;    name = xmalloc(strlen(pw-&amp;gt;pw_dir) + strlen(PARAMETER_DOTFILE) + 2);&lt;br /&gt;    strcpy(name, pw-&amp;gt;pw_dir);&lt;br /&gt;    strcat(name, &lt;font color="#666666"&gt;"/"&lt;/font&gt; PARAMETER_DOTFILE);&lt;br /&gt;    read_parameter_file_1(name);&lt;br /&gt;    free(name);&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="getparam"&gt;&lt;/a&gt;char*&lt;br /&gt;getparam(const char* name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *value = getenv(name);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( value == NULL ){&lt;br /&gt;        PARAMETER_ITEM *item = find_parameter_item(name);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( item != NULL )&lt;br /&gt;            value = item-&amp;gt;value;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; value;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** DIRECT connection **/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define MAX_DIRECT_ADDR_LIST 256&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="ADDRPAIR"&gt;&lt;/a&gt;struct ADDRPAIR &lt;/font&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; addr;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; mask;&lt;br /&gt;    char *name;&lt;br /&gt;    int negative;&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;&lt;a name="ADDRPAIR"&gt;&lt;/a&gt;struct ADDRPAIR &lt;/font&gt;direct_addr_list[MAX_DIRECT_ADDR_LIST];&lt;br /&gt;int n_direct_addr_list = 0;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="mask_addr"&gt;&lt;/a&gt;void&lt;br /&gt;mask_addr (void *addr, void *mask, int addrlen)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *a, *m;&lt;br /&gt;    a = addr;&lt;br /&gt;    m = mask;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; addrlen-- )&lt;br /&gt;        *a++ &amp;amp;= *m++;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="add_direct_addr"&gt;&lt;/a&gt;int&lt;br /&gt;add_direct_addr (struct in_addr *addr, struct in_addr *mask, int negative)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; iaddr;&lt;br /&gt;    char *s;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( MAX_DIRECT_ADDR_LIST &amp;lt;= n_direct_addr_list ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"direct address table is full!\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    iaddr = *addr;&lt;br /&gt;    mask_addr(&amp;amp;iaddr, mask, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(iaddr));&lt;br /&gt;    s = strdup(inet_ntoa(iaddr));&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"adding direct addr entry: %s%s/%s\n"&lt;/font&gt;,&lt;br /&gt;          negative? &lt;font color="#666666"&gt;"!"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;, s, inet_ntoa(*mask));&lt;br /&gt;    free(s);&lt;br /&gt;    memcpy( &amp;amp;direct_addr_list[n_direct_addr_list].addr,&lt;br /&gt;            &amp;amp;iaddr, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(iaddr));&lt;br /&gt;    memcpy( &amp;amp;direct_addr_list[n_direct_addr_list].mask,&lt;br /&gt;            mask, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(*mask));&lt;br /&gt;    direct_addr_list[n_direct_addr_list].name = NULL;&lt;br /&gt;    direct_addr_list[n_direct_addr_list].negative = negative;&lt;br /&gt;    n_direct_addr_list++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* add domain/host name entry to direct name table */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="add_direct_host"&gt;&lt;/a&gt;int&lt;br /&gt;add_direct_host( const char *name, int negative)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( MAX_DIRECT_ADDR_LIST &amp;lt;= n_direct_addr_list ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"direct address table is full!\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*name == '*')&lt;br /&gt;        name++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*name == '.')&lt;br /&gt;        name++;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"adding direct name entry: %s%s\n"&lt;/font&gt;, negative? &lt;font color="#666666"&gt;"!"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;, name);&lt;br /&gt;    direct_addr_list[n_direct_addr_list].name = downcase(strdup(name));&lt;br /&gt;    direct_addr_list[n_direct_addr_list].negative = negative;&lt;br /&gt;    n_direct_addr_list++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="parse_addr_pair"&gt;&lt;/a&gt;int&lt;br /&gt;parse_addr_pair (const char *str, struct in_addr *addr, struct in_addr *mask)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#B22222"&gt;/* NOTE: */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Assume already be splitted by separator&lt;br /&gt;       and formatted as folowing:&lt;br /&gt;       1)  12.34.56.789/255.255.255.0&lt;br /&gt;       2)  12.34.56.789/24&lt;br /&gt;       3)  12.34.56.&lt;br /&gt;       All above generates same addr/mask pair 12.34.56.0 and 255.255.255.0&lt;br /&gt;    */&lt;/font&gt;&lt;br /&gt;    const char *ptr;&lt;br /&gt;    u_char *dsta, *dstm;&lt;br /&gt;    int i, n;&lt;br /&gt;&lt;br /&gt;    assert( str != NULL );&lt;br /&gt;    addr-&amp;gt;s_addr = 0;&lt;br /&gt;    mask-&amp;gt;s_addr = 0;&lt;br /&gt;    ptr = str;&lt;br /&gt;    dsta = (u_char*)&amp;amp;addr-&amp;gt;s_addr;&lt;br /&gt;    dstm = (u_char*)&amp;amp;mask-&amp;gt;s_addr;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;4; i++ ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '\0' )&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;              &lt;font color="#B22222"&gt;/* case of format #3 */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !isdigit(*ptr) )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;          &lt;font color="#B22222"&gt;/* format error: */&lt;/font&gt;&lt;br /&gt;        *dsta++ = atoi( ptr );&lt;br /&gt;        *dstm++ = 255;          &lt;font color="#B22222"&gt;/* automatic mask for format #3 */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( isdigit(*ptr) ) &lt;font color="#B22222"&gt;/* skip digits */&lt;/font&gt;&lt;br /&gt;            ptr++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '.' )&lt;br /&gt;            ptr++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* At this point, *ptr points '/' or EOS ('\0') */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '\0' )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                       &lt;font color="#B22222"&gt;/* complete as format #3 */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr != '/' )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                      &lt;font color="#B22222"&gt;/* format error */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Now parse mask for format #1 or #2 */&lt;/font&gt;&lt;br /&gt;    ptr++;&lt;br /&gt;    mask-&amp;gt;s_addr = 0;                   &lt;font color="#B22222"&gt;/* clear automatic mask */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strchr( ptr, '.') ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of format #1 */&lt;/font&gt;&lt;br /&gt;        dstm = (u_char*)&amp;amp;mask-&amp;gt;s_addr;&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;4; i++) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !isdigit(*ptr) )&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;              &lt;font color="#B22222"&gt;/* format error: */&lt;/font&gt;&lt;br /&gt;            *dstm++ = atoi(ptr);&lt;br /&gt;            &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( isdigit(*ptr) )     &lt;font color="#B22222"&gt;/* skip digits */&lt;/font&gt;&lt;br /&gt;                ptr++;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *ptr == '.' )&lt;br /&gt;                ptr++;&lt;br /&gt;            &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;                  &lt;font color="#B22222"&gt;/* from for loop */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#B22222"&gt;/* complete as format #1 */&lt;/font&gt;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of format #2 */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !isdigit(*ptr) )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                  &lt;font color="#B22222"&gt;/* format error: */&lt;/font&gt;&lt;br /&gt;        n = atoi(ptr);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( n&amp;lt;0 || 32&amp;lt;n)&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                  &lt;font color="#B22222"&gt;/* format error */&lt;/font&gt;&lt;br /&gt;        mask-&amp;gt;s_addr = (n==0)? 0: htonl(((u_long)0xFFFFFFFF)&amp;lt;&amp;lt;(32-n));&lt;br /&gt;        &lt;font color="#B22222"&gt;/* complete as format #1 */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="initialize_direct_addr"&gt;&lt;/a&gt;void&lt;br /&gt;initialize_direct_addr (void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int negative;&lt;br /&gt;    int n_entries;&lt;br /&gt;    char *env = NULL, *beg, *next, *envkey = NULL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; addr, mask;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_SOCKS ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_version == 5 )&lt;br /&gt;            envkey = ENV_SOCKS5_DIRECT;&lt;br /&gt;        &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;            envkey = ENV_SOCKS4_DIRECT;&lt;br /&gt;        env = getparam(envkey);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;            env = getparam(ENV_SOCKS_DIRECT);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_HTTP ){&lt;br /&gt;        env = getparam(ENV_HTTP_DIRECT);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;        env = getparam(ENV_CONNECT_DIRECT);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;                 &lt;font color="#B22222"&gt;/* no entry */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"making direct addr list from: '%s'\n"&lt;/font&gt;, env);&lt;br /&gt;    env = strdup( env );        &lt;font color="#B22222"&gt;/* reallocate to modify */&lt;/font&gt;&lt;br /&gt;    beg = next = env;&lt;br /&gt;    n_entries = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;do&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( MAX_DIRECT_ADDR_LIST &amp;lt;= n_entries ) {&lt;br /&gt;            error(&lt;font color="#666666"&gt;"too many entries in %s"&lt;/font&gt;, envkey);&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;              &lt;font color="#B22222"&gt;/* from do loop */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;        next = strchr( beg, ',');&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( next != NULL )&lt;br /&gt;            *next++ = '\0';&lt;br /&gt;        addr.s_addr = 0;&lt;br /&gt;        mask.s_addr = 0;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*beg == '!') {&lt;br /&gt;            negative = 1;&lt;br /&gt;            beg++;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;            negative = 0;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !parse_addr_pair( beg, &amp;amp;addr, &amp;amp;mask ) ) {&lt;br /&gt;            add_direct_addr( &amp;amp;addr, &amp;amp;mask, negative );&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            add_direct_host( beg, negative );&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( next != NULL )&lt;br /&gt;            beg = next;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( next != NULL );&lt;br /&gt;&lt;br /&gt;    free( env );&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="cmp_addr"&gt;&lt;/a&gt;int&lt;br /&gt;cmp_addr (void *addr1, void *addr2, int addrlen)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; memcmp( addr1, addr2, addrlen );&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="is_direct_address"&gt;&lt;/a&gt;int&lt;br /&gt;is_direct_address (const struct in_addr addr)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int i, neg;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; iaddr;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Note: assume IPV4 address !! */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;n_direct_addr_list; i++ ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (direct_addr_list[i].name != NULL)&lt;br /&gt;            &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;                           &lt;font color="#B22222"&gt;/* it's name entry */&lt;/font&gt;&lt;br /&gt;        neg = direct_addr_list[i].negative;&lt;br /&gt;        iaddr = addr;&lt;br /&gt;        mask_addr( &amp;amp;iaddr, &amp;amp;direct_addr_list[i].mask,&lt;br /&gt;                   &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(&lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt;));&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (cmp_addr(&amp;amp;iaddr, &amp;amp;direct_addr_list[i].addr,&lt;br /&gt;                     &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(&lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt;)) == 0) {&lt;br /&gt;            char *a, *m;&lt;br /&gt;            a = strdup(inet_ntoa(direct_addr_list[i].addr));&lt;br /&gt;            m = strdup(inet_ntoa(direct_addr_list[i].mask));&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"match with: %s/%s%s\n"&lt;/font&gt;, a, m, neg? &lt;font color="#666666"&gt;" (negative)"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;);&lt;br /&gt;            free(a);&lt;br /&gt;            free(m);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; !neg? 1: 0;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"not matched, addr to be relayed: %s\n"&lt;/font&gt;, inet_ntoa(addr));&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                   &lt;font color="#B22222"&gt;/* not direct */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* check s1 is ends with s2.&lt;br /&gt;   return 1 if exact match or domain part match.&lt;br /&gt;   return 0 if s1 is shorter than s2 or partial match.&lt;br /&gt;   For example, &lt;br /&gt;    ends_with("bar.com", "bar.com")        =&amp;gt; 1 (exact match)&lt;br /&gt;    ends_with("foo.bar.com", "bar.com")    =&amp;gt; 1 (domain match)&lt;br /&gt;    ends_with("foo.beebar.com", "bar.com") =&amp;gt; 0 (partial match)&lt;br /&gt;    ends_with("bar", "bar.com")            =&amp;gt; 0 (shorter)&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="omain_match"&gt;&lt;/a&gt;domain_match(const char *s1, const char *s2)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int len1, len2;&lt;br /&gt;    const char *tail1, *tail2;&lt;br /&gt;    len1 = strlen(s1);&lt;br /&gt;    len2 = strlen(s2);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (len1 &amp;lt; len2 || len1 == 0 || len2 == 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;    tail1 = s1 + len1;&lt;br /&gt;    tail2 = s2 + len2;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (0 &amp;lt; len1 &amp;amp;&amp;amp; 0 &amp;lt; len2) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*--tail1 != *--tail2)&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;                              &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;        len1--, len2--;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (len2 != 0)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* Now exact match, domain match or partial match.&lt;br /&gt;       Return true if exact or domain match.&lt;br /&gt;       Or continue checking. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (tail1 == s1 || tail1[-1] == '.')&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                               &lt;font color="#B22222"&gt;/* match! */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                   &lt;font color="#B22222"&gt;/* not match */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Check given NAME is ends with one of &lt;br /&gt;   registered direct name entry.&lt;br /&gt;   Return 1 if matched, or 0.&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="is_direct_name"&gt;&lt;/a&gt;int&lt;br /&gt;is_direct_name (const char *name)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int len, i;&lt;br /&gt;    const char *tail;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"checking %s is for direct?\n"&lt;/font&gt;, name);&lt;br /&gt;    name = downcase(strdup(name));&lt;br /&gt;    len = strlen(name);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (len &amp;lt; 1)&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* false */&lt;/font&gt;&lt;br /&gt;    tail = &amp;amp;name[len];&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;n_direct_addr_list; i++ ) {&lt;br /&gt;        int dlen, neg;&lt;br /&gt;        const char *dname;&lt;br /&gt;        const char *n, *d;&lt;br /&gt;        dname = direct_addr_list[i].name;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (dname == NULL)&lt;br /&gt;            &lt;font color="#4169E1"&gt;continue&lt;/font&gt;;                           &lt;font color="#B22222"&gt;/* it's addr/mask entry */&lt;/font&gt;&lt;br /&gt;        neg = direct_addr_list[i].negative;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (domain_match(name, dname)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"match with: %s%s\n"&lt;/font&gt;, dname, neg? &lt;font color="#666666"&gt;" (negative)"&lt;/font&gt;: &lt;font color="#666666"&gt;""&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; (neg) {&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;       &lt;font color="#B22222"&gt;/* not direct */&lt;/font&gt;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;       &lt;font color="#B22222"&gt;/* direct*/&lt;/font&gt;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                   &lt;font color="#B22222"&gt;/* not matched */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* check to connect to HOST directyly?&lt;br /&gt;   return 1 if to be direct, 0 for else. */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="check_direct"&gt;&lt;/a&gt;int&lt;br /&gt;check_direct(const char *host)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct in_addr&lt;/font&gt; addr;&lt;br /&gt;    addr.s_addr = inet_addr(host);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (addr.s_addr != INADDR_NONE) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of IP address */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (is_direct_address(addr)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"%s is for direct.\n"&lt;/font&gt;, host);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                           &lt;font color="#B22222"&gt;/* true */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* case of hostname */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (is_direct_name(host)) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"%s is for direct.\n"&lt;/font&gt;, host);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; 1;                           &lt;font color="#B22222"&gt;/* true */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"%s is for not direct.\n"&lt;/font&gt;, host);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                    &lt;font color="#B22222"&gt;/* false */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/** TTY operation **/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;int intr_flag = 0;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="intr_handler"&gt;&lt;/a&gt;void&lt;br /&gt;intr_handler(int sig)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    intr_flag = 1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="tty_change_echo"&gt;&lt;/a&gt;void&lt;br /&gt;tty_change_echo(int fd, int enable)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static &lt;font color="#4169E1"&gt;struct termios&lt;/font&gt; ntio, otio;           &lt;font color="#B22222"&gt;/* new/old termios */&lt;/font&gt;&lt;br /&gt;    static sigset_t nset, oset;                 &lt;font color="#B22222"&gt;/* new/old sigset */&lt;/font&gt;&lt;br /&gt;    static &lt;font color="#4169E1"&gt;struct sigaction&lt;/font&gt; nsa, osa;           &lt;font color="#B22222"&gt;/* new/old sigaction */&lt;/font&gt;&lt;br /&gt;    static int disabled = 0;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( disabled &amp;amp;&amp;amp; enable ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* enable echo */&lt;/font&gt;&lt;br /&gt;        tcsetattr(fd, TCSANOW, &amp;amp;otio);&lt;br /&gt;        disabled = 0;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* resotore sigaction */&lt;/font&gt;&lt;br /&gt;        sigprocmask(SIG_SETMASK, &amp;amp;oset, NULL);&lt;br /&gt;        sigaction(SIGINT, &amp;amp;osa, NULL);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( intr_flag != 0 ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* re-generate signal  */&lt;/font&gt;&lt;br /&gt;            kill(getpid(), SIGINT);&lt;br /&gt;            sigemptyset(&amp;amp;nset);&lt;br /&gt;            sigsuspend(&amp;amp;nset);&lt;br /&gt;            intr_flag = 0;&lt;br /&gt;        }&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!disabled &amp;amp;&amp;amp; !enable) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* set SIGINTR handler and break syscall on singal */&lt;/font&gt;&lt;br /&gt;        sigemptyset(&amp;amp;nset);&lt;br /&gt;        sigaddset(&amp;amp;nset, SIGTSTP);&lt;br /&gt;        sigprocmask(SIG_BLOCK, &amp;amp;nset, &amp;amp;oset);&lt;br /&gt;        intr_flag = 0;&lt;br /&gt;        memset(&amp;amp;nsa, 0, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(nsa));&lt;br /&gt;        nsa.sa_handler = intr_handler;&lt;br /&gt;        sigaction(SIGINT, &amp;amp;nsa, &amp;amp;osa);&lt;br /&gt;        &lt;font color="#B22222"&gt;/* disable echo */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (tcgetattr(fd, &amp;amp;otio) == 0 &amp;amp;&amp;amp; (otio.c_lflag &amp;amp; ECHO)) {&lt;br /&gt;            disabled = 1;&lt;br /&gt;            ntio = otio;&lt;br /&gt;            ntio.c_lflag &amp;amp;= ~(ECHO | ECHOE | ECHOK | ECHONL);&lt;br /&gt;            (void) tcsetattr(fd, TCSANOW, &amp;amp;ntio);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define TTY_NAME &lt;/font&gt;&lt;font color="#666666"&gt;"/dev/tty"&lt;/font&gt;&lt;font color="#228B22"&gt;&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="tty_readpass"&gt;&lt;/a&gt;int&lt;br /&gt;tty_readpass( const char *prompt, char *buf, size_t size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int tty, ret = 0;&lt;br /&gt;&lt;br /&gt;    tty = open(TTY_NAME, O_RDWR);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( tty &amp;lt; 0 ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Unable to open %s\n"&lt;/font&gt;, TTY_NAME);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* can't open tty */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( size &amp;lt;= 0 )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* no room */&lt;/font&gt;&lt;br /&gt;    write(tty, prompt, strlen(prompt));&lt;br /&gt;    buf[0] = '\0';&lt;br /&gt;    tty_change_echo(tty, 0);                    &lt;font color="#B22222"&gt;/* disable echo */&lt;/font&gt;&lt;br /&gt;    ret = read(tty,buf, size-1);&lt;br /&gt;    tty_change_echo(tty, 1);                    &lt;font color="#B22222"&gt;/* restore */&lt;/font&gt;&lt;br /&gt;    write(tty, &lt;font color="#666666"&gt;"\n"&lt;/font&gt;, 1);                        &lt;font color="#B22222"&gt;/* new line */&lt;/font&gt;&lt;br /&gt;    close(tty);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strchr(buf,'\n') == NULL  )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; ret )&lt;br /&gt;        buf[ret] = '\0';&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#else  &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="w32_intr_handler"&gt;&lt;/a&gt;BOOL __stdcall&lt;br /&gt;w32_intr_handler(DWORD dwCtrlType)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dwCtrlType == CTRL_C_EVENT ) {&lt;br /&gt;        intr_flag = 1;&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; TRUE;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; FALSE;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#228B22"&gt;#define tty_readpass w32_tty_readpass&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="w32_tty_readpass"&gt;&lt;/a&gt;int&lt;br /&gt;w32_tty_readpass( const char *prompt, char *buf, size_t size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    HANDLE in = CreateFile(&lt;font color="#666666"&gt;"CONIN$"&lt;/font&gt;, GENERIC_READ|GENERIC_WRITE,&lt;br /&gt;                           0, NULL, OPEN_EXISTING, 0, NULL);&lt;br /&gt;    HANDLE out = CreateFile(&lt;font color="#666666"&gt;"CONOUT$"&lt;/font&gt;, GENERIC_WRITE,&lt;br /&gt;                            0, NULL, OPEN_EXISTING, 0, NULL);&lt;br /&gt;    DWORD mode;&lt;br /&gt;    DWORD ret, bytes;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (in == INVALID_HANDLE_VALUE || out == INVALID_HANDLE_VALUE)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot open console. (errno=%d)"&lt;/font&gt;, GetLastError());&lt;br /&gt;&lt;br /&gt;    WriteFile(out, prompt, strlen(prompt), &amp;amp;bytes, 0);&lt;br /&gt;    SetConsoleCtrlHandler(w32_intr_handler, TRUE ); &lt;font color="#B22222"&gt;/* add handler */&lt;/font&gt;&lt;br /&gt;    GetConsoleMode(in, &amp;amp;mode);&lt;br /&gt;    SetConsoleMode(in, mode&amp;amp;~ENABLE_ECHO_INPUT); &lt;font color="#B22222"&gt;/* disable echo */&lt;/font&gt;&lt;br /&gt;    ret = ReadFile(in, buf, size, &amp;amp;bytes, 0);&lt;br /&gt;    SetConsoleMode(in, mode);                   &lt;font color="#B22222"&gt;/* enable echo */&lt;/font&gt;&lt;br /&gt;    SetConsoleCtrlHandler( w32_intr_handler, FALSE ); &lt;font color="#B22222"&gt;/* remove handler */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( intr_flag )&lt;br /&gt;        GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); &lt;font color="#B22222"&gt;/* re-signal */&lt;/font&gt;&lt;br /&gt;    WriteFile(out,&lt;font color="#666666"&gt;"\n"&lt;/font&gt;, 1, &amp;amp;bytes, 0);&lt;br /&gt;    CloseHandle(in);&lt;br /&gt;    CloseHandle(out);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/*** User / Password ***/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* SOCKS5 and HTTP Proxy authentication may requires username and&lt;br /&gt;   password. We ll give it via environment variable or tty.&lt;br /&gt;   Username and password for authentication are decided by&lt;br /&gt;   following rules:&lt;br /&gt;&lt;br /&gt;   Username is taken from&lt;br /&gt;     1) server location spec (i.e. user@host:port)&lt;br /&gt;     2) environment variables (see tables.1)&lt;br /&gt;     3) system account name currently logged in.&lt;br /&gt;&lt;br /&gt;     Table.1 Order of environment variables for username&lt;br /&gt;&lt;br /&gt;        |  SOCKS v5   |  SOCKS v4   |   HTTP proxy    |&lt;br /&gt;      --+-------------+-------------+-----------------+&lt;br /&gt;      1 | SOCKS45_USER | SOCKS4_USER | HTTP_PROXY_USER |&lt;br /&gt;      --+-------------+-------------+                 |&lt;br /&gt;      2 |        SOCKS_USER         |                 |&lt;br /&gt;      --+---------------------------+-----------------+&lt;br /&gt;      3 |              CONNECT_USER                   |&lt;br /&gt;      --+---------------------------------------------+&lt;br /&gt;&lt;br /&gt;   Password is taken from&lt;br /&gt;     1) by environment variables (see table.2)&lt;br /&gt;     2) by entering from tty.&lt;br /&gt;&lt;br /&gt;     Table.2 Order of environment variables for password&lt;br /&gt;&lt;br /&gt;        |    SOCKS v5     |     HTTP proxy      |&lt;br /&gt;      --+-----------------+---------------------+&lt;br /&gt;      1 | SOCKS5_PASSWD   |                     |&lt;br /&gt;      --+-----------------+ HTTP_PROXY_PASSWORD |&lt;br /&gt;      2 | SOCKS5_PASSWORD |                     |&lt;br /&gt;      --+-----------------+---------------------+&lt;br /&gt;      3 |           CONNECT_PASSWORD            |&lt;br /&gt;      --+---------------------------------------+&lt;br /&gt;&lt;br /&gt;      Note: SOCKS5_PASSWD which is added in rev. 1.79&lt;br /&gt;            to share value with NEC SOCKS implementation.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="determine_relay_user"&gt;&lt;/a&gt;char *&lt;br /&gt;determine_relay_user ()&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *user = NULL;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* get username from environment variable, or system. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_method == METHOD_SOCKS) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL &amp;amp;&amp;amp; socks_version == 5)&lt;br /&gt;            user = getparam (ENV_SOCKS5_USER);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL &amp;amp;&amp;amp; socks_version == 4)&lt;br /&gt;            user = getparam (ENV_SOCKS4_USER);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;            user = getparam (ENV_SOCKS_USER);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_method == METHOD_HTTP) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;            user = getparam (ENV_HTTP_PROXY_USER);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;        user = getparam (ENV_CONNECT_USER);&lt;br /&gt;    &lt;font color="#B22222"&gt;/* determine relay user by system call if not yet. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (user == NULL)&lt;br /&gt;        user = getusername();&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; user;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="determine_relay_password"&gt;&lt;/a&gt;char *&lt;br /&gt;determine_relay_password ()&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *pass = NULL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL &amp;amp;&amp;amp; relay_method == METHOD_HTTP)&lt;br /&gt;        pass = getparam(ENV_HTTP_PROXY_PASSWORD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL &amp;amp;&amp;amp; relay_method == METHOD_SOCKS)&lt;br /&gt;        pass = getparam(ENV_SOCKS5_PASSWD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL &amp;amp;&amp;amp; relay_method == METHOD_SOCKS)&lt;br /&gt;        pass = getparam(ENV_SOCKS5_PASSWORD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (pass == NULL)&lt;br /&gt;        pass = getparam(ENV_CONNECT_PASSWORD);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; pass;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/*** network operations ***/&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* set_relay()&lt;br /&gt;   Determine relay informations:&lt;br /&gt;   method, host, port, and username.&lt;br /&gt;   1st arg, METHOD should be METHOD_xxx.&lt;br /&gt;   2nd arg, SPEC is hostname or hostname:port or user@hostame:port.&lt;br /&gt;   hostname is domain name or dot notation.&lt;br /&gt;   If port is omitted, use 80 for METHOD_HTTP method,&lt;br /&gt;   use 1080 for METHOD_SOCKS method.&lt;br /&gt;   Username is also able to given by 3rd. format.&lt;br /&gt;   2nd argument SPEC can be NULL. if NULL, use environment variable.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="set_relay"&gt;&lt;/a&gt;int&lt;br /&gt;set_relay( int method, char *spec )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *buf, *sep, *resolve;&lt;br /&gt;&lt;br /&gt;    relay_method = method;&lt;br /&gt;&lt;br /&gt;    read_parameter_file();&lt;br /&gt;    initialize_direct_addr();&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (n_direct_addr_list == 0) {&lt;br /&gt;        debug (&lt;font color="#666666"&gt;"No direct address are specified.\n"&lt;/font&gt;);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug (&lt;font color="#666666"&gt;"%d direct address entries.\n"&lt;/font&gt;, n_direct_addr_list);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( method ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_DIRECT:&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* nothing to do */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_SOCKS:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( socks_version ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 5:&lt;br /&gt;                spec = getparam(ENV_SOCKS5_SERVER);&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 4:&lt;br /&gt;                spec = getparam(ENV_SOCKS4_SERVER);&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            spec = getparam(ENV_SOCKS_SERVER);&lt;br /&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"Failed to determine SOCKS server.\n"&lt;/font&gt;);&lt;br /&gt;        relay_port = 1080;                      &lt;font color="#B22222"&gt;/* set default first */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* determine resolve method */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_resolve == RESOLVE_UNKNOWN ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ((socks_version == 5) &amp;amp;&amp;amp;&lt;br /&gt;                  ((resolve = getparam(ENV_SOCKS5_RESOLVE)) != NULL)) ||&lt;br /&gt;                 ((socks_version == 4) &amp;amp;&amp;amp;&lt;br /&gt;                  ((resolve = getparam(ENV_SOCKS4_RESOLVE)) != NULL)) ||&lt;br /&gt;                 ((resolve = getparam(ENV_SOCKS_RESOLVE)) != NULL) ) {&lt;br /&gt;                socks_resolve = lookup_resolve( resolve );&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_resolve == RESOLVE_UNKNOWN )&lt;br /&gt;                    fatal(&lt;font color="#666666"&gt;"Invalid resolve method: %s\n"&lt;/font&gt;, resolve);&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* default */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( socks_version == 5 )&lt;br /&gt;                    socks_resolve = RESOLVE_REMOTE;&lt;br /&gt;                &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;                    socks_resolve = RESOLVE_LOCAL;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_HTTP:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            spec = getparam(ENV_HTTP_PROXY);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"You must specify http proxy server\n"&lt;/font&gt;);&lt;br /&gt;        relay_port = 80;                        &lt;font color="#B22222"&gt;/* set default first */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; METHOD_TELNET:&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            spec = getparam(ENV_TELNET_PROXY);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( spec == NULL )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"You must specify telnet proxy server\n"&lt;/font&gt;);&lt;br /&gt;        relay_port = 23;                        &lt;font color="#B22222"&gt;/* set default first */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (expect( spec, HTTP_PROXY_PREFIX)) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* URL format like: "http://server:port/" */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* extract server:port part */&lt;/font&gt;&lt;br /&gt;        buf = strdup( spec + strlen(HTTP_PROXY_PREFIX));&lt;br /&gt;        buf[strcspn(buf, &lt;font color="#666666"&gt;"/"&lt;/font&gt;)] = '\0';&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* assume spec is aready "server:port" format */&lt;/font&gt;&lt;br /&gt;        buf = strdup( spec );&lt;br /&gt;    }&lt;br /&gt;    spec = buf;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check username in spec */&lt;/font&gt;&lt;br /&gt;    sep = strchr( spec, '@' );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( sep != NULL ) {&lt;br /&gt;        *sep = '\0';&lt;br /&gt;        relay_user = strdup( spec );&lt;br /&gt;        spec = sep +1;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_user == NULL)&lt;br /&gt;        relay_user = determine_relay_user();&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* split out hostname and port number from spec */&lt;/font&gt;&lt;br /&gt;    sep = strchr(spec,':');&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( sep == NULL ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* hostname only, port is already set as default */&lt;/font&gt;&lt;br /&gt;        relay_host = strdup( spec );&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* hostname and port */&lt;/font&gt;&lt;br /&gt;        relay_port = atoi(sep+1);&lt;br /&gt;        *sep = '\0';&lt;br /&gt;        relay_host = strdup( spec );&lt;br /&gt;    }&lt;br /&gt;    free(buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="resolve_port"&gt;&lt;/a&gt;u_short&lt;br /&gt;resolve_port( const char *service )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int port;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( service[strspn (service, digits)] == '\0'  ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* all digits, port number */&lt;/font&gt;&lt;br /&gt;        port = atoi(service);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* treat as service name */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;struct servent&lt;/font&gt; *ent;&lt;br /&gt;        ent = getservbyname( service, NULL );&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ent == NULL ) {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"Unknown service, '%s'\n"&lt;/font&gt;, service);&lt;br /&gt;            port = 0;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            port = ntohs(ent-&amp;gt;s_port);&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"service: %s =&amp;gt; %d\n"&lt;/font&gt;, service, port);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; (u_short)port;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="make_revstr"&gt;&lt;/a&gt;void&lt;br /&gt;make_revstr(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *ptr;&lt;br /&gt;    size_t len;&lt;br /&gt;    ptr = strstr(rcs_revstr, &lt;font color="#666666"&gt;": "&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!ptr) {&lt;br /&gt;        revstr = strdup(&lt;font color="#666666"&gt;"unknown"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;    ptr += 2;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* assume subversion's keyword expansion like "Revision: 96". */&lt;/font&gt;&lt;br /&gt;    minor_version = atoi(ptr);&lt;br /&gt;    revstr = xmalloc(20);&lt;br /&gt;    snprintf(revstr, 20, &lt;font color="#666666"&gt;"%d.%d"&lt;/font&gt;, major_version, minor_version);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="getarg"&gt;&lt;/a&gt;int&lt;br /&gt;getarg( int argc, char **argv )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int err = 0;&lt;br /&gt;    char *ptr, *server = (char*)NULL;&lt;br /&gt;    int method = METHOD_DIRECT;&lt;br /&gt;&lt;br /&gt;    progname = *argv;&lt;br /&gt;    argc--, argv++;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check optinos */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( (0 &amp;lt; argc) &amp;amp;&amp;amp; (**argv == '-') ) {&lt;br /&gt;        ptr = *argv + 1;&lt;br /&gt;        &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *ptr ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( *ptr ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 's':                           &lt;font color="#B22222"&gt;/* use SOCKS */&lt;/font&gt;&lt;br /&gt;                method = METHOD_SOCKS;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'n':                           &lt;font color="#B22222"&gt;/* no proxy */&lt;/font&gt;&lt;br /&gt;                method = METHOD_DIRECT;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'h':                           &lt;font color="#B22222"&gt;/* use http-proxy */&lt;/font&gt;&lt;br /&gt;                method = METHOD_HTTP;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 't':&lt;br /&gt;                method = METHOD_TELNET;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'S':                           &lt;font color="#B22222"&gt;/* specify SOCKS server */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    method = METHOD_SOCKS;&lt;br /&gt;                    server = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'H':                           &lt;font color="#B22222"&gt;/* specify http-proxy server */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    method = METHOD_HTTP;&lt;br /&gt;                    server = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'T':                           &lt;font color="#B22222"&gt;/* specify telnet proxy server */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    method = METHOD_TELNET;&lt;br /&gt;                    server = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'c':&lt;br /&gt;                 &lt;font color="#4169E1"&gt;if&lt;/font&gt; (1 &amp;lt; argc) {&lt;br /&gt;                      argv++, argc--;&lt;br /&gt;                      telnet_command = *argv;&lt;br /&gt;                 } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                      error(&lt;font color="#666666"&gt;"option '%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                      err++;&lt;br /&gt;                 }&lt;br /&gt;                 &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'P':&lt;br /&gt;                f_hold_session = 1;&lt;br /&gt;                &lt;font color="#B22222"&gt;/* without break */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'p':                          &lt;font color="#B22222"&gt;/* specify port to forward */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    local_type = LOCAL_SOCKET;&lt;br /&gt;                    local_port = resolve_port(*argv);&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'w':&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    connect_timeout = atoi(*argv);&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '4':&lt;br /&gt;                socks_version = 4;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '5':&lt;br /&gt;                socks_version = 5;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'a':&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    socks5_auth = *argv;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'R':                           &lt;font color="#B22222"&gt;/* specify resolve method */&lt;/font&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;                    argv++, argc--;&lt;br /&gt;                    socks_resolve = lookup_resolve( *argv );&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    error(&lt;font color="#666666"&gt;"option '-%c' needs argument.\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                    err++;&lt;br /&gt;                }&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'V':                           &lt;font color="#B22222"&gt;/* print version */&lt;/font&gt;&lt;br /&gt;                fprintf(stderr, &lt;font color="#666666"&gt;"%s\nVersion %s\n"&lt;/font&gt;, progdesc, revstr);&lt;br /&gt;                exit(0);&lt;br /&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; 'd':                           &lt;font color="#B22222"&gt;/* debug mode */&lt;/font&gt;&lt;br /&gt;                f_debug++;&lt;br /&gt;                &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                error(&lt;font color="#666666"&gt;"unknown option '-%c'\n"&lt;/font&gt;, *ptr);&lt;br /&gt;                err++;&lt;br /&gt;            }&lt;br /&gt;            ptr++;&lt;br /&gt;        }&lt;br /&gt;        argc--, argv++;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check error */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; err )&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; quit;&lt;br /&gt;&lt;br /&gt;    set_relay( method, server );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check destination HOST (MUST) */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( argc == 0  ) {&lt;br /&gt;        fprintf(stderr, &lt;font color="#666666"&gt;"%s\nVersion %s\n"&lt;/font&gt;, progdesc, revstr);&lt;br /&gt;        fprintf(stderr, usage, progname);&lt;br /&gt;        exit(0);&lt;br /&gt;    }&lt;br /&gt;    dest_host = argv[0];&lt;br /&gt;    &lt;font color="#B22222"&gt;/* decide port or service name from programname or argument */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ((ptr=strrchr( progname, '/' )) != NULL) ||&lt;br /&gt;         ((ptr=strchr( progname, '\\')) != NULL) )&lt;br /&gt;        ptr++;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;        ptr = progname;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dest_port == 0 ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* accept only if -P is not specified. */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 1 &amp;lt; argc ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* get port number from argument (prior to progname) */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#B22222"&gt;/* NOTE: This way is for cvs ext method. */&lt;/font&gt;&lt;br /&gt;            dest_port = resolve_port(argv[1]);&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strncmp( ptr, &lt;font color="#666666"&gt;"connect-"&lt;/font&gt;, 8) == 0 ) {&lt;br /&gt;            &lt;font color="#B22222"&gt;/* decide port number from program name */&lt;/font&gt;&lt;br /&gt;            char *str = strdup( ptr+8 );&lt;br /&gt;            str[strcspn( str, &lt;font color="#666666"&gt;"."&lt;/font&gt; )] = '\0';&lt;br /&gt;            dest_port = resolve_port(str);&lt;br /&gt;            free(str);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check port number */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( dest_port &amp;lt;= 0 ) {&lt;br /&gt;        error( &lt;font color="#666666"&gt;"You must specify the destination port correctly.\n"&lt;/font&gt;);&lt;br /&gt;        err++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; quit;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (relay_method != METHOD_DIRECT) &amp;amp;&amp;amp; (relay_port &amp;lt;= 0) ) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"Invalid relay port: %d\n"&lt;/font&gt;, dest_port);&lt;br /&gt;        err++;&lt;br /&gt;        &lt;font color="#4169E1"&gt;goto&lt;/font&gt; quit;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;quit:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* report for debugging */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"relay_method = %s (%d)\n"&lt;/font&gt;,&lt;br /&gt;          method_names[relay_method], relay_method);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method != METHOD_DIRECT ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"relay_host=%s\n"&lt;/font&gt;, relay_host);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"relay_port=%d\n"&lt;/font&gt;, relay_port);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"relay_user=%s\n"&lt;/font&gt;, relay_user);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( relay_method == METHOD_SOCKS ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"socks_version=%d\n"&lt;/font&gt;, socks_version);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"socks_resolve=%s (%d)\n"&lt;/font&gt;,&lt;br /&gt;              resolve_names[socks_resolve], socks_resolve);&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"local_type=%s\n"&lt;/font&gt;, local_type_names[local_type]);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( local_type == LOCAL_SOCKET ) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"local_port=%d\n"&lt;/font&gt;, local_port);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (f_hold_session)&lt;br /&gt;            debug (&lt;font color="#666666"&gt;"  with holding remote session.\n"&lt;/font&gt;);&lt;br /&gt;    }&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"dest_host=%s\n"&lt;/font&gt;, dest_host);&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"dest_port=%d\n"&lt;/font&gt;, dest_port);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( 0 &amp;lt; err ) {&lt;br /&gt;        fprintf(stderr, usage, progname);&lt;br /&gt;        exit(1);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#ifndef _WIN32&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* Time-out feature is not allowed for Win32 native compilers. */&lt;/font&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* MSVC and Borland C cannot but Cygwin and UNIXes can. */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* timeout signal hander */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="sig_timeout"&gt;&lt;/a&gt;void&lt;br /&gt;sig_timeout(void)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    signal( SIGALRM, SIG_IGN );&lt;br /&gt;    alarm( 0 );&lt;br /&gt;    error( &lt;font color="#666666"&gt;"timed out\n"&lt;/font&gt; );&lt;br /&gt;    exit(1);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* set timeout param = seconds, 0 clears */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="set_timeout"&gt;&lt;/a&gt;void&lt;br /&gt;set_timeout(int timeout)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#B22222"&gt;/* This feature is allowed for UNIX or cygwin environments, currently */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( timeout == 0 ) {&lt;br /&gt;        debug( &lt;font color="#666666"&gt;"clearing timeout\n"&lt;/font&gt; );&lt;br /&gt;        signal( SIGALRM, SIG_IGN );&lt;br /&gt;        alarm( 0 );&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug( &lt;font color="#666666"&gt;"setting timeout: %d seconds\n"&lt;/font&gt;, timeout );&lt;br /&gt;        signal(SIGALRM, (void *)sig_timeout);&lt;br /&gt;        alarm( timeout );&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="switch_ns"&gt;&lt;/a&gt;void&lt;br /&gt;switch_ns (struct sockaddr_in *ns)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    res_init();&lt;br /&gt;    memcpy (&amp;amp;_res.nsaddr_list[0], ns, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(*ns));&lt;br /&gt;    _res.nscount = 1;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"Using nameserver at %s\n"&lt;/font&gt;, inet_ntoa(ns-&amp;gt;sin_addr));&lt;br /&gt;}&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* !_WIN32 &amp;amp;&amp;amp; !__CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* TODO: IPv6&lt;br /&gt;   TODO: fallback if askpass execution failed.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="local_resolve"&gt;&lt;/a&gt;int&lt;br /&gt;local_resolve (const char *host, struct sockaddr_in *addr)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct hostent&lt;/font&gt; *ent;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strspn(host, dotdigits) == strlen(host) ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* given by IPv4 address */&lt;/font&gt;&lt;br /&gt;        addr-&amp;gt;sin_family = AF_INET;&lt;br /&gt;        addr-&amp;gt;sin_addr.s_addr = inet_addr(host);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"resolving host by name: %s\n"&lt;/font&gt;, host);&lt;br /&gt;        ent = gethostbyname (host);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ent ) {&lt;br /&gt;            memcpy (&amp;amp;addr-&amp;gt;sin_addr, ent-&amp;gt;h_addr, ent-&amp;gt;h_length);&lt;br /&gt;            addr-&amp;gt;sin_family = ent-&amp;gt;h_addrtype;&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"resolved: %s (%s)\n"&lt;/font&gt;,&lt;br /&gt;                  host, inet_ntoa(addr-&amp;gt;sin_addr));&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            debug(&lt;font color="#666666"&gt;"failed to resolve locally.\n"&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                          &lt;font color="#B22222"&gt;/* failed */&lt;/font&gt;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                                   &lt;font color="#B22222"&gt;/* good */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="open_connection"&gt;&lt;/a&gt;int&lt;br /&gt;open_connection( const char *host, u_short port )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    SOCKET s;&lt;br /&gt;    &lt;font color="#4169E1"&gt;struct sockaddr_in&lt;/font&gt; saddr;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* resolve address of proxy or direct target */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (local_resolve (host, &amp;amp;saddr) &amp;lt; 0) {&lt;br /&gt;        error(&lt;font color="#666666"&gt;"can't resolve hostname: %s\n"&lt;/font&gt;, host);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; SOCKET_ERROR;&lt;br /&gt;    }&lt;br /&gt;    saddr.sin_port = htons(port);&lt;br /&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"connecting to %s:%u\n"&lt;/font&gt;, inet_ntoa(saddr.sin_addr), port);&lt;br /&gt;    s = socket( AF_INET, SOCK_STREAM, 0 );&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( connect( s, (&lt;font color="#4169E1"&gt;struct sockaddr&lt;/font&gt; *)&amp;amp;saddr, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(saddr))&lt;br /&gt;         == SOCKET_ERROR) {&lt;br /&gt;        debug( &lt;font color="#666666"&gt;"connect() failed.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; SOCKET_ERROR;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; s;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="report_text"&gt;&lt;/a&gt;void&lt;br /&gt;report_text( char *prefix, char *buf )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static char work[1024];&lt;br /&gt;    char *tmp;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !f_debug )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( !f_report )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;                                 &lt;font color="#B22222"&gt;/* don't report */&lt;/font&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"%s \""&lt;/font&gt;, prefix);&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *buf ) {&lt;br /&gt;        memset( work, 0, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(work));&lt;br /&gt;        tmp = work;&lt;br /&gt;        &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( *buf &amp;amp;&amp;amp; ((tmp-work) &amp;lt; (int)&lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(work)-5) ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( *buf ) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\t': *tmp++ = '\\'; *tmp++ = 't'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\r': *tmp++ = '\\'; *tmp++ = 'r'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\n': *tmp++ = '\\'; *tmp++ = 'n'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;            &lt;font color="#4169E1"&gt;case&lt;/font&gt; '\\': *tmp++ = '\\'; *tmp++ = '\\'; &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;            default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;                &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( isprint(*buf) ) {&lt;br /&gt;                    *tmp++ = *buf;&lt;br /&gt;                } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                    int consumed = tmp - work;&lt;br /&gt;                    snprintf( tmp, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(work)-consumed,&lt;br /&gt;                              &lt;font color="#666666"&gt;"\\x%02X"&lt;/font&gt;, (unsigned char)*buf);&lt;br /&gt;                    tmp += strlen(tmp);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            buf++;&lt;br /&gt;            *tmp = '\0';&lt;br /&gt;        }&lt;br /&gt;        debug_(&lt;font color="#666666"&gt;"%s"&lt;/font&gt;, work);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    debug_(&lt;font color="#666666"&gt;"\"\n"&lt;/font&gt;);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="report_bytes"&gt;&lt;/a&gt;void&lt;br /&gt;report_bytes( char *prefix, char *buf, int len )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ! f_debug )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;    debug( &lt;font color="#666666"&gt;"%s"&lt;/font&gt;, prefix );&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; len ) {&lt;br /&gt;        fprintf( stderr, &lt;font color="#666666"&gt;" %02x"&lt;/font&gt;, *(unsigned char *)buf);&lt;br /&gt;        buf++;&lt;br /&gt;        len--;&lt;br /&gt;    }&lt;br /&gt;    fprintf(stderr, &lt;font color="#666666"&gt;"\n"&lt;/font&gt;);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="atomic_out"&gt;&lt;/a&gt;int&lt;br /&gt;atomic_out( SOCKET s, char *buf, int size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int ret, len;&lt;br /&gt;&lt;br /&gt;    assert( buf != NULL );&lt;br /&gt;    assert( 0&amp;lt;=size );&lt;br /&gt;    &lt;font color="#B22222"&gt;/* do atomic out */&lt;/font&gt;&lt;br /&gt;    ret = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; size ) {&lt;br /&gt;        len = send( s, buf+ret, size, 0 );&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 )&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"atomic_out() failed to send(), %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;        ret += len;&lt;br /&gt;        size -= len;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!f_report) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_out()  [some bytes]\n"&lt;/font&gt;);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt; xx xx xx xx ...\n"&lt;/font&gt;);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_out()  [%d bytes]\n"&lt;/font&gt;, ret);&lt;br /&gt;        report_bytes(&lt;font color="#666666"&gt;"&amp;gt;&amp;gt;&amp;gt;"&lt;/font&gt;, buf, ret);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="atomic_in"&gt;&lt;/a&gt;int&lt;br /&gt;atomic_in( SOCKET s, char *buf, int size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int ret, len;&lt;br /&gt;&lt;br /&gt;    assert( buf != NULL );&lt;br /&gt;    assert( 0&amp;lt;=size );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* do atomic in */&lt;/font&gt;&lt;br /&gt;    ret = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; size ) {&lt;br /&gt;        len = recv( s, buf+ret, size, 0 );&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == -1 ) {&lt;br /&gt;            fatal(&lt;font color="#666666"&gt;"atomic_in() failed to recv(), %d\n"&lt;/font&gt;, socket_errno());&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( len == 0 ) {&lt;br /&gt;            fatal( &lt;font color="#666666"&gt;"Connection closed by peer.\n"&lt;/font&gt;);&lt;br /&gt;        }&lt;br /&gt;        ret += len;&lt;br /&gt;        size -= len;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (!f_report) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_in()  [some bytes]\n"&lt;/font&gt;);&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt; xx xx xx xx ...\n"&lt;/font&gt;);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"atomic_in() [%d bytes]\n"&lt;/font&gt;, ret);&lt;br /&gt;        report_bytes(&lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt;"&lt;/font&gt;, buf, ret);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ret;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="line_input"&gt;&lt;/a&gt;int&lt;br /&gt;line_input( SOCKET s, char *buf, int size )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *dst = buf;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( size == 0 )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* no error */&lt;/font&gt;&lt;br /&gt;    size--;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( 0 &amp;lt; size ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( recv( s, dst, 1, 0) ) {        &lt;font color="#B22222"&gt;/* recv one-by-one */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKET_ERROR:&lt;br /&gt;            error(&lt;font color="#666666"&gt;"recv() error\n"&lt;/font&gt;);&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                          &lt;font color="#B22222"&gt;/* error */&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;case&lt;/font&gt; 0:&lt;br /&gt;            size = 0;                           &lt;font color="#B22222"&gt;/* end of stream */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;        default:&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;            &lt;font color="#B22222"&gt;/* continue reading until last 1 char is EOL? */&lt;/font&gt;&lt;br /&gt;            &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *dst == '\n' ) {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* finished */&lt;/font&gt;&lt;br /&gt;                size = 0;&lt;br /&gt;            } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;                &lt;font color="#B22222"&gt;/* more... */&lt;/font&gt;&lt;br /&gt;                size--;&lt;br /&gt;            }&lt;br /&gt;            dst++;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    *dst = '\0';&lt;br /&gt;    report_text( &lt;font color="#666666"&gt;"&amp;lt;&amp;lt;&amp;lt;"&lt;/font&gt;, buf);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* cut_token()&lt;br /&gt;   Span token in given string STR until char in DELIM is appeared.&lt;br /&gt;   Then replace contiguous DELIMS with '\0' for string termination&lt;br /&gt;   and returns next pointer.&lt;br /&gt;   If no next token, return NULL.&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="cut_token"&gt;&lt;/a&gt;char *&lt;br /&gt;cut_token( char *str, char *delim)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    char *ptr = str + strcspn(str, delim);&lt;br /&gt;    char *end = ptr + strspn(ptr, delim);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( ptr == str )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( ptr &amp;lt; end )&lt;br /&gt;        *ptr++ = '\0';&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; ptr;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="lookup"&gt;&lt;/a&gt;const char *&lt;br /&gt;lookup(int num, LOOKUP_ITEM *items)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    int i = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; (0 &amp;lt;= items[i].num) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (items[i].num == num)&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; items[i].str;&lt;br /&gt;        i++;&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"(unknown)"&lt;/font&gt;;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* readpass()&lt;br /&gt;   password input routine&lt;br /&gt;   Use ssh-askpass (same mechanism to OpenSSH)&lt;br /&gt;*/&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="readpass"&gt;&lt;/a&gt;char *&lt;br /&gt;readpass( const char* prompt, ...)&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    static char buf[1000];                      &lt;font color="#B22222"&gt;/* XXX, don't be fix length */&lt;/font&gt;&lt;br /&gt;    va_list args;&lt;br /&gt;    va_start(args, prompt);&lt;br /&gt;    vsnprintf(buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf), prompt, args);&lt;br /&gt;    va_end(args);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( getparam(ENV_SSH_ASKPASS)&lt;br /&gt;&lt;font color="#A020F0"&gt;#if !defined(_WIN32) &amp;amp;&amp;amp; !defined(__CYGWIN32__)&lt;/font&gt;&lt;br /&gt;         &amp;amp;&amp;amp; getenv(&lt;font color="#666666"&gt;"DISPLAY"&lt;/font&gt;)&lt;br /&gt;&lt;font color="#A020F0"&gt;#endif &lt;/font&gt;&lt;font color="#B22222"&gt;/* not _WIN32 &amp;amp;&amp;amp; not __CYGWIN32__ */&lt;/font&gt;&lt;font color="#A020F0"&gt;&lt;/font&gt;&lt;br /&gt;        ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* use ssh-askpass to get password */&lt;/font&gt;&lt;br /&gt;        FILE *fp;&lt;br /&gt;        char *askpass = getparam(ENV_SSH_ASKPASS), *cmd;&lt;br /&gt;        int cmd_size = strlen(askpass) +1 +1 +strlen(buf) +1 +1;&lt;br /&gt;        cmd = xmalloc(cmd_size);&lt;br /&gt;        snprintf(cmd, cmd_size, &lt;font color="#666666"&gt;"%s \"%s\""&lt;/font&gt;, askpass, buf);&lt;br /&gt;        fp = popen(cmd, &lt;font color="#666666"&gt;"r"&lt;/font&gt;);&lt;br /&gt;        free(cmd);&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( fp == NULL )&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;                        &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;        buf[0] = '\0';&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (fgets(buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf), fp) == NULL)&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; NULL;                        &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;        fclose(fp);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        tty_readpass( buf, buf, &lt;font color="#4169E1"&gt;sizeof&lt;/font&gt;(buf));&lt;br /&gt;    }&lt;br /&gt;    buf[strcspn(buf, &lt;font color="#666666"&gt;"\r\n"&lt;/font&gt;)] = '\0';&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; buf;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_do_auth_userpass"&gt;&lt;/a&gt;static int&lt;br /&gt;socks5_do_auth_userpass( int s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    unsigned char buf[1024], *ptr;&lt;br /&gt;    char *pass = NULL;&lt;br /&gt;    int len;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* do User/Password authentication. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* This feature requires username and password from&lt;br /&gt;       command line argument or environment variable,&lt;br /&gt;       or terminal. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; (relay_user == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"cannot determine user name.\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* get password from environment variable if exists. */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ((pass=determine_relay_password()) == NULL &amp;amp;&amp;amp;&lt;br /&gt;        (pass=readpass(&lt;font color="#666666"&gt;"Enter SOCKS5 password for %s@%s: "&lt;/font&gt;,&lt;br /&gt;                       relay_user, relay_host)) == NULL)&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Cannot get password for user: %s\n"&lt;/font&gt;, relay_user);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* make authentication packet */&lt;/font&gt;&lt;br /&gt;    ptr = buf;&lt;br /&gt;    PUT_BYTE( ptr++, 1 );                       &lt;font color="#B22222"&gt;/* subnegotiation ver.: 1 */&lt;/font&gt;&lt;br /&gt;    len = strlen( relay_user );                 &lt;font color="#B22222"&gt;/* ULEN and UNAME */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, len );&lt;br /&gt;    strcpy( ptr, relay_user );&lt;br /&gt;    ptr += len;&lt;br /&gt;    len = strlen( pass );                       &lt;font color="#B22222"&gt;/* PLEN and PASSWD */&lt;/font&gt;&lt;br /&gt;    PUT_BYTE( ptr++, strlen(pass));&lt;br /&gt;    strcpy( ptr, pass );&lt;br /&gt;    ptr += len;&lt;br /&gt;    memset (pass, 0, strlen(pass));             &lt;font color="#B22222"&gt;/* erase password */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* send it and get answer */&lt;/font&gt;&lt;br /&gt;    f_report = 0;&lt;br /&gt;    atomic_out( s, buf, ptr-buf );&lt;br /&gt;    f_report = 1;&lt;br /&gt;    atomic_in( s, buf, 2 );&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* check status */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( buf[1] == 0 )&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; 0;                               &lt;font color="#B22222"&gt;/* success */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;else&lt;/font&gt;&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_getauthname"&gt;&lt;/a&gt;static const char *&lt;br /&gt;socks5_getauthname( int auth )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( auth ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_REJECT: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"REJECTED"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_NOAUTH: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"NO-AUTH"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_GSSAPI: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"GSSAPI"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_USERPASS: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"USERPASS"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_CHAP: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"CHAP"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_EAP: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"EAP"&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_MAF: &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"MAF"&lt;/font&gt;;&lt;br /&gt;&lt;strong&gt;&lt;font color="#FF0000"&gt;    default:&lt;/font&gt;&lt;/strong&gt; &lt;font color="#4169E1"&gt;return&lt;/font&gt; &lt;font color="#666666"&gt;"(unknown)"&lt;/font&gt;;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#4169E1"&gt;typedef&lt;/font&gt; &lt;font color="#4169E1"&gt;struct&lt;/font&gt; {&lt;br /&gt;    char* name;&lt;br /&gt;    unsigned char auth;&lt;br /&gt;} AUTH_METHOD_ITEM;&lt;br /&gt;&lt;br /&gt;AUTH_METHOD_ITEM socks5_auth_table[] = {&lt;br /&gt;    { &lt;font color="#666666"&gt;"none"&lt;/font&gt;, SOCKS5_AUTH_NOAUTH },&lt;br /&gt;    { &lt;font color="#666666"&gt;"gssapi"&lt;/font&gt;, SOCKS5_AUTH_GSSAPI },&lt;br /&gt;    { &lt;font color="#666666"&gt;"userpass"&lt;/font&gt;, SOCKS5_AUTH_USERPASS },&lt;br /&gt;    { &lt;font color="#666666"&gt;"chap"&lt;/font&gt;, SOCKS5_AUTH_CHAP },&lt;br /&gt;    { NULL, -1 },&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_auth_parse_1"&gt;&lt;/a&gt;int&lt;br /&gt;socks5_auth_parse_1(char *start, char *end)&lt;/font&gt;&lt;/strong&gt;{&lt;br /&gt;    int i, len;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( ; *start; start++ )&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *start != ' ' &amp;amp;&amp;amp; *start != '\t') &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( end--; end &amp;gt;= start; end-- ) {&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *end != ' ' &amp;amp;&amp;amp; *end != '\t'){&lt;br /&gt;            end++;&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    len = end - start;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; ( i = 0; socks5_auth_table[i].name != NULL; i++ ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( strncmp(start, socks5_auth_table[i].name, len) == 0) {&lt;br /&gt;            &lt;font color="#4169E1"&gt;return&lt;/font&gt; socks5_auth_table[i].auth;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    fatal(&lt;font color="#666666"&gt;"Unknown auth method: %s\n"&lt;/font&gt;, start);&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="socks5_auth_parse"&gt;&lt;/a&gt;int&lt;br /&gt;socks5_auth_parse(char *start, unsigned char *auth_list, int max_auth)&lt;/font&gt;&lt;/strong&gt;{&lt;br /&gt;    char *end;&lt;br /&gt;    int i = 0;&lt;br /&gt;    &lt;font color="#4169E1"&gt;while&lt;/font&gt; ( i &amp;lt; max_auth ) {&lt;br /&gt;        end = strchr(start, ',');&lt;br /&gt;        &lt;font color="#4169E1"&gt;if&lt;/font&gt; (*start &amp;amp;&amp;amp; end) {&lt;br /&gt;            auth_list[i++] = socks5_auth_parse_1(start, end);&lt;br /&gt;            start = ++end;&lt;br /&gt;        } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;            &lt;font color="#4169E1"&gt;break&lt;/font&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( *start &amp;amp;&amp;amp; ( i &amp;lt; max_auth ) ){&lt;br /&gt;        &lt;font color="#4169E1"&gt;for&lt;/font&gt;( end = start; *end; end++ );&lt;br /&gt;        auth_list[i++] = socks5_auth_parse_1(start, end);&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        fatal(&lt;font color="#666666"&gt;"Too much auth method.\n"&lt;/font&gt;);&lt;br /&gt;    }&lt;br /&gt;    &lt;font color="#4169E1"&gt;return&lt;/font&gt; i;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;font color="#B22222"&gt;/* begin SOCKS5 relaying&lt;br /&gt;   And no authentication is supported.&lt;br /&gt; */&lt;/font&gt;&lt;br /&gt;&lt;strong&gt;&lt;font color="#4169E1"&gt;&lt;a name="begin_socks5_relay"&gt;&lt;/a&gt;int&lt;br /&gt;begin_socks5_relay( SOCKET s )&lt;/font&gt;&lt;/strong&gt;&lt;br /&gt;{&lt;br /&gt;    unsigned char buf[256], *ptr, *env = socks5_auth;&lt;br /&gt;    unsigned char n_auth = 0; unsigned char auth_list[10], auth_method;&lt;br /&gt;    int len, auth_result, i;&lt;br /&gt;&lt;br /&gt;    debug( &lt;font color="#666666"&gt;"begin_socks_relay()\n"&lt;/font&gt;);&lt;br /&gt;&lt;br /&gt;    &lt;font color="#B22222"&gt;/* request authentication */&lt;/font&gt;&lt;br /&gt;    ptr = buf;&lt;br /&gt;    PUT_BYTE( ptr++, 5);                        &lt;font color="#B22222"&gt;/* SOCKS version (5) */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL )&lt;br /&gt;        env = getparam(ENV_SOCKS5_AUTH);&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( env == NULL ) {&lt;br /&gt;        &lt;font color="#B22222"&gt;/* add no-auth authentication */&lt;/font&gt;&lt;br /&gt;        auth_list[n_auth++] = SOCKS5_AUTH_NOAUTH;&lt;br /&gt;        &lt;font color="#B22222"&gt;/* add user/pass authentication */&lt;/font&gt;&lt;br /&gt;        auth_list[n_auth++] = SOCKS5_AUTH_USERPASS;&lt;br /&gt;    } &lt;font color="#4169E1"&gt;else&lt;/font&gt; {&lt;br /&gt;        n_auth = socks5_auth_parse(env, auth_list, 10);&lt;br /&gt;    }&lt;br /&gt;    PUT_BYTE( ptr++, n_auth);                   &lt;font color="#B22222"&gt;/* num auth */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;for&lt;/font&gt; (i=0; i&amp;lt;n_auth; i++) {&lt;br /&gt;        debug(&lt;font color="#666666"&gt;"available auth method[%d] = %s (0x%02x)\n"&lt;/font&gt;,&lt;br /&gt;              i, socks5_getauthname(auth_list[i]), auth_list[i]);&lt;br /&gt;        PUT_BYTE( ptr++, auth_list[i]);         &lt;font color="#B22222"&gt;/* authentications */&lt;/font&gt;&lt;br /&gt;    }&lt;br /&gt;    atomic_out( s, buf, ptr-buf );              &lt;font color="#B22222"&gt;/* send requst */&lt;/font&gt;&lt;br /&gt;    atomic_in( s, buf, 2 );                     &lt;font color="#B22222"&gt;/* recv response */&lt;/font&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;if&lt;/font&gt; ( (buf[0] != 5) ||                       &lt;font color="#B22222"&gt;/* ver5 response */&lt;/font&gt;&lt;br /&gt;         (buf[1] == 0xFF) ) {                   &lt;font color="#B22222"&gt;/* check auth method */&lt;/font&gt;&lt;br /&gt;        error(&lt;font color="#666666"&gt;"No auth method accepted.\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;&lt;br /&gt;    }&lt;br /&gt;    auth_method = buf[1];&lt;br /&gt;&lt;br /&gt;    debug(&lt;font color="#666666"&gt;"auth method: %s\n"&lt;/font&gt;, socks5_getauthname(auth_method));&lt;br /&gt;&lt;br /&gt;    &lt;font color="#4169E1"&gt;switch&lt;/font&gt; ( auth_method ) {&lt;br /&gt;    &lt;font color="#4169E1"&gt;case&lt;/font&gt; SOCKS5_AUTH_REJECT:&lt;br /&gt;        error(&lt;font color="#666666"&gt;"No acceptable authentication method\n"&lt;/font&gt;);&lt;br /&gt;        &lt;font color="#4169E1"&gt;return&lt;/font&gt; -1;                              &lt;font color="#B22222"&gt;/* fail */&lt;/font&gt;&lt;br /&gt;&lt;br /&gt;    &lt;font col
