Archive for the ‘C/C++’ Category

select system call limitation in Linux

Tuesday, December 22nd, 2009

Try finding a network sample code of how to accept TCP connections and most likely you will find the select() system call in such code. The reason being that select() is the most popular (but not the only one as we will see) system call to wait for I/O in a list of file descriptors.

I am here to warn you, select() has some important limitations to be aware of. I must confess I used select for a long time without realizing its limitations, until, of course, I hit the limits.

About a year ago I started porting a heavily threaded networking real-time voice application for Windows to Linux. When the code was compiling and running apparentely without issues, we started doing scalability and stress tests. We used 32 telephony E1 cards (pretty much like a network card) where each E1 port can handle up to 30 calls. So we’re talking about 32 * 30 = 960 calls in a single server. Knowing in advance that I would need lots of file descriptors (Linux typically defaults to 1024 per process), we used the setrlimit() system call to increase the limit up to 10,000 which should be more than enough because a telephony call in this system requires about 4 file descriptors (for the network VoIP connection and the E1 side devices etc).

At some point during the stress test, calls stopped working and some threads were going crazy eating up 99% CPU. After finding out using “ps” and “pstack” which threads were the ones going crazy, I found out that were the ones waiting for I/O in some file descriptors using select(), like the embedded HTTP server or the Network-related code.

Reading carefully the select documentation you will find the answer by yourself. “man select” says:

“An fd_set is a fixed size buffer. Executing FD_CLR or FD_SET with a value of fd that is negative or is equal to or larger than FD_SETSIZE will result in undefined behavior.”

So, big deal you may say, you can split across threads the load to not have more than 1024 file descriptors in your select() call, right? WRONG! read it twice, the problem is with the highest file descriptor value provided in a fd_set structure, not the number of file descriptors in the fd set.

These 2 numbers are related but are in no way the same. Let’s say you have program that opens 2000 text files (either with open() or fopen()) to read from them and scan for a list of words, at the same time each time you hit a word you must connect and send a network message to some TCP server and read data from the TCP server too. Probably you would launch some threads for reading on the files and another thread to handle the network connection related data. Event though only 1 thread is using select() and that thread is providing select() with just 1 file descriptor (the TCP server connection), you cannot guarantee which file descriptor number will be assigned to that network connection. You could try to ensure that you always start the TCP connection before opening any files so you will get a lower-number file descriptor, but that is a very shaky design, if you later want to do other stuff that requires the use of file descriptors (use pipes, unix sockets, etc) you may hit the problem again.

The limitation comes from the way select() works, most concretely the data type used to represent the list of file descriptors, fd_set. Let’s take a look at fd_set in /usr/include/sys/select.h

You will see a definition pretty much like:

 
typedef struct  {
    long int fds_bits[32];
} fd_set;

I removed a bunch of macros to make the code more clear. As you see you have a static array of 32 long ints. This is just a bit map, where each bit represents a file descriptor number. 32 * sizeof(long int), for 32 bit platforms is 1024. So, if you do fd_set(&fd, 10), to add file descriptor 10 to an fd_set, it will just set to 1 the 10th bit in the bit map, what happens then if you do fd_set(&fd, 2000) ?, you guessed right, unpredictable. May be some sort of array overflow (fd_set is, at least on my system, implemented using the assembly instruction btsl, bit test and set).

Be aware also, all of this is on Linux, I am not sure about how select is implemented in other operating systems, like Windows. Given that we did not notice this problem on Windows servers, probably select is implemented differently.

Solution? use poll (or may be epoll when available). These 2 system calls are not as popular and available in most operating systems as select is, but whenever possible, I recommend using poll. There may be differences in the performance, for example, using FD_ISSET() is faster (just checking if a given bit is set in the bitmap) than iterating over the poll array, but I have found in my applications that the difference is just not critical.

In short, next time you find using select(), think it twice before deciding that is what you need.

I hate SELinux

Thursday, December 17th, 2009

I am not a security-savvy person, even though I know pretty well how to code defensively to avoid security issues in my C code, my security knowledge in a Linux system is pretty average (use firewall, do not run services as root etc). No wonder I really don’t know how to use or configure SELinux. But there is one thing I know about it. It can be a pain in the ass sometimes. This blog post is to describe 2 problems I have faced with SELinux. The easy solution would have been to disable SELinux. So I’ll start by showing you how to disable it in case you don’t want to mess with it at all.

