chdt

Christos Ricudis ricudis at paiko.gr
Wed Jan 9 22:59:01 EET 2002


Twra teleytaia bariomoyn yperbolika, kai eipa na katsw na paiksw ligo me
to /proc/ toy Solaris/SPARC. Me sygxwreite gia to off topic toy pragmatos,
alla endexetai to apotelesma na endiaferei orismenoys : 


/* chdt 0.1 (C) 2000-2001, Christos Ricudis ricudis at paiko.gr 

 This program executes a binary in system call trace mode 
 changing the result codes of some system calls as requested by 
 the user. 
 
 Compile with gcc -o chdt chdt.c. Run chdt without arguments for usage 
 reference.
 
 This program is supplied without warranties. 
 
 You should note that using this program to circumvent software licensing
 restrictions imposed by license managers is a violation of your licensing
 terms and it is probably illegal. For example :
 
 If you take an expired demo Sun Workshop license, and then move 
 /opt/SUNWspro/WS6/bin/acomp to /opt/SUNWspro/WS6/bin/acomp-orig and 
 replace /opt/SUNWspro/WS6/bin/acomp with a shell script that calls
 "chdt -t <some time before expiration> -- /opt/SUNWspro/WS6/bin/acomp-orig $*"
 then you are probably breaking Sun's licensing terms and it could
 put you into serious legal trouble.

 This software is public domain. No warranties are expressed or implied.
 Contains gas in high pressure. Do not dispose. Use by children without
 adult supervision is prohibited. Use only certified replacement parts. 
 Do not expose in direct sunlight. Do not use near water. Use while
 intoxicated may cause accidents. Keep away of reach of children. Do not
 use without doctors advice. Contains recycleable materials. Unplug from 
 wall outlet before cleaning. Do not use soaps, liquid cleaners or aerosols. 
 Do not use in pools, bathtubs, showers, or spa. Do not immerse in water. 
 Do not use while driving a motor vehicle. Do not use a damaged power cord.
 Do not dismantle. Do not expose in extreme temperatures. Never use during a
 lightning storm. Do not use while in wet conditions. Do not place on an 
 unstable cart, stand, or table. Use only the type and size of battery 
 specified. No user-serviceable parts inside. Consists of 100% pure recycled
 electrons. Actual size and color may differ. Do not drink and drive.
 
*/
 

#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/fault.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/systeminfo.h>
#include <sys/procfs_isa.h>
#include <sys/stropts.h>
#include <poll.h>
#include <unistd.h>

/* Synchronization primitives */


static int pfd1[2], pfd2[2];

void TELL_WAIT(void) {
	if (pipe(pfd1)<0 || pipe(pfd2)<0) {
		perror("pipe()");
		exit(1);
	}
}

void TELL_PARENT(pid_t pid) {
	if (write(pfd2[1],"c",1)!=1) {
		perror("write()");
		exit(1);
	}
}

void WAIT_PARENT(void) {
	char c; 
	if (read(pfd1[0],&c,1)!=1) {
		perror("read()");
	}
	if (c!='p') {
		printf("Mparmpoutsala\n");
		exit(1);
	}
}

void TELL_CHILD(pid_t pid) {
	if (write(pfd1[1],"p",1)!=1) {
		perror("write()");
		exit(1);
	}
}

void WAIT_CHILD(void) {
	char c; 
	if (read(pfd2[0],&c,1)!=1) {
		perror("read()");
	}
	if (c!='C') {
		printf("Karamparmpoutsala\n");
		exit(1);
	}
}

#define verbose if (vflag==1) 

