Advertising

Scanning on Linux from Canon TS5050 over the network

Turns out that ScanGear MP 3.70 works perfectly with my Canon TS5050.
rest of the post
About me

Simple multiuser chat for POSIX systems

Here's a little multiuser chat server written for various POSIX-compatible operating systems. Written and tested on Mac OS X 10.6, but it should work on your favorite Linux, too.

Placed in public domain, use it for whatever you want (since it's so simple). 177 lines of pure C powah, dood.

Code follows after the break. server.c:

#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define SLOTCOUNT 300

int listener = 0;
int slots[SLOTCOUNT] = {0};
int maxslot = 0;
int usage(char* call)
{
  char* fn = strrchr(call, '/')+1;
  if(!fn)
    fn = call;
  printf("usage: %s port\n", fn);
  return 1;
}

void broadcast_message(int sender, char* msg)
{
  int i;
  for(i = 0; i < SLOTCOUNT; i++)
  {
    if(!slots[i])
      continue;
    if(i == sender)
      continue;

    send(i, msg, strlen(msg), 0);
  }

  if(sender != 0)
    printf("%s", msg);
}

int work()
{
  maxslot = listener;
  do
  {
    fd_set set;
    int i;

    FD_ZERO(&set);

    FD_SET(1,        &set);
    FD_SET(listener, &set);
    for(i=0; i < SLOTCOUNT; i++)
    {
      if(slots[i])
      {
        FD_SET(slots[i], &set);
      }
    }

    int koliko = select(maxslot+1, &set, NULL, NULL, NULL);
    if(koliko==-1)
      err(5, "select()");
    
    if(FD_ISSET(1, &set))
    {

      int size;
      if(ioctl(1, FIONREAD, &size) != -1){
        char *buf;

    //    printf("Reading %d bytes...\n", size);
        buf = malloc(size+1);
        read(1, buf, size);
        buf[size] = 0;
    //    printf("Received %s\n", buf);

        broadcast_message(0, buf);

        free(buf);
      }
      else
        err(7, "ioctl() stdio");

    }
    if(FD_ISSET(listener, &set))
    {
      int accepted = accept(listener, NULL, NULL);
      if(accepted == -1)
        err(6, "accept()");

      slots[accepted] = accepted;
      if(accepted > maxslot)
        maxslot = accepted;
    }
  
    for(i = 0; i < SLOTCOUNT; i++)
    {
      if(slots[i] && FD_ISSET(slots[i], &set))
      {
    //    printf("Received on %d\n", i);


        int size;


        if(ioctl(i, FIONREAD, &size) != -1){

          if(size > 0)
          {
            char *buf;

    //        printf("Reading %d bytes...\n", size);
            buf = malloc(size+1);
            read(i, buf, size);
            buf[size] = 0;
    //        printf("Received %s\n", buf);
            
            broadcast_message(i, buf);

            free(buf);
          }
          else
          {
            shutdown(i, SHUT_RDWR);
            close(i);

            slots[i] = 0;

    //        printf("Disconnect on %d\n", i);
          }
        }
        else
          err(8, "ioctl() net");


      }
    }
    
  } while(1);
  return 0;
}


int main(int argc, char** argv)
{
  if(argc < 2)
    return usage(argv[0]);

  if((listener = socket(PF_INET, SOCK_STREAM, 0))==-1)
    err(1, "socket()");
  
  int one=1;
  setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  
  struct sockaddr_in socketAddress;
  memset(&socketAddress, 0, sizeof(socketAddress));
  socketAddress.sin_len = sizeof(socketAddress);
  socketAddress.sin_family = AF_INET;                   // Address family (IPv4 vs IPv6)
  socketAddress.sin_port = htons(atoi(argv[1]));        // If we passed 0, the actual port would get assigned automatically by kernel and we'd have to retrieve it. Also, we use network byte order for 16bit numbers here by using htons
  socketAddress.sin_addr.s_addr = htonl(INADDR_ANY);    // We must use "network byte order" format (big-endian) for the 32bit value here by using htonl

  printf("Listener: %d\n", listener);
  if(bind(listener, (struct sockaddr*) &socketAddress, sizeof(socketAddress))==-1)
    err(2, "bind()");

  if(listen(listener, 1) == -1)
    err(3, "listen()");

  return work();

}

Makefile:

CFLAGS=-g3
LDFLAGS=-g3

all: server

server: server.o
  gcc server.o $(LDFLAGS) -o server

clean:
  -rm server server.o

Note, in Makefiles, instead of two spaces, use tabs. You need to.

Try it out:

make
./server 1337

And on a few other terminals (or other machines):

telnet localhost 1337

Works over the network, too, of course.

Nota bene, you will probably need to install telnet on your Linux machine. Also, telnet does not come with latest Windows editions (Vista and 7); you will need to use putty over there.


rest of the post

close() of listening socket from another thread

Just a warning.

Calling close() on listening socket in another thread will NOT prevent another connection from being made. Instead, you must call shutdown(). This should abort existing select() calls (probably accept() too, but I didn't try).

Guess how I found out :-)


rest of the post

Mount remote GNU/Linux filesystem over SSH wth Dokan

If you are impaired with Windows, and you want something similar to sshfs (that is, mount a remote system as a local drive) look no further:



It's originally Japanese, and suffers from a bit of Engrish, but it is free and obviously developed by a genius, so it's all forgiven.

Hiroki Asakawa, thank you!


rest of the post