- To disable SELinux. Edit /etc/selinux/config and change the SELINUX policy from enforcing to

SELINUX=disabled

Be aware that you are disabling security “features”, whatever that means. So you may want to read this other article about disabling SELinux.

I wasn’t lucky enough to have SELinux disabled as an option. Developing with SELinux enabled is a good idea so you can notice compatibility problems with SELinux in your development environment before a customer that really *needs* SELinux enabled discovers them in your software, which, from the customer point of view is a plain bug.

The first problem I noticed after some CentOS upgrade, change the hard-drive or something along those lines, was that the command “ping” wasn’t working, it’s been a while since I had the problem so I don’t quite remember the exact error when pinging other systems, but it was most likely something like permission denied. Probably other network commands did not work either, but I could just notice ping at that moment. So, I used the good old strace to find out what was causing the problem.

The underlying ping problem was because the open() system call was failing with EACCESS when trying to open /etc/hosts. However I was able to “cat /etc/hosts”. So it wasn’t a simple permission problem, but a bit more complex SELinux problem. Eventually I found out that the solution was:

restorecon reset /etc/hosts

At which point the SELinux security context for this file got screwed up? I certainly don’t know. But that command restored it. The Z option of the ls command will show you the SELinux security context for any file.

ls -Z /etc/hosts

The second problem was that some libraries of one of the programs I am responsible for were not being loaded. Again, the problem was due to permission denied errors, this time when loading the shared libraries that required text relocation.

The solution was to recompile the shared libraries with the -fPIC option.

I am sure SELinux has its uses, however I have the feeling that sometimes makes things more complicated than needed in some environments. I recommend reading this blog post and particularly the comments in there.

Quick tip for debugging deadlocks

Sunday, September 27th, 2009

If you ever find yourself with a deadlock in your application, you can use gdb to attach to the application, then sometimes you find one of the threads that is stuck trying to lock mutex x. Then you need to find out who is currently holding x and therefore deadlocking your thread (and equally important why the other thread is not releasing it).

At least on recent libc implementations in Linux, the mutex object seems to have a member named “__owner”. Let me show you what I recently saw when debugging a deadlocked application.

(gdb) f 4
#4  0x0805ab46 in ACE_OS::mutex_lock (m=0xa074248) at include/ace/OS.i:1406
1406      ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), ace_result_),
(gdb) p *m
$8 = {__data = {__lock = 2, __count = 0, __owner = 17828, __kind = 0, __nusers = 1, {__spins = 0, __list = {__next = 0x0}}},
  __size = "\002\000\000\000\000\000\000\000�E\000\000\000\000\000\000\001\000\000\000\000\000\000", __align = 2}

We can see that the __owner is 17828. This number is the LWP (Light-weight process) id of the thread holding the lock. Now you can go to examine that thread stack and find out why that thread is also stuck.

This example also brings up a regular point of confusion for some Linux application developers. What is the difference between LWP and POSIX thread id ( the pthread_t type in pthread.h)?. The difference is that pthread_t is a user space concept, is simply an identifier for the thread library implementing POSIX threads to refer to the thread and its resources, state etc. However the LWP is an implementation detail of how the Linux kernel implements threads, which is done through the “thread group” concept and LWP’s, that are processes that share memory pages and other resources with the other processes in the same thread group.

From the Linux kernel point of view the pthread_t value doesn’t mean anything, the LWP id is how you identify threads in the kernel, and they share the same numbering as regular processes, since LWPs are just a special type of process. Knowing this is useful when using utilities like strace. When you want to trace a particular thread of a multi threaded application, you need to provide the LWP of the thread you want to trace, a common mistake is to provide the process id, which in a multithreaded application the process id is just the LWP of the first thread in the application (the one that started executing main()).

Here is how you get each identifier in a C program:

#include <stdio.h>
#include <syscall.h>
#include <pthread.h>
 
int main()
{
  pthread_t tid = pthread_self();
  int sid = syscall(SYS_gettid);
  printf("LWP id is %d\n", sid);
  printf("POSIX thread id is %d\n", tid);
  return 0;
}

It’s important to note that getting the POSIX thread id is much faster than the LWP, because pthread_self() is just a library call and libc most likely has this value cached somewhere in user space, no need to go down to the kernel. As you can see, getting the LWP requires a call to the syscall() function, which effectively executes the requested system call, this is expensive (well, compared with the time required to enter a simple user space function).

