--- /dev/null
+/* written by Andrew Tridgell (May 1992) */
+
+
+#include <stdio.h>
+#include <malloc.h>
+#include <varargs.h>
+#include <stdlib.h>
+#include <time.h>
+
+int xsize=0;
+int ysize=0;
+
+char **grid;
+char *wordfile;
+char **wordlist=NULL;
+int num_words=0;
+
+enum _Direction{ACROSS,DOWN};
+typedef enum _Direction Direction;
+typedef int BOOL;
+#define True 1
+#define False 0
+#define CONST const
+#define LONG_STRING_LENGTH 200
+
+char *strtidy();
+void read_a_line();
+char *my_fgets();
+
+
+#ifndef MSDOS
+#define randomize() srand(time(NULL))
+#define ctrlbrk(fn)
+#define BLACKSQUARE ' '
+#else
+#define BLACKSQUARE 'Û'
+#endif
+
+/*******************************************************************
+create a matrix of any dimension. The return must be cast correctly.
+********************************************************************/
+void *any_matrix(va_alist)
+va_dcl
+{
+int dimension;
+int el_size;
+int *dims=NULL;
+void **mat;
+int i,j,size,ptr_size,ppos,prod;
+int padding;
+void *next_ptr;
+va_list ap;
+
+/* first gather the arguments */
+va_start(ap);
+dimension = va_arg(ap, int);
+el_size = va_arg(ap, int);
+
+
+if (dimension <= 0) return(NULL);
+if (el_size <= 0) return(NULL);
+
+dims = (int *)malloc(dimension * sizeof(int));
+if (dims == NULL) return(NULL);
+for (i=0;i<dimension;i++)
+ dims[i] = va_arg(ap, int);
+va_end(ap);
+
+/* now we've disected the arguments we can go about the real business of
+creating the matrix */
+
+/* calculate how much space all the pointers will take up */
+ptr_size = 0;
+for (i=0;i<(dimension-1);i++)
+ {
+ prod=sizeof(void *);
+ for (j=0;j<=i;j++) prod *= dims[j];
+ ptr_size += prod;
+ }
+
+/* padding overcomes potential alignment errors */
+padding = (el_size - (ptr_size % el_size)) % el_size;
+
+/* now calculate the total memory taken by the array */
+{
+prod=el_size;
+for (i=0;i<dimension;i++) prod *= dims[i];
+size = prod + ptr_size + padding;
+}
+
+/* allocate the matrix memory */
+mat = (void **)malloc(size);
+
+if (mat == NULL)
+ {
+ fprintf(stdout,"Error allocating %d dim matrix of size %d\n",dimension,size);
+ free(dims);
+ return(NULL);
+ }
+
+/* now fill in the pointer values */
+next_ptr = (void *)&mat[dims[0]];
+ppos = 0;
+prod = 1;
+for (i=0;i<(dimension-1);i++)
+{
+int skip;
+if (i == dimension-2)
+ {
+ skip = el_size*dims[i+1];
+ next_ptr = (void *)(((char *)next_ptr) + padding); /* add in the padding */
+ }
+else
+ skip = sizeof(void *)*dims[i+1];
+
+for (j=0;j<(dims[i]*prod);j++)
+ {
+ mat[ppos++] = next_ptr;
+ next_ptr = (void *)(((char *)next_ptr) + skip);
+ }
+prod *= dims[i];
+}
+
+free(dims);
+return((void *)mat);
+}
+
+
+/*******************************************************************
+return a random number
+********************************************************************/
+int random_num(void)
+{
+return(rand());
+}
+
+
+/*******************************************************************
+this returns the number of lines in a text file
+********************************************************************/
+int num_text_lines(CONST char *fname)
+{
+FILE *file;
+int count = 0;
+char buf[2000];
+
+file = fopen(fname,"r");
+if (!file)
+ return(0);
+
+while (!feof(file))
+ {
+ read_a_line(buf,2000,file);
+ if (*buf) count++;
+ }
+
+fclose(file);
+return(count);
+}
+
+/*******************************************************************
+read a line from a file. If the line is of 0 length then read another
+********************************************************************/
+void read_a_line(char *buf,int maxlen,FILE *file)
+{
+my_fgets(buf,maxlen,file);
+if (strlen(buf) == 0)
+ my_fgets(buf,maxlen,file);
+}
+
+/*******************************************************************
+like fgets but remove trailing CR or LF
+********************************************************************/
+char *my_fgets(char *s,int n,FILE *stream)
+{
+char *ret;
+
+ret = fgets(s,n,stream);
+if (ret == NULL)
+ {
+ *s = 0;
+ return(NULL);
+ }
+
+return(strtidy(s,"\n\r "));
+}
+
+/*******************************************************************
+remove specified chars from front and back of a string
+********************************************************************/
+char *strtidy(char *str,CONST char *chars)
+{
+int len=strlen(str);
+while ((len > 0) && (strchr(chars,*str) != NULL))
+ {
+ memcpy(str,&str[1],len);
+ len--;
+ }
+while ((len > 0) && (strchr(chars,str[len-1]) != NULL))
+ {
+ str[len-1]=0;
+ len--;
+ }
+return(str);
+}
+
+
+
+
+/*******************************************************************
+load a list of words
+********************************************************************/
+char **load_word_list(char *fname,int *num)
+{
+FILE *file;
+int i;
+char line[LONG_STRING_LENGTH];
+char **list;
+*num = num_text_lines(fname);
+if (*num < 1)
+ return(NULL);
+
+list = (char **)malloc(sizeof(char *)*(*num));
+
+file = fopen(fname,"r");
+for (i=0;i<(*num);i++)
+ {
+ read_a_line(line,LONG_STRING_LENGTH,file);
+ list[i] = (char *)malloc(strlen(line)+1);
+ strcpy(list[i],line);
+ }
+fclose(file);
+
+return(list);
+}
+
+/*******************************************************************
+place a word
+********************************************************************/
+void PlaceWord(char *word,int i,int j,Direction dir)
+{
+int k;
+int len=strlen(word);
+if (dir == ACROSS)
+ {
+ for (k=0;k<len;k++)
+ grid[i+k][j] = word[k];
+ }
+else
+ {
+ for (k=0;k<len;k++)
+ grid[i][j+k] = word[k];
+ }
+}
+
+/*******************************************************************
+determine if a word is legal in a position
+********************************************************************/
+BOOL Legal(char *word,int i,int j,Direction dir)
+{
+int len=strlen(word);
+if (dir == ACROSS)
+ {
+ int k;
+ if (i+len > xsize) return(False);
+ if ((i != 0) && grid[i-1][j]) return(False);
+ if (((i+len) != xsize) && grid[i+len][j]) return(False);
+ for (k=0;k<len;k++)
+ if (grid[i+k][j] && (grid[i+k][j] != word[k])) return(False);
+ for (k=0;k<len;k++)
+ {
+ if ((j != 0) && grid[i+k][j-1] && !grid[i+k][j]) return(False);
+ if ((j != (ysize-1)) && grid[i+k][j+1] && !grid[i+k][j]) return(False);
+ }
+ }
+else
+ {
+ int k;
+ if (j+len > ysize) return(False);
+ if ((j != 0) && grid[i][j-1]) return(False);
+ if (((j+len) != ysize) && grid[i][j+len]) return(False);
+ for (k=0;k<len;k++)
+ if (grid[i][j+k] && (grid[i][j+k] != word[k])) return(False);
+ for (k=0;k<len;k++)
+ {
+ if ((i != 0) && grid[i-1][j+k] && !grid[i][j+k]) return(False);
+ if ((i != (xsize-1)) && grid[i+1][j+k] && !grid[i][j+k]) return(False);
+ }
+ }
+return(True);
+}
+
+/*******************************************************************
+score a word in a position
+********************************************************************/
+int Score(char *word,int i,int j,Direction dir)
+{
+int len=strlen(word);
+int score=0;
+if (dir == ACROSS)
+ {
+ int k;
+ for (k=0;k<len;k++)
+ if (grid[i+k][j])
+ {
+ if ((k == 0) || (k == (len-1)))
+ score += 2;
+ else
+ score += 3;
+ }
+ if ((j != 0) && (j != (ysize-1))) score++;
+ }
+else
+ {
+ int k;
+ for (k=0;k<len;k++)
+ if (grid[i][j+k])
+ {
+ if ((k == 0) || (k == (len-1)))
+ score += 4;
+ else
+ score += 6;
+ }
+ if ((i != 0) && (i != (xsize-1))) score++;
+ }
+return(score);
+}
+
+Direction last_dir=ACROSS;
+
+
+/*******************************************************************
+find the best position for a word
+********************************************************************/
+BOOL BestPosition(char *word,int *besti,int *bestj,Direction *dir)
+{
+int best;
+int i,j;
+Direction d;
+best = -1;
+for (i=0;i<xsize;i++)
+ for (j=0;j<ysize;j++)
+ {
+ int s;
+ d = ACROSS;
+ if (Legal(word,i,j,d))
+ {
+ s = Score(word,i,j,d);
+ if (last_dir != d) s++;
+ if (s > best || ((s == best) && ((random_num()%(xsize*ysize/4))!=0)))
+ {
+ best = s;
+ *besti = i;
+ *bestj = j;
+ *dir = d;
+ }
+ }
+ d = DOWN;
+ if (Legal(word,i,j,d))
+ {
+ s = Score(word,i,j,d);
+ if (last_dir != d) s++;
+ if (s > best || ((s == best) && ((random_num()%(xsize*ysize/4))!=0)))
+ {
+ best = s;
+ *besti = i;
+ *bestj = j;
+ *dir = d;
+ }
+ }
+ }
+return(best >= 0);
+}
+
+/*******************************************************************
+zero a crossword
+********************************************************************/
+void zero_crossword(void)
+{
+int i,j;
+for (i=0;i<xsize;i++)
+ for (j=0;j<ysize;j++)
+ grid[i][j] = 0;
+}
+
+
+/*******************************************************************
+build a crossword
+********************************************************************/
+int BuildCrossword(char **list,int num)
+{
+int i,j;
+Direction d;
+int remaining=num;
+int bad=0;
+BOOL *used = (BOOL *)malloc(sizeof(BOOL)*num);
+for (i=0;i<num;i++)
+ used[i] = False;
+zero_crossword();
+while (remaining > 0)
+ {
+ int choose=-1;
+ while (choose==-1)
+ {
+ choose = random_num() % num;
+ if (used[choose]) choose=-1;
+ }
+ used[choose] = True;
+ remaining--;
+ if (BestPosition(list[choose],&i,&j,&d))
+ PlaceWord(list[choose],i,j,d);
+ else
+ bad++;
+ }
+return(num-bad);
+}
+
+/*******************************************************************
+build a crossword
+********************************************************************/
+int BuildBestCrossword(char **list,int num)
+{
+int i,j;
+Direction d;
+int remaining=num;
+int bad=0;
+BOOL *used = (BOOL *)malloc(sizeof(BOOL)*num);
+int *scores = (int *)malloc(sizeof(int)*num);
+
+for (i=0;i<num;i++)
+ used[i] = False;
+
+zero_crossword();
+while (remaining > 0)
+ {
+ int n;
+ int choose;
+ for (i=0;i<num;i++)
+ scores[i] = -1;
+ for (n=0;n<num;n++)
+ if (!used[n] && BestPosition(list[n],&i,&j,&d))
+ scores[n] = Score(list[n],i,j,d);
+ {
+ int numbest=0,bestscore=scores[0];
+ int k;
+ for (n=0;n<num;n++)
+ {
+ if (scores[n] == bestscore) numbest++;
+ if (scores[n] > bestscore)
+ {
+ bestscore = scores[n];
+ numbest = 1;
+ }
+ }
+ if (bestscore < 0) return(num-remaining);
+ k = random_num() % numbest;
+ numbest=0;
+ for (n=0;n<num;n++)
+ {
+ if (scores[n] == bestscore)
+ {
+ if (numbest == k) choose=n;
+ numbest++;
+ }
+ }
+ }
+ BestPosition(list[choose],&i,&j,&d);
+ PlaceWord(list[choose],i,j,d);
+ used[choose] = True;
+ remaining--;
+ }
+return(num-remaining);
+}
+
+/*******************************************************************
+display the crossword
+********************************************************************/
+void DisplayCrossword(FILE *f)
+{
+int i,j;
+for (j=0;j<ysize;j++)
+ {
+ for (i=0;i<xsize;i++)
+ {
+ if (grid[i][j])
+ fputc(grid[i][j],f);
+ else
+ fputc(BLACKSQUARE,f);
+ }
+ fputc('\n',f);
+ }
+putchar('\n');
+}
+
+
+/*******************************************************************
+save the crossword in a pzl file
+********************************************************************/
+void SavePuzzle(char *fname)
+{
+FILE *f = fopen(fname,"w");
+int i,j;
+if (!f) return;
+
+fprintf(f,"%cXWORD0%s%c%c%2d%2d",42,"Sue2",3,3,xsize,ysize);
+
+for (j=0;j<ysize;j++)
+ for (i=0;i<xsize;i++)
+ fprintf(f,"%c %c",(grid[i][j]?grid[i][j]:' '),3);
+
+fclose(f);
+}
+
+
+/*******************************************************************
+save the crossword in a .cwd file (for ccwin15.zip)
+********************************************************************/
+void SaveCross(char *fname)
+{
+FILE *f = fopen(fname,"w");
+int i,j;
+char head[10];
+
+if (!f) return;
+
+memset(head,0,10);
+head[0] = 'j';
+head[4] = '\n';
+head[6] = 1;
+head[8] = xsize;
+head[9] = ysize;
+
+fwrite(head,1,10,f);
+
+for (j=0;j<ysize;j++)
+ for (i=0;i<xsize;i++)
+ fprintf(f,"%c",grid[i][j]?(char)toupper(grid[i][j]):0333);
+
+head[0] = 0;
+head[1] = 0;
+
+fwrite(head,1,2,f);
+
+fclose(f);
+}
+
+
+void copy_to(char **g)
+{
+int i,j;
+for (i=0;i<xsize;i++)
+for (j=0;j<ysize;j++)
+ g[i][j] = grid[i][j];
+}
+
+int cbreak(void)
+{
+return(0);
+}
+
+int main(int argc,char *argv[])
+{
+char **bestgrid;
+int best=-1;
+ctrlbrk(cbreak);
+
+randomize();
+if (argc < 4)
+ {
+ printf("angry: Xsize Ysize WordFile\n");
+ return(0);
+ }
+xsize = atoi(argv[1]);
+ysize = atoi(argv[2]);
+wordfile = argv[3];
+
+grid = (char **)any_matrix(2,sizeof(char),xsize,ysize);
+bestgrid = (char **)any_matrix(2,sizeof(char),xsize,ysize);
+if (!grid || !bestgrid)
+ {
+ printf("invalid xsize or ysize\n");
+ return(0);
+ }
+
+wordlist = load_word_list(wordfile,&num_words);
+while (True)
+ {
+ int n;
+ n = BuildBestCrossword(wordlist,num_words);
+ putchar('.');
+ if (n > best)
+ {
+ best = n;
+ copy_to(bestgrid);
+ printf("\nplaced %d words\n",best);
+ {
+ FILE *f = fopen("best.doc","w");
+ DisplayCrossword(stdout);
+ DisplayCrossword(f);
+ SavePuzzle("best.pzl");
+ SaveCross("best.cwd");
+ fclose(f);
+ }
+ }
+ fflush(stdout);
+ }
+}
--- /dev/null
+#include <stdio.h>
+#include <malloc.h>
+#include <stdarg.h>
+
+/*******************************************************************
+create a matrix of any dimension. The return must be cast correctly.
+********************************************************************/
+void *any_matrix(int dimension, int el_size, ...)
+{
+ int *dims=NULL;
+ void **mat;
+ int i,j,size,ptr_size,ppos,prod;
+ int padding;
+ void *next_ptr;
+ va_list ap;
+
+ if (dimension <= 0) return(NULL);
+ if (el_size <= 0) return(NULL);
+
+ dims = (int *)malloc(dimension * sizeof(int));
+ if (dims == NULL) return(NULL);
+
+ /* gather the arguments */
+ va_start(ap, el_size);
+ for (i=0;i<dimension;i++) {
+ dims[i] = va_arg(ap, int);
+ }
+ va_end(ap);
+
+ /* now we've disected the arguments we can go about the real
+ business of creating the matrix */
+
+ /* calculate how much space all the pointers will take up */
+ ptr_size = 0;
+ for (i=0;i<(dimension-1);i++) {
+ prod=sizeof(void *);
+ for (j=0;j<=i;j++) prod *= dims[j];
+ ptr_size += prod;
+ }
+
+ /* padding overcomes potential alignment errors */
+ padding = (el_size - (ptr_size % el_size)) % el_size;
+
+ /* now calculate the total memory taken by the array */
+ prod=el_size;
+ for (i=0;i<dimension;i++) prod *= dims[i];
+ size = prod + ptr_size + padding;
+
+ /* allocate the matrix memory */
+ mat = (void **)malloc(size);
+
+ if (mat == NULL) {
+ fprintf(stdout,"Error allocating %d dim matrix of size %d\n",dimension,size);
+ free(dims);
+ return(NULL);
+ }
+
+ /* now fill in the pointer values */
+ next_ptr = (void *)&mat[dims[0]];
+ ppos = 0;
+ prod = 1;
+ for (i=0;i<(dimension-1);i++) {
+ int skip;
+ if (i == dimension-2) {
+ skip = el_size*dims[i+1];
+ next_ptr = (void *)(((char *)next_ptr) + padding); /* add in the padding */
+ } else {
+ skip = sizeof(void *)*dims[i+1];
+ }
+
+ for (j=0;j<(dims[i]*prod);j++) {
+ mat[ppos++] = next_ptr;
+ next_ptr = (void *)(((char *)next_ptr) + skip);
+ }
+ prod *= dims[i];
+ }
+
+ free(dims);
+ return((void *)mat);
+}
+
+
+
+
+/*
+ double ****x;
+ double ***y;
+
+ x = (double ****)any_matrix(4, sizeof(double), 3, 6, 8, 2);
+
+ x[0][3][4][1] = 5.0;
+
+ y = x[1];
+
+ y[2][3][4] = 7.0;
+
+ free(x);
+*/
--- /dev/null
+/* simple appletalk bridge for rodney
+
+ Andrew Tridgell 1997
+*/
+
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <signal.h>
+#include <string.h>
+#include <netdb.h>
+#include <errno.h>
+#include <endian.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <linux/if_ether.h>
+
+#define DEBUG 0
+
+#define MAX_PACKET_LENGTH 1600
+#define HISTORY_LENGTH 20
+
+/* we should use /etc/ethers but I'm too lazy */
+#if 0
+#define HUB "00:00:0C:13:6F:18"
+#else
+#define HUB "00:00:C0:81:93:8E"
+#endif
+#define ETH0 "00:00:C0:1B:A2:B8"
+#define ETH1 "00:00:C0:6A:71:99"
+
+static int eth_fd0 = -1;
+static int eth_fd1 = -1;
+
+static char *if_eth0 = "eth0"; /* name of ethernet interface */
+static char *if_eth1 = "eth1"; /* name of ethernet interface */
+
+static char data[MAX_PACKET_LENGTH];
+
+static unsigned char hub_addr[ETH_ALEN];
+static unsigned char eth0_addr[ETH_ALEN];
+static unsigned char eth1_addr[ETH_ALEN];
+
+static unsigned history[HISTORY_LENGTH];
+static int history_pointer;
+
+static unsigned eth0_counter, eth1_counter, dup_counter, ip_counter;
+
+/* parse an ethernet address from string format to a byte array */
+static void parse_ether(unsigned char *addr, char *addr_str)
+{
+ unsigned x[6];
+ if (sscanf(addr_str, "%x:%x:%x:%x:%x:%x",
+ &x[0], &x[1], &x[2],
+ &x[3], &x[4], &x[5]) != 6) {
+ fprintf(stderr,"couldn't parse %s\n", addr_str);
+ }
+ addr[0] = x[0]; addr[1] = x[1]; addr[2] = x[2];
+ addr[3] = x[3]; addr[4] = x[4]; addr[5] = x[5];
+}
+
+/* pretty-print an ethernet address */
+static char *ether_str(unsigned char *addr)
+{
+ static char s[2][30];
+ static int i;
+ char *ret;
+
+ ret = s[i];
+
+ sprintf(ret,"%02x:%02x:%02x:%02x:%02x:%02x",
+ addr[0], addr[1], addr[2],
+ addr[3], addr[4], addr[5]);
+
+ i = (i+1)%2;
+
+ return ret;
+}
+
+
+/* fetch the protocol field in a ethernet or 802 packet */
+static unsigned get_protocol(char *data)
+{
+ unsigned short proto;
+
+ /* its either at offset 12 or 20 */
+ proto = *(unsigned short *)(data + 12);
+ proto = ntohs(proto);
+
+ if (proto < 1500) {
+ /* it must be an 802 packet */
+ proto = *(unsigned short *)(data + 20);
+ proto = ntohs(proto);
+ }
+
+ return proto;
+}
+
+/* a really simple checksum routine, probably quite hopeless */
+static unsigned csum(char *data,int len)
+{
+ unsigned sum=0;
+ int i;
+ for (i=0;i<len;i++)
+ sum ^= data[i] << ((i*15) % 28);
+ return sum;
+}
+
+
+/* close the ethernet fd and set it back to non-promiscuous */
+static void eth_close(int fd, char *interface)
+{
+ struct ifreq ifr;
+
+ strcpy(ifr.ifr_name, interface);
+ if(ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ perror("SIOCGIFFLAGS");
+ return;
+ }
+
+ ifr.ifr_flags &= ~IFF_PROMISC;
+ if(ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+ perror("SIOCSIFFLAGS");
+ return;
+ }
+
+ close(fd);
+}
+
+
+
+/* open an ethernet socket for the requested protocol and
+ return a file descriptor that can be used for reading/writing packets
+ to that interface
+
+ pstr specifies what packet types to accept
+ */
+static int eth_open(char *interface, char *pstr)
+{
+ int fd;
+ int protocol = -1;
+ struct ifreq ifr;
+
+ if (!strcmp(pstr,"802.2")) protocol=ETH_P_802_2;
+ if (!strcmp(pstr,"802.3")) protocol=ETH_P_802_3;
+ if (!strcmp(pstr,"etherII")) protocol=ETH_P_IPX;
+ if (!strcmp(pstr,"echo")) protocol=ETH_P_ECHO;
+ if (!strcmp(pstr,"x25")) protocol=ETH_P_X25;
+ if (!strcmp(pstr,"arp")) protocol=ETH_P_ARP;
+ if (!strcmp(pstr,"atalk")) protocol=ETH_P_ATALK;
+ if (!strcmp(pstr,"aarp")) protocol=ETH_P_AARP;
+ if (!strcmp(pstr,"all")) protocol=ETH_P_ALL;
+
+ if (protocol == -1) {
+ printf("Unknown protocol [%s]\n",pstr);
+ return -1;
+ }
+
+ if ((fd = socket(AF_INET, SOCK_PACKET, htons(protocol)))<0) {
+ perror("Error opening local ethernet socket\n");
+ return -1;
+ }
+
+ strcpy(ifr.ifr_name, interface);
+ if(ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ perror("SIOCGIFFLAGS");
+ return -1;
+ }
+
+ ifr.ifr_flags |= IFF_PROMISC;
+ if(ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) {
+ perror("SIOCSIFFLAGS");
+ return -1;
+ }
+
+ return fd;
+}
+
+
+static int eth_write(int fd, char *data, int len,char *iface)
+{
+ struct sockaddr dst;
+
+ dst.sa_family = AF_INET;
+ strcpy(dst.sa_data,iface);
+
+ return sendto(fd,data,len,0,&dst,sizeof(dst));
+}
+
+static int eth_read(int fd, char *buf)
+{
+ struct sockaddr_in from;
+ size_t fromlen = sizeof(from);
+
+ return recvfrom(fd, buf, MAX_PACKET_LENGTH, 0,
+ (struct sockaddr *) &from, &fromlen);
+}
+
+static void Usage(void)
+{
+ printf("Usage: \natalk_bridge\n\n");
+ printf("atalk_bridge [-f fr] [-0 eth0] [-1 eth1] port\n\n");
+ printf("fr = Ethernet frame type to bridge. Default is 802.2.\n");
+ printf(" Known values are:\n");
+ printf(" 802.2 802.3 etherII echo x25 arp atalk aarp all\n");
+ printf("if = Network interface to read from (default is eth0)\n");
+}
+
+
+void sig_int(int sig)
+{
+ eth_close(eth_fd0, if_eth0);
+ eth_close(eth_fd1, if_eth1);
+ printf("Wrote %d packets to eth0\n", eth0_counter);
+ printf("Wrote %d packets to eth1\n", eth1_counter);
+ printf("%d duplicate packets dropped\n", dup_counter);
+ printf("%d IP packets processed\n", ip_counter);
+ exit(0);
+}
+
+
+/* this is the guts of the program. A packet has arrived and we need to decide
+ what to do with it */
+static void process_packet(char *data, int len)
+{
+ int i;
+ unsigned sum;
+ struct ethhdr *hdr;
+ unsigned protocol;
+
+ if (len <= 0) return;
+
+ sum = csum(data, len);
+
+ /* work out where it is from */
+ hdr = (struct ethhdr *)data;
+ protocol = get_protocol(data);
+
+#if DEBUG
+ printf("packet %s -> %s len=%4d proto=%04x sum=%08x ",
+ ether_str(hdr->h_source),
+ ether_str(hdr->h_dest),
+ len, protocol, sum);
+#endif
+
+ /* if the packet is from or to us then it makes no sense
+ to bridge it */
+ if (memcmp(hdr->h_source, eth0_addr, ETH_ALEN) == 0 ||
+ memcmp(hdr->h_source, eth1_addr, ETH_ALEN) == 0 ||
+ memcmp(hdr->h_dest, eth0_addr, ETH_ALEN) == 0 ||
+ memcmp(hdr->h_dest, eth1_addr, ETH_ALEN) == 0) {
+ /* its from us, drop it */
+#if DEBUG
+ printf("own packet\n");
+#endif
+ return;
+ }
+
+ /* don't process any ARP or RARP packets */
+ if (protocol == ETH_P_ARP || protocol == ETH_P_RARP) {
+#if DEBUG
+ printf("ARP\n");
+#endif
+ return;
+ }
+
+ /* initially process IP packets to and from the hub, at
+ least until the bridge gets established. Once the arp tables
+ get flushed we will just be able to drop all these packets */
+ if (protocol == ETH_P_IP &&
+ memcmp(hdr->h_source, hub_addr, ETH_ALEN) == 0 &&
+ memcmp(hdr->h_dest, hub_addr, ETH_ALEN) == 0) {
+#if DEBUG
+ printf("IP\n");
+#endif
+ return;
+ }
+
+ /* is it a duplicate? */
+ for (i=0;i<HISTORY_LENGTH;i++)
+ if (sum == history[i]) {
+#if DEBUG
+ printf("duplicate %d\n", i);
+#endif
+ history[i] = 0;
+ dup_counter++;
+ return;
+ }
+ history[history_pointer] = sum;
+ history_pointer = (history_pointer+1) % HISTORY_LENGTH;
+
+ if (protocol == ETH_P_IP) {
+ printf("packet %s -> %s len=%4d proto=%04x sum=%08x\n",
+ ether_str(hdr->h_source),
+ ether_str(hdr->h_dest),
+ len, protocol, sum);
+ ip_counter++;
+ }
+
+ if (memcmp(hdr->h_source, hub_addr, ETH_ALEN) == 0) {
+ /* its from the hub (presumed to be on eth1). Send it to
+ eth0 */
+#if DEBUG
+ printf("to eth0\n");
+#endif
+ printf("packet %s -> %s len=%4d proto=%04x sum=%08x\n",
+ ether_str(hdr->h_source),
+ ether_str(hdr->h_dest),
+ len, protocol, sum);
+ eth0_counter++;
+ eth_write(eth_fd0, data, len, if_eth0);
+ } else {
+ /* its from a host on eth1, pass it on to eth1 */
+#if DEBUG
+ printf("to eth1\n");
+#endif
+ eth1_counter++;
+ eth_write(eth_fd1, data, len, if_eth1);
+ }
+}
+
+
+int main(int argc, char *argv[])
+{
+ int i;
+ char *pstr = "all";
+
+ if(getuid()) {
+ fprintf(stderr, "must be superuser\n");
+ exit(1);
+ }
+
+ fprintf(stderr,"atalk_bridge by Andrew Tridgell\n");
+
+ /* Process command-line args */
+ for(i=1; i<argc && argv[i][0]=='-'; ++i) switch(argv[i][1])
+ {
+ case 'f':
+ /* Selected frame types - from linux/if_ether.h */
+ pstr = argv[++i];
+ break;
+ case '0': if_eth0 = argv[++i]; break;
+ case '1': if_eth1 = argv[++i]; break;
+ default:
+ Usage();
+ break;
+ }
+
+ parse_ether(hub_addr, HUB);
+ parse_ether(eth0_addr, ETH0);
+ parse_ether(eth1_addr, ETH1);
+
+ eth_fd0 = eth_open(if_eth0, pstr);
+ if (eth_fd0 == -1) {
+ fprintf(stderr,"can't open %s\n", if_eth0);
+ exit(1);
+ }
+
+ eth_fd1 = eth_open(if_eth1, pstr);
+ if (eth_fd1 == -1) {
+ fprintf(stderr,"can't open %s\n", if_eth1);
+ eth_close(eth_fd0, if_eth0);
+ exit(1);
+ }
+
+ signal(SIGINT, sig_int);
+
+ printf("bridge started\n");
+
+ while (1) {
+ fd_set rfd;
+ int len, no;
+ struct timeval tv;
+
+ FD_ZERO(&rfd);
+ FD_SET(eth_fd0, &rfd);
+ FD_SET(eth_fd1, &rfd);
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ no = select(32, &rfd, NULL, NULL, &tv);
+
+ if (no == -1 && errno != EAGAIN) {
+ printf("select error\n");
+ break;
+ }
+
+ if (no == 0) {
+ /* zero the history */
+ memset(history, 0, sizeof(history));
+ continue;
+ }
+
+ /* is anything happening on the ethernet? */
+ if (FD_ISSET(eth_fd0, &rfd)) {
+ len = eth_read(eth_fd0, data);
+ process_packet(data, len);
+ }
+
+#if 0
+ /* this is commented out as it seems that we get all
+ packets on both file sockets! */
+ if (FD_ISSET(eth_fd1, &rfd)) {
+ len = eth_read(eth_fd1, data);
+ process_packet(data, len);
+ }
+#endif
+ }
+
+ return 0;
+}
--- /dev/null
+static void batchers_sort(int baseP,int N,void (*makesmaller)())
+{
+ int p, initq, q, r, d, x;
+
+ for (p=1; (1<<(p+1))<=N+1; p++);
+ p = 1<<p;
+
+ for (initq=p; p>0; p/=2)
+ {
+ q = initq;
+ r = 0;
+ d = p;
+ do
+ {
+ for (x=0; x<N-d; x++)
+ if ( (x & p) == r)
+ makesmaller(baseP+x,baseP+x+d);
+ d = q - p;
+ q /= 2;
+ r = p;
+ } while (q != p/2);
+ }
+}
+
+void makesmaller(int n1,int n2)
+{
+ printf("%d %d\n",n1,n2);
+}
+
+main(int argc,char *argv[])
+{
+ batchers_sort(0,atoi(argv[1]),makesmaller);
+}
--- /dev/null
+#include <stdio.h>
+
+main(int argc,char *argv[])
+{
+ int count=1;
+ if (argc > 1)
+ count = atoi(argv[1]);
+ while (count--)
+ {
+ putc(7,stdout);
+ fflush(stdout);
+ usleep(200000);
+ }
+}
--- /dev/null
+typedef unsigned uint32;
+
+static inline int bcount1(uint32 x)
+{
+ int count=0;
+ int i;
+ for (i=0;i<32;i++)
+ if (x & (1<<i)) count++;
+ return count;
+}
+
+static inline int bcount2(uint32 x)
+{
+ int count;
+ for (count=0; x; count++)
+ x &= (x-1);
+ return count;
+}
+
+
+static int pop_count[256];
+
+static void init_eval_tables(void)
+{
+ int i;
+
+ for (i=0;i<256;i++) {
+ int j, ret=0;
+ for (j=0;j<8;j++)
+ if (i & (1<<j))
+ ret++;
+ pop_count[i] = ret;
+ }
+}
+
+static inline int pop_count16(uint32 x)
+{
+ return pop_count[(x)&0xFF] + pop_count[((x)>>8)&0xFF];
+}
+
+static inline int pop_count32(uint32 x)
+{
+ return pop_count16((x) & 0xFFFF) + pop_count16((x) >> 16);
+}
+
+int main(void)
+{
+ int i;
+ uint32 x;
+
+ init_eval_tables();
+
+ for (i=0;i<1000000;i++) {
+ x = random();
+ if (pop_count32(x) != bcount1(x))
+ printf("x=%x\n", x);
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+a quick hack to test an idea for 16 bit BMG string searches
+
+Inspired by the fact that Padre is slow when lots of alternates are
+specified in a query
+
+This method reduces the density of zero entries in the delta_table and
+also makes the list of candidate targets much smaller when a zero
+entry is hit.
+
+It still needs a lot of optimisation. In particular it needs to be
+hard wired for 16 bit operation. Currently it can compile for ngraph
+based matching, although n>2 would be silly.
+
+Sample usage:
+
+compile it with "gcc -O2 -o bmg16 -DTAG=short bmg.c"
+
+run it with "bmg16 'hello|goodbye|yellow|blue' /usr/dict/words"
+
+Andrew Tridgell
+30/3/95
+*/
+
+#include <stdio.h>
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* this determines if the algorithm is 8 or 16 bit - it works for both */
+#ifndef TAG
+#define TAG short
+#endif
+
+typedef unsigned TAG tag;
+typedef unsigned char uchar;
+
+
+#define TABLE_SIZE (1<<(sizeof(tag)*8))
+#define DELIMITERS "|"
+#define MAX_ALTERNATES 255
+#define AVG_ALTERNATES 4
+#define PUNCTUATION " \t,;:.\"'`"
+#define CASE_MASK (~(1<<5))
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+/* this is a case insensitive character match */
+#define CHAR_EQUAL(c1,c2) (((c1)&CASE_MASK) == ((c2)&CASE_MASK))
+
+static uchar delta_table[TABLE_SIZE];
+static uchar target_list[TABLE_SIZE][AVG_ALTERNATES];
+static uchar target_list_len[TABLE_SIZE];
+static uchar *targets[MAX_ALTERNATES];
+static int target_lengths[MAX_ALTERNATES];
+static int num_targets = 0;
+static int min_target_length = (1<<30);
+
+/* extract a tag value from a buffer. Obviously if the tag size
+ were fixed (8 or 16 bit) this would be much faster */
+static inline tag tag_value(uchar *buf)
+{
+ int i;
+ unsigned int ret=0;
+ for (i=0;i<sizeof(tag);i++)
+ ret |= (buf[i]<<(8*i));
+ return(ret);
+}
+
+/* check if two characters match using the rules for
+ punctuation */
+static inline int uchar_match(uchar c,uchar b)
+{
+ return(CHAR_EQUAL(c,b) || (b==' ' && strchr(PUNCTUATION,c)));
+}
+
+/* check if two tags are equal. This is quite general, and slow */
+static inline int tag_equal(tag t,uchar *buf,int offset)
+{
+ int i;
+ if (offset>0) offset=0;
+ for (i=-offset;i<sizeof(tag);i++)
+ if (!uchar_match((t>>(8*i))&0xFF,buf[i])) return(0);
+ return(1);
+}
+
+/* compare two strings */
+static inline int strnequal(uchar *s1,uchar *s2,int n)
+{
+ while (n--) {
+ if (!uchar_match(*s2,*s1)) return(0);
+ s1++; s2++;
+ }
+ return(1);
+}
+
+
+/* generate a table of what chars occur at all in the targets */
+static void generate_char_table(char *char_table)
+{
+ int has_space=0;
+ uchar c;
+ int i,j;
+ uchar *p = (uchar *)PUNCTUATION;
+
+ memset(char_table,0,256);
+ for (i=0;i<num_targets;i++)
+ for (j=0;j<target_lengths[i];j++) {
+ c = targets[i][j];
+ if (c == ' ')
+ has_space = 1;
+ else
+ char_table[c & CASE_MASK] = char_table[c | ~CASE_MASK] = 1;
+ }
+ if (has_space)
+ for (i=0;i<strlen(p);i++)
+ char_table[p[i]] = 1;
+}
+
+
+
+/* check if a tag is possible */
+static inline int valid_tag(char *char_table,tag t)
+{
+ if (!char_table[(t>>(8*(sizeof(tag)-1)))&0xFF]) return(0);
+ return(1);
+}
+
+
+/* build the tables needed for the bmg search */
+void bmg_build_table(uchar *target_string)
+{
+ uchar *p = (uchar *)strdup(target_string);
+ uchar *tok;
+ int i,j;
+ int t;
+ char char_table[256];
+
+ num_targets = 0;
+
+ /* parse the command */
+ for (tok=strtok(p,DELIMITERS); tok; tok = strtok(NULL,DELIMITERS)) {
+ targets[num_targets] = strdup(tok);
+ target_lengths[num_targets] = strlen(tok);
+ min_target_length = MIN(min_target_length,target_lengths[num_targets]);
+ num_targets++;
+ }
+ free(p);
+
+ if (min_target_length < sizeof(tag))
+ printf("Error! you have a target smaller than the tag\n");
+
+ if (!num_targets) return;
+
+ generate_char_table(char_table);
+
+ /* built the bmg table - this is a mess */
+ for (t=0;t<TABLE_SIZE;t++) {
+
+ delta_table[t] = min_target_length;
+ target_list_len[t] = 0;
+
+ if (!valid_tag(char_table,t))
+ continue;
+
+ for (i=0;i<num_targets;i++)
+ {
+ for (j=(target_lengths[i]-sizeof(tag));j+sizeof(tag)>=1;j--)
+ if (tag_equal(t,targets[i]+j,j))
+ {
+ delta_table[t] = MIN(delta_table[t],
+ target_lengths[i]-(j+sizeof(tag)));
+ if (target_list_len[t] < AVG_ALTERNATES) {
+ target_list[t][target_list_len[t]] = i;
+ target_list_len[t]++;
+ } else {
+ target_list_len[t] = MAX_ALTERNATES;
+ }
+ break;
+ }
+ }
+ }
+}
+
+
+/* some counters to see how we did */
+static int stringops=0;
+static int comparisons=0;
+
+/* check if a proposed match is valid */
+static inline int check_target(uchar *buf,int pos,int i)
+{
+ int posi = pos-target_lengths[i];
+ if (posi<0) return(0);
+ stringops++;
+ if (strnequal(targets[i],buf+posi,target_lengths[i])) {
+ printf("Found target %d (%s) at %d\n",i,targets[i],posi);
+ return(1);
+ }
+ return(0);
+}
+
+
+/* the search proper - it takes a buffer and finds the targets previously
+ specified when building the bmg tables */
+void bmg_search(uchar *buf,int len)
+{
+ int pos = 0;
+ int found = 0;
+ int hits=0;
+ int i;
+
+ stringops=0;
+ comparisons=0;
+
+ for (pos=min_target_length; pos <= len;)
+ {
+ tag v = tag_value(buf+pos-sizeof(tag));
+ int skip = delta_table[v];
+ comparisons++;
+ if (skip) {
+ pos += skip;
+ continue;
+ }
+
+ if (target_list_len[v] <= AVG_ALTERNATES)
+ for (found=0,i=0;i<target_list_len[v] && !found;i++)
+ found = check_target(buf,pos,target_list[v][i]);
+ else
+ for (found=0,i=0;i<num_targets && !found;i++)
+ found = check_target(buf,pos,i);
+
+ if (found) hits++;
+ pos++;
+ }
+
+ printf("\nGot %d hits with %d comparisons and %d stringops\n",
+ hits,comparisons,stringops);
+}
+
+
+/* a simple harness to test the above */
+int main(int argc,char *argv[])
+{
+ uchar *target;
+ uchar *buf;
+ char *fname;
+ int fd;
+ int len;
+
+ if (argc < 3) {
+ printf("Usage: bmg string|string|string... file\n");
+ exit(1);
+ }
+
+ target = (uchar *)argv[1];
+ fname = argv[2];
+ fd = open(fname,O_RDONLY);
+ if (fd < 0) {
+ printf("couldn't open %s\n",fname);
+ exit(1);
+ }
+ len = lseek(fd,0,SEEK_END);
+ lseek(fd,0,SEEK_SET);
+ buf = (uchar *)malloc(len);
+ if (!buf) {
+ printf("failed to alloc buffer\n");
+ exit(1);
+ }
+ len = read(fd,buf,len);
+ close(fd);
+ printf("Loaded %d bytes\n",len);
+
+ bmg_build_table(target);
+ printf("Finished building tables\n");
+ bmg_search(buf,len);
+ return(0);
+}
+
--- /dev/null
+/* COPYRIGHT (C) The Australian National University 1995 */
+/*************************************************************************/
+/* bmg2.c */
+/* Digraph Boyer-Moore-Gosper algorithm */
+/* */
+/***************************************************************************/
+
+/* $Id: bmg2.c,v 1.1 2000/10/10 02:16:17 tridge Exp $ */
+
+/*
+a digraph version of the bmg algorithm
+
+Andrew Tridgell
+30/3/95
+
+Last modified 5/5/95
+
+This module has the following interface:
+
+int bmg_build_table(uchar *target_string,uchar *char_map,int wsmode);
+void bmg_search(uchar *buf,int len,void (*fn)());
+
+You call bmg_build_table() with the list of search terms, separated by
+| The char_map[] is a character array which maps characters from the
+data into characters in the search string. If this is null then a
+default mapping is performed. The default mapping maps all non
+alphanumeric characters to a space and other characters to themselves.
+
+If wsmode is true then the search routine will only find words that begin
+with the target strings. If wsmode is 0 then it will accept the
+targets at any alignment.
+
+bmg_search() is called with a pointer to the data, the length of the
+data and a function to call when a match is found. This function will
+be called with a pointer to the point at which the match was
+found. When this function returns the search will automatically
+continue from where it left off, calling fn() at each matching string.
+
+Calling bmg_build_table() with a NULL target_string will free the tables
+that are created by bmg_build_table().
+*/
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+#if !AJT
+#include "const.h"
+#endif
+
+typedef unsigned short tag;
+
+#define TAB14 0
+#define TAB16 0
+
+/* if you have targets longer than 255 chars they will be truncated */
+#define MAX_TARGET_LENGTH 255
+
+/* this is what is used to delimit search alternates in the target
+ string passed to the bmg_build_table() routine */
+#define DELIMITERS "|"
+#define SPACE_CHAR ' '
+
+/* the following defines are optimisation constants. Leave them
+ alone unless you know the code */
+#define DIGRAPH_THRESHOLD 3
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+
+struct target {
+ int next;
+ u_char *str;
+ u_char length;
+};
+
+static u_char space_char = SPACE_CHAR;
+static u_char char_bits = 0;
+static int max_char = 0;
+static int table_size = 0;
+static u_char *delta_table = NULL;
+#if TAB14 || TAB16
+static u_char *delta_table2 = NULL;
+#endif
+static tag *tag_table = NULL;
+static struct target *targets = NULL;
+static tag num_targets = 0;
+static int min_target_length = MAX_TARGET_LENGTH;
+static int max_target_length = 0;
+static tag char_table[256];
+static tag char_table_shifted[256];
+static int wsmode=0;
+static int digraph=1;
+static int tagsize=2;
+
+#if TAB14
+#define TAGV2(buf) ((((tag)(((u_char *)buf)[1])&0x7F)<<7)|(((u_char *)buf)[0]&0x7f))
+#endif
+#if TAB16
+#define TAGV2(buf) ((((tag)(((u_char *)buf)[1]))<<8)|(((u_char *)buf)[0]))
+#endif
+
+/* extract a digraph tag value from a buffer. This must be fast, and
+ is a clear candidate for assembly optimisation */
+static inline tag tag_value16(u_char *buf)
+{
+ return(char_table_shifted[buf[1]]|char_table[buf[0]]);
+}
+
+/* this is like tag_value16 but it uses the unmapped characters */
+static inline tag tag_value16u(u_char *buf)
+{
+ return((buf[1]<<char_bits)|buf[0]);
+}
+
+/* check if two characters match */
+static inline int u_char_match(u_char c,u_char b)
+{
+ return(char_table[c] == b);
+}
+
+/* compare two strings. We unroll a bit for speed. */
+static inline int strnequal(u_char *s1,u_char *s2,int n)
+{
+ while (n>3) {
+ if (!(u_char_match(s2[0],s1[0]) &&
+ u_char_match(s2[1],s1[1]) &&
+ u_char_match(s2[2],s1[2]))) return(0);
+ s1 += 3; s2 += 3;
+ n -= 3;
+ }
+ while (n) {
+ if (!u_char_match(s2[0],s1[0])) return(0);
+ s1++; s2++;
+ n--;
+ }
+ return(1);
+}
+
+/* add a tag to the delta table. Possibly update the list of targets
+ for the tag as well */
+static inline void add_to_table(tag t,int i,int j)
+{
+ int skip = targets[i].length-(j+tagsize);
+ int a;
+
+ delta_table[t] = MIN(delta_table[t],skip);
+
+ if (skip == 0) {
+ targets[i].next = MAX(targets[i].next,(int)t);
+ tag_table[t] = (tag)i;
+ }
+}
+
+
+/* remap the character tables and the targets to pack them into a small
+ area in the delta table - this helps the cacheing */
+static void remap_char_table(void)
+{
+ int i,j;
+ u_char target_chars[256];
+
+ /* work out what chars exist in the targets */
+ memset(target_chars,0,256);
+ for (i=0;i<num_targets;i++)
+ for (j=0;j<targets[i].length;j++)
+ target_chars[targets[i].str[j]] = 1;
+
+ /* force a space to exist */
+ if (wsmode) target_chars[SPACE_CHAR] = 1;
+
+ /* map each of the chars to a number */
+ j = 1;
+ for (i=0;i<256;i++)
+ if (target_chars[i]) target_chars[i] = j++;
+ max_char = j;
+
+ /* remember what the space is */
+ space_char = target_chars[SPACE_CHAR];
+
+ /* remap the targets */
+ for (i=0;i<num_targets;i++)
+ for (j=0;j<targets[i].length;j++)
+ targets[i].str[j] = target_chars[targets[i].str[j]];
+
+ /* remap the char table */
+ for (i=0;i<256;i++)
+ char_table[i] = target_chars[char_table[i]];
+
+ /* find how many bits are needed for the char table */
+ char_bits = 0;
+ i = max_char-1;
+ while (i) {
+ char_bits++;
+ i /= 2;
+ }
+
+ /* create the shifted table */
+ for (i=0;i<256;i++)
+ char_table_shifted[i] = char_table[i]<<char_bits;
+}
+
+
+int compare_targets(struct target *t1,struct target *t2)
+{
+ return(t1->next - t2->next);
+}
+
+int compare_targets2(int *t1,int *t2)
+{
+ return(targets[*t1].next - targets[*t2].next);
+}
+
+
+static void free_old_tables(void)
+{
+ int i;
+ /* free up from the last search */
+ for (i=0;i<num_targets;i++) free(targets[i].str);
+ if (targets) {free(targets); targets = NULL;}
+ if (tag_table) {free(tag_table); tag_table = NULL;}
+ if (delta_table) {free(delta_table); delta_table = NULL;}
+#if TAB14 || TAB16
+ if (delta_table2) {free(delta_table2); delta_table2 = NULL;}
+#endif
+ num_targets = 0;
+}
+
+/* build the tables needed for the bmg search */
+int bmg_build_table(u_char *target_string,u_char *char_map,int mode)
+{
+ u_char *p;
+ u_char *tok;
+ int i,j;
+ int t;
+ int dodigraph=0;
+
+ /* remember the wsmode */
+ wsmode = mode;
+
+ /* clean up from a previous run */
+ free_old_tables();
+ space_char = SPACE_CHAR;
+
+ if (!target_string) return(-1);
+
+ if (char_map) {
+ for (i=0;i<256;i++)
+ char_table[i] = char_map[i];
+ } else {
+ for (i=0;i<256;i++)
+ char_table[i] = isalnum(i)?i:SPACE_CHAR;
+ }
+
+ min_target_length = MAX_TARGET_LENGTH;
+ max_target_length = 0;
+
+ /* count the targets */
+ p = (u_char *)strdup(target_string);
+ for (tok=strtok(p,DELIMITERS); tok; tok = strtok(NULL,DELIMITERS))
+ num_targets++;
+ free(p);
+
+ /* allocate the targets */
+ targets = (struct target *)malloc(sizeof(targets[0])*num_targets);
+
+ if (!targets) {
+ free_old_tables();
+ return(-3);
+ }
+
+ /* parse the command */
+ p = (u_char *)strdup(target_string);
+ if (!p) {
+ free_old_tables();
+ return(-3);
+ }
+ i = 0;
+ for (tok=strtok(p,DELIMITERS); tok; tok = strtok(NULL,DELIMITERS)) {
+ int l = strlen(tok);
+ targets[i].next = -1;
+ targets[i].str = strdup(tok);
+ if (!targets[i].str) {
+ free_old_tables();
+ return(-3);
+ }
+ l = MIN(l,MAX_TARGET_LENGTH);
+ targets[i].length = l;
+ min_target_length = MIN(min_target_length,targets[i].length);
+ max_target_length = MAX(max_target_length,targets[i].length);
+ if (targets[i].str[l-1]==' ') dodigraph=1;
+ i++;
+ }
+ free(p);
+
+
+ /* determine if we will do a digraph search or not */
+ if (!dodigraph && num_targets<DIGRAPH_THRESHOLD) {
+ digraph=0;
+ tagsize=1;
+ } else {
+ digraph = 1;
+ tagsize = 2;
+ }
+
+ if (!num_targets) {
+ free_old_tables();
+ return(-2);
+ }
+
+ remap_char_table();
+
+ /* build the bmg table - this is a mess */
+ if (digraph)
+ table_size = 1<<(char_bits*2);
+ else
+ table_size = 256;
+
+ delta_table = (u_char *)malloc(table_size*sizeof(delta_table[0]));
+ tag_table = (tag *)malloc(table_size*sizeof(tag_table[0]));
+
+ if (!delta_table || !tag_table) {
+ free_old_tables();
+ return(-3);
+ }
+
+#if TAB14 || TAB16
+ if (digraph) {
+#if TAB14
+ int tabsize=(1<<14);
+#else
+ int tabsize=(1<<16);
+#endif
+ delta_table2 = (u_char *)malloc(tabsize*sizeof(delta_table[0]));
+ if (!delta_table2) {
+ free_old_tables();
+ return(-3);
+ }
+ }
+#endif
+
+ for (t=0;t<table_size;t++) {
+ delta_table[t] = min_target_length;
+ tag_table[t] = num_targets;
+ }
+
+ if (digraph)
+ {
+ for (i=0;i<num_targets;i++)
+ {
+ int length = targets[i].length;
+ char *str = targets[i].str;
+ u_char c[2];
+ c[1] = str[0];
+ if (length == min_target_length) {
+ if (wsmode) {
+ c[0] = space_char;
+ t = tag_value16u(c);
+ add_to_table(t,i,-1);
+ } else {
+ for (c[0]=0;;c[0]++)
+ {
+ /* this little loop handles the first char in each
+ target - our tags must match for any possible char
+ to the left of it */
+ t = tag_value16u(c);
+ add_to_table(t,i,-1);
+ if (c[0] == (max_char-1)) break;
+ }
+ }
+ }
+ for (j=MAX(0,length-(min_target_length+1));j<=(length-2);j++)
+ {
+ t = tag_value16u(str+j);
+ add_to_table(t,i,j);
+ }
+ }
+ }
+ else
+ {
+ for (t=0;t<256;t++)
+ for (i=0;i<num_targets;i++)
+ {
+ int length = targets[i].length;
+ char *str = targets[i].str;
+ for (j=(length-1);j>=(length-min_target_length);j--)
+ if (char_table[t] == str[j]) {
+ add_to_table(t,i,j);
+ break; /* go to the next target */
+ }
+ }
+ }
+
+
+ if (num_targets>1)
+ {
+ int *target_map1 = (int *)malloc(sizeof(int)*num_targets);
+ int *target_map2 = (int *)malloc(sizeof(int)*num_targets);
+ if (!target_map1 || !target_map2) {
+ free_old_tables();
+ return(-3);
+ }
+
+ for (i=0;i<num_targets;i++) target_map1[i]=i;
+
+ /* sort the targets by the "next" value thay have in the target struct */
+ qsort(target_map1,num_targets,sizeof(int),(int (*)())compare_targets2);
+ qsort(targets,num_targets,sizeof(targets[0]),(int (*)())compare_targets);
+
+ for (i=0;i<num_targets;i++) target_map2[target_map1[i]]=i;
+
+ for (t=0;t<table_size;t++) {
+ if (delta_table[t]) continue;
+ tag_table[t] = target_map2[tag_table[t]];
+ while (tag_table[t] &&
+ targets[tag_table[t]-1].next == targets[tag_table[t]].next)
+ tag_table[t]--;
+ }
+ free(target_map1);
+ free(target_map2);
+ }
+
+ for (i=0;i<num_targets-1;i++)
+ if (targets[i].next == targets[i+1].next)
+ targets[i].next = i+1;
+ else
+ targets[i].next = -1;
+ targets[num_targets-1].next = -1;
+
+#if TAB14
+ if (digraph) {
+ u_char c[2];
+ for (c[0]=0;c[0]<(1<<7);c[0]++)
+ for (c[1]=0;c[1]<(1<<7);c[1]++)
+ delta_table2[TAGV2(c)] = delta_table[tag_value16(c)];
+ }
+#endif
+#if TAB16
+ if (digraph) {
+ tag v;
+ u_char *c = (u_char *)&v;
+ for (t=0;t<(1<<16);t++) {
+ v = t;
+ delta_table2[TAGV2(c)] = delta_table[tag_value16(c)];
+ }
+ }
+#endif
+
+ return(0);
+}
+
+
+/* check if a single proposed match is valid */
+static inline int check_target(u_char *buf,int i,void (*fn)())
+{
+ if (wsmode && char_table[buf[-1]]!=space_char) return(0);
+ if (strnequal(targets[i].str,buf,targets[i].length) && fn) {
+ fn(buf);
+ return(1);
+ }
+ return(0);
+}
+
+
+/* check if a proposed match is valid against the list of alternates
+ for this tag */
+static void check_targets(u_char *buf,tag v,void (*fn)())
+{
+ int i = tag_table[v];
+ do {
+ u_char *buf2 = buf-targets[i].length;
+ u_char *str = targets[i].str;
+ if (u_char_match(*buf2,*str))
+ check_target(buf2,i,fn);
+ i = targets[i].next;
+ } while (i != -1);
+}
+
+
+/* the search proper, 8 bit version - it takes a buffer and finds the
+ targets previously specified when building the bmg tables */
+#define TAGV(buf) ((buf)[0])
+#define DELTAB(buf) delta_table[TAGV(buf)]
+#define TAGSIZE 1
+static void bmg_search8(u_char *buf,int len,void (*fn)())
+{
+ u_char *bufend = buf + len - (TAGSIZE-1);
+ u_char k;
+
+ buf += min_target_length - TAGSIZE;
+ bufend -= 8*MAX_TARGET_LENGTH;
+
+ while (buf<bufend)
+ {
+ buf += DELTAB(buf);
+ buf += DELTAB(buf);
+ buf += DELTAB(buf);
+ buf += (k = DELTAB(buf));
+ if (!k) {
+ if (DELTAB(buf-2) < 3 && DELTAB(buf-1) < 2)
+ check_targets(buf+TAGSIZE,TAGV(buf),fn);
+ buf++;
+ }
+ }
+
+ bufend += 8*MAX_TARGET_LENGTH;
+
+ while (buf<bufend)
+ {
+ buf += (k = DELTAB(buf));
+ if (!k) {
+ if (DELTAB(buf-2) < 3 && DELTAB(buf-1) < 2)
+ check_targets(buf+TAGSIZE,TAGV(buf),fn);
+ buf++;
+ }
+ }
+}
+
+#undef TAGV
+#undef TAGSIZE
+#undef DELTAB
+
+
+#define TAGV(buf) tag_value16(buf)
+#if TAB14 || TAB16
+#define DELTAB(buf) delta_table2[TAGV2(buf)]
+#else
+#define DELTAB(buf) delta_table[TAGV(buf)]
+#endif
+#define TAGSIZE 2
+/* this code is identical to the 8 bit search, except for the above two
+ macros */
+static void bmg_search16(u_char *buf,int len,void (*fn)())
+{
+ u_char *bufend = buf + len - (TAGSIZE-1);
+ int k;
+
+ buf += min_target_length - TAGSIZE;
+ bufend -= 8*MAX_TARGET_LENGTH;
+
+ while (buf<bufend)
+ {
+ buf += DELTAB(buf);
+ buf += DELTAB(buf);
+ buf += DELTAB(buf);
+ buf += (k=DELTAB(buf));
+ if (!k) {
+ if (DELTAB(buf-2) < 3 && DELTAB(buf-1) < 2)
+ check_targets(buf+TAGSIZE,TAGV(buf),fn);
+ buf++;
+ }
+ }
+
+ bufend += 8*MAX_TARGET_LENGTH;
+
+ while (buf<bufend)
+ {
+ buf += (k = DELTAB(buf));
+ if (!k) {
+ if (DELTAB(buf-2) < 3 && DELTAB(buf-1) < 2)
+ check_targets(buf+TAGSIZE,TAGV(buf),fn);
+ buf++;
+ }
+ }
+}
+
+
+
+/* choose 8 or 16 bit search */
+void bmg_search(u_char *buf,int len,void (*fn)())
+{
+ int i,j;
+ if (!num_targets || !buf || !fn || len<1) return;
+
+ /* a special case - check the start of the buffer */
+ for (j=0;j<max_target_length;j++) {
+ for (i=0;i<num_targets;i++)
+ if (len >= targets[i].length && check_target(buf,i,fn)) break;
+ buf++; len--;
+ }
+
+ if (len < 1) return;
+
+ if (digraph)
+ bmg_search16(buf,len,fn);
+ else
+ bmg_search8(buf,len,fn);
+}
--- /dev/null
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+
+static int hits=0;
+
+void hit_fn(char *buf)
+{
+#if 0
+ printf("hit[%d]=[%5.5s]\n",hits,buf);
+#endif
+ hits++;
+}
+
+
+/* a simple harness to test the above */
+int main(int argc,char *argv[])
+{
+ char *target;
+ char *buf;
+ char *fname;
+ int fd;
+ int len;
+ struct timeval t1,t2;
+
+ if (argc < 3) {
+ printf("Usage: bmg string|string|string... file\n");
+ exit(1);
+ }
+
+ target = argv[1];
+ fname = argv[2];
+ fd = open(fname,O_RDONLY);
+ if (fd < 0) {
+ printf("couldn't open %s\n",fname);
+ exit(1);
+ }
+ len = lseek(fd,0,SEEK_END);
+ lseek(fd,0,SEEK_SET);
+ buf = (char *)malloc(len);
+ if (!buf) {
+ printf("failed to alloc buffer\n");
+ exit(1);
+ }
+ len = read(fd,buf,len);
+ close(fd);
+ printf("Loaded %d bytes\n",len);
+
+ gettimeofday(&t1,NULL);
+ bmg_build_table(target,NULL,0);
+ gettimeofday(&t2,NULL);
+ printf("Table build took %ld msecs\n",
+ (t2.tv_sec-t1.tv_sec)*1000 + (t2.tv_usec-t1.tv_usec)/1000);
+
+ gettimeofday(&t1,NULL);
+ bmg_search(buf,len,hit_fn);
+ gettimeofday(&t2,NULL);
+ printf("Search took %ld msec\n",
+ (t2.tv_sec-t1.tv_sec)*1000 + (t2.tv_usec-t1.tv_usec)/1000);
+ printf("Got %d hits\n",hits);
+ return(0);
+}
+
--- /dev/null
+/*
+Simple binary search tree implementation.
+
+Andrew Tridgell
+May 1994
+*/
+
+
+
+/* these are the functions that are defines in this file */
+void *bst_insert(void *tree,void *data,int size,int (*compare)());
+void *bst_find(void *tree,void *data,int (*compare)());
+
+struct bst_struct
+{
+ struct bst_struct *ltree;
+ struct bst_struct *rtree;
+ void *data;
+ int data_len;
+}
+
+
+/* find an element in a tree */
+void *bst_find(void *tree,void *data,int (*compare)())
+{
+ int ret;
+ struct bst_struct *bstree = tree;
+ if (!bstree || !data || !compare) return(NULL);
+
+ ret = compare(data,bstree->data);
+ if (ret < 0)
+ return(bst_find(bstree->ltree,data,compare));
+ if (ret > 0)
+ return(bst_find(bstree->rtree,data,compare));
+
+ return(bstree->data);
+}
+
+/* create a bst bode */
+void *bst_create_node(coid *data,int size)
+{
+ struct bst_struct *bstree = (struct bst_struct *)malloc(sizeof(*bstree));
+ bstree->ltree = NULL;
+ bstree->rtree = NULL;
+ bstree->data = malloc(size);
+ if (!bstree->data)
+ {
+ free(bstree); return(NULL);
+ }
+ memcpy(bstree->data,data,size);
+ bstree->data_len = size;
+}
+
+/* insert an element into a tree, returning the new tree */
+void *bst_insert(void *tree,void *data,int size,int (*compare)())
+{
+ int ret;
+ struct bst_struct *bstree = tree;
+ if (!data || !compare) return(NULL);
+
+ if (!bstree)
+ return(bst_create_node(data,size));
+
+ ret = compare(data,bstree->data);
+ if (ret < 0)
+ bstree->ltree = bst_insert(bstree->ltree,data,size,compare);
+ if (ret > 0)
+ bstree->rtree = bst_insert(bstree->rtree,data,size,compare);
+
+ if (ret == 0)
+ {
+ /* replace the existing element */
+ if (bstree->data) free(bstree(data));
+ bstree->data = (void *)malloc(size);
+ if (!bstree->data) return(NULL);
+ memcpy(bstree->data,data,size);
+ bstree->data_len = size;
+ }
+
+ return(bstree);
+}
+
+
+/* find an element in a tree */
+void bst_inorder(void *tree,int (*fn)())
+{
+ struct bst_struct *bstree = tree;
+ if (!bstree || !fn) return;
+
+ bst_inorder(bstree->ltree,fn);
+ fn(bstree->data,bstree->data_len);
+ bst_inorder(bstree->rtree,fn);
+}
+
+
+#if 1
+/* test a bstree */
+bst_test(int size)
--- /dev/null
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ SMB Byte handling
+ Copyright (C) Andrew Tridgell 1992-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ This file implements macros for machine independent short and
+ int manipulation
+
+Here is a description of this file that I emailed to the samba list once:
+
+> I am confused about the way that byteorder.h works in Samba. I have
+> looked at it, and I would have thought that you might make a distinction
+> between LE and BE machines, but you only seem to distinguish between 386
+> and all other architectures.
+>
+> Can you give me a clue?
+
+sure.
+
+The distinction between 386 and other architectures is only there as
+an optimisation. You can take it out completely and it will make no
+difference. The routines (macros) in byteorder.h are totally byteorder
+independent. The 386 optimsation just takes advantage of the fact that
+the x86 processors don't care about alignment, so we don't have to
+align ints on int boundaries etc. If there are other processors out
+there that aren't alignment sensitive then you could also define
+CAREFUL_ALIGNMENT=0 on those processors as well.
+
+Ok, now to the macros themselves. I'll take a simple example, say we
+want to extract a 2 byte integer from a SMB packet and put it into a
+type called uint16 that is in the local machines byte order, and you
+want to do it with only the assumption that uint16 is _at_least_ 16
+bits long (this last condition is very important for architectures
+that don't have any int types that are 2 bytes long)
+
+You do this:
+
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
+#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
+
+then to extract a uint16 value at offset 25 in a buffer you do this:
+
+char *buffer = foo_bar();
+uint16 xx = SVAL(buffer,25);
+
+We are using the byteoder independence of the ANSI C bitshifts to do
+the work. A good optimising compiler should turn this into efficient
+code, especially if it happens to have the right byteorder :-)
+
+I know these macros can be made a bit tidier by removing some of the
+casts, but you need to look at byteorder.h as a whole to see the
+reasoning behind them. byteorder.h defines the following macros:
+
+SVAL(buf,pos) - extract a 2 byte SMB value
+IVAL(buf,pos) - extract a 4 byte SMB value
+SVALS(buf,pos) signed version of SVAL()
+IVALS(buf,pos) signed version of IVAL()
+
+SSVAL(buf,pos,val) - put a 2 byte SMB value into a buffer
+SIVAL(buf,pos,val) - put a 4 byte SMB value into a buffer
+SSVALS(buf,pos,val) - signed version of SSVAL()
+SIVALS(buf,pos,val) - signed version of SIVAL()
+
+RSVAL(buf,pos) - like SVAL() but for NMB byte ordering
+RIVAL(buf,pos) - like IVAL() but for NMB byte ordering
+RSSVAL(buf,pos,val) - like SSVAL() but for NMB ordering
+RSIVAL(buf,pos,val) - like SIVAL() but for NMB ordering
+
+it also defines lots of intermediate macros, just ignore those :-)
+
+*/
+
+/* some switch macros that do both store and read to and from SMB buffers */
+
+#define RW_PCVAL(read,inbuf,outbuf,len) \
+ if (read) { PCVAL (inbuf,0,outbuf,len) } \
+ else { PSCVAL(inbuf,0,outbuf,len) }
+
+#define RW_PIVAL(read,inbuf,outbuf,len) \
+ if (read) { PIVAL (inbuf,0,outbuf,len) } \
+ else { PSIVAL(inbuf,0,outbuf,len) }
+
+#define RW_PSVAL(read,inbuf,outbuf,len) \
+ if (read) { PSVAL (inbuf,0,outbuf,len) } \
+ else { PSSVAL(inbuf,0,outbuf,len) }
+
+#define RW_CVAL(read, inbuf, outbuf, offset) \
+ if (read) (outbuf) = CVAL (inbuf,offset); \
+ else SCVAL(inbuf,offset,outbuf);
+
+#define RW_IVAL(read, inbuf, outbuf, offset) \
+ if (read) (outbuf)= IVAL (inbuf,offset); \
+ else SIVAL(inbuf,offset,outbuf);
+
+#define RW_SVAL(read, inbuf, outbuf, offset) \
+ if (read) (outbuf)= SVAL (inbuf,offset); \
+ else SSVAL(inbuf,offset,outbuf);
+
+#undef CAREFUL_ALIGNMENT
+
+/* we know that the 386 can handle misalignment and has the "right"
+ byteorder */
+#ifdef __i386__
+#define CAREFUL_ALIGNMENT 0
+#endif
+
+#ifndef CAREFUL_ALIGNMENT
+#define CAREFUL_ALIGNMENT 1
+#endif
+
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define PVAL(buf,pos) ((unsigned)CVAL(buf,pos))
+#define SCVAL(buf,pos,val) (CVAL(buf,pos) = (val))
+
+
+#if CAREFUL_ALIGNMENT
+
+#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
+#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
+#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
+#define SIVALX(buf,pos,val) (SSVALX(buf,pos,val&0xFFFF),SSVALX(buf,pos+2,val>>16))
+#define SVALS(buf,pos) ((int16)SVAL(buf,pos))
+#define IVALS(buf,pos) ((int32)IVAL(buf,pos))
+#define SSVAL(buf,pos,val) SSVALX((buf),(pos),((uint16)(val)))
+#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
+#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
+#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
+
+#else
+
+/* this handles things for architectures like the 386 that can handle
+ alignment errors */
+/*
+ WARNING: This section is dependent on the length of int16 and int32
+ being correct
+*/
+
+/* get single value from an SMB buffer */
+#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
+#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
+#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
+#define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos)))
+
+/* store single value in an SMB buffer */
+#define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val))
+#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
+#define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val))
+#define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val))
+
+#endif
+
+
+/* macros for reading / writing arrays */
+
+#define SMBMACRO(macro,buf,pos,val,len,size) \
+{ int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
+
+#define SSMBMACRO(macro,buf,pos,val,len,size) \
+{ int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
+
+/* reads multiple data from an SMB buffer */
+#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
+#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
+#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
+#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
+#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
+#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
+
+/* stores multiple data in an SMB buffer */
+#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
+#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
+#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
+#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
+#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
+#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
+
+
+/* now the reverse routines - these are used in nmb packets (mostly) */
+#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+
+#define RSVAL(buf,pos) SREV(SVAL(buf,pos))
+#define RIVAL(buf,pos) IREV(IVAL(buf,pos))
+#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
+#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
+
+#define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
+ RW_PCVAL(read,inbuf,outbuf,len) \
+ DEBUG(5,("%s%04x %s: ", \
+ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \
+ if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
+ { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
+ DEBUG(5,("\n"));
+
+#define DBG_RW_PSVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
+ RW_PSVAL(read,inbuf,outbuf,len) \
+ DEBUG(5,("%s%04x %s: ", \
+ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \
+ if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
+ { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
+ DEBUG(5,("\n"));
+
+#define DBG_RW_PIVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
+ RW_PIVAL(read,inbuf,outbuf,len) \
+ DEBUG(5,("%s%04x %s: ", \
+ tab_depth(depth), PTR_DIFF(inbuf,base),string)); \
+ if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
+ { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
+ DEBUG(5,("\n"));
+
+#define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
+ RW_CVAL(read,inbuf,outbuf,0) \
+ DEBUG(5,("%s%04x %s: %02x\n", \
+ tab_depth(depth), PTR_DIFF(inbuf,base), string, outbuf));
+
+#define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \
+ RW_SVAL(read,inbuf,outbuf,0) \
+ DEBUG(5,("%s%04x %s: %04x\n", \
+ tab_depth(depth), PTR_DIFF(inbuf,base), string, outbuf));
+
+#define DBG_RW_IVAL(string,depth,base,read,inbuf,outbuf) \
+ RW_IVAL(read,inbuf,outbuf,0) \
+ DEBUG(5,("%s%04x %s: %08x\n", \
+ tab_depth(depth), PTR_DIFF(inbuf,base), string, outbuf));
+
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#ifdef SOLARIS2
+#include <sys/rusage.h>
+#endif
+
+#include <sys/resource.h>
+#include <unistd.h>
+
+/*Blocksize is 1M words (on intels, this is 1Mb)
+*/
+
+#define MAXBSIZE (1024*1024)
+#define LOOPTIME 2.0
+
+typedef unsigned int ui;
+
+double readtime(void);
+double read_test(ui);
+void build_buffer(int, int);
+
+ui buf[MAXBSIZE * sizeof(ui *)];
+FILE *record;
+
+double readtime()
+ {
+ struct rusage r;
+ double rv;
+
+ getrusage(RUSAGE_SELF,&r);
+
+#ifdef SOLARIS2 || _POSIX_C_SOURCE
+ rv = (double)r.ru_utime.tv_sec + (double)(r.ru_utime.tv_nsec/1e9);
+#else
+ rv = (double)r.ru_utime.tv_sec + (double)(r.ru_utime.tv_usec/1e6);
+#endif
+ return(rv);
+ }
+
+main()
+ {
+ double t,wps;
+ int str;
+ ui count,buflen;
+ int i,pcount=0;
+ char strbuf[10];
+
+ /* Open our log file */
+ for(i=1; i<32; ++i)
+ {
+ sprintf(strbuf,"cache.%d",i);
+ if (access(strbuf,0)) break;
+ }
+ record=fopen(strbuf,"w");
+ if (record==NULL) printf("Could not open record file %s. No record kept\n",strbuf);
+ else printf("\t\tA copy of this run will be kept in %s\n\n",strbuf);
+
+ printf("Memory tester v1.0\n");
+ printf("Author: Anthony.Wesley@anu.edu.au, January 1996\n\n");
+ printf("On this machine, one word = %d bytes\n",sizeof(ui *));
+ printf("Reported access times are in nS per word.\n\n");
+ if (record!=NULL)
+ {
+ fprintf(record,"On this machine, one word = %d bytes\n",sizeof(ui *));
+ fprintf(record,"Reported access times are in nS per word.\n\n");
+ }
+
+ /* Start with a block of 256 words, each word is of type (ui *) */
+ build_buffer(256,1);
+ count=8;
+ do
+ {
+ count *= 2;
+ t = read_test(count);
+ }
+ while(t < 2);
+
+ fflush(stdout);
+
+ print_header();
+ count = (ui)((double)count * LOOPTIME / t);
+ for(buflen=256; buflen<=MAXBSIZE; buflen*=2)
+ {
+ if (buflen<256*1024) sprintf(strbuf,"%uk",buflen/256);
+ else sprintf(strbuf,"%uM",buflen/(256*1024));
+
+ printf("%-5.5s|",strbuf); fflush(stdout);
+ if (record!=NULL) fprintf(record,"%-5.5s|",strbuf);
+
+ for(str=1; str<buflen; str*=2)
+ {
+ build_buffer(buflen,str);
+
+ while(1)
+ {
+ t = read_test(count);
+ if (t<1.0) count*=3; else break;
+ }
+
+ wps = (double)(count) / t;
+ wps = 1.0e9 / wps;
+ if (wps>=1000)
+ {
+ printf("1k+ ");
+ if (record!=NULL) fprintf(record,"1k+ ");
+ }
+ else
+ {
+ printf("%-3d ", (int)wps);
+ if (record!=NULL) fprintf(record,"%-3d ", (int)wps);
+ }
+
+ fflush(stdout); if (record!=NULL) fflush(record);
+
+ count = (ui)((double)count * LOOPTIME / t);
+ }
+ putchar('\n');
+ if (record!=NULL) putc('\n',record);
+ }
+
+ if (record!=NULL) fclose(record);
+ }
+
+double read_test(ui count)
+ {
+ double t1;
+ register ui *o,i=0;
+
+ o=(ui *)buf[0];
+ t1=readtime(); while(i<count)
+ {
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o); o=(ui *)(*o);
+ i+=64;
+ }
+ return(readtime()-t1);
+ }
+
+void
+build_buffer(int size, int stridelen)
+ {
+ ui i;
+
+ for(i=0; i<(size-stridelen); i+=stridelen)
+ buf[i]=(ui)&buf[i+stridelen];
+ buf[i] = (ui)&buf[0];
+ }
+
+print_header()
+ {
+ char strbuf[32];
+ unsigned v,val,i;
+ char c=0;
+
+ printf(
+"Block|--------------------------Memory Stride (words)------------------------\n");
+printf("size |");
+
+ if (record!=NULL)
+ {
+ fprintf(record,
+ "Block|--------------------------Memory Stride (words)------------------------\n");
+ fprintf(record,"size |");
+ }
+
+ for(val=1; val<=(1024*128); val*=2)
+ {
+ v=val;
+ if (val>=(1024*1024)) { c='M'; v = val / (1024*1024); }
+ else if (val>=1024) { c='k'; v = val / 1024; }
+
+ sprintf(strbuf,"%d%c",v,c);
+ if (v>64 && c) {strbuf[2]=c; strbuf[3]=0;}
+ printf("%-3s ",strbuf);
+ if (record!=NULL) fprintf(record,"%-3s ",strbuf);
+ }
+ putchar('\n'); if (record!=NULL) putc('\n',record);
+ printf(" |\n");
+ if (record!=NULL) fprintf(record," |\n");
+ }
--- /dev/null
+/* convert a tcpdump capture file to a netmon .cap file.
+
+ Andrew Tridgell, October 1997
+
+ This only works for 32 bit boxes at the moment. Change the typedefs
+ to work on other sytems
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <memory.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+/* change the following 3 lines to make things work on
+ systems with different word sizes */
+typedef int int32;
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+
+
+#define DEBUG 0
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+/* tcpdump file format */
+struct tcpdump_file_header {
+ uint32 magic;
+ uint16 major;
+ uint16 minor;
+ int32 zone;
+ uint32 sigfigs;
+ uint32 snaplen;
+ uint32 linktype;
+};
+
+struct tcpdump_packet {
+ struct timeval ts;
+ uint32 caplen;
+ uint32 len;
+};
+
+
+/* .cap file format */
+struct cap_header {
+ char rtss[4];
+ char minor;
+ char major;
+ uint16 captype;
+ char starttime[16];
+ uint32 frameoffset;
+ uint32 framelength;
+ uint32 unknown[24];
+};
+
+struct cap_packet {
+ uint32 cap_time; /* milliseconds */
+ uint16 len;
+ uint16 caplen;
+};
+
+/* file format is:
+ header
+ frames
+ frameoffsets
+ */
+
+
+static void swap_uint32(uint32 *x)
+{
+ char c, *p = (char *)x;
+ c = p[0]; p[0] = p[3]; p[3] = c;
+ c = p[1]; p[1] = p[2]; p[2] = c;
+}
+
+static void swap_int32(int32 *x)
+{
+ char c, *p = (char *)x;
+ c = p[0]; p[0] = p[3]; p[3] = c;
+ c = p[1]; p[1] = p[2]; p[2] = c;
+}
+
+static void swap_uint16(uint16 *x)
+{
+ char c, *p = (char *)x;
+ c = p[0]; p[0] = p[1]; p[1] = c;
+}
+
+
+static void swap_netmon_header(struct cap_header *h)
+{
+ swap_uint16(&h->captype);
+ swap_uint32(&h->frameoffset);
+ swap_uint32(&h->framelength);
+}
+
+static void swap_netmon_packet(struct cap_packet *p)
+{
+ swap_uint32(&p->cap_time);
+ swap_uint16(&p->len);
+ swap_uint16(&p->caplen);
+}
+
+static void swap_tcpdump_header(struct tcpdump_file_header *h)
+{
+ swap_uint32(&h->magic);
+ swap_uint16(&h->major);
+ swap_uint16(&h->minor);
+ swap_int32(&h->zone);
+ swap_uint32(&h->sigfigs);
+ swap_uint32(&h->snaplen);
+ swap_uint32(&h->linktype);
+}
+
+static void swap_tcpdump_packet(struct tcpdump_packet *p)
+{
+ swap_uint32(&p->ts.tv_sec);
+ swap_uint32(&p->ts.tv_usec);
+ swap_uint32(&p->len);
+ swap_uint32(&p->caplen);
+}
+
+
+int convert_tcpdump_to_cap(char *infile, char *outfile)
+{
+ uint32 *framestart = NULL;
+ int maxframes = 1000000;
+ int i;
+ int fd1, fd2, fd3;
+ int snaplen;
+ struct tcpdump_file_header tcpdump_header;
+ struct tcpdump_packet tcpdump_pkt;
+ char *data;
+ struct cap_header cap_header;
+ struct cap_packet cap_pkt;
+ struct timeval tval1;
+ char pad[4];
+ int swap_tcpdump = 0;
+ int swap_netmon = 0;
+
+ fd1 = open(infile, O_RDONLY);
+ if (fd1 == -1) {
+ perror(infile);
+ exit(1);
+ }
+
+ fd2 = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd2 == -1) {
+ perror(outfile);
+ exit(1);
+ }
+
+ fd3 = open("cap.dat", O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd3 == -1) {
+ perror("cap.dat");
+ exit(1);
+ }
+
+ if (read(fd1, &tcpdump_header, sizeof(tcpdump_header)) !=
+ sizeof(tcpdump_header)) {
+ printf("can't read tcpdump header\n");
+ return 0;
+ }
+
+ write(fd3, &tcpdump_header, sizeof(tcpdump_header));
+
+ /* tcpdump files can be in either byte order. */
+ if (tcpdump_header.magic != TCPDUMP_MAGIC) {
+ swap_tcpdump = 1;
+ swap_tcpdump_header(&tcpdump_header);
+ }
+
+ if (tcpdump_header.magic != TCPDUMP_MAGIC) {
+ printf("bad magic number %x\n", tcpdump_header.magic);
+ return 0;
+ }
+
+ /* check if we are little endian. If not, we need to
+ convert the network monitor output */
+ i=1;
+ if (((char *)&i)[0] != 1) swap_netmon = 1;
+
+ /* setup the basic netmon header */
+ memset(&cap_header, 0, sizeof(cap_header));
+ strcpy(cap_header.rtss, "RTSS");
+ cap_header.minor = 1;
+ cap_header.major = 1;
+ cap_header.captype = tcpdump_header.linktype;
+
+ /* write it out. we will have to write it again once
+ we've worked out the rest of the parameters */
+ write(fd2, &cap_header, sizeof(cap_header));
+
+ snaplen = tcpdump_header.snaplen;
+
+ printf("tcpdump-%d.%d snaplen=%d linktype=%d\n",
+ tcpdump_header.major, tcpdump_header.minor,
+ snaplen, tcpdump_header.linktype);
+
+ data = (char *)malloc(snaplen);
+
+ framestart = (uint32 *)malloc(maxframes * sizeof(framestart[0]));
+
+ if (!framestart) {
+ perror("malloc");
+ exit(1);
+ }
+
+ memset(pad, 0, sizeof(pad));
+
+ for (i=0; 1 ; i++) {
+ if (i == maxframes-1) {
+ framestart = (uint32 *)realloc(framestart,
+ maxframes*2*
+ sizeof(framestart[0]));
+ maxframes *= 2;
+ if (!framestart) {
+ perror("malloc");
+ exit(1);
+ }
+ }
+
+ if (read(fd1, &tcpdump_pkt, sizeof(tcpdump_pkt)) !=
+ sizeof(tcpdump_pkt))
+ break;
+
+ write(fd3, &tcpdump_pkt, sizeof(tcpdump_pkt));
+
+ if (swap_tcpdump)
+ swap_tcpdump_packet(&tcpdump_pkt);
+
+ if (i == 0)
+ tval1 = tcpdump_pkt.ts;
+
+#if DEBUG
+ printf("frame %d of length=%d:%d\n",
+ i+1, tcpdump_pkt.caplen, tcpdump_pkt.len);
+#endif
+
+ lseek(fd1, 8, SEEK_CUR);
+
+ if (read(fd1, data, tcpdump_pkt.caplen) != tcpdump_pkt.caplen)
+ break;
+
+ write(fd3, data, tcpdump_pkt.caplen);
+
+ if (tcpdump_pkt.caplen > tcpdump_pkt.len)
+ tcpdump_pkt.caplen = tcpdump_pkt.len;
+
+ framestart[i] = lseek(fd2, 0, SEEK_CUR);
+
+ cap_pkt.cap_time = (tcpdump_pkt.ts.tv_sec - tval1.tv_sec)*1000 +
+ (tcpdump_pkt.ts.tv_usec - tval1.tv_usec)/1000;
+ cap_pkt.caplen = tcpdump_pkt.caplen;
+ cap_pkt.len = tcpdump_pkt.len;
+
+ if (swap_netmon)
+ swap_netmon_packet(&cap_pkt);
+
+ write(fd2, &cap_pkt, sizeof(cap_pkt));
+ write(fd2, data, tcpdump_pkt.caplen);
+
+ if (tcpdump_pkt.caplen % 4 != 0) {
+ write(fd2, pad, 4 - (tcpdump_pkt.caplen % 4));
+ }
+
+#if DEBUG
+ printf("frame %d of length=%d:%d\n",
+ i+1, tcpdump_pkt.caplen, tcpdump_pkt.len);
+#endif
+ }
+
+ cap_header.frameoffset = lseek(fd2, 0, SEEK_CUR);
+ cap_header.framelength = i*4;
+
+ if (swap_netmon) {
+ int j;
+ for (j=0;j<i;j++)
+ swap_uint32(&framestart[j]);
+ swap_netmon_header(&cap_header);
+ }
+
+ write(fd2, framestart, i*4);
+
+ lseek(fd2, 0, SEEK_SET);
+
+ write(fd2, &cap_header, sizeof(cap_header));
+
+ close(fd1);
+ close(fd2);
+ close(fd3);
+
+ printf("converted %d frames\n", i);
+
+ return i;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 3) {
+ printf("Convert a tcpdump capture file to a netmon .cap file\n");
+ printf("\tUsage: capconvert <infile> <outfile>\n");
+ exit(1);
+ }
+
+ convert_tcpdump_to_cap(argv[1], argv[2]);
+
+ return 0;
+}
--- /dev/null
+/*
+ * capq - print out state of CAP queue (obtained from capqd).
+ *
+ * capq [-c] [-i interval] [-h cap-host]
+ *
+ * Author: Paul Mackerras, June 1993.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <math.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/termios.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <termios.h>
+
+#define CAPQD_PORT 6123 /* capqd's well-known port number */
+#define CAP_HOST_DFLT "cafe" /* default value for -h option */
+
+FILE *capqd_w, *capqd_r; /* streams to and from capqd */
+char *cap_host; /* hostname where capqd is */
+
+/* used for terminal capabilities */
+char termcap_entry[1024], string_caps[1024];
+
+#define MAXLINES 100 /* max # lines for continuous display */
+#define MAXCOLS 100 /* max # columns */
+
+double last_change_time; /* cap_host's time of last queue change */
+double our_time; /* time according to our clock */
+double host_time_diff; /* cap_host's clock - our clock */
+double timez[MAXLINES]; /* start time for each line of display */
+int num_lines; /* # entries valid in timez[] */
+
+/* Convert from a timeval to a floating-point number of seconds */
+#define double_time(x) ((x)->tv_sec + (x)->tv_usec / 1.0E6)
+
+/* Termcap routines */
+extern int tgetent();
+extern int tgetnum();
+extern char *tgetstr();
+extern int tgetflag();
+extern short ospeed;
+
+/* Option values */
+int continuous; /* => display the queue continuously */
+double interval; /* with updates at this interval */
+
+/* Capability strings and terminal information from termcap */
+int screen_lines; /* screen has this many lines */
+int screen_width; /* and this many columns */
+char *term; /* terminal type */
+char *home; /* go to top-left corner of screen */
+char *init_str; /* initialize terminal */
+char *finish_str; /* reset terminal before exit */
+char *clr_screen; /* clear whole screen */
+char *clr_eol; /* clear to end of line */
+char *clr_eos; /* clear to end of screen */
+
+int size_changed; /* set when the window size changes */
+
+void getout();
+void hoist();
+int outchar();
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int fd, c, n;
+ int queue_empty;
+ double t;
+ char *ptr;
+ extern char *optarg;
+ fd_set ready;
+ struct timeval *timo, tval;
+ struct termios tio;
+
+ /* set defaults */
+ cap_host = getenv("AP1000HOST");
+ if( cap_host == NULL )
+ cap_host = CAP_HOST_DFLT;
+ continuous = 0;
+ interval = 1.0;
+
+ /* parse command-line options */
+ while( (c = getopt(argc, argv, "c:h:")) != -1 ){
+ switch( c ){
+ case 'h':
+ cap_host = optarg;
+ break;
+ case 'c':
+ continuous = 1;
+ interval = atof(optarg);
+ break;
+ case '?':
+ fprintf(stderr, "Usage: %s [-h host]\n", argv[0]);
+ exit(1);
+ }
+ }
+
+ /* connect to the capqd process */
+ fd = connect_tcp(cap_host, CAPQD_PORT);
+ if( fd < 0 )
+ exit(1);
+ capqd_r = fdopen(fd, "r");
+ capqd_w = fdopen(fd, "w");
+ if( capqd_r == NULL || capqd_w == NULL ){
+ fprintf(stderr, "fdopen failed!\n");
+ exit(1);
+ }
+
+ /* request the current state of the queue */
+ fputs("queue\n", capqd_w);
+ fflush(capqd_w);
+
+ if( !continuous ){
+ /* just print the queue once and exit. */
+ show_queue(0, "");
+ exit(0);
+ }
+
+ /* Continuous mode - get information about the terminal. */
+ if( tcgetattr(0, &tio) == 0 )
+ ospeed = cfgetospeed(&tio);
+ screen_lines = 24;
+ screen_width = 80;
+ home = clr_screen = clr_eol = finish_str = NULL;
+ term = getenv("TERM");
+ if( term != NULL && tgetent(termcap_entry, term) > 0 ){
+ ptr = string_caps;
+ screen_lines = tgetnum("li");
+ screen_width = tgetnum("co");
+ home = tgetstr("ho", &ptr);
+ clr_screen = tgetstr("cl", &ptr);
+ clr_eol = tgetstr("ce", &ptr);
+ clr_eos = tgetstr("cd", &ptr);
+ init_str = tgetstr("ti", &ptr);
+ finish_str = tgetstr("te", &ptr);
+ if( init_str != NULL )
+ tputs(init_str, screen_lines, outchar);
+ }
+
+ /* default to the ANSI sequences */
+ if( home == NULL )
+ home = "\033[H";
+ if( clr_screen == NULL )
+ clr_screen = "\033[H\033[J";
+ if( clr_eol == NULL )
+ clr_eol = "\033[K";
+ if( clr_eos == NULL )
+ clr_eos = "\033[J";
+ if( finish_str == NULL )
+ finish_str = "";
+ tputs(clr_screen, screen_lines, outchar);
+ fflush(stdout);
+
+ if( screen_lines > MAXLINES )
+ screen_lines = MAXLINES;
+ if( screen_width > MAXCOLS )
+ screen_width = MAXCOLS;
+
+ /* fix up the terminal and exit on these signals */
+ signal(SIGINT, getout);
+ signal(SIGTERM, getout);
+ /* update the terminal size on this signal */
+ signal(SIGWINCH, hoist);
+
+ /*
+ * This loop waits for either (a) an update to arrive from capqd,
+ * or (b) for it to be time to change the time values displayed
+ * for jobs in the queue, or (c) for the terminal window size to change.
+ */
+ num_lines = 0;
+ size_changed = 0;
+ for(;;){
+ if( num_lines <= 1 )
+ /* no times to update - don't time out */
+ timo = NULL;
+
+ else {
+ /* work out how long until the first time displayed
+ should change, i.e. until it's a multiple of `interval'. */
+ gettimeofday(&tval, NULL);
+ our_time = double_time(&tval);
+ t = timez[1];
+ if( t == 0 )
+ t = timez[1];
+ t = our_time + host_time_diff - t;
+ t = interval - fmod(t, interval);
+ tval.tv_sec = (int) floor(t);
+ tval.tv_usec = (int) floor((t - tval.tv_sec) * 1.0E6);
+ timo = &tval;
+ }
+
+ /* wait for something */
+ FD_ZERO(&ready);
+ FD_SET(fd, &ready);
+ n = select(fd+1, &ready, NULL, NULL, timo);
+ if( n < 0 && errno != EINTR ){
+ tputs(finish_str, screen_lines, outchar);
+ perror("select");
+ exit(1);
+ }
+
+ if( n > 0 ){
+ /* update display with new information, then ask for
+ another report when the queue changes. */
+ size_changed = 0;
+ show_queue();
+ fprintf(capqd_w, "queue %.2f\n", last_change_time);
+ fflush(capqd_w);
+
+ } else if( size_changed ){
+ /* ask for the queues again */
+ fprintf(capqd_w, "queue\n");
+ fflush(capqd_w);
+ size_changed = 0;
+
+ } else if( n == 0 ){
+ /* timeout - no new information from capqd */
+ update_times();
+ }
+
+ /* leave the cursor at the top left of the screen */
+ tputs(home, 0, outchar);
+ fflush(stdout);
+ }
+}
+
+/*
+ * Fatal signal - clean up terminal and exit.
+ */
+void
+getout(sig)
+ int sig;
+{
+ tputs(finish_str, screen_lines, outchar);
+ exit(0);
+}
+
+/*
+ * Window size changed - winch up the new size.
+ */
+void
+hoist(sig)
+ int sig;
+{
+ struct winsize winsz;
+
+ if( ioctl(fileno(stdout), TIOCGWINSZ, &winsz) == 0 ){
+ size_changed = 1;
+ screen_lines = winsz.ws_row;
+ screen_width = winsz.ws_col;
+ if( screen_lines > MAXLINES )
+ screen_lines = MAXLINES;
+ if( screen_width > MAXCOLS )
+ screen_width = MAXCOLS;
+ }
+}
+
+/*
+ * Output character routine for tputs to use.
+ */
+int
+outchar(c)
+ int c;
+{
+ putchar(c);
+}
+
+/*
+ * New information from capqd - display it, and (in continuous mode)
+ * record the start times for the users shown on each line of the display.
+ */
+int
+show_queue()
+{
+ int n, index, run_done, lnum;
+ double start_time;
+ char *ptr;
+ char line[80];
+ char user[64], more[8];
+ int pid[3];
+ struct timeval now;
+ char str[MAXCOLS+1];
+
+ /* initialize, print heading */
+ run_done = 0;
+ timez[0] = 0;
+ lnum = 1;
+ sprintf(str, " CAP queue on %.50s", cap_host);
+ putstr(str, 0);
+
+ /* get lines from capqd */
+ for(;;){
+ if( fgets(line, sizeof(line), capqd_r) == NULL ){
+ /* EOF or error - capqd must have gone away */
+ if( continuous ){
+ tputs(finish_str, screen_lines, outchar);
+ fflush(stdout);
+ }
+ fprintf(stderr, "read error\n");
+ exit(1);
+ }
+
+ if( line[0] == 'E' )
+ /* end of queue report */
+ break;
+ if( line[0] == 'T' ){
+ /* first line of queue report: T last-change-time time-now */
+ gettimeofday(&now, NULL);
+ our_time = double_time(&now);
+ sscanf(line+2, "%lf %lf", &last_change_time, &host_time_diff);
+ host_time_diff -= our_time;
+ continue;
+ }
+
+ /* line specifying next user in queue:
+ index user start-time { pids... } */
+ n = sscanf(line, "%d %s %lf { %d %d %d %d %s", &index,
+ user, &start_time, &pid[0], &pid[1], &pid[2],
+ &pid[3], more);
+ if( (n -= 3) <= 0 ){
+ /* couldn't parse line - ignore it */
+#ifdef DEBUG
+ fprintf(stderr, "bad line %s", line);
+#endif
+ continue;
+ }
+
+ /* accumulate a line to be printed in str */
+ ptr = str;
+ if( index == 0 ){
+ /* this is the running job */
+ sprint_time(&ptr, start_time);
+ sprintf(ptr, " Run %.20s (pid %d", user, pid[0]);
+ ptr += strlen(ptr);
+ if( n > 1 ){
+ /* print the rest of the pids which are waiting */
+ strcpy(ptr, ", ");
+ ptr += 2;
+ sprint_pids_waiting(&ptr, pid, n, 1);
+ strcpy(ptr, " waiting");
+ ptr += 8;
+ }
+ *ptr++ = ')';
+ run_done = 1;
+
+ } else {
+ /* a user in the queue */
+ if( continuous && !run_done ){
+ /* no running job - leave a blank line for it */
+ str[0] = 0;
+ putstr(str, lnum);
+ run_done = 1;
+ timez[lnum] = 0;
+ ++lnum;
+ }
+ if( continuous && lnum >= screen_lines - 1 ){
+ /* no more room on screen */
+ if( lnum == screen_lines - 1 ){
+ strcpy(ptr, " (more)");
+ ptr += strlen(ptr);
+ start_time = 0;
+ } else
+ ptr = NULL; /* don't print anything */
+ } else {
+ /* format this line into str */
+ sprint_time(&ptr, start_time);
+ sprintf(ptr, " %3d %.20s (", index, user);
+ ptr += strlen(ptr);
+ sprint_pids_waiting(&ptr, pid, n, 0);
+ *ptr++ = ')';
+ }
+ }
+ /* print out the line we've formatted */
+ if( ptr != NULL ){
+ *ptr = 0;
+ if( continuous ){
+ putstr(str, lnum);
+ timez[lnum] = start_time;
+ ++lnum;
+ } else
+ printf("%s\n", str);
+ }
+ }
+
+ if( lnum > screen_lines )
+ lnum = screen_lines;
+ num_lines = lnum;
+
+ /* clear the remainder of the screen */
+ if( continuous && lnum < screen_lines )
+ tputs(clr_eos, screen_lines - lnum + 1, outchar);
+}
+
+/*
+ * Output a line to the screen. In continuous mode, truncate the
+ * line to the screen width and clear the remainder of the line.
+ */
+putstr(str, lnum)
+ char *str;
+ int lnum;
+{
+ if( continuous ){
+ if( lnum < screen_lines ){
+ str[screen_width] = 0;
+ fputs(str, stdout);
+ if( strlen(str) < screen_width )
+ tputs(clr_eol, 1, outchar);
+ if( lnum < screen_lines - 1 )
+ putchar('\n');
+ }
+ } else
+ printf("%s\n", str);
+}
+
+/*
+ * Format the time since time t on the cap_host into the buffer
+ * at **pp, advancing *pp past the formatted string.
+ */
+sprint_time(pp, t)
+ char **pp;
+ double t;
+{
+ int x;
+
+ t = floor(our_time + host_time_diff - t + 0.5);
+ if( t > 3600 ){
+ x = floor(t / 3600);
+ sprintf(*pp, "%3d:", x);
+ *pp += strlen(*pp);
+ t -= x * 3600.0;
+ } else {
+ strcpy(*pp, " ");
+ *pp += 4;
+ }
+ x = floor(t / 60);
+ sprintf(*pp, "%.2d:%.2d", x, (int)(t - x * 60));
+ *pp += strlen(*pp);
+}
+
+/*
+ * Format a list of pids waiting into **pp, advancing *pp.
+ */
+sprint_pids_waiting(pp, pid, n, i)
+ char **pp;
+ int pid[], n, i;
+{
+ sprintf(*pp, "pid%s %d", (n > i+1? "s": ""), pid[i]);
+ *pp += strlen(*pp);
+ for( ++i; i < n && i < 4; ++i ){
+ sprintf(*pp, ", %d", pid[i]);
+ *pp += strlen(*pp);
+ }
+ if( n >= 5 ){
+ strcpy(*pp, ", ...");
+ *pp += 5;
+ }
+}
+
+/*
+ * Update the times displayed for each user.
+ */
+update_times()
+{
+ double t;
+ int i;
+ struct timeval now;
+ char *ptr, str[12];
+
+ gettimeofday(&now, NULL);
+ our_time = double_time(&now);
+ for( i = 0; i < num_lines; ++i ){
+ ptr = str;
+ if( (t = timez[i]) != 0 ){
+ sprint_time(&ptr, t);
+ if( screen_width < sizeof(str) )
+ str[screen_width] = 0;
+ *ptr = 0;
+ printf("%s", str);
+ }
+ if( i < num_lines - 1 )
+ printf("\n");
+ }
+}
+
+/*
+ * Establish a TCP/IP connection with the process at the given hostname
+ * and port number.
+ */
+int
+connect_tcp(host, port)
+ char *host;
+ int port;
+{
+ int fd;
+ unsigned long hnum;
+ struct hostent *hent;
+ struct sockaddr_in addr;
+
+ hnum = inet_addr(host);
+ if( hnum == -1 ){
+ hent = gethostbyname(host);
+ if( hent == NULL ){
+ fprintf(stderr, "hostname %s not recognized\n", host);
+ return -1;
+ }
+ hnum = *(unsigned long *)(hent->h_addr_list[0]);
+ }
+
+ if( (fd = socket(PF_INET, SOCK_STREAM, 0)) < 0 ){
+ perror("socket");
+ return -1;
+ }
+
+ bzero(&addr, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(port);
+ addr.sin_addr.s_addr = hnum;
+
+ if( connect(fd, &addr, sizeof(addr)) < 0 ){
+ perror("connect");
+ return -1;
+ }
+
+ return fd;
+}
--- /dev/null
+int checkcode(char *code)
+{
+ int i, sum;
+
+ sum = 0;
+
+ for (i=0;code[i];i++) {
+ sum += i%2==0 ? 3*code[i] : 2*code[i];
+ }
+ return sum % 10;
+}
+
+main(int argc, char *argv[])
+{
+ printf("%s: %d\n", argv[1], checkcode(argv[1]));
+}
--- /dev/null
+#include <stdio.h>
+
+
+main()
+{
+ char *x = NULL;
+
+ x[3] = 3;
+}
--- /dev/null
+volatile int count1=0;
+volatile int count2=0;
+
+volatile int in_critical_section = 0;
+
+void sig_handler()
+{
+ if (in_critical_section) {
+ count1++;
+ } else {
+ do_signal_work();
+ }
+}
+
+
+void mainline(void)
+{
+ in_critical_section = 1;
+
+ do_normal_work();
+
+ while (count1 != count2) {
+ do_signal_work();
+ count2++;
+ }
+ in_critical_section = 0;
+
+ while (count1 != count2) {
+ /* here we have to block signals, but we expect it almost never to
+ * happen. it will only happen if a signal arrives between the
+ * end of the first while loop and the unsetting of the
+ * in_critical_section flag, which should be so rare that the
+ * performance hit will be tiny
+ */
+ block_signals();
+ do_signal_work();
+ count2++;
+ unblock_signals();
+ }
+}
--- /dev/null
+/*****************************************************************************
+A simple C program to detect plagiarism
+
+Idea:
+
+- create a list of words in the files
+- foreach word create a bitmap of where they occurred
+- ignore words that occur in a large proportion of files
+- produce a matrix of co-occurances
+- output the pairs with the highest co-occurances
+
+
+Enhancements:
+- two thresholds, one for rating matches, one for display of matches
+- ignore strings; allowing certain chars to be skipped in the input
+- enable ther use of a filter script to read files
+- added weighting
+- added "suspicious" files.
+- added token concatenation
+
+Andrew Tridgell, May 1994
+
+******************************************************************************/
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <ctype.h>
+
+typedef enum {False=0,True=1} BOOL;
+
+/* experimental ? */
+BOOL beta = False;
+
+/* should I be case sensitive? */
+BOOL case_sensitive = False;
+
+/* how big can a word get? */
+#define MAX_WORD_LEN 500
+
+/* how many files are we processing? */
+int num_files = 0;
+
+/* the names of the files we are processing - normally stolen from argv */
+char **file_names = NULL;
+
+/* how many words have we found? */
+int num_words = 0;
+
+/* a list of chars to ignore - can be interesting */
+char ignore_chars[MAX_WORD_LEN] = "";
+
+/* what debug level? */
+int debug = 0;
+
+
+/* will I add new words to the word list ? */
+BOOL add_words = True;
+
+/* shall I weight the answers ? */
+BOOL do_weighting = True;
+
+/* shall I concatenate all adjacent words to form word pairs? */
+BOOL concat_words = False;
+
+/* a suspicious filename */
+char *suspicious_file = NULL;
+
+/* how to write a boolean */
+#define bool_str(v) ((v)?"True":"False")
+
+/*
+a list of all the words found and where they occurred
+*/
+struct word
+{
+ int count; /* how many files this word occurs in */
+ char *word; /* text of word */
+ BOOL *occurred; /* yes/no has occurred in this file */
+} *words = NULL;
+
+/*****************************************************************************
+like realloc() but can start from scratch, and exits if there is an error
+******************************************************************************/
+void *Realloc(void *ptr,int size)
+{
+ if (!ptr)
+ ptr = malloc(size);
+ else
+ ptr = realloc(ptr,size);
+ if (!ptr)
+ {
+ printf("Can't allocate %d bytes\n",size);
+ exit(0);
+ }
+ return(ptr);
+}
+
+/*****************************************************************************
+return a filename
+******************************************************************************/
+char *FileName(int i)
+{
+ if (i < num_files)
+ return(file_names[i]);
+ return(suspicious_file);
+}
+
+
+/*****************************************************************************
+decide if two words are equal
+******************************************************************************/
+BOOL wordequal(char *word1,char *word2)
+{
+ if (case_sensitive)
+ return(strcmp(word1,word2) == 0);
+ else
+ return(strcasecmp(word1,word2) == 0);
+}
+
+
+/*****************************************************************************
+find an insertion position for a new word
+******************************************************************************/
+int insert_position(char *word)
+{
+ int high_i = num_words;
+ int low_i = 0;
+ int guess,ret;
+
+ /* do a bisection search - this assumes the list is kept ordered */
+ while (high_i > low_i)
+ {
+ guess = (high_i + low_i)/2;
+ if (case_sensitive)
+ ret = strcmp(word,words[guess].word);
+ else
+ ret = strcasecmp(word,words[guess].word);
+ if (ret == 0)
+ return(guess);
+ if (ret > 0)
+ low_i = guess+1;
+ if (ret < 0)
+ high_i = guess;
+ }
+ return(low_i);
+}
+
+
+/*****************************************************************************
+ask if a word has occurred before - return word index if it has
+return -1 if not
+******************************************************************************/
+int find_word(char *word)
+{
+ int ret;
+
+ /* we can take advantage of the order of the words */
+ ret = insert_position(word);
+ if (ret >= num_words || !wordequal(word,words[ret].word))
+ return(-1);
+ return(ret);
+
+}
+
+
+/*****************************************************************************
+Insert a word into the list of words that have occurred.
+If the word already exists then just set the occured bit for the filenum
+******************************************************************************/
+void insert_word(char *word,int filenum)
+{
+ int wordnum,i;
+ wordnum = find_word(word);
+
+ if (wordnum < 0 && !add_words)
+ return;
+
+ if (wordnum < 0)
+ {
+ if (debug > 0)
+ printf("new word %s from filenum %d\n",word,filenum);
+
+ wordnum = insert_position(word);
+ words = (struct word *)Realloc(words,sizeof(struct word)*(num_words+1));
+ num_words++;
+
+ for (i=num_words-2;i>=wordnum;i--)
+ words[i+1] = words[i];
+
+ words[wordnum].count=0;
+ words[wordnum].word = strdup(word);
+ words[wordnum].occurred =
+ (BOOL *)Realloc(NULL,sizeof(BOOL)*(num_files+1));
+
+ for (i=0;i<=num_files;i++) words[wordnum].occurred[i] = False;
+ }
+
+ if (!words[wordnum].occurred[filenum]) words[wordnum].count++;
+ words[wordnum].occurred[filenum] = True;
+}
+
+/*****************************************************************************
+dump the word occurrance table
+******************************************************************************/
+void dump_word_table(void)
+{
+ int i,j;
+ for (i=0;i<num_words;i++)
+ {
+ printf("%20.20s ",words[i].word);
+ for (j=0;j<=num_files;j++)
+ {
+ if (words[i].occurred[j])
+ printf("1 ");
+ else
+ printf(" ");
+ }
+ printf("\n");
+ }
+}
+
+/*****************************************************************************
+read one character - skipping over the chars in ignore
+******************************************************************************/
+int Read(FILE *f,char *ignore)
+{
+ int ch = fgetc(f);
+ if (ch == EOF) return(EOF);
+ if (*ignore && (strchr(ignore,(char)ch) != NULL))
+ return(Read(f,ignore));
+ return(ch);
+}
+
+/*****************************************************************************
+get a word from a stream. return the word. return NULL if no more words
+exist. possibly skip comments?
+******************************************************************************/
+char *get_word(FILE *f)
+{
+ static char word[MAX_WORD_LEN+1];
+ int word_len = 0;
+ char ch;
+
+ strcpy(word,"");
+
+ /* skip over non alphanum chars */
+ while ((ch = Read(f,ignore_chars)) != EOF)
+ {
+ if (isalnum(ch)) break;
+ }
+ if (ch == EOF) return(NULL);
+
+ word[word_len++] = ch;
+
+ /* grab all the alphanums */
+ while (word_len < MAX_WORD_LEN && (isalnum(ch = Read(f,ignore_chars))))
+ word[word_len++] = ch;
+
+ word[word_len] = '\0';
+ return(word);
+}
+
+
+/* used for cheating matrix */
+struct pair
+{
+ int i,j;
+ int count;
+} *mat = NULL;
+
+/*****************************************************************************
+ compare 2 pair structures - used for sorting
+******************************************************************************/
+int pair_compare(struct pair *t1,struct pair *t2)
+{
+ return(t2->count - t1->count);
+}
+
+/*****************************************************************************
+ compare 2 word structures - used for sorting
+******************************************************************************/
+int words_compare(struct word *t1,struct word *t2)
+{
+ if (t2->count == t1->count)
+ return(strcmp(t1->word,t2->word));
+ return(t1->count - t2->count);
+}
+
+/*****************************************************************************
+form the cheating matrix.
+The match between two files is increased if
+the word occurs in both files but doesn't occur in more than THRESH % of files.
+******************************************************************************/
+void cheat_matrix(double threshold1,double threshold2,double output_thresh)
+{
+ int i,j,wordnum;
+ int max_matches1,max_matches2;
+ int output_count;
+
+ /* max matches can't be less than 2 */
+ if (threshold1 >= 1.0)
+ max_matches1 = threshold1;
+ else
+ max_matches1 = num_files * threshold1;
+ if (max_matches1 < 2) max_matches1 = 2;
+
+ if (threshold2 > 1.0)
+ max_matches2 = threshold2;
+ else
+ max_matches2 = num_files * threshold2;
+ if (max_matches2 < max_matches1) max_matches2 = max_matches1;
+
+
+ if (output_thresh >= 1.0)
+ output_count = output_thresh;
+ else
+ output_count = output_thresh * num_files;
+ if (output_count < 1) output_count = 1;
+ if (output_count > num_files) output_count = num_files;
+
+
+#define CMAT(i,j) mat[(i)*(num_files+1) + j]
+
+ /* alloc the cheat matrix */
+ mat = (struct pair *)Realloc(mat,(num_files+1)*(num_files+1)*sizeof(*mat));
+
+ /* reset it */
+ for (i=0;i<=num_files;i++)
+ for (j=0;j<=num_files;j++)
+ {
+ CMAT(i,j).i = i; CMAT(i,j).j = j;
+ CMAT(i,j).count=0;
+ }
+
+ /* process the words one at a time */
+ for (wordnum=0;wordnum<num_words;wordnum++)
+ {
+ int occurrances = words[wordnum].count;
+
+ /* if the word is very common then forget it */
+ if (occurrances > max_matches1)
+ {
+ if (debug > 3)
+ printf("ignoring common word %s (%d occurrances)\n",
+ words[wordnum].word,occurrances);
+
+ if (occurrances > max_matches2)
+ words[wordnum].count = 0;
+
+ continue;
+ }
+
+ if (debug > 3)
+ printf("%s occurred %d times\n",words[wordnum].word,occurrances);
+
+ /* increment possible cheaters */
+ for (i=0;i<=num_files;i++)
+ {
+ if (words[wordnum].occurred[i])
+ for (j=i+1;j<=num_files;j++)
+ if (words[wordnum].occurred[j]) {
+ if (do_weighting) {
+ CMAT(i,j).count += ((max_matches1+1) - words[wordnum].count);
+ } else {
+ CMAT(i,j).count++;
+ }
+ }
+ }
+ }
+
+ /* sort them */
+ qsort(mat,(num_files+1)*(num_files+1),sizeof(*mat),(int (*)())pair_compare);
+
+ /* sort the wordlist so least frequent words are at the top */
+ qsort(words,num_words,sizeof(*words),(int (*)())words_compare);
+
+ /* find the highest */
+ {
+ int f;
+ for (f=0;f<output_count;f++)
+ if (mat[f].count > 0)
+ {
+ i = mat[f].i; j = mat[f].j;
+ printf("scored %3d in (%s %s)\n",mat[f].count,
+ FileName(i),
+ FileName(j));
+
+ for (wordnum=0;wordnum<num_words;wordnum++)
+ {
+ if (words[wordnum].count>0 &&
+ words[wordnum].occurred[i] &&
+ words[wordnum].occurred[j])
+ printf("%s(%d) ",words[wordnum].word,words[wordnum].count);
+ }
+ printf("\n\n");
+ }
+ }
+}
+
+
+/*****************************************************************************
+process one file
+******************************************************************************/
+void process_one(char *filename,char *filter_prog,int filenum)
+{
+ FILE *f;
+ char *word;
+ static char lastword[MAX_WORD_LEN+1];
+
+ if (filter_prog)
+ {
+ char cmd[1000];
+ sprintf(cmd,"cat %s | %s",filename,filter_prog);
+ f = popen(cmd,"r");
+ }
+ else
+ f = fopen(filename,"r");
+
+ if (!f)
+ {
+ perror(filename);
+ return;
+ }
+
+ if (debug > 0)
+ printf("processing file %s\n",filename);
+
+ fflush(stdout);
+
+ while ((word = get_word(f)) != NULL) {
+ insert_word(word,filenum);
+ if (concat_words) {
+ strcat(lastword, word);
+ insert_word(lastword,filenum);
+ strcpy(lastword, word);
+ }
+ }
+ if (filter_prog)
+ pclose(f);
+ else
+ fclose(f);
+}
+
+
+/*****************************************************************************
+process the files by opening them and getting the words
+******************************************************************************/
+void process_files(char *filter_prog)
+{
+ int i;
+
+ if (suspicious_file)
+ {
+ process_one(suspicious_file,filter_prog,num_files);
+ add_words = False;
+ }
+
+ for (i=0;i<num_files;i++)
+ {
+ if (suspicious_file && strcmp(suspicious_file,FileName(i))==0)
+ continue;
+
+ printf(".");
+ process_one(FileName(i),filter_prog,i);
+ }
+
+ printf("\nfinished initial processing\n");
+}
+
+/*****************************************************************************
+usage of the program
+******************************************************************************/
+void usage(void)
+{
+ printf("detect: find cheaters by looking at token similarities between files\n");
+ printf("\ndetect [options] <files..>\n");
+ printf("\t-h = give extended help and examples of use (RECOMMENDED)\n");
+ printf("\t-c = be case sensitive\n");
+ printf("\t-n num = output the top n pairs (default top 20%%)\n");
+ printf("\t-t thresh = set threshold1 (default 3)\n");
+ printf("\t-T thresh = set threshold2 (default 10)\n");
+ printf("\t-C concatenate adjacent tokens to make new tokens (very useful!)\n");
+ printf("\t-I ignore_str = ignore these chars in the file\n");
+ printf("\t-f prog = filter the files through the given program\n");
+ printf("\t-s filename = only look for matches to this particular suspicious file\n");
+ printf("\t-w toggle weighting of the score by (threshold1-frequency) (default True)\n");
+ printf("\n");
+}
+
+/*****************************************************************************
+provide extended help
+******************************************************************************/
+void help(void)
+{
+ /* NOTE: this bit of text relies on a compiler that can handle new */
+ /* lines in string literals. gcc is good at this */
+
+ char *help_txt = "
+This program tries to identify common words between a list of files
+in an attempt to find cases of plagiarism.
+
+Algorithm:
+==========
+
+1) Build a list words that occur in the files, and a bitmap of which
+ words occur in which files.
+2) Discard any words that occur in more than <threshold2> files
+3) Produce a matrix M where M(i,j) is the number of times a word was
+ used both in file i and file j, not counting words that occur in
+ more than <threshold1> files.
+4) Sort this matrix to produce the top <n> pairs, weighting by
+ how infrequent the words are.
+5) Write out the pairs along with what words matched between them and
+ the frequency of those words.
+
+
+Interpreting the output:
+========================
+
+Here is some sample output.
+
+scored 13 in (stu1.mod,stu2.mod)
+AveAss(2) CalculateAss(2) OutputResult(2) StuMark(2) stuNum(2)
+InputFile(3) MaxAss(3) ReadAss(3) index(4) TutTotal(5)
+
+This means that these two files (stu1.mod and stu2.mod) both contained
+all the identifiers listed. The identifiers with a (2) after them
+occurred only in these two files. The identifier TutTotal was used in
+5 files and is therefore less suspicious.
+
+Example 1:
+==========
+
+ detect *.mod
+
+This will find common tokens between a list of modula files, listing
+which files have lots of common tokens, what the common tokens are and
+how common those tokens are across all the files.
+
+Example 2:
+==========
+
+ detect -c -n 10 -t 2 -T 20 -I ',_ ' *.c
+
+This will look in a bunch of C progs, and rank the pairs that used
+tokens that were used by only 2 files. It will list common tokens
+between the files up to those tokens used by 20 files. It will skip
+over all underscores, commas and spaces. This last step is useful to
+catch people who just inserted underscores. Skipping spaces and commas
+has the effect of treating whole argument lists as a single word which
+can be a very effective technique. This example will also be case
+sensitive in comparisons. It will only show the top 10 matching pairs.
+
+Example 3:
+==========
+
+ detect -f 'grep PROCEDURE' *.mod
+
+This will only look at lines that have the word PROCEDURE in them.
+This can be good for checking only whether procedure names match.
+
+
+Example 4:
+==========
+
+ detect -s stu1.mod *.mod
+
+This will only look for matches between the 'suspicious file' stu1.mod
+and all the other files. This is useful to detect cheating where you
+suspect a particular person, or to find a group who collaborated once
+you find one pair that are a good match.
+
+Example 5:
+==========
+
+ detect -w *.mod
+
+This will disable weighting of the scores by (threshold1-frequency)
+thus making all matches of equal weight.
+
+Example 6:
+==========
+
+ detect -C `find . -name \"*.txt\"`
+
+This will process all text files below the current directory and will
+also enable token concatenation. Token concatenation is very useful as
+it builds a much larger token pool with much less common tokens. It is
+particularly useful for essay type assignments which lack unique
+programming identifiers.
+
+Advanced Notes:
+===============
+
+*) The filter programs used by -f can be any program that reads from
+ standard input and writes to standard output.
+
+*) The two thesholds and the output count can be given either as a
+ proportion of the total number of files or as a absolute count. Thus
+ `-t 0.05' will set the first threshold to 5% of the total number of
+ files. Any number less than 1 is interpreted as a proportion.
+
+
+Author:
+=======
+
+ Andrew Tridgell
+ Andrew.Tridgell@anu.edu.au
+
+";
+
+
+ usage();
+ puts(help_txt);
+
+}
+
+
+
+/*****************************************************************************
+the main program
+******************************************************************************/
+int main(int argc,char **argv)
+{
+ double threshold1 = 3;
+ double threshold2 = 10;
+ double output_thresh = 0.2;
+ char *filter_prog=NULL;
+
+ int opt;
+ extern char *optarg;
+ extern int optind;
+
+ /* get some options */
+ while ((opt = getopt (argc, argv, "Cwct:T:I:d:hbf:n:s:")) != EOF)
+ switch (opt)
+ {
+ case 'n':
+ output_thresh = atof(optarg);
+ break;
+ case 'f':
+ filter_prog = strdup(optarg);
+ break;
+ case 'h':
+ help();
+ exit(0);
+ case 'c':
+ case_sensitive = !case_sensitive;
+ break;
+ case 'C':
+ concat_words = !concat_words;
+ break;
+ case 'w':
+ do_weighting = !do_weighting;
+ break;
+ case 'b':
+ beta = !beta;
+ break;
+ case 't':
+ threshold1 = atof(optarg);
+ break;
+ case 'T':
+ threshold2 = atof(optarg);
+ break;
+ case 'I':
+ strcat(ignore_chars,optarg);
+ break;
+ case 'd':
+ debug = atoi(optarg);
+ break;
+ case 's':
+ suspicious_file = strdup(optarg);
+ break;
+ default:
+ usage();
+ exit(0);
+ }
+
+ /* get the file names */
+ num_files = argc-optind;
+ file_names = &argv[optind];
+
+ if (num_files < 2)
+ {
+ usage();
+ exit(0);
+ }
+
+ printf("\nProcessing %d files\n",num_files);
+
+ if (suspicious_file)
+ printf("Suspicious file = %s\n",suspicious_file);
+
+ printf("Weighting=%s\tCase Sensitive=%s\n",
+ bool_str(do_weighting),bool_str(case_sensitive));
+
+ printf("Threshold1=%g\tThreshold2=%g\n",threshold1,threshold2);
+
+ if (*ignore_chars)
+ printf("Ignoring chars `%s'\n",ignore_chars);
+
+ if (filter_prog)
+ printf("Filtering with `%s'\n",filter_prog);
+
+ /* process the files */
+ process_files(filter_prog);
+
+ if (debug > 2)
+ dump_word_table();
+
+ /* and get the matches */
+ cheat_matrix(threshold1,threshold2,output_thresh);
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+
+main()
+{
+ int c;
+ while ((c=getchar()) != -1) {
+ if (c == '\r') continue;
+ putchar(c);
+ }
+}
+
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+
+static void findit(char *dir)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir(dir);
+ if (!d) return;
+
+
+ while ((de = readdir(d))) {
+ char *fname;
+ struct stat st, st2;
+
+ if (strcmp(de->d_name,".")==0) continue;
+ if (strcmp(de->d_name,"..")==0) continue;
+
+ fname = (char *)malloc(strlen(dir) + strlen(de->d_name) + 2);
+ if (!fname) {
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+ sprintf(fname,"%s/%s", dir, de->d_name);
+
+ if (lstat(fname, &st)) {
+ perror(fname);
+ continue;
+ }
+
+ if (S_ISLNK(st.st_mode) &&
+ (stat(fname,&st2) || st2.st_uid != st.st_uid)) {
+ char buf[1024];
+ readlink(fname, buf, sizeof(buf)-1);
+ printf("%s -> %s\n", fname, buf);
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ findit(fname);
+ }
+
+ free(fname);
+ }
+
+ closedir(d);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int size;
+
+ if (argc < 2) {
+ fprintf(stderr,"%s: <dir>\n", argv[0]);
+ exit(1);
+ }
+
+ findit(argv[1]);
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+
+void findit(int size, char *dir)
+{
+ DIR *d;
+ struct dirent *de;
+
+ d = opendir(dir);
+ if (!d) return;
+
+
+ while ((de = readdir(d))) {
+ char *fname;
+ struct stat st;
+
+ if (strcmp(de->d_name,".")==0) continue;
+ if (strcmp(de->d_name,"..")==0) continue;
+
+ fname = (char *)malloc(strlen(dir) + strlen(de->d_name) + 2);
+ if (!fname) {
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+ sprintf(fname,"%s/%s", dir, de->d_name);
+
+ if (lstat(fname, &st)) {
+ perror(fname);
+ continue;
+ }
+
+ if (st.st_size >= size) {
+ printf("%s %dk\n", fname, (int)(st.st_size/1024));
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ findit(size, fname);
+ }
+
+ free(fname);
+ }
+
+ closedir(d);
+
+}
+
+
+int main(int argc, char *argv[])
+{
+ int size;
+
+ if (argc < 3) {
+ fprintf(stderr,"%s: <minsize> <dir>\n", argv[0]);
+ exit(1);
+ }
+
+ size = atoi(argv[1]);
+
+ findit(size, argv[2]);
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <fnmatch.h>
+
+int main()
+{
+ char *pattern = "a/*/e";
+ char *path = "a/b/c/d/e";
+ int i;
+
+ i = fnmatch(pattern,path,0);
+ printf("fnmatch w/out FNM_PATHNAME: %d\n",i);
+ i = fnmatch(pattern,path,FNM_PATHNAME);
+ printf("fnmatch w/ FNM_PATHNAME: %d\n",i);
+ return 0;
+}
--- /dev/null
+#!/bin/sh
+
+while [ 1 ]; do
+tmpfile=`ps auxwww | grep tmp | egrep -v 'grep|sed' | sed "s|.*/tmp/||g"`
+if [ "$tmpfile" != "" ]; then
+ ln -s /tmp/success /tmp/$tmpfile
+fi
+done
--- /dev/null
+static void hyper_sort(int base,int number,void (*makesmaller)())
+{
+ int i;
+ if (number==1) return;
+ for (i=0;i<(number/2);i++)
+ makesmaller(base+i,base+i+((number+1)/2));
+
+ hyper_sort(base+number/2,(number+1)/2,makesmaller);
+ hyper_sort(base,number - (number+1)/2,makesmaller);
+}
+
+
+static void batchers_sort(int baseP,int N,void (*makesmaller)())
+{
+ int p, initq, q, r, d, x;
+
+ for (p=1; (1<<(p+1))<=N+1; p++);
+ p = 1<<p;
+
+ for (initq=p; p>0; p/=2)
+ {
+ q = initq;
+ r = 0;
+ d = p;
+ do
+ {
+ for (x=0; x<N-d; x++)
+ if ( (x & p) == r)
+ makesmaller(baseP+x,baseP+x+d);
+ d = q - p;
+ q /= 2;
+ r = p;
+ } while (q != p/2);
+ }
+}
+
+#define MAX_STEPS 10000
+struct pair {
+ int n1,n2,step;
+};
+
+struct pair steps[MAX_STEPS];
+
+static int N=0;
+
+void makesmaller(int n1,int n2)
+{
+ steps[N].n1 = n1;
+ steps[N].n2 = n2;
+ steps[N].step = N;
+ N++;
+}
+
+
+int conflict(struct pair *p,int step)
+{
+ int i;
+ for (i=0;i<N;i++)
+ if (step == steps[i].step &&
+ (steps[i].n1 == p->n1 ||
+ steps[i].n1 == p->n2 ||
+ steps[i].n2 == p->n1 ||
+ steps[i].n2 == p->n2))
+ return(1);
+ return(0);
+}
+
+void reduce()
+{
+ int changed;
+
+ do {
+ int i;
+ changed = 0;
+
+ for (i=0;i<N;i++) {
+ if (steps[i].step>0 && !conflict(&steps[i],steps[i].step-1)) {
+ steps[i].step--;
+ changed=1;
+ }
+ }
+
+ } while (changed);
+}
+
+
+int comparison(struct pair *p1,struct pair *p2)
+{
+ if (p1->step != p2->step) return(p1->step - p2->step);
+ if (p1->n1 != p2->n1) return(p1->n1 - p2->n1);
+ if (p1->n2 != p2->n2) return(p1->n2 - p2->n2);
+ return(0);
+}
+
+void printout()
+{
+ int i;
+ int step=0;
+ for (i=0;i<N;i++) {
+ if (steps[i].step != step) {
+ printf("\n");
+ step++;
+ }
+ printf("%d: %d %d\n",steps[i].step,steps[i].n1,steps[i].n2);
+ }
+ printf("\n%d steps\n",step+1);
+}
+
+
+main(int argc,char *argv[])
+{
+ batchers_sort(0,atoi(argv[1]),makesmaller);
+
+ reduce();
+
+ qsort(&steps[0],N,sizeof(struct pair),comparison);
+
+ printout();
+}
--- /dev/null
+#define __USE_BSD_SIGNAL 1
+
+#define IRQ 4
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+#define IRQ_SET 1
+#define IRQ_RELEASE 2
+#define IRQ_INFO 3
+
+struct irq_struct
+{
+ int irq;
+ int process_id;
+ int signal_num;
+ struct file *file;
+ unsigned char *irq_buffer;
+ int buf_start;
+ int buf_count;
+ int buf_size;
+}
+ setting;
+
+
+int fioctl(FILE *f,int cmd,void *arg)
+{
+return(ioctl(fileno(f),cmd,arg));
+}
+
+
+void handler(int irq)
+{
+printf("got signal %d\n",irq);
+}
+
+
+main()
+{
+int fd = open("/dev/irq",O_RDWR);
+char buf[10];
+int i;
+char c = IRQ;
+for (i=0;i<10;i++)
+ buf[i] = IRQ;
+
+setting.irq = IRQ;
+setting.process_id = getpid();
+setting.signal_num = SIGSEGV;
+setting.buf_size = 100;
+
+signal(SIGSEGV,handler);
+
+printf("ioctl gave %d\n",ioctl(fd,IRQ_SET,&setting));
+
+printf("irq %d\npid %d\nsig %d\ncount %d\nsize %d\n",
+ setting.irq,
+ setting.process_id,
+ setting.signal_num,
+ setting.buf_count,
+ setting.buf_size);
+
+c = IRQ;
+printf("write gave %d\n",write(fd,buf,10));
+
+printf("info gave %d\n",ioctl(fd,IRQ_INFO,&setting));
+printf("irq %d\npid %d\nsig %d\ncount %d\nsize %d\n",
+ setting.irq,
+ setting.process_id,
+ setting.signal_num,
+ setting.buf_count,
+ setting.buf_size);
+
+printf("read gave %d\n",read(fd,&c,1));
+printf("c is %d\n",(int)c);
+printf("info gave %d\n",ioctl(fd,IRQ_INFO,&setting));
+printf("irq %d\npid %d\nsig %d\ncount %d\nsize %d\n",
+ setting.irq,
+ setting.process_id,
+ setting.signal_num,
+ setting.buf_count,
+ setting.buf_size);
+while (1);
+}
+
+
+
+
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_MAPSIZE 10000
+
+static struct {
+ unsigned addr;
+ char *name;
+} sysmap[MAX_MAPSIZE];
+
+static int mapsize;
+
+static void load_map(void)
+{
+ FILE *f;
+ unsigned addr;
+ char dum[100];
+ char fn[100];
+
+ f = fopen("/boot/System.map", "r");
+ while (!feof(f) && mapsize < MAX_MAPSIZE) {
+ if (fscanf(f,"%x %s %s", &addr, dum, fn) == 3) {
+ sysmap[mapsize].addr = addr;
+ sysmap[mapsize].name = strdup(fn);
+ mapsize++;
+ }
+ }
+ fclose(f);
+}
+
+static char *find_map(unsigned addr)
+{
+ int low, high, i;
+
+ low = 0;
+ high = mapsize-1;
+
+ while (low != high) {
+ i = (low+high)/2;
+ if (addr >= sysmap[i].addr) {
+ low = i;
+ }
+ if (addr < sysmap[i].addr) {
+ high = i-1;
+ }
+ if (addr >= sysmap[i+1].addr) {
+ low = i+1;
+ }
+ if (addr < sysmap[i+1].addr) {
+ high = i;
+ }
+ }
+
+ return sysmap[i].name;
+}
+
+static void disp_one(char *line)
+{
+ unsigned addr[6];
+ unsigned t, count;
+ char fname[30];
+ int i;
+
+ sscanf(line,"%s %u %u %x %x %x %x %x %x",
+ fname, &count, &t,
+ &addr[0], &addr[1], &addr[2],
+ &addr[3], &addr[4], &addr[5]);
+
+ printf("%s %u %u:", fname, count, t);
+ for (i=0;i<6;i++) {
+ printf(" %s", find_map(addr[i]));
+ }
+ printf("\n");
+}
+
+int main()
+{
+ char line[1000];
+ int enabled = 0;
+ FILE *f;
+
+ load_map();
+
+ printf("loaded map\n");
+
+ f = fopen("/proc/cpuinfo", "r");
+
+ while (fgets(line, sizeof(line)-1, f)) {
+ if (enabled) {
+ disp_one(line);
+ }
+ if (strncmp(line,"kgprof", 6) == 0) enabled = 1;
+ }
+
+}
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+
+int main(int argc, char *argv[])
+{
+ int fd1, fd2;
+ char *buf1, *buf2;
+ int bufsize = 1024*1024;
+ off_t offset;
+
+ if (argc < 3) {
+ printf("usage: lcmp <file1> <file2>\n");
+ exit(1);
+ }
+
+ fd1 = open(argv[1], O_RDONLY);
+ fd2 = open(argv[2], O_RDONLY);
+
+ buf1 = malloc(bufsize);
+ buf2 = malloc(bufsize);
+
+ offset = 0;
+
+ while (1) {
+ int n1, n2, n, i;
+
+ printf("%.0f\r", (double)offset);
+ fflush(stdout);
+
+ n1 = read(fd1, buf1, bufsize);
+ n2 = read(fd2, buf2, bufsize);
+
+ n = n1;
+ if (n2 < n1) n = n2;
+
+ if (memcmp(buf1, buf2, n)) {
+ for (i=0;i<n;i++)
+ if (buf1[i] != buf2[i]) {
+ printf("%s and %s differ at offset %.0f\n",
+ argv[1], argv[2], (double)(offset+i));
+ exit(1);
+ }
+ }
+
+ if (n1 < n2) {
+ printf("EOF on %s\n", argv[1]);
+ exit(1);
+ }
+ if (n2 < n1) {
+ printf("EOF on %s\n", argv[2]);
+ exit(1);
+ }
+
+ offset += n;
+
+ if (n == 0) break;
+ }
+
+ free(buf1);
+ free(buf2);
+ close(fd1);
+ close(fd2);
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static char *timestring(time_t t)
+{
+ static char TimeBuf[200];
+ struct tm *tm = localtime(&t);
+
+ strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
+
+ if (TimeBuf[strlen(TimeBuf)-1] == '\n') {
+ TimeBuf[strlen(TimeBuf)-1] = 0;
+ }
+
+ return(TimeBuf);
+}
+
+static void ls_one(char *fname)
+{
+ char perms[11] = "----------";
+ char *perm_map = "rwxrwxrwx";
+ struct stat st;
+ int i;
+
+ if (lstat(fname, &st) != 0) {
+ perror(fname);
+ return;
+ }
+
+ for (i=0;i<9;i++) {
+ if (st.st_mode & (1<<i)) perms[9-i] = perm_map[8-i];
+ }
+ if (S_ISLNK(st.st_mode)) perms[0] = 'l';
+ if (S_ISDIR(st.st_mode)) perms[0] = 'd';
+ if (S_ISBLK(st.st_mode)) perms[0] = 'b';
+ if (S_ISCHR(st.st_mode)) perms[0] = 'c';
+ if (S_ISSOCK(st.st_mode)) perms[0] = 's';
+ if (S_ISFIFO(st.st_mode)) perms[0] = 'p';
+
+
+ printf("%s %11.0f %s %s\n",
+ perms,
+ (double)st.st_size, timestring(st.st_mtime), fname);
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+
+ for (i=1; i<argc;i++) {
+ ls_one(argv[i]);
+ }
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+
+#define LOCK_SET 1
+#define LOCK_CLEAR 0
+
+/* a byte range locking function - return 0 on success
+ this functions locks/unlocks 1 byte at the specified offset */
+static int tdb_brlock(int fd, off_t offset, int set, int rw_type, int lck_type)
+{
+ struct flock fl;
+
+ fl.l_type = set==LOCK_SET?rw_type:F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = offset;
+ fl.l_len = 1;
+ fl.l_pid = 0;
+
+ if (fcntl(fd, lck_type, &fl) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+
+main()
+{
+ int fd = open("lcktest.dat", O_RDWR|O_CREAT|O_TRUNC, 0600);
+
+ tdb_brlock(fd, 0, LOCK_SET, F_RDLCK, F_SETLKW);
+
+ if (fork()) {
+ /* parent */
+ close(fd);
+
+ fd = open("lcktest.dat", O_RDWR, 0600);
+
+ if (tdb_brlock(fd, 0, LOCK_SET, F_WRLCK, F_SETLKW) == 0) {
+ printf("child doesn't hold lock\n");
+ } else {
+ printf("child does hold lock\n");
+ }
+ }
+ sleep(2);
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+
+#define FNAME "locktest.dat"
+
+#ifdef GLIBC_HACK_FCNTL64
+/* this is a gross hack. 64 bit locking is completely screwed up on
+ i386 Linux in glibc 2.1.95 (which ships with RedHat 7.0). This hack
+ "fixes" the problem with the current 2.4.0test kernels
+*/
+
+#define fcntl fcntl64
+#undef F_SETLKW
+#undef F_SETLK
+#define F_SETLK 13
+#define F_SETLKW 14
+
+#include <asm/unistd.h>
+int fcntl64(int fd, int cmd, struct flock * lock)
+{
+ return syscall(__NR_fcntl64, fd, cmd, lock);
+}
+#endif /* HACK_FCNTL64 */
+
+
+static pid_t child_pid;
+
+typedef unsigned long long ull;
+
+static int brlock(int fd, off_t offset, size_t len, int set, int rw_type, int lck_type)
+{
+ struct flock fl;
+
+ fl.l_type = set?rw_type:F_UNLCK;
+ fl.l_whence = SEEK_SET;
+ fl.l_start = offset;
+ fl.l_len = len;
+ fl.l_pid = 0;
+
+ if (fcntl(fd, lck_type, &fl) != 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static void child_main(int pfd)
+{
+ int fd;
+ off_t ofs;
+ size_t len;
+ int ret;
+ char line[1000];
+ struct stat st;
+
+ while ((fd = open(FNAME,O_RDWR)) == -1) sleep(1);
+
+ while (1) {
+ read(pfd, &ofs, sizeof(ofs));
+ read(pfd, &len, sizeof(len));
+
+ /* check that we can't lock that range */
+ if (brlock(fd, ofs, len, 1, F_WRLCK, F_SETLK) == 0) {
+ printf("ERROR: able to lock range %lld:%lld\n", (ull)ofs, (ull)len);
+ goto failed;
+ }
+
+ /* but we should be able to lock just before and after it */
+ if (brlock(fd, ofs+len, 1, 1, F_WRLCK, F_SETLK) == -1) {
+ printf("ERROR: unable to lock range %lld:%lld\n", (ull)ofs+len, (ull)1);
+ goto failed;
+ }
+ if (brlock(fd, ofs-1, 1, 1, F_WRLCK, F_SETLK) == -1) {
+ printf("ERROR: unable to lock range %lld:%lld\n", (ull)ofs-1, (ull)1);
+ goto failed;
+ }
+
+ /* and remove them again */
+ if (brlock(fd, ofs+len, 1, 0, F_WRLCK, F_SETLK) == -1) {
+ printf("ERROR: unable to unlock range %lld:%lld\n", (ull)ofs+len, (ull)1);
+ goto failed;
+ }
+ if (brlock(fd, ofs-1, 1, 0, F_WRLCK, F_SETLK) == -1) {
+ printf("ERROR: unable to unlock range %lld:%lld\n", (ull)ofs-1, (ull)1);
+ goto failed;
+ }
+
+ /* seems OK */
+ ret = 0;
+ write(pfd, &ret, sizeof(ret));
+ }
+
+ failed:
+
+ fstat(fd, &st);
+ snprintf(line, sizeof(line), "egrep POSIX.*%u /proc/locks", (int)st.st_ino);
+ system(line);
+
+ ret = -1;
+ write(pfd, &ret, sizeof(ret));
+ sleep(10);
+ exit(1);
+}
+
+static void parent_main(int pfd)
+{
+ int fd = open(FNAME,O_RDWR|O_CREAT|O_TRUNC, 0600);
+ off_t ofs;
+ size_t len;
+ int ret, i;
+ struct {
+ off_t ofs;
+ size_t len;
+ } tests[] = {
+ {7, 1},
+ {1<<30, 1<<25},
+#if (_FILE_OFFSET_BITS == 64)
+ {1LL<<40, 1<<10},
+ {1LL<<61, 1<<30},
+ {(1LL<<62) - 10, 1},
+#endif
+ };
+
+
+ if (fd == -1) {
+ perror(FNAME);
+ goto failed;
+ }
+
+ for (i=0;i<sizeof(tests)/sizeof(tests[0]); i++) {
+ ofs = tests[i].ofs;
+ len = tests[i].len;
+
+ if (brlock(fd, ofs, len, 1, F_WRLCK, F_SETLK) == -1) {
+ printf("lock 1 failed\n");
+ goto failed;
+ }
+
+ write(pfd, &ofs, sizeof(ofs));
+ write(pfd, &len, sizeof(len));
+
+ read(pfd, &ret, sizeof(ret));
+ if (ret != 0) {
+ printf("child reported failure\n");
+ goto failed;
+ }
+
+ printf("test %d OK\n", i);
+ }
+ printf("all tests OK\n");
+ kill(child_pid, SIGKILL);
+ waitpid(child_pid, NULL, 0);
+ return;
+
+ failed:
+ kill(child_pid, SIGKILL);
+ waitpid(child_pid, NULL, 0);
+ exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int pfd[2];
+
+ socketpair(AF_UNIX, SOCK_STREAM, 0, pfd);
+
+ if ((child_pid=fork()) == 0) {
+ close(pfd[0]);
+ child_main(pfd[1]);
+ } else {
+ close(pfd[1]);
+ parent_main(pfd[0]);
+ }
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+
+typedef int BOOL;
+typedef char pstring[1024];
+#define True 1
+#define False 0
+#define DEBUG(l,x)
+
+/****************************************************************************
+line strncpy but always null terminates. Make sure there is room!
+****************************************************************************/
+char *StrnCpy(char *dest,char *src,int n)
+{
+ char *d = dest;
+ while (n-- && (*d++ = *src++)) ;
+ *d = 0;
+ return(dest);
+}
+
+/*******************************************************************
+ convert a string to upper case
+********************************************************************/
+void strupper(char *s)
+{
+ while (*s)
+ {
+#ifdef KANJI
+ if (is_shift_jis (*s)) {
+ s += 2;
+ } else if (is_kana (*s)) {
+ s++;
+ } else {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
+#else
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+#endif
+ }
+}
+
+
+static char *map_filename(char *s, /* This is null terminated */
+ char *pattern, /* This isn't. */
+ int len) /* This is the length of pattern. */
+{
+ static pstring matching_bit; /* The bit of the string which matches */
+ /* a * in pattern if indeed there is a * */
+ char *sp; /* Pointer into s. */
+ char *pp; /* Pointer into p. */
+ char *match_start; /* Where the matching bit starts. */
+ pstring pat;
+
+ StrnCpy(pat, pattern, len); /* Get pattern into a proper string! */
+ strcpy(matching_bit,""); /* Match but no star gets this. */
+ pp = pat; /* Initialise the pointers. */
+ sp = s;
+ if ((len == 1) && (*pattern == '*')) {
+ return NULL; /* Impossible, too ambiguous for */
+ /* words! */
+ }
+
+ while ((*sp) /* Not the end of the string. */
+ && (*pp) /* Not the end of the pattern. */
+ && (*sp == *pp) /* The two match. */
+ && (*pp != '*')) { /* No wildcard. */
+ sp++; /* Keep looking. */
+ pp++;
+ }
+ if (!*sp && !*pp) /* End of pattern. */
+ return matching_bit; /* Simple match. Return empty string. */
+ if (*pp == '*') {
+ pp++; /* Always interrested in the chacter */
+ /* after the '*' */
+ if (!*pp) { /* It is at the end of the pattern. */
+ StrnCpy(matching_bit, s, sp-s);
+ return matching_bit;
+ } else {
+ /* The next character in pattern must match a character further */
+ /* along s than sp so look for that character. */
+ match_start = sp;
+ while ((*sp) /* Not the end of s. */
+ && (*sp != *pp)) /* Not the same */
+ sp++; /* Keep looking. */
+ if (!*sp) { /* Got to the end without a match. */
+ return NULL;
+ } else { /* Still hope for a match. */
+ /* Now sp should point to a matching character. */
+ StrnCpy(matching_bit, match_start, sp-match_start);
+ /* Back to needing a stright match again. */
+ while ((*sp) /* Not the end of the string. */
+ && (*pp) /* Not the end of the pattern. */
+ && (*sp == *pp)) { /* The two match. */
+ sp++; /* Keep looking. */
+ pp++;
+ }
+ if (!*sp && !*pp) /* Both at end so it matched */
+ return matching_bit;
+ else
+ return NULL;
+ }
+ }
+ }
+ return NULL; /* No match. */
+}
+
+
+static void do_fwd_mangled_map(char *s, char *MangledMap)
+{
+ /* MangledMap is a series of name pairs in () separated by spaces.
+ * If s matches the first of the pair then the name given is the
+ * second of the pair. A * means any number of any character and if
+ * present in the second of the pair as well as the first the
+ * matching part of the first string takes the place of the * in the
+ * second.
+ *
+ * I wanted this so that we could have RCS files which can be used
+ * by UNIX and DOS programs. My mapping string is (RCS rcs) which
+ * converts the UNIX RCS file subdirectory to lowercase thus
+ * preventing mangling.
+ */
+ char *start=MangledMap; /* Use this to search for mappings. */
+ char *end; /* Used to find the end of strings. */
+ char *match_string;
+ pstring new_string; /* Make up the result here. */
+ char *np; /* Points into new_string. */
+
+ DEBUG(5,("Mangled Mapping '%s' map '%s'\n", s, MangledMap));
+ while (*start) {
+ while ((*start) && (*start != '('))
+ start++;
+ start++; /* Skip the ( */
+ if (!*start)
+ continue; /* Always check for the end. */
+ end = start; /* Search for the ' ' or a ')' */
+ DEBUG(5,("Start of first in pair '%s'\n", start));
+ while ((*end) && !((*end == ' ') || (*end == ')')))
+ end++;
+ if (!*end) {
+ start = end;
+ continue; /* Always check for the end. */
+ }
+ DEBUG(5,("End of first in pair '%s'\n", end));
+ if ((match_string = map_filename(s, start, end-start))) {
+ DEBUG(5,("Found a match\n"));
+ /* Found a match. */
+ start = end+1; /* Point to start of what it is to become. */
+ DEBUG(5,("Start of second in pair '%s'\n", start));
+ end = start;
+ np = new_string;
+ while ((*end) /* Not the end of string. */
+ && (*end != ')') /* Not the end of the pattern. */
+ && (*end != '*')) /* Not a wildcard. */
+ *np++ = *end++;
+ if (!*end) {
+ start = end;
+ continue; /* Always check for the end. */
+ }
+ if (*end == '*') {
+ strcpy(np, match_string);
+ np += strlen(match_string);
+ end++; /* Skip the '*' */
+ while ((*end) /* Not the end of string. */
+ && (*end != ')') /* Not the end of the pattern. */
+ && (*end != '*')) /* Not a wildcard. */
+ *np++ = *end++;
+ }
+ if (!*end) {
+ start = end;
+ continue; /* Always check for the end. */
+ }
+ *np++ = '\0'; /* NULL terminate it. */
+ DEBUG(5,("End of second in pair '%s'\n", end));
+ strcpy(s, new_string); /* Substitute with the new name. */
+ DEBUG(5,("s is now '%s'\n", s));
+ }
+ start = end; /* Skip a bit which cannot be wanted */
+ /* anymore. */
+ start++;
+ }
+}
+
+
+main(int argc,char *argv[])
+{
+ char name[100];
+
+ strcpy(name,argv[2]);
+
+ do_fwd_mangled_map(name,argv[1]);
+ printf("name=%s\n",name);
+}
--- /dev/null
+/*
+** Assumptions:
+**
+** + dst and src are 8-byte aligned.
+** + Copying at least 8 bytes of data
+*/
+
+void
+dlmemcpy(char *dst, char *src, int nbytes)
+ {
+
+ __asm__("
+ pushal
+ movl %0,%%edi
+ movl %1,%%esi
+ movl %2,%%eax
+ movl %%eax,%%ecx
+ and $7, %%eax
+ shr $3, %%ecx
+.align 32
+1:
+ fldl (%%esi)
+ fstpl (%%edi)
+ add $8,%%esi
+ add $8,%%edi
+ dec %%ecx
+ jne 1b
+2:
+ movl %%eax,%%ecx
+ rep
+ movsb
+ popal
+ " :: "g"(dst), "g"(src), "g"(nbytes));
+
+ }
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#define LEN 0x1000
+#define ADDR 0x0
+#define SIZE 8*1024
+
+int main()
+{
+ int fdpair[2];
+ int fd, i=0;
+ int mapfd, status;
+ char *map;
+ char buf[LEN];
+ char lastbuf[LEN];
+
+ fd = open("mem.dat", O_WRONLY|O_CREAT|O_TRUNC, 0600);
+ if (fd == -1) {
+ perror("open");
+ exit(1);
+ }
+
+ mapfd = open("/dev/zero", O_RDWR);
+ if (mapfd == -1) {
+ perror("open");
+ exit(1);
+ }
+
+ map = mmap(0, SIZE*LEN, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE,
+ mapfd, 0);
+
+ while (i < SIZE && pipe(fdpair) == 0) {
+ if (fork()) {
+ memset(buf,'Z', LEN);
+ if (read(fdpair[0], buf, LEN) != LEN) {
+ perror("read");
+ exit(1);
+ }
+ if (memcmp(lastbuf,buf,LEN)) {
+ if (write(fd,buf,LEN) != LEN) {
+ perror("write");
+ exit(1);
+ } else {
+ printf(".");
+ fflush(stdout);
+ }
+ }
+ memcpy(lastbuf, buf, LEN);
+ waitpid(-1, &status, 0);
+ } else {
+ if (write(fdpair[1],ADDR,LEN) != LEN) {
+ perror("write");
+ exit(1);
+ }
+ _exit(0);
+ }
+ close(fdpair[0]);
+ close(fdpair[1]);
+
+ map[i*LEN] = i++;
+ }
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ int *buf;
+ int size;
+ int i, count;
+
+ if (argc < 2) {
+ printf("memtest <size>\n");
+ exit(1);
+ }
+
+ size = atoi(argv[1]);
+
+ buf = (int *)malloc(size);
+
+ size /= sizeof(*buf);
+
+ count = 0;
+
+ for (i=0;i<size;i++)
+ buf[i] = i;
+
+ while (count < (1<<30)) {
+ i = random() % size;
+
+ if (buf[i] != i)
+ printf("\nbuf[%d]=%d\n", i, buf[i]);
+
+ count++;
+ if (count % 100000 == 0)
+ printf("%d\r", count);
+ fflush(stdout);
+
+ buf[i] = i;
+ }
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netdb.h>
+
+#include <signal.h>
+
+#include <errno.h>
+
+
+int FROM = 6005;
+int TO = 6000;
+char host_name[100];
+struct hostent *hp;
+struct sockaddr_in sock_in;
+struct sockaddr_in sock_out;
+int s;
+struct sockaddr in_addr;
+int in_addrlen;
+int in_fd,out_fd;
+#define BUFSIZE 4096
+char buffer[BUFSIZE];
+
+void transfer(int from,int to)
+{
+ int num_ready,num_read,ret;
+ ioctl(from, FIONREAD, &num_ready);
+
+
+ num_read = read(from,buffer,num_ready<BUFSIZE?num_ready:BUFSIZE);
+
+ if (num_read == 0)
+ {
+ fprintf(stderr,"read 0 bytes. exiting.\n");
+ exit(0);
+ }
+
+ ret = write(to,buffer,num_read);
+
+ if (ret < 0)
+ perror("(child) write");
+
+ fprintf(stderr,"transfer(%d,%d): %d:%d\n",from,to,num_ready,ret);
+}
+
+
+int main(int argc,char *argv[])
+{
+
+ if (argc < 3)
+ {
+ printf("Usage: netpipe <from_port> <to_port>\n");
+ return 0;
+ }
+
+ FROM = atoi(argv[1]);
+ TO = atoi(argv[2]);
+
+ /* get my host name */
+ if (gethostname(host_name, sizeof(host_name)) == -1)
+ {
+ perror("gethostname");
+ return -1;
+ }
+
+ /* get host info */
+ if ((hp = gethostbyname(host_name)) == 0)
+ {
+ /* Probly doesn't run TCP/IP. oh well. */
+ fprintf(stderr, "Gethostbyname: Unknown host.\n");
+ return -1;
+ }
+
+ memset(&sock_in, 0, sizeof(sock_in));
+ memcpy(&sock_in.sin_addr, hp->h_addr, hp->h_length);
+ sock_in.sin_port = htons( FROM );
+ sock_in.sin_family = hp->h_addrtype;
+ sock_in.sin_addr.s_addr = INADDR_ANY;
+ s = socket(hp->h_addrtype, SOCK_STREAM, 0);
+ if (s == -1)
+ {
+ perror("socket");
+ return -1;
+ }
+
+ /* now we've got a socket - we need to bind it */
+ while (bind(s, (struct sockaddr * ) &sock_in,sizeof(sock_in)) < 0)
+ {
+ perror("bind");
+ close(s);
+ return -1;
+ }
+
+ /* ready to listen */
+ if (listen(s, 5) == -1)
+ {
+ perror("listen");
+ close(s);
+ return -1;
+ }
+
+
+ /* now accept incoming connections - forking a new process
+ for each incoming connection */
+ fprintf(stderr,"waiting for a connection\n");
+ while (in_fd = accept(s,&in_addr,&in_addrlen))
+ {
+ if (fork()==0)
+ {
+ fprintf(stderr,"child is starting in_fd=%d\n",in_fd);
+
+ /* create a socket to write to */
+ out_fd = socket(hp->h_addrtype, SOCK_STREAM, 0);
+ if (out_fd == -1)
+ {
+ perror("(child) socket");
+ return -1;
+ }
+
+ /* and connect it to the destination */
+ sock_out = sock_in;
+ sock_out.sin_port = htons(TO);
+ if (connect(out_fd,(struct sockaddr *)&sock_out,sizeof(sock_out))<0)
+ {
+ perror("(child) connect");
+ close(out_fd);
+ return -1;
+ }
+
+ /* now just do some reading and writing */
+ fprintf(stderr,"(child) entering select loop\n");
+ while (1)
+ {
+ fd_set fds;
+ int select_ret;
+
+ FD_ZERO(&fds);
+ FD_SET(in_fd, &fds);
+ FD_SET(out_fd, &fds);
+
+ if ((select_ret = select(255,&fds,NULL,NULL,NULL)) <= 0)
+ {
+ perror("(child) select");
+ close(in_fd);
+ close(out_fd);
+ return -1;
+ }
+
+ if (FD_ISSET(in_fd, &fds))
+ transfer(in_fd,out_fd);
+
+ if (FD_ISSET(out_fd, &fds))
+ transfer(out_fd,in_fd);
+
+ }
+
+ }
+ }
+
+ fprintf(stderr,"in_fd=%d. exiting.\n",in_fd);
+ close(s);
+}
+
+
+
+
+
+
+
+
+
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+
+static int am_sender;
+
+#define rprintf fprintf
+#define FERROR stderr
+#define exit_cleanup(x) exit(1)
+#define do_fork fork
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+
+#define TOTAL_SIZE (10*1024*1024)
+
+static int write_loop(int fd, char *buf, int size)
+{
+ int total=0;
+
+ while (size) {
+ int n = write(fd, buf, size);
+ if (n <= 0) break;
+ size -= n;
+ buf += n;
+ total += n;
+ }
+ return total;
+}
+
+int piped_child(char *command,int *f_in,int *f_out)
+{
+ int pid;
+ int to_child_pipe[2];
+ int from_child_pipe[2];
+
+ if (pipe(to_child_pipe) < 0 ||
+ pipe(from_child_pipe) < 0) {
+ rprintf(FERROR,"pipe: %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+
+ pid = do_fork();
+ if (pid < 0) {
+ rprintf(FERROR,"fork: %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+ if (pid == 0)
+ {
+ if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+ close(to_child_pipe[1]) < 0 ||
+ close(from_child_pipe[0]) < 0 ||
+ dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
+ rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+ if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
+ if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
+ system(command);
+ exit_cleanup(RERR_IPC);
+ }
+
+ if (close(from_child_pipe[1]) < 0 ||
+ close(to_child_pipe[0]) < 0) {
+ rprintf(FERROR,"Failed to close : %s\n",strerror(errno));
+ exit_cleanup(RERR_IPC);
+ }
+
+ *f_in = from_child_pipe[0];
+ *f_out = to_child_pipe[1];
+
+ return pid;
+}
+
+static void sender(int fin, int fout)
+{
+ int n;
+ char buf[1024];
+ int total = 0;
+
+ while (total < TOTAL_SIZE) {
+ n = read(fin, buf, sizeof(buf));
+ if (n <= 0) {
+ fprintf(stderr,"write error in sender at %d\n", total);
+ break;
+ }
+ write_loop(fout, buf, n);
+ total += n;
+ fprintf(stderr, "-");
+ }
+ fprintf(stderr, "sender done\n");
+}
+
+static void generator(int fd)
+{
+ int n;
+ char buf[1024];
+ int total=0;
+
+ while (total < TOTAL_SIZE) {
+ n = 1 + random() % (sizeof(buf)-1);
+ n = write_loop(fd, buf, n);
+ if (n <= 0) {
+ fprintf(stderr,"write error in generator at %d\n", total);
+ break;
+ }
+ total += n;
+ fprintf(stderr, "*");
+ }
+ fprintf(stderr, "generator done\n");
+}
+
+static void receiver(int fd)
+{
+ ssize_t n;
+ ssize_t total=0;
+ char buf[1024];
+
+ while (total < TOTAL_SIZE) {
+ n = read(fd, buf, sizeof(buf));
+ if (n <= 0) {
+ fprintf(stderr,"read error in receiver\n");
+ break;
+ }
+ total += n;
+ fprintf(stderr, "+");
+ }
+ fprintf(stderr, "receiver done\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int c, f_in, f_out;
+
+ while ((c = getopt(argc, argv, "s")) != -1) {
+ switch (c){
+ case 's':
+ am_sender = 1;
+ break;
+ }
+ }
+
+ if (am_sender) {
+ sender(0, 1);
+ } else {
+ char *command = argv[1];
+ printf("running %s\n", command);
+ piped_child(command, &f_in, &f_out);
+ if (fork()) {
+ generator(f_out);
+ } else {
+ receiver(f_in);
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+
+main()
+{
+ struct in_addr ip;
+
+ ip.s_addr = 0x12345678;
+
+ if (strcmp(inet_ntoa(ip),"18.52.86.120") != 0 &&
+ strcmp(inet_ntoa(ip),"120.86.52.18") != 0) {
+ fprintf(stderr,"broken inet_ntoa\n");
+ exit(0);
+ }
+
+ /* not a broken inet_ntoa */
+ exit(1);
+}
--- /dev/null
+#include <stdio.h>
+
+main(int argc,char *argv[])
+{
+ char *s = "Press any key to continue....";
+ if (argc > 1)
+ s = argv[1];
+ puts(s);
+ getc(stdin);
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/*******************************************************************
+find the difference in milliseconds between two struct timeval
+values
+********************************************************************/
+int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
+{
+ return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
+ ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
+}
+
+/*******************************************************************
+sleep for a specified number of milliseconds
+********************************************************************/
+void msleep(int t)
+{
+ int tdiff=0;
+ struct timeval tval,t1,t2;
+
+ gettimeofday(&t1, NULL);
+ gettimeofday(&t2, NULL);
+
+ while (tdiff < t) {
+ tval.tv_sec = (t-tdiff)/1000;
+ tval.tv_usec = 1000*((t-tdiff)%1000);
+
+ errno = 0;
+ select(0,NULL,NULL, NULL, &tval);
+
+ gettimeofday(&t2, NULL);
+ tdiff = TvalDiff(&t1,&t2);
+ }
+}
+
+/****************************************************************************
+Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
+else
+if SYSV use O_NDELAY
+if BSD use FNDELAY
+****************************************************************************/
+int set_blocking(int fd, int set)
+{
+ int val;
+#ifdef O_NONBLOCK
+#define FLAG_TO_SET O_NONBLOCK
+#else
+#ifdef SYSV
+#define FLAG_TO_SET O_NDELAY
+#else /* BSD */
+#define FLAG_TO_SET FNDELAY
+#endif
+#endif
+
+ if((val = fcntl(fd, F_GETFL, 0)) == -1)
+ return -1;
+ if(set) /* Turn blocking on - ie. clear nonblock flag */
+ val &= ~FLAG_TO_SET;
+ else
+ val |= FLAG_TO_SET;
+ return fcntl( fd, F_SETFL, val);
+#undef FLAG_TO_SET
+}
+
+
+int main()
+{
+ int fdpair[2];
+ char buf[512] = {0,};
+
+ pipe(fdpair);
+ if (fork()) {
+ fd_set fds;
+ while (1) {
+ int ret;
+
+ FD_ZERO(&fds);
+ FD_SET(fdpair[1], &fds);
+
+ if (select(10, NULL, &fds, NULL, NULL) == 1) {
+ printf("writing ..\n"); fflush(stdout);
+ ret = write(fdpair[1], buf, sizeof(buf));
+ printf("wrote %d\n", ret); fflush(stdout);
+ }
+ }
+ } else {
+ set_blocking(fdpair[0], 0);
+ while (1) {
+ int ret = read(fdpair[0], buf, 40);
+ msleep(100);
+ }
+ }
+
+ return 0;
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#define BUFSIZE 0x8000
+
+
+struct timeval tp1,tp2;
+
+static void start_timer()
+{
+ gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+ gettimeofday(&tp2,NULL);
+ return((tp2.tv_sec - tp1.tv_sec) +
+ (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+int main(int argc, char *argv[])
+{
+ int fdpair[2];
+ int fd, size, i=0;
+ char buf[BUFSIZE];
+
+ if (argc < 2) {
+ printf("Usage: pipespeed megabytes\n");
+ exit(1);
+ }
+
+ memset(buf,'Z',BUFSIZE);
+
+ size = atoi(argv[1]) * 0x100000;
+
+ fd = open("/dev/null", O_WRONLY);
+ if (fd == -1) {
+ perror("open");
+ exit(1);
+ }
+
+ if (pipe(fdpair) != 0) {
+ perror("pipe");
+ exit(1);
+ }
+
+ if (fork() == 0) {
+ close(fdpair[1]);
+ while (i<size) {
+ int n = read(fdpair[0], buf, BUFSIZE);
+ if (n <= 0) exit(1);
+ write(fd, buf, n);
+ i += n;
+ }
+ exit(0);
+ }
+
+ close(fdpair[0]);
+
+ start_timer();
+
+ while (i<size) {
+ int n = write(fdpair[1], buf, BUFSIZE);
+ if (n <= 0) {
+ printf("pipe write error\n");
+ exit(1);
+ }
+ i += n;
+ }
+
+ printf("%g MB/sec\n", (i/(0x100000))/end_timer());
+
+ return 0;
+}
--- /dev/null
+#include <pwd.h>
+#include <sys/types.h>
+#include <dlfcn.h>
+
+struct passwd *getpwuid(uid_t uid)
+{
+ static void *h;
+ static struct passwd * (*getpwuid_orig)(uid_t uid);
+ if (!h) {
+ h = dlopen("/lib/libc.so.6", RTLD_LAZY);
+ getpwuid_orig = dlsym(h, "getpwuid");
+ }
+
+ return getpwuid_orig(uid+1);
+}
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+#include <dlfcn.h>
+
+void *shmat(int shmid, const void *shmaddr, int shmflag)
+{
+ static void *h;
+ static void *(*shmat_orig)(int , const void *, int );
+ static int count;
+ if (!h) {
+ h = dlopen("/lib/libc.so.6", RTLD_LAZY);
+ shmat_orig = dlsym(h, "shmat");
+ count = atoi(getenv("SHMAT_COUNT"));
+ }
+
+ fprintf(stderr,"shmat(%d, %p, 0x%x)\n", shmid, shmaddr, shmflag);
+
+ if (! count) return NULL;
+
+ count--;
+
+ return shmat_orig(shmid, shmaddr, shmflag);
+}
--- /dev/null
+/* Here is an implementation of these routines for
+ output to Postscript files */
+
+
+
+FILE *outfile;
+
+#define PTS_PER_INCH 72
+#define P_SCALE_X 0.5
+#define P_SCALE_Y 0.5
+#define PAGE_WIDTH 8 /* inches */
+#define PAGE_HEIGHT 8 /* inches */
+#define P_MAXX ((int)(PAGE_WIDTH*PTS_PER_INCH/P_SCALE_X))
+#define P_MAXY ((int)(PAGE_HEIGHT*PTS_PER_INCH/P_SCALE_Y))
+#define P_ORIGIN_X 0
+#define P_ORIGIN_Y 100
+#define P_LINE_WIDTH 1.0
+#define P_FONT "Courier-Bold"
+#define P_FONT_SIZE 12
+#define P_FONT_WIDTH (36.0*P_FONT_SIZE/60)
+#define P_LINE_CAP 0
+#define P_MAC1 "/x { moveto } def"
+#define P_MAC2 "/y { lineto } def"
+#define P_MAC3 "/z { stroke } def"
+
+
+
+void start_graphics()
+{
+/* Start it going */
+ outfile = stdout;
+ fprintf(outfile,"%c!\ninitgraphics\n",'%');
+/* Setup scaling etc. */
+ fprintf(outfile,"%-4.2f %-4.2f scale\n",P_SCALE_X,P_SCALE_Y);
+ fprintf(outfile,"%d %d translate\n",P_ORIGIN_X,P_ORIGIN_Y);
+/* Define some macros */
+ fprintf(outfile,"%s\n%s\n%s\n",P_MAC1,P_MAC2,P_MAC3);
+/* Default text size etc. */
+ fprintf(outfile,"/%s findfont\n",P_FONT);
+ fprintf(outfile,"%d scalefont\n",(int)(P_FONT_SIZE/P_SCALE_X));
+ fprintf(outfile,"setfont\n");
+/* Default line width, style etc. */
+ fprintf(outfile,"%-3.1f setlinewidth\n",P_LINE_WIDTH);
+ fprintf(outfile,"%d setlinecap\n",P_LINE_CAP);
+ fprintf(outfile,"[] 0 setdash\n");
+}
+
+void end_graphics()
+{
+/* display it */
+ fprintf(outfile,"showpage\n");
+/* close file */
+/* fclose(outfile);*/
+}
+
+int get_maxx()
+{
+ return(P_MAXX);
+}
+
+int get_maxy()
+{
+ return(P_MAXY);
+}
+
+int new_y(y)
+int y;
+/* Flip in Y direction to make origin in bottom left */
+{
+ return(get_maxy()-y);
+}
+
+void draw_line(x1,y1,x2,y2)
+int x1,y1,x2,y2;
+{
+ fprintf(outfile,"%d %d x %d %d y z\n",x1,new_y(y1),x2,new_y(y2));
+}
+
+int descender()
+/* Height of descender */
+{
+ return(char_height()/3);
+}
+
+void graph_text(x,y,str)
+int x,y;
+char *str;
+{
+ fprintf(outfile,"%d %d x (%s) show\n",x,new_y(y)+descender(),str);
+}
+
+void choose_line_type(type)
+int type;
+{
+char *dashing;
+double width;
+int index;
+index = type % 6;
+switch (index)
+{
+ case 0 : dashing="[] 0"; width=1.2; break;
+ case 1 : dashing="[6] 0"; width=1.2; break;
+ case 2 : dashing="[4] 1"; width=1.2; break;
+ case 3 : dashing="[] 0"; width=1.8; break;
+ case 4 : dashing="[6] 0"; width=1.8; break;
+ case 5 : dashing="[4] 1"; width=1.8; break;
+}
+ fprintf(outfile,"%-3.1f setlinewidth\n",
+ width*P_LINE_WIDTH);
+ fprintf(outfile,"%s setdash\n",dashing);
+
+}
+
+void wait_for_end()
+{
+}
+
+int char_width()
+{
+ return((int)(P_FONT_WIDTH/P_SCALE_X));
+}
+
+int char_height()
+{
+ return((int)(P_FONT_SIZE/P_SCALE_Y));
+}
+
+/* End of PostScript specific routines */
+
--- /dev/null
+#include <stdio.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+
+
+int pwdauth(char *user,char *password)
+{
+ struct passwd *pass = getpwnam(user);
+ if (!pass) {
+ errno = EINVAL; /* Note: SunOS returns EACCES */
+ return(-1);
+ }
+ if (strcmp(crypt(password,pass->pw_passwd),pass->pw_passwd)) {
+ errno = EACCES;
+ return(-1);
+ }
+ return(0);
+}
+
+int grpauth(char *group,char *password)
+{
+ struct group *grp = getgrnam(user);
+ if (!grp) {
+ errno = EINVAL;
+ return(-1);
+ }
+ if (grp->gr_passwd &&
+ strcmp(crypt(password,grp->gr_passwd),grp->gr_passwd)) {
+ errno = EACCES;
+ return(-1);
+ }
+ return(0);
+}
+
+
+main(int argc,char *argv[])
+{
+ char *pass = getpass("Password: ");
+
+
+ errno=0;
+ printf("res=%d (%s,%s)\n",pwdauth(argv[1],pass),argv[1],pass);
+ printf("errno=%d\n",errno);
+}
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+
+
+unsigned char Data[100001];
+unsigned char keystream[1001];
+int Rpoint[300];
+
+
+main (int argc,char *argv[]) {
+ FILE *fd;
+ int i,j,k;
+ int size;
+ char ch;
+ char *name;
+ int cracked;
+ int sizemask;
+ int maxr;
+ int rsz;
+ int pos;
+ int Rall[300]; /* resource allocation table */
+
+ if (argc<2) {
+ printf("usage: glide filename (username)");
+ exit(1);
+ }
+
+ /* read PWL file */
+
+ fd=fopen(argv[1],"rb");
+ if(fd==NULL) {
+ printf("can't open file %s",argv[2]);
+ exit(1);
+ }
+ size=0;
+ while(!feof(fd)) {
+ Data[size++]=fgetc(fd);
+ }
+ size--;
+ fclose(fd);
+
+ /* find username */
+ name=argv[1];
+ if(argc>2) {
+ name=argv[2];
+ } else {
+ char *p = strrchr(name,'/');
+ if (p) name = p+1;
+ }
+ printf("Username: %s\n",name);
+
+ /* copy encrypted text into keystream */
+ cracked=size-0x0208;
+ if(cracked<0) cracked=0;
+ if(cracked>1000) cracked=1000;
+ memcpy(keystream,Data+0x208,cracked );
+
+ /* generate 20 bytes of keystream */
+ for(i=0;i<20;i++) {
+ ch=toupper(name[i]);
+ if(ch==0) break;
+ if(ch=='.') break;
+ keystream[i]^=ch;
+ };
+ cracked=20;
+
+
+ /* find allocated resources */
+
+ sizemask=keystream[0]+(keystream[1]<<8);
+ printf("Sizemask: %04X\n",sizemask);
+
+ for(i=0;i<256;i++) Rall[i]=0;
+
+ maxr=0;
+ for(i=0x108;i<0x208;i++) {
+ if(Data[i]!=0xff) {
+ Rall[Data[i]]++;
+ if (Data[i]>maxr) maxr=Data[i];
+ }
+ }
+ maxr=(((maxr/16)+1)*16); /* resource pointer table size appears
+to be divisible by 16 */
+
+ /* search after resources */
+
+ Rpoint[0]=0x0208+2*maxr+20+2; /* first resource */
+ for(i=0;i<maxr;i++) {
+ /* find size of current resource */
+ pos=Rpoint[i];
+ rsz=Data[pos]+(Data[pos+1]<<8);
+ rsz^=sizemask;
+ printf("Analyzing block with size:
+%04x\t(%d:%d)\n",rsz,i,Rall[i]);
+ if( (Rall[i]==0) && (rsz!=0) ) {
+ printf("unused resource has nonzero size !!!\n");
+ exit(0);
+ }
+
+ pos+=rsz;
+
+ /* Resources have a tendency to have the wrong size for some
+reason */
+ /* check for correct size */
+
+ if(i<maxr-1) {
+ while(Data[pos+3]!=keystream[1]) {
+ printf(":(%02x)",Data[pos+3]);
+ pos+=2; /* very rude may fail */
+ }
+ }
+
+ pos+=2; /* include pointer in size */
+ Rpoint[i+1]=pos;
+ }
+ Rpoint[maxr]=size;
+
+ /* insert Table data into keystream */
+ for(i=0;i <= maxr;i++) {
+ keystream[20+2*i]^=Rpoint[i] & 0x00ff;
+ keystream[21+2*i]^=(Rpoint[i] >> 8) & 0x00ff;
+ }
+ cracked+=maxr*2+2;
+
+ printf("%d bytes of keystream recovered\n",cracked);
+
+ /* decrypt resources */
+ for(i=0;i < maxr;i++) {
+ rsz=Rpoint[i+1]-Rpoint[i];
+ if (rsz>cracked) rsz=cracked;
+ printf("Resource[%d] (%d)\n",i,rsz);
+ for(j=0;j<rsz;j++) printf("%c",Data[Rpoint[i]+j]^keystream[j]);
+ printf("\n");
+ }
+
+
+ exit(0);
+}
--- /dev/null
+/* quick test of semaphore speed */
+
+/*
+
+Results with the following defines:
+ #define NSEMS 20
+ #define NPROCS 60
+ #define NUMOPS 10000
+
+ OSF1 dominion.aquasoft.com.au V4.0 564 alpha (233 MHz)
+ fcntl: 132.814 secs
+ ipc: 13.5186 secs
+
+ Linux dominion.aquasoft.com.au 2.0.30 (alpha 233 MHz)
+ fcntl: 16.9473 secs
+ ipc: 61.9336 secs
+
+ Linux 2.1.57 on a P120
+ fcntl: 21.3006 secs
+ ipc: 93.9982 secs
+
+ Solaris 2.5 on a Ultra170
+ fcntl: 192.805 secs
+ ipc: 18.6859 secs
+
+ IRIX 6.4 on a Origin200
+ fcntl: 183.488 secs
+ ipc: 10.4431 secs
+
+ SunOS 4.1.3 on a 2 CPU sparc 10
+ fcntl: 198.239 secs
+ ipc: 150.026 secs
+
+ Solaris 2.5.1 on a 4 CPU SPARCsystem-600
+ fcntl: 312.025 secs
+ ipc: 24.5416 secs
+
+ Linux 2.1.131 on K6/200
+ fcntl: 8.27074 secs
+ ipc: 49.7771 secs
+
+ Linux 2.0.34 on P200
+ fcntl: 7.99596 secs
+ ipc: 52.3388 secs
+
+ AIX 4.2 on 2-proc RS6k with 233MHz processors
+ fcntl: 12.4272 secs
+ ipc: 5.41895 secs
+
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/time.h>
+#ifdef HAVE_POSIX_SEM
+#include <semaphore.h>
+#endif
+
+#define NSEMS 20
+#define NPROCS 60
+#define NUMOPS 10000
+
+#define SEMAPHORE_KEY 0x569890
+#define SHM_KEY 0x568698
+
+static int fcntl_fd;
+static int sem_id;
+static int shm_id;
+static int *shm_p;
+static int mypid;
+
+#ifdef HAVE_POSIX_SEM
+static sem_t posix_sems[NSEMS];
+#endif
+
+static int state[NSEMS];
+
+#define BUFSIZE (1024)
+static char buf1[BUFSIZE];
+static char buf2[BUFSIZE];
+
+#ifdef NO_SEMUN
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+};
+#endif
+
+
+static struct timeval tp1,tp2;
+
+static void start_timer()
+{
+ gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+ gettimeofday(&tp2,NULL);
+ return((tp2.tv_sec - tp1.tv_sec) +
+ (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+
+/************************************************************************
+ USING FCNTL LOCKS
+ ***********************************************************************/
+void fcntl_setup(void)
+{
+ fcntl_fd = open("fcntl.locks", O_RDWR | O_CREAT | O_TRUNC, 0600);
+ write(fcntl_fd, state, sizeof(state));
+}
+
+void fcntl_close(void)
+{
+ unlink("fcntl.locks");
+}
+
+void fcntl_sem_lock(int i)
+{
+ struct flock lock;
+ int ret;
+
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = i*sizeof(int);
+ lock.l_len = sizeof(int);
+ lock.l_pid = 0;
+
+ errno = 0;
+
+ if (fcntl(fcntl_fd, F_SETLKW, &lock) != 0) {
+ perror("WRLCK");
+ exit(1);
+ }
+}
+
+void fcntl_sem_unlock(int i)
+{
+ struct flock lock;
+ int ret;
+
+ lock.l_type = F_UNLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = i*sizeof(int);
+ lock.l_len = sizeof(int);
+ lock.l_pid = 0;
+
+ errno = 0;
+
+ if (fcntl(fcntl_fd, F_SETLKW, &lock) != 0) {
+ perror("WRLCK");
+ exit(1);
+ }
+}
+
+
+
+/************************************************************************
+ USING SYSV IPC SEMAPHORES
+ ***********************************************************************/
+void ipc_setup(void)
+{
+ int i;
+ union semun su;
+
+ su.val = 1;
+
+ sem_id = semget(SEMAPHORE_KEY, NSEMS,
+ IPC_CREAT|IPC_EXCL|0600);
+ if (sem_id == -1) {
+ sem_id = semget(SEMAPHORE_KEY, 0, 0);
+ if (sem_id != -1) {
+ semctl(sem_id, 0, IPC_RMID, su);
+ sem_id = semget(SEMAPHORE_KEY, NSEMS,
+ IPC_CREAT|IPC_EXCL|0600);
+ }
+ }
+ if (sem_id == -1) {
+ perror("semget");
+ exit(1);
+ }
+
+ for (i=0;i<NSEMS;i++) {
+ semctl(sem_id, i, SETVAL, su);
+ }
+
+ if (sem_id == -1) {
+ perror("semget");
+ exit(1);
+ }
+}
+
+void ipc_close(void)
+{
+ union semun su;
+ su.val = 1;
+ semctl(sem_id, 0, IPC_RMID, su);
+}
+
+
+void ipc_change(int i, int op)
+{
+ struct sembuf sb;
+ sb.sem_num = i;
+ sb.sem_op = op;
+ sb.sem_flg = 0;
+ if (semop(sem_id, &sb, 1)) {
+ fprintf(stderr,"semop(%d,%d): ", i, op);
+ perror("");
+ exit(1);
+ }
+}
+
+void ipc_sem_lock(int i)
+{
+ ipc_change(i, -1);
+}
+
+void ipc_sem_unlock(int i)
+{
+ ipc_change(i, 1);
+}
+
+
+#ifdef HAVE_POSIX_SEM
+/************************************************************************
+ USING POSIX semaphores
+ ***********************************************************************/
+void posix_setup(void)
+{
+ int i;
+
+ for (i=0;i<NSEMS;i++) {
+ if (sem_init(&posix_sems[i], 1, 1) != 0) {
+ fprintf(stderr,"failed to setup semaphore %d\n", i);
+ break;
+ }
+ }
+}
+
+void posix_close(void)
+{
+ int i;
+
+ for (i=0;i<NSEMS;i++) {
+ if (sem_close(&posix_sems[i]) != 0) {
+ fprintf(stderr,"failed to close semaphore %d\n", i);
+ break;
+ }
+ }
+}
+
+
+void posix_lock(int i)
+{
+ if (sem_wait(&posix_sems[i]) != 0) fprintf(stderr,"failed to get lock %d\n", i);
+}
+
+void posix_unlock(int i)
+{
+ if (sem_post(&posix_sems[i]) != 0) fprintf(stderr,"failed to release lock %d\n", i);
+}
+#endif
+
+
+void test_speed(char *s, void (*lock_fn)(int ), void (*unlock_fn)(int ))
+{
+ int i, j, status;
+ pid_t pids[NPROCS];
+
+ for (i=0;i<NSEMS;i++) {
+ lock_fn(i);
+ }
+
+ for (i=0;i<NPROCS;i++) {
+ pids[i] = fork();
+ if (pids[i] == 0) {
+ mypid = getpid();
+ srandom(mypid ^ time(NULL));
+ for (j=0;j<NUMOPS;j++) {
+ unsigned sem = random() % NSEMS;
+
+ lock_fn(sem);
+ memcpy(buf2, buf1, sizeof(buf1));
+ unlock_fn(sem);
+ memcpy(buf1, buf2, sizeof(buf1));
+ }
+ exit(0);
+ }
+ }
+
+ sleep(1);
+
+ printf("%s: ", s);
+ fflush(stdout);
+
+ start_timer();
+
+ for (i=0;i<NSEMS;i++) {
+ unlock_fn(i);
+ }
+
+ for (i=0;i<NPROCS;i++)
+ waitpid(pids[i], &status, 0);
+
+ printf("%g secs\n", end_timer());
+}
+
+int main(int argc, char *argv[])
+{
+ srandom(getpid() ^ time(NULL));
+
+ printf("NPROCS=%d NSEMS=%d NUMOPS=%d\n", NPROCS, NSEMS, NUMOPS);
+
+
+ fcntl_setup();
+ test_speed("fcntl", fcntl_sem_lock, fcntl_sem_unlock);
+ fcntl_close();
+
+ ipc_setup();
+ test_speed("ipc", ipc_sem_lock, ipc_sem_unlock);
+ ipc_close();
+
+#ifdef HAVE_POSIX_SEM
+ posix_setup();
+ test_speed("posix", posix_lock, posix_unlock);
+ posix_close();
+#endif
+
+ return 0;
+}
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+
+
+main(int argc, char *argv[])
+{
+ sethostid(strtol(argv[1], NULL, 0));
+}
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+
+#if USE_SHM
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+/* return a pointer to a anonymous shared memory segment of size "size"
+ which will persist across fork() but will disappear when all processes
+ exit
+
+ The memory is not zeroed
+
+ This function uses system5 shared memory. It takes advantage of a property
+ that the memory is not destroyed if it is attached when the id is removed
+ */
+void *shm_setup(int size)
+{
+ int shmid;
+ void *ret;
+
+ shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
+ if (shmid == -1) {
+ printf("can't get shared memory\n");
+ exit(1);
+ }
+ ret = (void *)shmat(shmid, 0, 0);
+ if (!ret || ret == (void *)-1) {
+ printf("can't attach to shared memory\n");
+ return NULL;
+ }
+ /* the following releases the ipc, but note that this process
+ and all its children will still have access to the memory, its
+ just that the shmid is no longer valid for other shm calls. This
+ means we don't leave behind lots of shm segments after we exit
+
+ See Stevens "advanced programming in unix env" for details
+ */
+ shmctl(shmid, IPC_RMID, 0);
+
+
+
+ return ret;
+}
+#endif
+
+
+
+#if USE_DEVZERO
+#include <sys/mman.h>
+#include <fcntl.h>
+
+/* return a pointer to a /dev/zero shared memory segment of size "size"
+ which will persist across fork() but will disappear when all processes
+ exit
+
+ The memory is zeroed automatically
+
+ This relies on /dev/zero being shared mmap capable, which it is
+ only under some OSes (Linux 2.1 _not_ included)
+ */
+void *shm_setup(int size)
+{
+ void *ret;
+ int fd;
+
+ fd = open("/dev/zero", O_RDWR);
+ if (fd == -1) {
+ return NULL;
+ }
+ ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE,
+ fd, 0);
+
+ /* note that we don't need to keep the file open */
+ close(fd);
+ if (ret == (void *)-1) return NULL;
+ return ret;
+}
+#endif
+
+
+#if USE_MAPANON
+#include <sys/mman.h>
+
+/* return a pointer to a /dev/zero shared memory segment of size "size"
+ which will persist across fork() but will disappear when all processes
+ exit
+
+ The memory is zeroed automatically
+
+ This relies on anonyous shared mmap, which only some OSes can
+ do. Linux 2.1 is _not_ one of them.
+ */
+void *shm_setup(int size)
+{
+ void *ret;
+ ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED,
+ -1, 0);
+ if (ret == (void *)-1) return NULL;
+ return ret;
+}
+#endif
+
+
+#if USE_MAPFILE
+#include <sys/mman.h>
+#include <fcntl.h>
+
+/* return a pointer to a /dev/zero shared memory segment of size "size"
+ which will persist across fork() but will disappear when all processes
+ exit
+
+ The memory is zeroed automatically
+
+ This relies only on shared mmap, which almost any mmap capable OS
+ can do. Linux can do this as of version 1.2 (I believe). certainly
+ all recent versions can do it.
+ */
+void *shm_setup(int size)
+{
+ void *ret;
+ int fd, zero=0;
+ char template[20] = "/tmp/shm.XXXXXX";
+
+ /* mkstemp() isn't really portable but use it if it exists as
+ otherwise you are open to some nasty soft-link /tmp based
+ hacks */
+ fd = mkstemp(template);
+ if (fd == -1) {
+ return NULL;
+ }
+ lseek(fd, size, SEEK_SET);
+ write(fd, &zero, sizeof(zero));
+ ret = mmap(0, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED,
+ fd, 0);
+ close(fd);
+ unlink(template);
+ if (ret == (void *)-1) return NULL;
+ return ret;
+}
+#endif
+
+
+int main(int argc, char *argv[])
+{
+ volatile char *buf;
+ int size;
+ pid_t child, parent;
+
+ if (argc < 2) {
+ printf("shm_sample <size>\n");
+ exit(1);
+ }
+
+ size = atoi(argv[1]);
+
+ buf = shm_setup(size);
+
+ if (!buf) {
+ printf("shm_setup(%d) failed\n", size);
+ exit(1);
+ }
+ memset(buf, 0, sizeof(int));
+
+ parent = getpid();
+ child = fork();
+
+ if (!child) {
+ *(int *)buf = parent;
+ return 0;
+ }
+
+ waitpid(child, 0, 0);
+
+ if (*(int *)buf == 0) {
+ printf("memory not shared?\n");
+ } else {
+ printf("pid via shm is %d real pid is %d\n",
+ *(int *)buf, parent);
+ }
+
+ return 0;
+}
+
--- /dev/null
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+void *shm_setup(int size)
+{
+ int shmid;
+ void *ret;
+
+ shmid = shmget(IPC_PRIVATE, size, SHM_R | SHM_W);
+ if (shmid == -1) {
+ printf("can't get shared memory\n");
+ exit(1);
+ }
+ ret = (void *)shmat(shmid, 0, 0);
+ if (!ret || ret == (void *)-1) {
+ printf("can't attach to shared memory\n");
+ return NULL;
+ }
+ /* the following releases the ipc, but note that this process
+ and all its children will still have access to the memory, its
+
+ means we don't leave behind lots of shm segments after we exit
+
+ See Stevens "advanced programming in unix env" for details
+ */
+ shmctl(shmid, IPC_RMID, 0);
+
+
+
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ volatile char *buf;
+ int size;
+
+ if (argc < 2) {
+ printf("shm_size <size>\n");
+ exit(1);
+ }
+
+ size = atoi(argv[1]);
+
+ buf = shm_setup(size);
+
+ if (!buf) {
+ printf("shm_setup(%d) failed\n", size);
+ exit(1);
+ }
+ return 0;
+}
+
--- /dev/null
+#include <stdio.h>
+#include <sys/types.h>
+
+main()
+{
+ printf("char : %d\n", sizeof(char));
+ printf("short : %d\n", sizeof(short));
+ printf("int : %d\n", sizeof(int));
+ printf("long : %d\n", sizeof(long));
+ printf("long long : %d\n", sizeof(long long));
+ printf("int * : %d\n", sizeof(int *));
+ printf("time_t : %d\n", sizeof(time_t));
+ printf("off_t : %d\n", sizeof(off_t));
+ printf("uid_t : %d\n", sizeof(uid_t));
+}
--- /dev/null
+/* convert a snoop capture file to a netmon .cap file.
+ by Seiichi Tatsukawa (stat@rational.com), March 1998.
+
+ Based on capconvert.c by Andrew Tridgell, October 1997
+
+ This only works for 32 bit boxes at the moment. Change the typedefs
+ to work on other sytems
+*/
+
+#include <stdlib.h>
+#ifdef WIN32
+#include <io.h>
+#else
+#include <unistd.h>
+#endif
+#include <memory.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <time.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+
+/* change the following 3 lines to make things work on
+ systems with different word sizes */
+typedef int int32;
+typedef unsigned int uint32;
+typedef unsigned short uint16;
+
+
+/* #define _DEBUG 1 */
+
+#define SNOOP_MAGIC "snoop\0\0\0"
+
+#ifndef WIN32
+#define O_BINARY 0
+#else
+#pragma pack(push)
+#pragma pack(1)
+
+struct timeval {
+ uint32 tv_sec; /* seconds */
+ int32 tv_usec; /* and microseconds */
+};
+#endif
+
+/* snoop file format */
+struct snoop_file_header {
+ union {
+ uint32 m[2];
+ char magic[8];
+ } u;
+ uint16 major;
+ uint16 minor;
+ uint32 linktype;
+};
+
+struct snoop_packet {
+ uint32 caplen;
+ uint32 len;
+ uint32 offset;
+ uint32 pad1;
+ struct timeval ts;
+};
+
+
+/* .cap file format */
+typedef struct _systemtime {
+ uint16 wYear;
+ uint16 wMonth;
+ uint16 wDayOfWeek;
+ uint16 wDay;
+ uint16 wHour;
+ uint16 wMinute;
+ uint16 wSecond;
+ uint16 wMilliseconds;
+} systemtime_t;
+
+struct cap_header {
+ char rtss[4];
+ char minor;
+ char major;
+ uint16 captype;
+ systemtime_t starttime;
+ uint32 frameoffset;
+ uint32 framelength;
+ uint32 unknown[24];
+};
+
+struct cap_packet {
+ uint32 cap_time; /* milliseconds */
+ uint16 len;
+ uint16 caplen;
+};
+
+#ifdef WIN32
+#pragma pack(pop)
+#endif
+
+/* file format is:
+ header
+ frames
+ frameoffsets
+ */
+
+
+static void swap_uint32(uint32 *x)
+{
+ char c, *p = (char *)x;
+ c = p[0]; p[0] = p[3]; p[3] = c;
+ c = p[1]; p[1] = p[2]; p[2] = c;
+}
+
+static void swap_int32(int32 *x)
+{
+ char c, *p = (char *)x;
+ c = p[0]; p[0] = p[3]; p[3] = c;
+ c = p[1]; p[1] = p[2]; p[2] = c;
+}
+
+static void swap_uint16(uint16 *x)
+{
+ char c, *p = (char *)x;
+ c = p[0]; p[0] = p[1]; p[1] = c;
+}
+
+
+static void swap_netmon_header(struct cap_header *h)
+{
+ swap_uint16(&h->captype);
+ swap_uint16(&h->starttime.wYear);
+ swap_uint16(&h->starttime.wMonth);
+ swap_uint16(&h->starttime.wDayOfWeek);
+ swap_uint16(&h->starttime.wDay);
+ swap_uint16(&h->starttime.wHour);
+ swap_uint16(&h->starttime.wMinute);
+ swap_uint16(&h->starttime.wSecond);
+ swap_uint16(&h->starttime.wMilliseconds);
+ swap_uint32(&h->frameoffset);
+ swap_uint32(&h->framelength);
+}
+
+static void swap_netmon_packet(struct cap_packet *p)
+{
+ swap_uint32(&p->cap_time);
+ swap_uint16(&p->len);
+ swap_uint16(&p->caplen);
+}
+
+static void swap_snoop_header(struct snoop_file_header *h)
+{
+ swap_uint16(&h->major);
+ swap_uint16(&h->minor);
+ swap_uint32(&h->linktype);
+}
+
+static void swap_snoop_packet(struct snoop_packet *p)
+{
+ swap_uint32(&p->caplen);
+ swap_uint32(&p->len);
+ swap_uint32(&p->offset);
+ swap_uint32(&((p->ts).tv_sec));
+ swap_int32(&((p->ts).tv_usec));
+}
+
+int convert_snoop_to_cap(char *infile, char *outfile)
+{
+ int i;
+ int fd1, fd2;
+ int snaplen;
+ int offsetlen;
+ struct snoop_file_header snoop_header;
+ struct snoop_packet snoop_pkt;
+ char *data;
+ struct cap_header cap_header;
+ struct cap_packet cap_pkt;
+ struct timeval tval1;
+ char pad[4];
+ int swap_snoop = 0;
+ int swap_netmon = 0;
+ struct tm *starttm;
+ uint32 foffset;
+ FILE *tmpf;
+ int fd3;
+ int j;
+
+ fd1 = open(infile, O_RDONLY | O_BINARY);
+ if (fd1 == -1) {
+ perror(infile);
+ exit(1);
+ }
+
+ fd2 = open(outfile, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
+ if (fd2 == -1) {
+ perror(outfile);
+ exit(1);
+ }
+
+ if ((tmpf = tmpfile()) == NULL) {
+ perror("tmpfile()");
+ exit(1);
+ }
+ fd3 = fileno(tmpf);
+ if (fd3 == -1) {
+ perror("tmpfile()");
+ exit(1);
+ }
+
+ if (read(fd1, &snoop_header, sizeof(snoop_header)) !=
+ sizeof(snoop_header)) {
+ printf("can't read snoop header\n");
+ return 0;
+ }
+
+ /* snoop files can be in either byte order. */
+ if (memcmp(snoop_header.u.magic, SNOOP_MAGIC, 8) != 0) {
+ printf("bad magic number %x\n", snoop_header.u.magic);
+ return 0;
+ }
+
+ if (snoop_header.u.m[1] == 'p') {
+ swap_snoop = 1;
+ swap_snoop_header(&snoop_header);
+#if _DEBUG
+ fprintf(stderr, "Bytes swapping snoop file.\n");
+#endif
+ }
+
+ /* check if we are little endian. If not, we need to
+ convert the network monitor output */
+ i=1;
+ if (((char *)&i)[0] != 1) {
+ swap_netmon = 1;
+#if _DEBUG
+ fprintf(stderr, "Bytes swapping cap file.\n");
+#endif
+ }
+
+ /* setup the basic netmon header */
+ memset(&cap_header, 0, sizeof(cap_header));
+ strcpy(cap_header.rtss, "RTSS");
+ cap_header.minor = 1;
+ cap_header.major = 1;
+ cap_header.captype = 1; /* snoop_header.linktype; */
+
+ /* write it out. we will have to write it again once
+ we've worked out the rest of the parameters */
+ write(fd2, &cap_header, sizeof(cap_header));
+
+ /* snaplen = snoop_header.snaplen; */
+ snaplen = 4500;
+
+ printf("snoop-%d.%d linktype=%d\n",
+ snoop_header.major, snoop_header.minor,
+ snoop_header.linktype);
+
+ data = (char *)malloc(snaplen);
+
+ memset(pad, 0, sizeof(pad));
+
+ for (i=0; 1 ; i++) {
+ if (read(fd1, &snoop_pkt, sizeof(snoop_pkt)) !=
+ sizeof(snoop_pkt))
+ break;
+
+ if (swap_snoop)
+ swap_snoop_packet(&snoop_pkt);
+
+ if (i == 0)
+ tval1 = snoop_pkt.ts;
+
+ if (read(fd1, data, snoop_pkt.caplen) != snoop_pkt.caplen)
+ break;
+
+#if _DEBUG
+ fprintf(stderr, "frame %d of length=%d:%d\n",
+ i+1, snoop_pkt.caplen, snoop_pkt.len);
+#endif
+ offsetlen = snoop_pkt.offset -
+ (sizeof(snoop_pkt) + snoop_pkt.caplen);
+ if (offsetlen > 0)
+ lseek(fd1, offsetlen, SEEK_CUR);
+
+ if (snoop_pkt.caplen > snoop_pkt.len)
+ snoop_pkt.caplen = snoop_pkt.len;
+
+ foffset = lseek(fd2, 0, SEEK_CUR);
+
+ cap_pkt.cap_time = (snoop_pkt.ts.tv_sec - tval1.tv_sec)*1000 +
+ (snoop_pkt.ts.tv_usec - tval1.tv_usec)/1000;
+ cap_pkt.caplen = snoop_pkt.caplen;
+ cap_pkt.len = snoop_pkt.len;
+
+ if (swap_netmon)
+ swap_netmon_packet(&cap_pkt);
+
+ write(fd2, &cap_pkt, sizeof(cap_pkt));
+ write(fd2, data, snoop_pkt.caplen);
+ write(fd3, &foffset, sizeof(foffset));
+
+ if (snoop_pkt.caplen % 4 != 0) {
+ write(fd2, pad, 4 - (snoop_pkt.caplen % 4));
+ }
+
+#if _DEBUG
+ fprintf(stderr, "frame %d of length=%d:%d\n",
+ i+1, snoop_pkt.caplen, snoop_pkt.len);
+#endif
+ }
+
+ cap_header.frameoffset = lseek(fd2, 0, SEEK_CUR);
+ cap_header.framelength = i*4;
+
+ if ((starttm = localtime((time_t *)&tval1.tv_sec)) != NULL) {
+ cap_header.starttime.wYear = 1900 + starttm->tm_year;
+ cap_header.starttime.wMonth = starttm->tm_mon + 1;
+ cap_header.starttime.wDayOfWeek = starttm->tm_wday;
+ cap_header.starttime.wDay = starttm->tm_mday;
+ cap_header.starttime.wHour = starttm->tm_hour;
+ cap_header.starttime.wMinute = starttm->tm_min;
+ cap_header.starttime.wSecond = starttm->tm_sec;
+ cap_header.starttime.wMilliseconds = tval1.tv_usec/1000;
+ }
+
+ if (swap_netmon)
+ swap_netmon_header(&cap_header);
+
+ lseek(fd3, 0, SEEK_SET);
+ for (j = 0; j < i; j++) {
+ if (read(fd3, &foffset, sizeof(foffset)) != sizeof(foffset)) {
+ perror("read(tmpfile)");
+ exit(2);
+ }
+ if (swap_netmon)
+ swap_uint32(&foffset);
+ write(fd2, &foffset, sizeof(foffset));
+ }
+
+ lseek(fd2, 0, SEEK_SET);
+
+ write(fd2, &cap_header, sizeof(cap_header));
+
+ close(fd1);
+ close(fd2);
+ fclose(tmpf);
+
+ printf("converted %d frames\n", i);
+
+ return i;
+}
+
+int main(int argc, char *argv[])
+{
+ if (argc < 3) {
+ printf("Convert a snoop capture file to a netmon .cap file\n");
+ printf("\tUsage: capconvert <infile> <outfile>\n");
+ exit(1);
+ }
+
+ convert_snoop_to_cap(argv[1], argv[2]);
+
+ return 0;
+}
--- /dev/null
+CFLAGS = -Wall
+
+all: sock_sink sock_source
+
+sock_sink: sock_sink.o socklib.o
+ $(CC) -o $@ sock_sink.o socklib.o
+
+sock_source: sock_source.o socklib.o
+ $(CC) -o $@ sock_source.o socklib.o
+
+clean:
+ rm -f *.o sock_sink sock_source *~
--- /dev/null
+#include "socklib.h"
+
+
+static char *tcp_options="";
+static int port=7001;
+static int bufsize=8192;
+static char *host;
+
+static void sender(void)
+{
+ int fd, total=0;
+ char *buf;
+
+ fd = open_socket_out(host, port);
+
+ set_socket_options(fd, tcp_options);
+
+ buf = (char *)malloc(bufsize);
+
+ if (!buf) {
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+
+ memset(buf, 'Z', bufsize);
+
+ start_timer();
+
+ while (1) {
+ int ret = read(fd, buf, bufsize);
+ if (ret <= 0) break;
+ total += ret;
+ if (end_timer() > 2.0) {
+ report_time(total);
+ total = 0;
+ start_timer();
+ }
+ }
+}
+
+
+static void usage(void)
+{
+ printf("-p port\n-t socket options\n-H host\n-b bufsize\n\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ extern char *optarg;
+
+ while ((opt = getopt (argc, argv, "p:t:H:b:h")) != EOF) {
+ switch (opt) {
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 't':
+ tcp_options = optarg;
+ break;
+ case 'H':
+ host = optarg;
+ break;
+ case 'b':
+ bufsize = atoi(optarg);
+ break;
+
+ case 'h':
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ printf("host=%s port=%d options=[%s]\n", host, port, tcp_options);
+
+ sender();
+
+ return 0;
+}
--- /dev/null
+#include "socklib.h"
+
+
+static char *tcp_options="";
+static int port=7001;
+static int bufsize=8192;
+
+static void server(int fd)
+{
+ char *buf;
+ int total=0;
+
+ signal(SIGPIPE, SIG_IGN);
+
+ set_socket_options(fd, tcp_options);
+
+ buf = (char *)malloc(bufsize);
+ if (!buf) {
+ fprintf(stderr,"out of memory\n");
+ exit(1);
+ }
+
+ memset(buf, 'Z', bufsize);
+
+ start_timer();
+
+ while (1) {
+ int ret = write(fd, buf, bufsize);
+ if (ret <= 0) break;
+ total += ret;
+ if (end_timer() > 2.0) {
+ report_time(total);
+ total = 0;
+ start_timer();
+ }
+ }
+ report_time(total);
+
+ exit(0);
+}
+
+static void listener(void)
+{
+ int sock;
+
+ sock = open_socket_in(SOCK_STREAM, port, INADDR_ANY);
+
+ if (listen(sock, 5) == -1) {
+ fprintf(stderr,"listen failed\n");
+ exit(1);
+ }
+
+ while (1) {
+ struct sockaddr addr;
+ int in_addrlen = sizeof(addr);
+ int fd;
+
+ printf("waiting for connection\n");
+
+ fd = accept(sock,&addr,&in_addrlen);
+
+ if (fd != -1) {
+ printf("accepted\n");
+ if (fork() == 0) server(fd);
+ }
+ }
+}
+
+
+static void usage(void)
+{
+ printf("-p port\n-t socket options\n-b bufsize\n\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ extern char *optarg;
+
+ while ((opt = getopt (argc, argv, "p:t:H:b:h")) != EOF) {
+ switch (opt) {
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 't':
+ tcp_options = optarg;
+ break;
+ case 'b':
+ bufsize = atoi(optarg);
+ break;
+
+ case 'h':
+ default:
+ usage();
+ exit(1);
+ }
+ }
+
+ printf("port=%d options=[%s]\n", port, tcp_options);
+
+ listener();
+
+ return 0;
+}
--- /dev/null
+#include "socklib.h"
+
+static char *last_ptr=NULL;
+
+
+/****************************************************************************
+ Get the next token from a string, return False if none found
+ handles double-quotes.
+Based on a routine by GJC@VILLAGE.COM.
+Extensively modified by Andrew.Tridgell@anu.edu.au
+****************************************************************************/
+BOOL next_token(char **ptr,char *buff,char *sep)
+{
+ char *s;
+ BOOL quoted;
+
+ if (!ptr) ptr = &last_ptr;
+ if (!ptr) return(False);
+
+ s = *ptr;
+
+ /* default to simple separators */
+ if (!sep) sep = " \t\n\r";
+
+ /* find the first non sep char */
+ while(*s && strchr(sep,*s)) s++;
+
+ /* nothing left? */
+ if (! *s) return(False);
+
+ /* copy over the token */
+ for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
+ {
+ if (*s == '\"')
+ quoted = !quoted;
+ else
+ *buff++ = *s;
+ }
+
+ *ptr = (*s) ? s+1 : s;
+ *buff = 0;
+ last_ptr = *ptr;
+
+ return(True);
+}
+
+/****************************************************************************
+open a socket of the specified type, port and address for incoming data
+****************************************************************************/
+int open_socket_in(int type, int port, uint32 socket_addr)
+{
+ struct hostent *hp;
+ struct sockaddr_in sock;
+ char host_name[1000];
+ int res;
+ int one=1;
+
+ /* get my host name */
+ if (gethostname(host_name, sizeof(host_name)) == -1) {
+ fprintf(stderr,"gethostname failed\n"); return -1;
+ }
+
+ /* get host info */
+ if ((hp = gethostbyname(host_name)) == 0) {
+ fprintf(stderr,"Get_Hostbyname: Unknown host %s\n",host_name);
+ return -1;
+ }
+
+ bzero((char *)&sock,sizeof(sock));
+ memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
+
+#ifdef HAVE_SOCK_SIN_LEN
+ sock.sin_len = sizeof(sock);
+#endif
+ sock.sin_port = htons( port );
+ sock.sin_family = hp->h_addrtype;
+ sock.sin_addr.s_addr = socket_addr;
+ res = socket(hp->h_addrtype, type, 0);
+ if (res == -1) {
+ fprintf(stderr, "socket failed\n"); return -1;
+ }
+
+ setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+ /* now we've got a socket - we need to bind it */
+ if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) {
+ return(-1);
+ }
+
+ return res;
+}
+
+
+/* open a socket to a tcp remote host with the specified port
+ based on code from Warren */
+int open_socket_out(char *host, int port)
+{
+ int type = SOCK_STREAM;
+ struct sockaddr_in sock_out;
+ int res;
+ struct hostent *hp;
+
+ res = socket(PF_INET, type, 0);
+ if (res == -1) {
+ return -1;
+ }
+
+ hp = gethostbyname(host);
+ if (!hp) {
+ fprintf(stderr,"unknown host: %s\n", host);
+ return -1;
+ }
+
+ memcpy(&sock_out.sin_addr, hp->h_addr, hp->h_length);
+ sock_out.sin_port = htons(port);
+ sock_out.sin_family = PF_INET;
+
+ if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))) {
+ close(res);
+ fprintf(stderr,"failed to connect to %s - %s\n",
+ host, strerror(errno));
+ return -1;
+ }
+
+ return res;
+}
+
+
+
+enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
+
+struct
+{
+ char *name;
+ int level;
+ int option;
+ int value;
+ int opttype;
+} socket_options[] = {
+ {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
+ {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
+ {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
+#ifdef TCP_NODELAY
+ {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
+#endif
+#ifdef IPTOS_LOWDELAY
+ {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
+#endif
+#ifdef IPTOS_THROUGHPUT
+ {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
+#endif
+#ifdef SO_SNDBUF
+ {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
+#endif
+#ifdef SO_RCVBUF
+ {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
+#endif
+#ifdef SO_SNDLOWAT
+ {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
+#endif
+#ifdef SO_RCVLOWAT
+ {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
+#endif
+#ifdef SO_SNDTIMEO
+ {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
+#endif
+#ifdef SO_RCVTIMEO
+ {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
+#endif
+ {NULL,0,0,0,0}};
+
+
+
+/****************************************************************************
+set user socket options
+****************************************************************************/
+void set_socket_options(int fd, char *options)
+{
+ char tok[200];
+
+ while (next_token(&options,tok," \t,"))
+ {
+ int ret=0,i;
+ int value = 1;
+ char *p;
+ BOOL got_value = False;
+
+ if ((p = strchr(tok,'=')))
+ {
+ *p = 0;
+ value = atoi(p+1);
+ got_value = True;
+ }
+
+ for (i=0;socket_options[i].name;i++)
+ if (strcasecmp(socket_options[i].name,tok)==0)
+ break;
+
+ if (!socket_options[i].name)
+ {
+ DEBUG(0,("Unknown socket option %s\n",tok));
+ continue;
+ }
+
+ switch (socket_options[i].opttype)
+ {
+ case OPT_BOOL:
+ case OPT_INT:
+ ret = setsockopt(fd,socket_options[i].level,
+ socket_options[i].option,(char *)&value,sizeof(int));
+ break;
+
+ case OPT_ON:
+ if (got_value)
+ DEBUG(0,("syntax error - %s does not take a value\n",tok));
+
+ {
+ int on = socket_options[i].value;
+ ret = setsockopt(fd,socket_options[i].level,
+ socket_options[i].option,(char *)&on,sizeof(int));
+ }
+ break;
+ }
+
+ if (ret != 0)
+ DEBUG(0,("Failed to set socket option %s\n",tok));
+ }
+}
+
+
+static struct timeval tp1,tp2;
+
+void start_timer()
+{
+ gettimeofday(&tp1,NULL);
+}
+
+double end_timer()
+{
+ gettimeofday(&tp2,NULL);
+ return((tp2.tv_sec - tp1.tv_sec) +
+ (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+void report_time(int total)
+{
+ printf("%g MB/sec\n", (total/(1.0e6))/end_timer());
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <math.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <unistd.h>
+#include <strings.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+
+
+#define uint32 unsigned
+#define BOOL int
+#define False 0
+#define True 1
+
+#define DEBUG(l, x) printf x
+
+int open_socket_in(int type, int port, uint32 socket_addr);
+int open_socket_out(char *host, int port);
+double end_timer();
+void report_time(int total);
+void start_timer();
+void set_socket_options(int fd, char *options);
+
+
+
+
+
--- /dev/null
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <syslog.h>
+
+/*******************************************************************
+ return the IP addr of the client as a string
+ ******************************************************************/
+char *client_addr(int fd)
+{
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static char addr_buf[100];
+ static int initialised;
+
+ if (initialised) return addr_buf;
+
+ initialised = 1;
+
+ if (getpeername(fd, &sa, &length)) {
+ exit(1);
+ }
+
+ strncpy(addr_buf,
+ (char *)inet_ntoa(sockin->sin_addr), sizeof(addr_buf));
+ addr_buf[sizeof(addr_buf)-1] = 0;
+
+ return addr_buf;
+}
+
+
+/*******************************************************************
+ return the DNS name of the client
+ ******************************************************************/
+char *client_name(int fd)
+{
+ struct sockaddr sa;
+ struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
+ int length = sizeof(sa);
+ static char name_buf[100];
+ struct hostent *hp;
+ char **p;
+ char *def = "UNKNOWN";
+ static int initialised;
+
+ if (initialised) return name_buf;
+
+ initialised = 1;
+
+ strcpy(name_buf,def);
+
+ if (getpeername(fd, &sa, &length)) {
+ exit(1);
+ }
+
+ /* Look up the remote host name. */
+ if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
+ sizeof(sockin->sin_addr),
+ AF_INET))) {
+
+ strncpy(name_buf,(char *)hp->h_name,sizeof(name_buf));
+ name_buf[sizeof(name_buf)-1] = 0;
+ }
+
+
+ /* do a forward lookup as well to prevent spoofing */
+ hp = gethostbyname(name_buf);
+ if (!hp) {
+ strcpy(name_buf,def);
+ } else {
+ for (p=hp->h_addr_list;*p;p++) {
+ if (memcmp(*p, &sockin->sin_addr, hp->h_length) == 0) {
+ break;
+ }
+ }
+ if (!*p) {
+ strcpy(name_buf,def);
+ }
+ }
+
+ return name_buf;
+}
+
+
+int main(int argc, char *argv[])
+{
+ char *service = argv[1];
+
+ openlog("socklog", LOG_PID, LOG_DAEMON);
+ syslog(LOG_ERR, "%s connection from %s [%s]",
+ service, client_name(0), client_addr(0));
+ exit(0);
+}
--- /dev/null
+/* a simple program to detect if an email arriving on standard input is SPAM */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+
+
+/* a single occurance of any of these strings gets it banned */
+static char *spam_strings[] = {
+"Extractor Pro",
+"HUGE PROFITS",
+"removed from this advertiser",
+"Adult Entertainment",
+"PAY PLAN",
+"FREE REPORT",
+"RED HOT",
+"$$$",
+"MoneyMaker",
+"cash register",
+"build your business",
+"having sex",
+"home video",
+"fraction of the price",
+"ALL PRICES",
+"Game List",
+"electron28",
+" rape ",
+" sex ",
+"secrets of success",
+"attractive woman",
+"love life",
+"beautiful women",
+"INTRODUCTORY OFFER",
+"ORDER IT NOW",
+"CREDIT CARD",
+"Money Making",
+"FREE TAPE",
+"Network Marketing",
+"HOME BUSINESS",
+"Cold Cash",
+"Adult Entertainment",
+"COMMISSIONS",
+"TOP PRICE",
+"DON'T BELIEVE THEM",
+"BELIEVE ME",
+"HERE'S THE PROOF",
+"SIMPLE DETAILS",
+"DOLLAR BILL",
+"MAKE MONEY",
+NULL};
+
+
+
+/* SPAM_WORDS_LIMIT occurances of any of these strings gets it banned */
+#define SPAM_WORDS_LIMIT 2
+static char *spam_words[] = {
+ "profit",
+ "Profit",
+ "PROFIT",
+
+ "cash",
+ "Cash",
+ "CASH",
+
+ "opportunity",
+ "Opportunity",
+ "OPPORTUNITY",
+
+ "money",
+ "Money",
+ "MONEY",
+
+ "Coming soon",
+
+ "business",
+
+ "video",
+
+ "marketing",
+
+ NULL};
+
+
+static int match_spam_strings(char *buf, int size)
+{
+ int i;
+
+ for (i=0;spam_strings[i];i++) {
+ if (memmem(buf, size, spam_strings[i], strlen(spam_strings[i])))
+ return 1;
+ }
+
+ return 0;
+}
+
+
+static int match_spam_words(char *buf, int size)
+{
+ int i;
+ int count=0;
+
+ for (i=0;spam_words[i];i++) {
+ if (memmem(buf, size, spam_words[i], strlen(spam_words[i]))) {
+ count++;
+ }
+ }
+
+ if (count >= SPAM_WORDS_LIMIT)
+ return 1;
+
+ return 0;
+}
+
+
+/* messages longer than this get truncated */
+#define MAXBUF 0xFFFF
+
+int main(int argc, char *argv[])
+{
+ char *buf;
+ int size;
+
+ if (argc != 2) {
+ fprintf(stderr,"spamstopper <spamfile>\n");
+ exit(1);
+ }
+
+ buf = (char *)malloc(MAXBUF);
+ if (!buf) return 0;
+
+ size = 0;
+ while (1) {
+ int n = read(0, buf+size, MAXBUF-(size+1));
+ if (n <= 0) break;
+ size += n;
+ }
+
+ if (size <= 0) return 0;
+
+ buf[size] = 0;
+
+ if (match_spam_strings(buf, size) ||
+ match_spam_words(buf, size)) {
+ char *spamfile = argv[1];
+ int fd;
+
+ fd = open(spamfile,O_CREAT|O_WRONLY|O_APPEND, 0666);
+ if (fd == -1) {
+ perror(spamfile);
+ exit(1);
+ }
+ write(fd, buf, size);
+ close(fd);
+ return 0;
+ }
+
+ /* its OK, pass it on */
+ write(1,buf,size);
+
+ return 0;
+}
+
+
--- /dev/null
+#include <stdio.h>
+#include <math.h>
+#include <sys/time.h>
+
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+/* for solaris */
+#ifdef SOLARIS
+#include <limits.h>
+#include <sys/times.h>
+struct tms tp1,tp2;
+
+static void start_timer()
+{
+ times(&tp1);
+}
+
+static double end_timer()
+{
+ times(&tp2);
+ return((tp2.tms_utime - tp1.tms_utime)/(1.0*CLK_TCK));
+}
+
+#elif (defined(LINUX))
+
+#include <sys/resource.h>
+struct rusage tp1,tp2;
+
+static void start_timer()
+{
+ getrusage(RUSAGE_SELF,&tp1);
+}
+
+
+static double end_timer()
+{
+ getrusage(RUSAGE_SELF,&tp2);
+ return((tp2.ru_utime.tv_sec - tp1.ru_utime.tv_sec) +
+ (tp2.ru_utime.tv_usec - tp1.ru_utime.tv_usec)*1.0e-6);
+}
+
+#else
+
+#include <sys/time.h>
+
+struct timeval tp1,tp2;
+
+static void start_timer()
+{
+ gettimeofday(&tp1,NULL);
+}
+
+static double end_timer()
+{
+ gettimeofday(&tp2,NULL);
+ return((tp2.tv_sec - tp1.tv_sec) +
+ (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
+}
+
+#endif
+
+static FILE *f;
+
+static void dumpval(double val)
+{
+ fwrite((void *)&val,sizeof(val),1,f);
+}
+
+
+
+static void memcpy_test(int size)
+{
+ int i;
+ int loops = 5.0e8 / size;
+ char *p1 = (char *)malloc(size);
+ char *p2 = (char *)malloc(size);
+ double t;
+
+ memset(p2,42,size);
+ start_timer();
+
+ for (i=0;i<loops;i++)
+ {
+ memcpy(p1,p2,size);
+ memcpy(p2,p1,size);
+ }
+
+ t = end_timer();
+ dumpval(*(double *)p1);
+ dumpval(*(double *)p2);
+ free(p1); free(p2);
+
+ printf("%g Mb/S\n",i*2.0*size/(1.0e6*t));
+}
+
+
+main()
+{
+ int loops = 100000;
+ int l;
+ double d=0;
+ double t;
+ int i;
+
+#define ADD_SIZE 1*1024
+
+ f = fopen("/dev/null","w");
+
+ printf("Floating point - sin() - ");
+ l = 1024;
+ start_timer();
+ for (i=0;i<loops;i++)
+ d += sin((double)i);
+ t = end_timer();
+ printf("%g MOPS\n",loops/(1.0e6*t));
+ dumpval(d);
+
+ printf("Floating point - log() - ");
+ l = 1024;
+ start_timer();
+ for (i=0;i<loops;i++)
+ d += log((double)(i+1));
+ t = end_timer();
+ printf("%g MOPS\n",loops/(1.0e6*t));
+ dumpval(d);
+
+ printf("Memcpy - 1kB - ");
+ memcpy_test(1024);
+
+ printf("Memcpy - 100kB - ");
+ memcpy_test(1024*100);
+
+ printf("Memcpy - 1MB - ");
+ memcpy_test(1024*1024);
+
+ printf("Memcpy - 10MB - ");
+ memcpy_test(1024*1024*10);
+
+ loops *= 10;
+ printf("Adding integers - ");
+ l = ADD_SIZE;
+ {
+ int *p1 = (int *)malloc(l*sizeof(int));
+ int sum;
+ for (i=0;i<l;i++)
+ p1[i] = i;
+ start_timer();
+ for (i=0;i<loops/100;i++)
+ {
+ int j;
+ sum = i;
+ for (j=0;j<l;j++)
+ sum += p1[j];
+ }
+ t = end_timer();
+ dumpval(sum);
+ free(p1);
+ }
+ printf("%g MOPS\n",0.01*(loops*l)/(1.0e6*t));
+
+ printf("Adding floats (size %d) - ",sizeof(float));
+ l = ADD_SIZE;
+ {
+ float *p1 = (float *)malloc(l*sizeof(float));
+ float sum;
+ for (i=0;i<l;i++)
+ p1[i] = i;
+ start_timer();
+ for (i=0;i<loops/100;i++)
+ {
+ int j;
+ sum = i;
+ for (j=0;j<l;j++)
+ sum += p1[j];
+ }
+ t = end_timer();
+ dumpval(sum);
+ free(p1);
+ }
+ printf("%g MOPS\n",0.01*(loops*l)/(1.0e6*t));
+
+ printf("Adding doubles (size %d) - ",sizeof(double));
+ l = ADD_SIZE;
+ {
+ double *p1 = (double *)malloc(l*sizeof(double));
+ double sum;
+ for (i=0;i<l;i++)
+ p1[i] = i;
+ start_timer();
+ for (i=0;i<loops/100;i++)
+ {
+ int j;
+ sum = i;
+ for (j=0;j<l;j++)
+ sum += p1[j];
+ }
+ t = end_timer();
+ dumpval(sum);
+ free(p1);
+ }
+ printf("%g MOPS\n",0.01*(loops*l)/(1.0e6*t));
+
+}
--- /dev/null
+/*
+ tridge@linuxcare.com January 2000
+
+ This is a sample program that demonstrates a deadlock in sshd when
+ handling large amounts of bi-directional data. This deadlock has
+ been the cause of lots of problems with rsync over ssh. Although the
+ problem only maniifests itself occasionally it makes large rsync
+ over ssh transfers unreliable.
+
+ Luckily the fix is very easy - tell sshd to use socketpair() instead
+ of pipe(). Just remove the line:
+ #define USE_PIPES 1
+ from near the bottom of includes.h in the ssh sources.
+
+ Note that fixing the problem by playing with the write sizes or by
+ using non-blocking writes due to the following bugs in various OSes.
+
+ - in Linux 2.2 a write to a non-blocking pipe will either return
+ EAGAIN if no space is avaiilable or will block if not. This is fixed
+ in Linux 2.3.
+
+ - Under IRIX and OSF1 a select on a blocking pipe may return before
+ PIPE_BUF can be written. When a subsequent write of more than 1 byte
+ is done the write blocks.
+
+ - under some versions of OpenBSD a select on a non-blocking pipe
+ will always return immediately, even when no space is available.
+
+ The sum of all these factors means it is not possible to write
+ portable code that uses pipes in a way that won't allow deadlocks,
+ unless writes are restricted to a single byte after a select on a
+ blocking pipe. The performance of that solution would be terrible.
+
+running this code:
+
+ 1) "make nettest"
+ 2) nettest "ssh localhost nettest -s"
+ 3) if it blocks then you have hit the deadlock.
+
+*/
+
+
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <stdlib.h>
+
+#define TOTAL_SIZE (10*1024*1024)
+
+
+static int fd_pair(int fd[2])
+{
+ return socketpair(AF_UNIX, SOCK_STREAM, 0, fd);
+}
+
+
+static int write_loop(int fd, char *buf, int size)
+{
+ int total=0;
+
+ while (size) {
+ int n = write(fd, buf, size);
+ if (n <= 0) break;
+ size -= n;
+ buf += n;
+ total += n;
+ }
+ return total;
+}
+
+static int piped_child(char *command,int *f_in,int *f_out)
+{
+ int pid;
+ int to_child_pipe[2];
+ int from_child_pipe[2];
+
+ if (fd_pair(to_child_pipe) < 0 ||
+ fd_pair(from_child_pipe) < 0) {
+ fprintf(stderr,"fd_pair: %s\n",strerror(errno));
+ exit(1);
+ }
+
+
+ pid = fork();
+ if (pid < 0) {
+ fprintf(stderr,"fork: %s\n",strerror(errno));
+ exit(1);
+ }
+
+ if (pid == 0) {
+ if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
+ close(to_child_pipe[1]) < 0 ||
+ close(from_child_pipe[0]) < 0 ||
+ dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
+ fprintf(stderr,"Failed to dup/close : %s\n",strerror(errno));
+ exit(1);
+ }
+ if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
+ if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
+ system(command);
+ exit(1);
+ }
+
+ if (close(from_child_pipe[1]) < 0 ||
+ close(to_child_pipe[0]) < 0) {
+ fprintf(stderr,"Failed to close : %s\n",strerror(errno));
+ exit(1);
+ }
+
+ *f_in = from_child_pipe[0];
+ *f_out = to_child_pipe[1];
+
+ return pid;
+}
+
+static void sender(int fin, int fout)
+{
+ int n;
+ char buf[1024];
+ int total = 0;
+
+ while (total < TOTAL_SIZE) {
+ n = read(fin, buf, sizeof(buf));
+ if (n <= 0) {
+ fprintf(stderr,"write error in sender at %d\n", total);
+ break;
+ }
+ write_loop(fout, buf, n);
+ total += n;
+ fprintf(stderr, "-");
+ }
+ fprintf(stderr, "sender done\n");
+}
+
+static void generator(int fd)
+{
+ int n;
+ char buf[1024];
+ int total=0;
+
+ while (total < TOTAL_SIZE) {
+ n = 1 + random() % (sizeof(buf)-1);
+ n = write_loop(fd, buf, n);
+ if (n <= 0) {
+ fprintf(stderr,"write error in generator at %d\n", total);
+ break;
+ }
+ total += n;
+ fprintf(stderr, "*");
+ }
+ fprintf(stderr, "generator done\n");
+}
+
+static void receiver(int fd)
+{
+ ssize_t n;
+ ssize_t total=0;
+ char buf[1024];
+
+ while (total < TOTAL_SIZE) {
+ n = read(fd, buf, sizeof(buf));
+ if (n <= 0) {
+ fprintf(stderr,"read error in receiver\n");
+ break;
+ }
+ total += n;
+ fprintf(stderr, "+");
+ }
+ fprintf(stderr, "receiver done\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int c, f_in, f_out;
+ int am_sender = 0;
+
+ while ((c = getopt(argc, argv, "s")) != -1) {
+ switch (c){
+ case 's':
+ am_sender = 1;
+ break;
+ }
+ }
+
+ if (am_sender) {
+ sender(0, 1);
+ } else {
+ char *command = argv[1];
+ printf("running %s\n", command);
+ piped_child(command, &f_in, &f_out);
+ if (fork()) {
+ generator(f_out);
+ } else {
+ receiver(f_in);
+ }
+ }
+
+ return 0;
+}