--- fbgrab-1.0/fbgrab.c	2002-04-15 22:22:54.000000000 +0200
+++ fbgrab/fbgrab.c	2006-05-31 15:08:09.000000000 +0200
@@ -9,6 +9,9 @@
  *
  * For features and differences, read the manual page. 
  *
+ * Support for transporting images over network
+ * 	(C) 2006 by Harald Welte <laforge@gnumonks.org>
+ *
  * This program has been checked with "splint +posixlib" without
  * warnings. Splint is available from http://www.splint.org/ .
  * Patches and enhancements of fbgrab have to fulfill this too.
@@ -18,7 +21,13 @@
 #include <stdlib.h> 
 #include <unistd.h>
 #include <fcntl.h>
+#include <string.h>
 #include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/sendfile.h>
+#include <sys/socket.h>
+#include <netdb.h>
 
 #include <getopt.h>
 #include <sys/vt.h>   /* to handle vt changing */
@@ -30,6 +39,10 @@
 #define MAX_LEN 512
 #define UNDEFINED -1
 
+static int quiet;
+
+#define qrintf(x, args...) do { if (!quiet) printf(x, ## args); } while (0)
+
 /*@noreturn@*/ static void fatal_error(char *message)
 {
     fprintf(stderr, "%s\n", message);
@@ -38,8 +51,8 @@
 
 static void usage(char *binary)
 {
-    printf("Usage:   %s\t[-hi] [-{C|c} vt] [-d dev] [-s n]\n"
-	   "\t\t[-f fromfile -w n -h n -b n] filename.png\n", binary);
+    printf("Usage:   %s\t[-hi] [-{C|c} vt] [-d dev] [-s n] [-D]\n"
+	   "\t\t[-f fromfile -w n -h n -b n] [-H host [-P port]] filename.png\n", binary);
 }
 
 static void help(char *binary)
@@ -62,6 +75,10 @@ static void help(char *binary)
     printf("\t-w n  \tset width to n pixels, required when reading from file\n"
 	   "\t\tcan be used to force width when reading from framebuffer\n");
     printf("\t-?    \tprint this usage information\n");
+    printf("\t-H host\thostname to where the image is to be sent\n");
+    printf("\t-P port\tport number at destination host (default 2342)\n");
+    printf("\t-D\tdaemonize\n");
+    printf("\t-q\tquiet\n");
 }
 
 