New Project – Sangoma Bridge

Wednesday, September 9th, 2009

A couple of months ago I wrote a little application for Regulus Labs. The application is a simple daemon bridge between Sangoma E1 devices receving ISDN PRI calls and a TCP IP server. Everything received on the telephony side was simply bridged to the configured TCP IP server. The bridge supports PRI voice calls and V.110 data calls.

Even when the application is simple in nature, learning about V.110 to get it to work was interesting :)

Today I made the project public ( thanks to Tzury Bar Yochay from Regulus Labs) in google code:

http://code.google.com/p/sbridge/

Hopefully somebody else will find it useful.

Debugging information in separate files

Monday, August 31st, 2009

Debugging information in Linux ELF binaries is usually stored in the binary itself. This had been really convenient to me, for example, I always compile my openr2 library with -ggdb3 -O0. I don’t care about optimizations nor the increase in size in the binary and users can always change those flags using CFLAGS when configuring openr2. Is convenient because if my users ever get a core dump, I was able to jump right in and get a useful backtrace and examine the stack. Alternatively they could get the stack trace themselves and send it to me without worrying about anything else than launching gdb with the right arguments.

However, when you ship non-open source software or you’re just concerned with the size of all the debugging information in lots of libraries, you want to separate the debugging information from the binary holding the program/library itself. In Windows this is the default behavior you get with the well known PDB (Program Data Base) files. For Linux though, you need some tricks to get the debugging information separate. This is of course what most distributions do, they include an extra package with debugging information, so when you install a package you get just the binary code, then, if you need to debug it you download the debugging package.

If you ever need this, you can follow the instructions in this web page to get it to work:

http://sources.redhat.com/gdb/current/onlinedocs/gdb_17.html#SEC166

The way I solved it for our internal build system is just to always compile with -ggdb3 and then:

1. Create a copy of the debugging symbols in a separate binary

objcopy --only-keep-debug somelibrary.so somelibrary.so.dbg

2. Remove the debugging information from the code binary.

objcopy --strip-debug somelibrary.so

3. Add a reference to the code binary so gdb knows where to look for the debugging information

objcopy --add-gnu-debuglink somelibrary.so.dbg somelibrary.so

This last step is simply putting a file name reference inside the ELF binary so GDB (or some other debugger) knows which file name will have the debugging information for this .so (or an executable if that’s what you’re building). In the red hat web page more advanced techniques are explained to make sure you don’t end up with a version mismatch between the debugging information and your library or executable.

A Tale of Two Bugs

Sunday, May 25th, 2008

It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the age of bug-hunting!

Recently I fixed 2 bugs, yeah, I know I spent a lot of time fixing bugs but this 2 were quite interesting to me, not because of the bugs itself, but rather because of some stuff I learned in the process like the implementation of variadic functions and how the C++ compiler optimizes certain stuff unveiling odd bugs.

Bug 1

Let’s analyze the first one, it was a bug I had with some Unicall R2 installation in 64 bits. The problem was simple, as soon as I loaded chan_unicall.so Asterisk crashed :-)

After running Asterisk with gdb I found the crash happened inside libc function strlen that was being called by uc_log(), the Unicall logging function. As most logging C functions, uc_log is a variadic function. uc_log does not do any complicated stuff, is mostly just a wrapper to vsnprintf and the variable arguments were just passed on to vsnprintf and there the crash was occurring, so, how can one see the arguments a variadic function receives using gdb? First, one must know how variadic functions are implemented by the compiler and platform you are working on.

Most common implementation of variadic functions in C is just to define va_list as an unsigned char* pointing to the last argument of the function and each call to va_arg() retrieves the next chunk of memory of the specified size and increment va_list to point to the start of the next argument, therefore, displaying arguments is just matter of printing the memory area after the last argument. However, AMD64 has a different implementation, va_list is an array of 1 structure with members:

.gp_offset
.fp_offset
.overflow_arg_area
.reg_save_area

gp_offset is how many bytes after reg_save_area the first argument is. To print the first variable argument that we know is an “int” we do:

(gdb) p *(int *)(((char *)arg_ptr[0].reg_save_area)+arg_ptr[0].gp_offset)

however, gp_offset will be only incremented after calling va_arg() macro, if you want to see more arguments you must increment reg_save_area by the number of bytes you know arguments take, in the case of uc_log, initial value of gp_offset is 24, probably because it receive 3 fixed arguments (8 bytes * 3). So, the first variable argument starts at .reg_save_area + 24, the second at .reg_save_area + 32 (we’re in a 64 bit machine).

