#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/modreq.h>

#define s(a,b,c,d) (((d*256+c)*256+b)*256+a)                    
#define DEBUG_VALUES 1

char letter[]="XDFNEU";   /* Keep this in line with the case statement below
                            and linux/include/linux/modreq.h */
                            
char* matchline(char* name, int where, int major, int ruser)
{
  FILE* infile;
  char c, line[100];
  static char inst[100];
  char* result=NULL;
  int   fmaj;
  int   suser;
    
  if (!(infile=fopen(name,"r"))) {
    fprintf(stderr,"modreq: Could not open config file %s for reading\n",name);
    exit(1);
  }
  
  while(!result && !feof(infile)) {
    fscanf(infile," %c",&c);
    switch(c) {
      case '#' : fscanf(infile,"%*[^\n]\n",NULL);
                 break;
      
      case 'D' :
      case 'F' :
      case 'N' :
      case 'E' :
      case 'U' : fscanf(infile," %99s %d %99[^\n]\n",line,&suser,inst);
      		 if (*line=='"') {
      		   fmaj=((256*line[4]+line[3])*256+line[2])*256+line[1]; 
                 }
                 else if (*line=='*') {
                   fmaj=major;
                 }
                 else {
                   sscanf(line," %d",&fmaj);
                 }
                 printf("Compare %d,%d to %d,%d\n",letter[where],major,c,fmaj);
                 if (c!=letter[where] || fmaj!=major || suser>ruser)
                   break;
                 result=inst;
		 break;
      default  : fprintf(stderr,"modreq: Unknown line in config file, starting with '%c'\n",c);
    }
  }
  fclose(infile);
  return result;
} 

int main(int argc, char* argv[])
{
  int devicer;
  int devicew;
  int what[3];
  char* module;
  char smajor[5]={0,0,0,0,0};
  int result;
  char command[100];  
  int debug=0xff;
    
  if ((devicer=open("/dev/modreq",O_RDONLY))<0) {
    fprintf(stderr,"%s: Could not open device /dev/modreq for reading\n",argv[0]);
    exit(1);
  }
  if ((devicew=open("/dev/modreq",O_WRONLY))<0) {
    fprintf(stderr,"%s: Could not open device /dev/modreq for writing\n",argv[0]);
    exit(1);
  }

  what[0]=1;
  while(what[0]!=EXECUTABLES || what[1]!=1869902627 || !what[2]) {
    read(devicer,(char*)what,3*sizeof(int));
    *((int*)smajor)=what[1];
    if (debug&DEBUG_VALUES)
      printf("where=%d, major=%d(\"%s\"), suser=%d\n",what[0],what[1],smajor,what[2]);

    result=0;
    module=matchline("/etc/modreq.config",what[0],what[1],what[2]);

    if (module) {
    	sprintf(command,"%s\n",module);
	printf("Sending '%s'\n",command);
    	system(command);
    	result=1;
    }
    write(devicew,&result,sizeof(int));
  }
  close(devicer);
  close(devicew);
}