@@ -228,7 +245,8 @@ static void write_PNG(unsigned char *out
     
     png_init_io(png_ptr, outfile);
     
-    png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+    //png_set_compression_level(png_ptr, Z_BEST_COMPRESSION);
+    png_set_compression_level(png_ptr, Z_BEST_SPEED);
     
     bit_depth = 8;
     color_type = PNG_COLOR_TYPE_RGB_ALPHA;
@@ -241,7 +259,7 @@ static void write_PNG(unsigned char *out
     
     png_write_info(png_ptr, info_ptr);
     
-    printf ("Now writing PNG file\n");
+    qrintf ("Now writing PNG file\n");
     
     png_write_image(png_ptr, row_pointers);
     
@@ -266,7 +284,7 @@ static void convert_and_write(unsigned c
     
     memset(outbuffer, 0, bufsize);
 
-    printf ("Converting image from %i\n", bits);
+    qrintf ("Converting image from %i\n", bits);
     
     switch(bits) 
     {
@@ -295,6 +313,77 @@ static void convert_and_write(unsigned c
 }
 
 
+static int net_init(const char *host, const char *service)
+{
+	struct addrinfo hints, *res, *ressave;
+	int n, sockfd = -1;
+
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_socktype = SOCK_STREAM;
+
+	n = getaddrinfo(host, service, &hints, &res);
+	if (n < 0) {
+		fprintf(stderr, "getaddrinfo() error %s\n",
+			gai_strerror(n));
+		return -1;
+	}
+
+	ressave = res;
+	while (res) {
+		sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if (sockfd >= 0) {
+			if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
+				break;
+			close(sockfd);
+			sockfd = -1;
+		}
+		res = res->ai_next;
+	}
+
+	freeaddrinfo(ressave);
+	return sockfd;
+}
+
+#define NET_FILE_HDR_MAGIC	0x23421102
+
+struct net_file_hdr {
+	u_int32_t magic;
+	u_int32_t size;
+};
+
+static int net_send_file(int sockfd, const char *fname)
+{
+	int rc, fd = open(fname, O_RDONLY);
+	struct stat st;
+	off_t off = 0;
+	struct net_file_hdr nh;
+
+	if (fd < 0)
+		return fd;
+
+	rc = fstat(fd, &st);
+	if (rc < 0) {
+		close(fd);
+		return rc;
+	}
+
+	nh.magic = htonl(NET_FILE_HDR_MAGIC);
+	nh.size = htonl(st.st_size);
+
+	rc = write(sockfd, &nh, sizeof(nh));
+	if (rc < 0) {
+		close(fd);
+		return rc;
+	}
+	
+	rc = sendfile(sockfd, fd, &off, st.st_size);
+
+	close(fd);
+
+	return rc;
+}
+
+
 /********
  * MAIN *
  ********/
@@ -312,6 +401,9 @@ int main(int argc, char **argv)
     struct fb_var_screeninfo fb_varinfo;
     int waitbfg=0; /* wait before grabbing (for -C )... */
     int interlace = PNG_INTERLACE_NONE;
+    char *hostname = NULL, *service = "2342";
+    int loop = 0, sockfd = -1;
+    int daemonize = 0;
 
     memset(infile, 0, MAX_LEN);
     memset(&fb_varinfo, 0, sizeof(struct fb_var_screeninfo));
@@ -319,7 +411,7 @@ int main(int argc, char **argv)
 
     for(;;)
     {
-	optc=getopt(argc, argv, "f:w:b:gh:iC:c:d:s:?");
+	optc=getopt(argc, argv, "f:w:b:gh:iC:c:Dd:qs:?H:P:l");
 	if (optc==-1)
 	    break;
 	switch (optc) 
@@ -337,6 +429,9 @@ int main(int argc, char **argv)
 	case 'd':
 	    device = optarg;
 	    break;
+	case 'D':
+	    daemonize = 1;
+	    break;
 	case 'f':
 	    strncpy(infile, optarg, MAX_LEN);
 	    break;
@@ -349,12 +444,24 @@ int main(int argc, char **argv)
 	case 'i':
 	    interlace = PNG_INTERLACE_ADAM7;
 	    break;
+	case 'l':
+	    loop = 1;
+	    break;
+	case 'q':
+	    quiet = 1;
+	    break;
 	case 's':
 	    (void) sleep((unsigned int) atoi(optarg));
 	    break;
 	case 'w':
 	    width = atoi(optarg);
 	    break;    
+	case 'H':
+	    hostname = optarg;
+	    break;
+	case 'P':
+	    service = optarg;
+	    break;
 	default:
 	    usage(argv[0]);
 	}
@@ -412,6 +519,16 @@ int main(int argc, char **argv)
     if(buf_p == NULL)
 	fatal_error("Not enough memory");
 
+	if (hostname) {
+    		sockfd = net_init(hostname, service);
+		if (sockfd < 0) {
+			fprintf(stderr, "unable to connect to %s:%s\n",
+				hostname, service);
+			exit(1);
+		}
+	}
+
+loop:
     memset(buf_p, 0, buf_size);
 
     read_framebuffer(infile, buf_size, buf_p);
@@ -421,6 +538,11 @@ int main(int argc, char **argv)
 
     convert_and_write(buf_p, outfile, width, height, bitdepth, interlace);
    
+    	if (sockfd >= 0)
+    		net_send_file(sockfd, outfile);
+    if (loop)
+    	goto loop;
+
     (void) free(buf_p);
 
     return 0;