So, what about .fp_offset and .overflow_arg_area?, well, it seems .reg_save_area is quite limited (possibly limited by the number of the processor registers) and you can never go beyond .gp_offset == 40, therefore that will only work for up to 6 arguments (including the fixed ones). .overflow_arg_area is used for any subsequent argument and .fp_offset is the pointer to the next argument on that memory area. Well, that’s enough, let’s get straight to the point, the crash was caused because unicall.h include the following prototype:

extern const char *uc_statet2str(int state);

That function returned the value passed to uc_log(…., uc_state2str()) … so what’s the issue? well, read once again the prototype and how uc_log used it. Is not a typo here in my blog, the prototype really is uc_statet2str, and the function call is uc_state2str, indeed there is a typo in the header file causing the compiler to default to the return value “int” and not const char* when compiling libmfcr2, for 64 bit platform there is 4 bytes of difference between char* and int causing a crash due to invalid memory read.

Bug 2

This one is easier to explain with a chunk of code, can you tell what’s wrong with it and what possible outputs will have when running it as “./test t”?


#include <stdio.h>
#include <string.h>

#define SIZE 100

int main(int argc, char *argv[])
{

        char *bufptr = NULL;
        if (argc == 2) {

                char inblock_buff[SIZE];
                bufptr = inblock_buff;
                strcpy(bufptr, "some buffer");
        }

        printf("buffer: %s\n", bufptr);
        if (argc == 2 && argv[1][0] == 't') {

                char otherbuff[SIZE];
                otherbuff[0] = 0;
        }

        printf("buffer: %s\n", bufptr);
        return 0;
}

Indeed, the output will depend on how you compile it and even probably will depend on the compiler implementation? The thing is, that if you compile this code in Linux with gcc 4.1.2 as gcc -O2 bug.c -o bug, and then run it as ./bug t

The output is:

buffer: some buffer
buffer: some buffer

But, compiling without optimizations gcc -O0 bug.c -o bug the output is:

buffer: some buffer
buffer:

When the second if() block is optimized-out the value of the block variable inblock_buff is not overwritten and therefore bufptr remains pointing to “some buffer” and the code seems to “work”, but when -O0 the second if() block is not optimized and the bug arise, bufptr will point to char 0 printing nothing. In my particular case this buffer was the input of the keyboard of a 5250 session, hence, in some cases the keyboard input was just ignored.

IJW (It Just Works) and COM Interop

Wednesday, March 26th, 2008

As I promised in my last post, today I am going to give an overview about how to call C# code from C++. After googling around a bit you will find there are at least 2 well-known ways to call C# from C++.

It Just Works

The first one I want to mention is “IJW” that stands for “It Just Works”. As the name implies, there is nothing much to discuss about IJW, is pretty easy to use, all one have to do is specify the /clr switch in the Microsoft VS compiler. This switch will cause your C++ code to be compiled to IL (Intermediate Language) and therefore will run in a managed environment. Nice isn’t it? However there is a catch, even though your code will be compiled to IL, the classes are not managed, which means among other things that the CLR will not take care of the memory. This is kind of obvious, since the original code was meant to take care of the memory itself, all the /clr switch does is give the opportunity to that old C++ code to run in managed environment.

Once that we have this C++ code working on a managed environment, there is some new fun stuff we can do with it.


#using <mscorlib.dll>
#using <myassembly.dll>

#include <stdio.h>

using namespace System;
using namespace MyNameSpace;

void callSomethingInMyAssembly()
{

    Console::WriteLine("In Managed Environment!");
    MyAssemblyClass::MyStaticMethod();
}

#pragma unmanaged


void oldAndCrappyFunction()
{
    callSomethingInMyAssembly();
}

The compiler pragma directive “managed” and “unmanaged” will help you to switch from managed to unmanaged and viceversa. This way you can call managed code from your old unmanaged code. Be aware that this solution will not work when you have an old DLL that other components depend on, since the resulting DLL will be a DLL with IL code and therefore not callable from other unmanaged DLLs.

COM Interop

To use COM Interop, the managed code, in this case, a C# class needs to allocate an UUID to be used when creating a COM instance. The following code shows how to create code with an interface and class with UUIDs.

using System;

using System.Runtime.InteropServices;

