/************************************************************************/ /* hsh version 0.02 by Arny - cs6171@scitsc.wlv.ac.uk */ /* This really isnt completely ready yet, but it should compile with */ /* ansi compatible compilers (such as gcc) under Linux and SunOS. */ /* This version now has a password option, a command to get zombies, */ /* and the displayfile function has been changed so that it works under */ /* more circumstances, although it is still very badly written. I also */ /* noticed that version 0.01 wasn't *very* good when run from a "rsh */ /* host 'sh -i'" session, so fflush(3)'ing is always done now. Keep an */ /* eye out for newer versions - there is still much to be done. */ /* (c) 1994/95 Arny - I accept no responsiblity for anything this does. */ /************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #define MAXCOMLEN 1024 /* length of the command line */ #define MAXARGS 512 /* number of arguments in the command line */ #define MAXWIDTH 80 /* screen width, used for the 'more' command */ #define MAXLINES 23 /* screen length */ #define PROMPT "hsh$ " /* if you want I/O to a socket #define PORTNUM to the port number, */ /* if you dont, dont. */ #define PORTNUM 7890 /* if you want to be asked for a passwd, define PASSWD to the encrypted */ /* passwd (as produced by passwd(1) or crypt(3) ) with double quotes */ /* #define PASSWD "RAMdLCxgo2EFU" */ /* if you are compiling for linux and you *really* want 'more' to go */ /* backwards and forwards on single keystrokes #define TTYMANIP, but */ /* for the sake of reliability and portability I wouldn't recommend it. */ /* #define TTYMANIP */ #ifdef TTYMANIP #include #endif /* end of comments (I dont like them), you're on your own now..... */ #ifdef PORTNUM void bulk(); #endif void help(); int commandlinetoagg(char**,char*); char *procom(char*); int getargc(char**); void arnwaitpid(char**); void arnsetid(char**); void arnsetgid(char**); void arnsetpgid(char**); void arnspawn(char**); void aswait(char**); void asbg(char**); void arnexec(char**); void cutarg(int,char**); void displaypinfo(); void displayids(); void displaygids(); void displaypids(); void pwdatanam(char**); void pwdatauid(char**); void displayhostinfo(char**); void dispinetaddr(char*,int); char inbuf[MAXCOMLEN+1]; #ifdef PORTNUM main() { int sd,cd,n; int coninflen=sizeof(struct sockaddr_in); struct sockaddr_in sa; struct sockaddr_in coninf; sa.sin_family=AF_INET; sa.sin_port=htons(PORTNUM); sa.sin_addr.s_addr=htonl(INADDR_ANY); if((sd=socket(AF_INET,SOCK_STREAM,0))==-1) { perror("cant create socket"); exit(1); }; if(bind(sd,(struct sockaddr*)&sa,sizeof(sa))) { perror("cant bind to address"); exit(1); }; if(listen(sd,2)) { perror("error with listen"); exit(1); }; if((cd=accept(sd,(struct sockaddr*)&coninf,&coninflen))<0) { perror("error with accept"); exit(1); }; close(STDIN_FILENO); dup(cd); close(STDOUT_FILENO); dup(cd); close(STDERR_FILENO); dup(cd); close(cd); bulk(); close(sd); } void bulk() #else main() #endif { char *argv[MAXARGS+1]; #ifdef PASSWD while(1) { printf("password: "); fflush(stdout); if(fgets(inbuf,MAXCOMLEN,stdin)==NULL) exit(0); if(!strcmp(crypt(procom(inbuf),PASSWD),PASSWD)) break; sleep(1); }; #endif while(1) { printf(PROMPT); fflush(stdout); if(fgets(inbuf,MAXCOMLEN,stdin)==NULL) break; if(*procom(inbuf)=='\0') continue; printf("\"%s\"\n",inbuf); fflush(stdout); if(commandlinetoagg(argv,inbuf)) continue; if (!strcmp(*argv,"exit")) break; else if (!strcmp(*argv,"ihelp")) help(); else if (!strcmp(*argv,"imore")) displayfile(argv[1]); else if (!strcmp(*argv,"cd")) changedir(argv); else if (!strcmp(*argv,"imkdir")) makedir(argv[1]); else if (!strcmp(*argv,"ird")) removedir(argv[1]); else if (!strcmp(*argv,"pwd")) pcwd(); else if (!strcmp(*argv,"ils")) directory(argv); else if (!strcmp(*argv,"waitpid")) arnwaitpid(argv); else if (!strcmp(*argv,"setid")) arnsetid(argv); else if (!strcmp(*argv,"setgid")) arnsetgid(argv); else if (!strcmp(*argv,"setpgid")) arnsetpgid(argv); else if (!strcmp(*argv,"pinfo")) displaypinfo(); else if (!strcmp(*argv,"pwdata")) pwdatanam(argv); else if (!strcmp(*argv,"pwdatauid")) pwdatauid(argv); else if (!strcmp(*argv,"hinfo")) displayhostinfo(argv); else if (*argv==NULL); else arnspawn(argv); }; } void help() { printf("\ninternal commands recognised are:\n"); printf("\texit, ihelp, imore, cd, imkdir, ird, pwd, ils,\n"); printf("\twaitpid,\n"); printf("\tsetid, setgid, setpgid, pinfo,\n"); printf("\tpwdata, pwdatauid, hinfo.\n\n"); } int commandlinetoagg(char **argv,char *cmdline) { int i,argnumber=0,inword=0; for(i=0;cmdline[i]!='\0';i++) { if ((cmdline[i]!=' ')&&(!inword)) { argv[argnumber]=(cmdline+i); if((++argnumber)>=MAXARGS) { printf("too many arguments\n"); *argv=NULL; return(1); }; inword=1; }; if (cmdline[i]==' ') { cmdline[i]='\0'; inword=0; }; }; argv[argnumber]=NULL; return(0); } char *procom(char *astring) { int i; for(i=0;astring[i]!='\0';i++) { if(astring[i]=='\r') astring[i]='\0'; if(astring[i]=='\n') astring[i]='\0'; }; return(astring); } changedir(char **argv) { if (getargc(argv)!=2) { printf("usage: %s path\n",*argv); return(1); }; if (chdir(argv[1])) { perror("error when trying to change directory "); return(1); }; return(0); } makedir(char *dirname) { printf("sorry, function not written yet....\n"); return(1); } removedir(char *dirname) { printf("sorry, function not written yet....\n"); return(1); } pcwd() { char *achpoint; achpoint=(char*)getcwd(NULL,800); printf("%s\n",achpoint); free(achpoint); return(0); } directory(char **argv) { printf("sorry, function not written yet....\n"); return(1); } displayfile(char *filename) { char tempch,lines,horizpos; unsigned char pages; int tempint; char keybuf[32]; long pagetable[UCHAR_MAX+1]; FILE *afilepoint; #ifdef TTYMANIP struct termio old,new; if(!isatty(STDIN_FILENO)) { printf("input is not a tty\n"); return(1); }; #endif if ((afilepoint=fopen(filename,"r"))==NULL) { printf("error opening file\n"); return(1); }; #ifdef TTYMANIP if(ioctl(STDIN_FILENO,TCGETA,&old)) { printf("error getting terminal status, too risky to try to change\n"); return(1); }; new=old; new.c_lflag&=~(ICANON|ECHO); ioctl(STDIN_FILENO,TCSETA,&new); #endif for (tempint=0;tempint<=UCHAR_MAX;tempint++) pagetable[tempint]=0; pages=0; lines=0; horizpos=0; while ((tempch=getc(afilepoint))!=EOF) { switch(tempch) { case 9 : putchar(9); horizpos+=((horizpos+7)%8)+1; break; case 10: printf("\n"); horizpos=0; lines++; break; default: if ((tempch>31)&&(tempch<127)) { putchar(tempch); horizpos++; }; }; if (horizpos>=MAXWIDTH) { horizpos-=MAXWIDTH; lines++; }; if (lines>=MAXLINES) { pages++; fflush(stdout); #ifdef TTYMANIP if(read(STDIN_FILENO,keybuf,24)==0) break; switch (*keybuf) { case 'q': ioctl(STDIN_FILENO,TCSETA,&old); fclose(afilepoint); return(1); case 'c': ioctl(STDIN_FILENO,TCSETA,&old); fclose(afilepoint); return(1); case 'b': printf("\n\n\n"); horizpos=0; pages-=2; fseek(afilepoint,pagetable[pages],SEEK_SET); break; }; #else if(fgets(keybuf,24,stdin)==NULL) break; if(*keybuf=='q') break; if(*keybuf=='c') break; if(*keybuf=='b') { printf("\n\n\n"); horizpos=0; pages-=2; fseek(afilepoint,pagetable[pages],SEEK_SET); }; #endif pagetable[pages]=ftell(afilepoint); lines=0; }; }; #ifdef TTYMANIP ioctl(STDIN_FILENO,TCSETA,&old); #endif fclose(afilepoint); return(0); } int getargc(char **argv) { int count; for(count=0;argv[count]!=NULL;count++); return(count); } void arnwaitpid(char **argv) { int status; if(getargc(argv)!=2) { printf("usage: %s pid\n",*argv); return; }; printf("return value of waitpid=%d\n",waitpid(atoi(argv[1]),&status,WNOHANG)); printf("status=%d\n",status); } void arnsetid(char **argv) { int realid,effid; displayids(); if (getargc(argv)!=3) { printf("usage: %s realid effectiveid\n",argv[0]); return; }; realid=atoi(argv[1]); effid=atoi(argv[2]); printf("trying to set: real id = %d , effective id = %d\n",realid,effid); if (setreuid(realid,effid)) { printf("failed\n"); perror("setreuid"); } else printf("success\n"); displayids(); return; } void arnsetgid(char **argv) { int realgid,effgid; displaygids(); if (getargc(argv)!=3) { printf("usage: %s realgid effectivegid\n",argv[0]); return; }; realgid=atoi(argv[1]); effgid=atoi(argv[2]); printf("trying to set: real gid = %d , effective gid = %d\n",realgid,effgid); if (setregid(realgid,effgid)) { printf("failed\n"); perror("setregid"); } else printf("success\n"); displaygids(); return; } void arnsetpgid(char **argv) { int pid,pgid; displaypids(); if (getargc(argv)!=3) { printf("usage: %s pid pgid\n",argv[0]); return; }; pid=atoi(argv[1]); pgid=atoi(argv[2]); printf("trying to set the process group of process %d to %d\n",pid,pgid); if (setpgid(pid,pgid)) { printf("failed\n"); perror("setpgid"); } else printf("success\n"); displaypids(); return; } void displayids() { printf("real uid = %d , effective uid = %d\n",getuid(),geteuid()); } void arnspawn(char **argv) { int argcdec; argcdec=(getargc(argv)-1); if (strcmp(argv[argcdec],"&")) aswait(argv); else { argv[argcdec]=NULL; asbg(argv); }; } void aswait(char **argv) { int childpid,waitstat,waitret; switch(childpid=fork()) { case -1 : printf("can not fork, :-(\n"); break; case 0 : arnexec(argv); default : printf("program forked, waiting for child process (%d) to exit.....\n",childpid); waitret=waitpid(childpid,&waitstat,0); printf("return value of wait : %d wait status : %d\n",waitret,waitstat); } } void asbg(char **argv) { int childpid; switch(childpid=fork()) { case -1 : printf("can not fork, :-(\n"); break; case 0 : arnexec(argv); default : printf("program forked, child process id : %d\n",childpid); sleep(1); } } void arnexec(char **argv) { int x,fdin,fdout,trunc,append; for(x=1,trunc=1;argv[x]!=NULL;x++) if(!(trunc=(strcmp(argv[x],"<")))) break; if (!trunc) { printf("redirecting stdin from filename >%s<\n",argv[x+1]); if ((fdin=open(argv[x+1],O_RDONLY))== -1) { perror("cannot open file"); printf("cannot open file for stdin, better luck next time ;-)\n"); exit(1); }; if (close(STDIN_FILENO)) { perror("cannot close"); printf("sorry but I'm confused again\n"); exit(1); }; if (dup(fdin)!=STDIN_FILENO) { printf("something wrong with dup(2), sorry but I'm out a here\n"); close(fdin); exit(1); }; if (close(fdin)) { perror("cannot close"); printf("sorry but I'm confused again\n"); exit(1); }; cutarg(x,argv); cutarg(x,argv); } for(x=1,trunc=1;argv[x]!=NULL;x++) if(!(trunc=(strcmp(argv[x],">")))) break; if (trunc) for(x=1,append=1;argv[x]!=NULL;x++) if(!(append=(strcmp(argv[x],">>")))) break; if ((!trunc)||(!append)) { printf("redirecting stdout to filename >%s<\n",argv[x+1]); if ((fdout=open(argv[x+1],O_WRONLY|O_CREAT|(trunc?0:O_TRUNC)|(append?0:O_APPEND),0666))== -1) { perror("cannot open file"); printf("cannot open file for stdout, better luck next time ;-)\n"); exit(1); }; if (close(STDOUT_FILENO)) { perror("cannot close"); printf("sorry but I'm confused again\n"); exit(1); }; if (dup(fdout)!= STDOUT_FILENO) { printf("something wrong with dup(2), sorry but I'm out a here\n"); close(fdout); exit(1); }; if (close(fdout)) { perror("cannot close"); printf("sorry but I'm confused again\n"); exit(1); }; cutarg(x,argv); cutarg(x,argv); }; if ((execvp(argv[0],argv))==-1) { printf("can not use command, sorry\n"); exit(1); }; printf("whats happened? exec has a strange return value! I'm confused ;-O\n"); exit(1); } void cutarg(int x,char **argv) { for(;argv[x]!=NULL;x++) argv[x]=argv[x+1]; } void displaypinfo() { displayids(); displaygids(); displaypids(); } void displaygids() { printf("real group id = %d , effective group id = %d\n",getgid(),getegid()); } void displaypids() { printf("pid = %d , parent pid = %d , process group = %d\n",getpid(),getppid(),getpgrp()); } void pwdatanam(char **argv) { struct passwd *a; if(getargc(argv)!=2) { printf("usage: %s username\n",*argv); return; }; if((a=getpwnam(argv[1]))==NULL) { printf("%s: cant get info\n",*argv); perror(*argv); return; }; printf("username=%s passwd=%s uid=%d gid=%d gecos=%s home=%s shell=%s\n", a->pw_name,a->pw_passwd,a->pw_uid,a->pw_gid,a->pw_gecos,a->pw_dir,a->pw_shell); } void pwdatauid(char **argv) { struct passwd *a; if(getargc(argv)!=2) { printf("usage: %s uid\n",*argv); return; }; if((a=getpwuid(atoi(argv[1])))==NULL) { printf("%s: cant get info\n",*argv); perror(*argv); return; }; printf("username=%s passwd=%s uid=%d gid=%d gecos=%s home=%s shell=%s\n", a->pw_name,a->pw_passwd,a->pw_uid,a->pw_gid,a->pw_gecos,a->pw_dir,a->pw_shell); } void displayhostinfo(char **argv) { int c; struct hostent *he; if(getargc(argv)!=2) { printf("usage: %s hostname\n",*argv); return; }; if((he=gethostbyname(argv[1]))==NULL) { printf("%s: error with gethostbyname\n",*argv); return; }; if(he->h_addrtype!=AF_INET) printf("warning, address returned is a type I dont know of\n"); printf("official name=\"%s\"\n",he->h_name); printf("length of address=%d\n",he->h_length); printf("aliases:\n"); for(c=0;he->h_aliases[c]!=NULL;c++) printf("\"%s\"\n",he->h_aliases[c]); printf("addresses:\n"); for(c=0;he->h_addr_list[c]!=NULL;c++) dispinetaddr(he->h_addr_list[c],he->h_length); } void dispinetaddr(char *a,int b) { int c; for(c=0;c