diff --git a/src/uncompressor.c b/src/uncompressor.c new file mode 100644 index 0000000000000000000000000000000000000000..95f0fc4af9e3f5b10b1aaa62d2008f55721a456d --- /dev/null +++ b/src/uncompressor.c @@ -0,0 +1,252 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#ifndef __NT__ +#include <unistd.h> +#include <string.h> +#else +#include <windows.h> +#endif +#include <zlib.h> + + +#ifdef __NT__ +#define DELIM ';' +#define SLASH '\\' +#define ISSLASH(X) ((X)=='\\' || (X)=='/') +#else +#define DELIM ':' +#define SLASH '/' +#define ISSLASH(X) ((X)=='/') +#endif + +#define FEND(X,Y) (strchr(X,Y)?strchr(X,Y):(X)+strlen(X)) + + +gzFile gz; + +static void gr(char *ptr, int len) +{ +/* fprintf(stderr,"Reading %d\n",len); */ + if(gzread(gz, ptr, len) != len) + { + puts("Failed to decompress data!\n"); + exit(1); + } +} + +#define GR(X) gr( (char *) & (X), sizeof(X)) +static unsigned int rint(void) +{ + unsigned char x[4]; + gr(x,4); +/* fprintf(stderr,"Got 0x%02x%02x%02x%02x\n",x[0],x[1],x[2],x[3]); */ + return (x[0] << 24) | (x[1]<<16) | (x[2]<<8) | x[3]; +} + +#if !( SEEK_TO - 0 ) +#define SEEK_TO -1 +#endif + +#if !( SEEK_SET - 0 ) +#define SEEK_SET 0 +#endif + + +void my_uncompress(char *file) +{ + unsigned int len; + char buffer[8192]; + int fd; + char *d; + + fd=open(file, O_RDONLY); + if(fd == -1) return; + + if(lseek(fd, SEEK_TO, SEEK_SET)<0) + { + perror("lseek"); +/* fprintf(stderr,"SEEK_TO=%d\n",SEEK_TO); */ + exit(1); + } + + gz=gzdopen(fd,"rb"); + if(!gz) + { + puts("gzdopen failed!"); + exit(1); + } + +#ifdef __NT__ + d=getenv("TMP"); + if(!d) d=getenv("TEMP"); + if(!d) d="C:\\Windows\\temp"; +#else + d=getenv("TMPDIR"); + if(!d) d="/tmp"; +#endif + if(chdir(d)<0) + { + perror("chdir"); + exit(1); + } +/* fprintf(stderr,"Changing dir to %s\n",d); */ + + while(1) + { + char type; + int len; + char *data; + GR(type); + + len=rint(); +/* fprintf(stderr,"namelen=%d\n",len); */ + + gr(buffer, len); + buffer[len]=0; + + +/* fprintf(stderr,"Type %c: %s\n",type,buffer); */ + + switch(type) + { + case 'q': /* quit */ + exit(0); + + case 'w': /* write */ + puts(buffer); + break; + + case 'e': /* setenv */ +/* fprintf(stderr,"putenv(%s)\n",buffer); */ + putenv(buffer); + break; + + case 's': /* execute */ + /* We ignore error so that we can continue with + * file deletion + */ + /* FIXME: + * Add support for concatenating all the parameters + * to this command + */ +/* fprintf(stderr,"system(%s)\n",buffer); */ + system(buffer); + break; + + case 'd': /* dir */ + /* We ignore mkdir errors and just assume that the + * directory already exists + */ + /* fprintf(stderr,"mkdir(%s)\n",buffer); */ + mkdir(buffer, 0777); + break; + + case 'f': /* file */ + { + FILE *f; + /* fprintf(stderr,"file(%s)\n",buffer); */ + f=fopen(buffer,"wb"); + if(!f) + { + perror("fopen"); + fprintf(stderr,"Failed to open %s\n",buffer); + exit(1); + } + len=rint(); + while(len) + { + int r=len > sizeof(buffer) ? sizeof(buffer) : len; + gr(buffer, r); + if(fwrite(buffer, 1, r, f) != r) + { + perror("fwrite"); + exit(1); + } + len-=r; + } + if(fclose(f)<0) + { + perror("fclose"); + exit(1); + } + } + break; + + case 'D': +/* fprintf(stderr,"unlink(%s)\n",buffer); */ + if(unlink(buffer)<0 && rmdir(buffer)<0) + { + perror("unlink"); +/* exit(1); */ + } + break; + + default: + fprintf(stderr,"Wrong type (%c (%d))!\n",type,type); + exit(1); + } + } +} + +int main(int argc, char **argv) +{ + char tmp[16384]; + char *file; + +#ifdef __NT__ + _fmode=_O_BINARY; + if(SearchPath(0, + argv[0], + ".exe", + sizeof(tmp), + tmp, + &file)) + my_uncompress(tmp); +#else + char *path=getenv("PATH"); + char *pos; + file=argv[0]; + if(!path || strchr(file, SLASH)) + { + my_uncompress(file); + perror("open"); + exit(1); + } + + pos=path; + while(1) + { + char *next; + next=FEND(pos,DELIM); + if(next!=pos) + { + char *ptr=tmp; + struct stat buf; + + memcpy(ptr=tmp,pos,next-pos); + ptr+=next-pos; + if(*ptr != '/' +#ifdef __NT + && *ptr != SLASH +#endif + ) + *(ptr++)='/'; + + memcpy(ptr, + file, + strlen(file)); + ptr+=strlen(file); + *ptr=0; + + my_uncompress(tmp); + } + if(!*next) break; + pos=next+1; + } +#endif + puts("Failed to find self!"); + exit(9); +}