namespace ManagedNameSpace
{

/* The GUID should be generated using guidgen.exe */
[Guid("EF870CF7-DA0F-4bf7-89DD-DE21E4701E21")]
public interface IManagedComponent
{
        void ManagedMethod();
}

[Guid("687EADD7-0B02-457a-85E5-84BEF198F7BA")]

public class ManagedClass : IManagedComponent
{
        public void ManagedMethod()
        {

                Console.WriteLine("in managed environment!\n");
        }
}

}

You can create a UUID using the tool guidgen.exe. The class should be compiled with

C:\csc /target:library mycomponent.cs

That will generate a mycomponent.dll assembly. In order to other COM components to use our C# class we must register the DLL, we can do so using regasm utility:

C:\regasm mycomponent.dll /tlb:mycomponent.tlb

Now that the DLL is registered you can use it from any language that supports COM, C++ included. Before proceeding to call this C# code from C++, you may be wondering about that mycomponent.tlb file specified as argument to regasm /tlb switch. That file is known as a “type library” and is used by the COM infrastructure to save meta-data about the types involved in the exported interfaces, that way any language that supports COM can interact with any other COM component, in this case, written in C#.

Finally let’s call our C# component from C++ code.

#include <windows.h>
#include <iostream>


using namespace std;

#import <mscorlib.tlb> raw_interfaces_only

#import "dtcom.tlb" no_namespace named_guids

int main(int argc, char *argv[])
{

        IManagedComponent *component;
        HRESULT hr;

        /* COM require an initialize routine */
        CoInitialize(NULL);

        hr = CoCreateInstance(CLSID_ManagedClass, NULL,
                        CLSCTX_INPROC_SERVER, IID_IManagedComponent, reinterpret_cast<void **>(&component));

        if ( FAILED(hr) ) {
                cerr << "Could not create component instance." << endl;

                return -1;
        } 

        cout << "Calling managed methods." << endl;
        component->ManagedMethod();

        /* COM Require to release the instance */
        component->Release();

        /* Close COM */
        CoUninitialize();

        return 0;
}

As you can see we use the CoCreateInstance COM function to create an object that references (indirectly via CCW ) to the C# object.

So, that’s it, you can learn more about COM at Wikipedia.

PInvoke ( How to Call C from C# )

Monday, February 4th, 2008

I will be coding some C# stuff for Windows this year. We have a bunch of C/C++ APIs which we want to make available to our customers from C#, however, since I have known of the Mono existence for a while, I quickly realized that 90% the C# interfaces I will code on Windows for our C/C++ APIs can be made available for our Linux product as well. This post will briefly show how to call C/C++ code from C#.

As most of the readers probably know, C# is one of the primary languages of the .NET platform, thus, runs in a managed environment and cannot call unmanaged code w/o some intermediate mechanism, but don’t fear, it is quite easy, that mechanism is PInvoke, that stands for Platform Invoke. Let’s see an example of how it is done, on Linux.

1. Create a C file, libtest.c with this content:


#include <stdio.h>

void print(const char *message)
{

        printf("%s\\n", message);
}

That’s a simple pseudo-wrapper for printf. But represents any C function in the library you want to call. If you have a C++ function don’t forget to put extern “C” to avoid mangling the name.

2. Compile it as a shared library: gcc -fPIC -shared libtest.c -o libtest.so

3. Let’s create the C# file that will call our C API. It’s quite easy using PInvoke, all we need is define our entry points.

using System;

using System.Runtime.InteropServices;

public class Tester
{
        [DllImport("libtest.so", EntryPoint="print")]

        static extern void print(string message);

        public static void Main(string[] args)
        {

                print("Hello World C# => C++");
        }
}

We define a test class that declares a method “print”. However we do not write the body of the method since we declare it extern and static because it will not depend on the class instance data. Using C# attribute DllImport we specify the DLL ( in Linux, the shared object ) where the method will be defined.

4. Compile the C# file: mcs test.cs

5. Run it: mono test.exe

Unless you have the library libtest.so in a standard library path like “/usr/lib”, you are likely to see a System.DllNotFoundException, to fix this you can move your libtest.so to /usr/lib, or better yet, just add your CWD to the library path: export LD_LIBRARY_PATH=`pwd`

6. Run it again :) … now you should see the hello world C# => C++ message.

The DllImport attribute supports other arguments to tweak its behavior, refer to MSDN for DllImport documentation. Also keep in mind this is a extremely simple example, when more complex data types are involved we need to read about marshaling.

