diff --git a/.gitignore b/.gitignore
index 47c6788..84b4a43 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,4 @@
# File produce by procstat.c
procstat
+# File produce by netboot.c
+netboot
diff --git a/git-loc b/git-loc
new file mode 100755
index 0000000..1853b06
--- /dev/null
+++ b/git-loc
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+
+import re
+from email.utils import parsedate
+from time import mktime
+from datetime import datetime
+from os import popen
+import os
+from sys import argv,stderr,stdout
+import getopt
+
+
+opts, args = getopt.getopt(argv[1:],None, ['svg'])
+needsvg = False
+for o, a in opts:
+ if o == "--svg":
+ needsvg = True
+extfolder = False
+if len(args) == 1:
+ extfolder = True
+ targetfolder = args[0]
+
+
+fc=0
+locs=0
+adds=None
+cmt=None
+
+h=[]
+
+def pop():
+ if adds is not None:
+ pstr="%s %8u %5s %5s %7s %s \t%s"%(d,locs,'+'+str(adds),'-'+str(dels),hsh,who,cmt.strip())
+ if needsvg: stderr.write(pstr+'\n')
+ else: print(pstr)
+ h.append((d,locs,adds,dels,hsh,who,cmt))
+
+prevfolder = os.getcwd()
+if extfolder:
+ os.chdir(targetfolder)
+
+for x in popen('git log --no-color --reverse -p'):
+ if x.startswith('commit'):
+ pop()
+ hsh=x[7:14];
+ if x.startswith('Author'):
+ who=x.replace("Author: ",'').replace('\n','');
+ who=re.sub(">.*","",who);
+ who=re.sub(".*<","",who);
+ if x.startswith('Date'):
+ fc=1
+ d=datetime(*parsedate(x[5:])[:7])
+ t=mktime(parsedate(x[5:]))
+ adds=0
+ dels=0
+ if fc==2:
+ cmt=x[:-1]
+ fc=0
+ if fc==1:
+ if len(x)==1: fc=2
+ if x.startswith('+') and not x.startswith('+++'):
+ adds+=1
+ locs+=1
+ if x.startswith('-') and not x.startswith('---'):
+ dels+=1
+ locs-=1
+
+pop()
+os.chdir(prevfolder)
+
+def makesvg():
+ def quoteone(x):
+ if x in 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789': return x
+ return "%02x;"%(ord(x),)
+
+ def quote(s):
+ return ''.join([quoteone(x) for x in s])
+
+ mlocs=max([locs for d,locs,adds,dels,hsh,who,cmt in h])
+ yscale=800.0/mlocs
+
+ svg=stdout
+ svg.write(""""""
+ """"""
+ """\n""")
+
+if needsvg: makesvg()
diff --git a/netboot.c b/netboot.c
new file mode 100644
index 0000000..04793c4
--- /dev/null
+++ b/netboot.c
@@ -0,0 +1,298 @@
+/* http://brokestream.com/netboot.html
+
+ To build it: gcc -o netboot netboot.c
+
+ netboot.c
+ Version 2010-01-19
+
+ Copyright (C) 2007-2010 Ivan Tikhonov
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+ Ivan Tikhonov, kefeer@brokestream.com
+
+*/
+
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+void tftpd(int s) {
+ static int f;
+ static int blksize = 512;
+ static int last_sent = 0;
+ static int was_last = 0;
+ {
+ unsigned char p[1500];
+ struct sockaddr_in peer;
+ int peerl = sizeof(peer);
+ int n = recvfrom(s,p,1500,0,(struct sockaddr *)&peer,&peerl);
+ if(p[1] == 1) {
+ unsigned char o[1500];
+ unsigned char *pp = p+2;
+ unsigned char *epp = p+n;
+ while(pp>8)&0xff,no&0xff};
+ lseek(f,(no-1)*blksize,SEEK_SET);
+ n = read(f,o+4,blksize);
+ sendto(s,o,n+4,0,(struct sockaddr *)&peer,peerl);
+ last_sent = no;
+ if(n 1 && argc < 5) {
+ fprintf(stderr, "Usage : ./netboot \n");
+ fprintf(stderr, "Example: ./netboot 192.168.0.255 192.168.0.1 192.168.0.55 00:11:ee:ff:66:ef\n");
+ fprintf(stderr, "Example: ./netboot 192.168.0.255 192.168.0.1 192.168.0.55 -66-ef\n");
+ fprintf(stderr, "\nTo find out who requesting boot run: ./netboot\n");
+ exit(1);
+ }
+
+ if(argc == 5) {
+ bc = inet_addr(argv[1]);
+ sc = inet_addr(argv[2]);
+ cc = inet_addr(argv[3]);
+
+ { char *p = argv[4]; while(*p) {
+ int d;
+ if(p[0]>='0'&&p[0]<='9') { d = (p[0]-'0')<<4; }
+ else if(p[0]>='a'&&p[0]<='f') { d = (p[0]-'a'+0xa)<<4; }
+ else if(p[0]>='A'&&p[0]<='F') { d = (p[0]-'A'+0xa)<<4; }
+ else { p++; continue; }
+ if(p[1]>='0'&&p[1]<='9') { d = d|(p[1]-'0'); }
+ else if(p[1]>='a'&&p[1]<='f') { d = d|(p[1]-'a'+0xa); }
+ else if(p[1]>='A'&&p[1]<='F') { d = d|(p[1]-'A'+0xa); }
+
+ macpat[6-macskip] = d;
+ macskip--;
+ p+=2;
+ }}
+ }
+
+ if(cc) {
+ fprintf(stderr, "mac pattern:");
+ { int i = macskip;
+ while(i--) { fprintf(stderr,"?? "); }
+ i = 0; while(i<(6-macskip)) { fprintf(stderr, "%02x ",macpat[i]); i++; }
+ }
+ fprintf(stderr, "\n");
+ }
+
+ { struct sockaddr_in b = { AF_INET, htons(67), {0xffffffff} };
+ if(bind(s, (struct sockaddr *)&b, sizeof(b)) != 0) {
+ fprintf(stderr, "Can not bind broadcast address. DHCP will not work! Try run it as root?\n");
+ }
+ }
+
+ if(cc)
+ { struct sockaddr_in b = { AF_INET, htons(67), {sc} };
+ r = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if(bind(r, (struct sockaddr *)&b, sizeof(b)) != 0) {
+ fprintf(stderr, "Can not bind server address. DHCP WILL NOT WORK! Try run it as root?\n");
+ }
+ }
+
+ if(cc)
+ { struct sockaddr_in b = { AF_INET, htons(69), {sc} };
+ t = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
+ if(bind(t, (struct sockaddr *)&b, sizeof(b)) != 0) {
+ fprintf(stderr, "Can not bind tftp server address. TFTP WILL NOT WORK! Try run it as root?\n");
+ }
+ }
+
+ { int v = 1;
+ setsockopt(r,SOL_SOCKET,SO_BROADCAST,&v,sizeof(v));
+ }
+
+ {
+ struct passwd *nobody;
+ nobody = getpwnam("nobody");
+ if (nobody && nobody->pw_uid) setuid(nobody->pw_uid);
+ }
+
+
+ for(;;) {
+ fd_set rset;
+ int n;
+
+ FD_ZERO(&rset);
+ FD_SET(s,&rset);
+ if(t != -1) FD_SET(t,&rset);
+ n = select((t>s?t:s)+1,&rset,0,0,0);
+
+ if(cc&&FD_ISSET(t,&rset)) {
+ tftpd(t);
+ }
+
+ if(FD_ISSET(s,&rset)) {
+ int type, pos97 = -1, pos12=-1;
+ unsigned char p[1500] = {0xff};
+ recv(s,p,1500,0);
+ if(p[0] == 2) continue;
+
+
+ { int i = 240;
+ for(;i<1500;) {
+ if(p[i] == 0xff) break;
+ if(p[i] == 0x0) { i++; continue; }
+ if(p[i] == 53) { type = p[i+2]; }
+ if(p[i] == 97) { pos97 = i+1; }
+ if(p[i] == 12) { pos12 = i+1; }
+ i += p[i+1] + 2;
+ }
+ }
+
+ printf("request %u from %02x-%02x-%02x-%02x-%02x-%02x ",type,p[28],p[29],p[30],p[31],p[32],p[33]);
+ if(pos12!=-1) { printf("(%.*s)\n", p[pos12],p+pos12+1);
+ } else { printf("(%s)\n", p+44); }
+ if(!cc) continue;
+
+ if(memcmp(p+28+macskip,macpat,(6-macskip))) continue;
+
+ printf("matched\n");
+
+ if(type == 1 || type == 3) {
+ int i,m;
+ p[0] = 2;
+ p[12] = 0; p[13] = 0; p[14] = 0; p[15] = 0;
+
+ *(uint32_t*)(p+16)=(uint32_t)cc;
+ *(uint32_t*)(p+20)=(uint32_t)sc;
+
+ i = 240;
+
+
+ if(pos97 != -1) {
+ p[i++] = 97;
+ { int n = p[pos97++];
+ p[i++] = n;
+ while(n--) { p[i++] = p[pos97++]; }
+ }
+ }
+
+ p[i++] = 53; p[i++] = 1;
+ p[i++] = type==1 ? 2 : 5;
+
+ p[i++] = 51; p[i++] = 4;
+ p[i++] = 255; p[i++] = 255; p[i++] = 255; p[i++] = 255;
+
+ p[i++] = 54; p[i++] = 4;
+ *(uint32_t*)(p+i)=(uint32_t)sc; i+=4;
+
+ p[i++] = 60; p[i++] = 9;
+ p[i++] = 'P'; p[i++] = 'X'; p[i++] = 'E'; p[i++] = 'C'; p[i++] = 'l'; p[i++] = 'i'; p[i++] = 'e'; p[i++] = 'n'; p[i++] = 't';
+
+ if(type == 3) {
+ p[i++] = 1; p[i++] = 4;
+ p[i++] = 255; p[i++] = 0; p[i++] = 0; p[i++] = 0;
+ p[i++] = 12; p[i++] = 9;
+ p[i++] = 'p'; p[i++] = 'x'; p[i++] = 'e'; p[i++] = 'c'; p[i++] = 'l'; p[i++] = 'i'; p[i++] = 'e'; p[i++] = 'n'; p[i++] = 't';
+ p[i++] = 67; m = i++;
+ p[i++] = 'p'; p[i++] = 'x'; p[i++] = 'e'; p[i++] = 'l'; p[i++] = 'i'; p[i++] = 'n'; p[i++] = 'u'; p[i++] = 'x'; p[i++] = '.'; p[i++] = '0'; p[i++] = '\0';
+ p[m] = i - m - 2;
+ }
+
+ p[i++] = 43; m = i++;
+ {
+ if(type == 1) {
+ p[i++] = 6; p[i++] = 1; p[i++] = 0;
+
+ p[i++] = 8; p[i++] = 7;
+ p[i++] = 0; p[i++] = 0; p[i++] = 1;
+ *(uint32_t*)(p+i)=(uint32_t)sc; i+=4;
+ }
+ p[i++] = 255;
+ }
+ p[m] = i - m - 2;
+ p[i++] = 255;
+
+ { struct sockaddr_in a = { AF_INET, htons(68), {bc} };
+ sendto(r,p,i,0,(struct sockaddr *)&a,sizeof(a));
+ }
+ }
+ }
+ }
+}