int main (int argc, char *argv[]) {

	pid_t pid1,pid2,pid3;
	int i,fildes,j;
	void *p;
	int retval;
	char pids[100];
	char fullpid[100];
	char *c;
	sysset_t sysset;
	struct prstatus piocs;
	struct prrun piocr;
	int fdesc;
	char *buffer;
	FILE *fp;
	struct pollfd pfd;
	int dummy;
	int ld,hd;
	extern char *optarg;
	extern int optind;
	int validopts;
	char arc;
	char *chost;
	char *cdom;
	char *ctime;
	time_t regtime;
	int vflag;
	long piocflags;
	prgreg_t regret=0;
	prgregset_t regs;
	
	/* Process command line arguments */


	chost=NULL;
	ctime=NULL;
	cdom=NULL;	
	validopts=0;
	while ((arc = getopt(argc, argv, "vh:d:t:")) != EOF) {
        	switch (arc) {
			case 'h':
				chost=optarg;
		        	break;
			case 'd':
				cdom=optarg;
		        	break;
			case 't':
				ctime=optarg;
				regtime=atol(ctime);
		        	break;
		        case 'v':
		        	vflag++;
		}
	}
	
	validopts=((chost!=NULL) || (cdom!=NULL) || (ctime!=NULL));
	
	if (argc<=optind) validopts=0;
	
	if (!validopts) {
		printf("Usage : %s [ -v ] [ -h HOSTID ] [ -d DOMAIN ] [ -t TIME ]  -- <arglist>\n\n",argv[0]);
		printf("\t -v              : Be debuggingly verbose in annoying quantities\n");
		printf("\t -h HOSTID       : Change hostid to HOSTID\n");
		printf("\t -d DOMAIN       : Change domain to DOMAIN\n");
		printf("\t -t TIME         : Change time (as reported by time(3)) to TIME.\n");
		printf("\t                   the TIME argument is the desired time in UNIX epoch format\n");
		printf("\t <arglist>       : Argument list passed to exec()\n\n");
		printf("\t At least one of -h, -d, -t is required\n");
		printf("\nExample : %s -h 1919977934 -- /usr/bin/hostid\n",argv[0]);
		exit(1);
	}
	
	for (i=0;i<optind;i++) *argv++;

	/* here we are */

	TELL_WAIT();
	
	if (!(pid1=fork())) {
		/* wait for parent to do its dirty work */
		WAIT_PARENT();
		execvp(*argv,argv);
	} else {
		p=NULL;
		verbose printf("Child PID = %d our pid=%d\n",pid1,getpid());
		sprintf(pids,"/proc/%d",pid1);
		verbose printf("Opening %s\n",pids);
		if ((fp=fopen(pids,"r+"))==NULL) {
			verbose perror("fopen()");
		}
		fdesc=fileno(fp);
		premptyset(&sysset);
		if (chost!=NULL || cdom!=NULL) {
			verbose printf("Stopping child process at exit of system call SYS_systeminfo\n");
			praddset(&sysset,SYS_systeminfo);
		} 
		if (ctime!=NULL) {
			verbose printf("Stopping child process at exit of system call SYS_time\n");
			praddset(&sysset,SYS_time);
		}
		
		piocflags=PR_FORK;
		
		if (ioctl(fdesc, PIOCSET, &piocflags)<0) {
			verbose perror("ioctl(PIOCSET)");
		}
			                
		if (ioctl(fdesc, PIOCSEXIT, &sysset) < 0) {
			verbose perror("ioctl(PIOCSEXIT)");
		}
		verbose printf("Setup completed, allowing child to continue\n");
		
		TELL_CHILD(pid1);
    
		verbose printf("Entering event loop\n");
		while (1) {
		
			pfd.fd=fdesc;
			pfd.events=POLLPRI;
			
			if (poll(&pfd,1,-1)<0) {
				verbose perror("poll");
				break;
			}
		
			if (ioctl(fdesc,PIOCSTATUS,&piocs)==-1) {
				verbose perror("ioctl(PIOCSTATUS)");
				break;
			}
			regret=0;
			if (piocs.pr_flags&&PR_STOPPED) {
				verbose printf("Stopped\n");
				if (piocs.pr_why&&PR_SYSEXIT) {
					verbose printf("Stopped because of syscall %d\n",piocs.pr_what);
					verbose printf("PR_SYSCALL = %d\n",piocs.pr_syscall);
					verbose printf("PR_NSYSARG = %d\n",piocs.pr_nsysarg);
					verbose printf("PR_SYSARG = [ ");
					for (i=0;i<piocs.pr_nsysarg;i++) { 
						verbose printf("%lu ",piocs.pr_sysarg[i]);
					}
					verbose printf("]\n");
					if (piocs.pr_what==SYS_systeminfo) {
						if (piocs.pr_sysarg[0]==SI_HW_SERIAL && chost!=NULL) {
							verbose printf("Intercepting serial number\n");
							lseek(fdesc,piocs.pr_sysarg[1],SEEK_SET);
							buffer=malloc(piocs.pr_sysarg[2]);
							read(fdesc,buffer,piocs.pr_sysarg[2]);
							verbose printf("Host ID : ==%s==\n",buffer);
							verbose printf("We change it to : ==%s==\n",chost);
							lseek(fdesc,piocs.pr_sysarg[1],SEEK_SET);
							write(fdesc,chost,strlen(chost)+1);
							verbose printf("Put syscall's return code into R_O0 register\n");
							regret=strlen(chost)+1;
							free(buffer);
						}
						if (piocs.pr_sysarg[0]==SI_SRPC_DOMAIN && cdom!=NULL) {
							verbose printf("Intercepting domain name\n");
							lseek(fdesc,piocs.pr_sysarg[1],SEEK_SET);
							buffer=malloc(piocs.pr_sysarg[2]);
							read(fdesc,buffer,piocs.pr_sysarg[2]);
							verbose printf("Domain name : ==%s==\n",buffer);
							verbose printf("We change it to : ==%s==\n",cdom);
							lseek(fdesc,piocs.pr_sysarg[1],SEEK_SET);
							write(fdesc,cdom,strlen(cdom)+1);
							verbose printf("Put syscall's return code into R_O0 register\n");
							regret=strlen(cdom)+1;
							free(buffer);
						}
					}
					if (piocs.pr_what==SYS_time) {
						verbose printf("Put syscall's return code into R_O0 register\n");
						verbose printf("Desired time : %d\n",regtime);
						regret=regtime;
					}
				}
				verbose printf("Current registers contents : \n");
				for (i=0;i<NPRGREG;i++) {
					verbose printf("reg[%d]=%d\t",i,piocs.pr_reg[i]);
				}
				verbose printf("\n");
				if (regret!=0) { 
					for (i=0;i<NPRGREG;i++) {
						regs[i]=piocs.pr_reg[i];
					}
					regs[R_O0]=regret;
					verbose printf("Setting system registers\n");
					if (ioctl(fdesc,PIOCSREG,&regs)<0) {
						verbose perror("ioctl(PIOCSREG)");
						break;
					}
				}
				verbose printf("Restarting process\n");
				if (ioctl(fdesc,PIOCRUN,NULL)<0) {
					verbose perror("ioctl(PIOCRUN)");
					break;
				}
			}
		}
		
		verbose printf("Waiting for child to terminate\n");
		wait(&dummy);
		ld = dummy & 0xff;
		hd = dummy << 8 ;
		verbose printf("wait() return code = %d lo = %d hi = %d\n",dummy,ld,hd);
		if (ld==0) {
			return(hd);
		} else {
			return(0);
		}
	}
}

-- 
Christos Ricudis

ric-NOSPAM-udis at paiko.gr			Remove -NOSPAM- to reply
spamoula at paiko.gr				Send your spam here




More information about the Linux-greek-users mailing list