So that’s it, in my next post I will write about how to call C# code from C/C++ using COM Interop and managed C++.

Asterisk Asynchronous AGI

Monday, December 24th, 2007

I have been coding some new stuff for Asterisk lately, but the feature I like the most is Asynchronous AGI. I got the idea from MAGI, an old patch written by David Pollak that allowed AGI execution thru the manager interface. For those ignoring what AGI and AMI are, go read:

Asterisk Gateway Interface ( AGI )
Asterisk Manager API ( AMI )

So, my patch, allow users to execute AGI commands using “Action: AGI” and get the response reading “Event: AsyncAGI”. The manager header “CommandID” can be specified to match up the responses. Let’s see an example

In extensions.ael you would put something like this:

context sample-async-agi {
    test => {
        AGI(agi:async);
    };
};

That will put the channel to wait AGI commands. The channel will NOT do anything but wait for Hangup or any AGI command you ask it to execute. AGI commands can arrive from 2 sources. The most important and useful source of commands is the manager, but with my patch you can also execute AGI from the command line. Let’s see how it is done from the manager:

# telnet localhost 5038
Action: Login
Username: test
Secret: test

Action: AGI
Channel: SIP/33-blah
Command: EXEC Playback tt-monkeys
CommandID: MyCommandID

That would cause Asterisk to execute the “Playback” application on channel SIP/33-blah, which MUST be in AGI(agi:async) application. After executing the command you will be able to read an event with the AGI response url-encoded. If the channel is not in Async AGI, the command will not be executed and you will get an error response.

As I said, you can use the command line to execute Async AGI as well, just like this:

tcore*CLI> agi exec SIP/testing-09a5b960 “EXEC startmusiconhold”
tcore*CLI> agi exec SIP/testing-09a5b960 “EXEC stopmusiconhold”
tcore*CLI> agi exec SIP/testing-09a5b960 “EXEC Dial(Agent/23)”

That will start MOH, then stop it, and finally will dial to the Agent 23. This means you can implement a Queue without using native buggy Asterisk queues. You can receive calls and send them to Async AGI to put them on hold, then, when you detect availability of some of your Agents, Dial() to that agent.

If you want to learn more about this feature here is the mantis bug entry: http://bugs.digium.com/view.php?id=11282.

If you want the patch back-ported to 1.4, I have one here: http://www.moythreads.com/asterisk-1.4.15-async-agi.patch

In case you find this patch useful, please try it in trunk as well and provide feedback in mantis. Even when some people has found this patch useful, some of the top developers at asterisk-dev are hesitating in accepting it because similar results can be obtained thru the use of FastAGI, however, me and other people at asterisk-dev are trying to prove the patch also makes easier the implementation of some applications.

This is a hot discussion we got some weeks ago about it: http://lists.digium.com/pipermail/asterisk-dev/2007-December/031046.html

See you!

Hidden Message? not really, just encoded

Wednesday, October 24th, 2007

Today I read a post in Damog’s blog where he gave a nice PERL tip based in a “hidden message”. Even when some people might argue that the message is really hidden, to me it seems like it is simply encoded, that’s not the same, is it?

In anycase, if some of you were lazy enough to not decode the message here is a program that does just that:


#include <stdio.h>
#include <stdlib.h>

#include <string.h>

int main(int argc, char *argv[])
{

  FILE *handle;
  char char_byte[9], *c;

  long binval;
  if ( argc < 2 ) {
    return -1;
  }
  handle = fopen(argv[1], "r");
  if ( NULL == handle ) {

    perror("error");
    return -1;
  }
  memset(char_byte, '0', sizeof(char_byte) - 1);
  char_byte[8] = 0;

  c = char_byte;
  while ( 0 != fread(c, 1, 1, handle) ) {

    if ( *c != '1' && *c != '0' ) {

      continue;
    }
    if ( !*(c + 1) ) {
      binval = strtol(char_byte, NULL, 2);

      printf("%c", binval);
      c = char_byte;

      continue;
    }
    c++;
  }
  printf("\\n");
  fclose(handle);

  return 0;
}

1. Copy and paste the program.
2. Copy and paste the encoded message in Damog’s post or the other post he mentioned.
3. gcc readasbin.c -o readasbin.exe
4. ./readbin.exe message.txt

Jeez … I should have used PERL :)