/**************************************************************************** * NCSA Mosaic for the X Window System * * Software Development Group * * National Center for Supercomputing Applications * * University of Illinois at Urbana-Champaign * * 605 E. Springfield, Champaign IL 61820 * * mosaic@ncsa.uiuc.edu * * * * Copyright (C) 1993, Board of Trustees of the University of Illinois * * * * NCSA Mosaic software, both binary and source (hereafter, Software) is * * copyrighted by The Board of Trustees of the University of Illinois * * (UI), and ownership remains with the UI. * * * * The UI grants you (hereafter, Licensee) a license to use the Software * * for academic, research and internal business purposes only, without a * * fee. Licensee may distribute the binary and source code (if released) * * to third parties provided that the copyright notice and this statement * * appears on all copies and that no charge is associated with such * * copies. * * * * Licensee may make derivative works. However, if Licensee distributes * * any derivative work based on or derived from the Software, then * * Licensee will (1) notify NCSA regarding its distribution of the * * derivative work, and (2) clearly notify users that such derivative * * work is a modified version and not the original NCSA Mosaic * * distributed by the UI. * * * * Any Licensee wishing to make commercial use of the Software should * * contact the UI, c/o NCSA, to negotiate an appropriate license for such * * commercial use. Commercial use includes (1) integration of all or * * part of the source code into a product for sale or license by or on * * behalf of Licensee to third parties, or (2) distribution of the binary * * code or source code to third parties that need it to utilize a * * commercial product sold or licensed by or on behalf of Licensee. * * * * UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR * * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED * * WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE * * USERS OF THIS SOFTWARE. * * * * By using or copying this Software, Licensee agrees to abide by the * * copyright law and all other applicable laws of the U.S. including, but * * not limited to, export control laws, and the terms of this license. * * UI shall have the right to terminate this license immediately by * * written notice upon Licensee's breach of, or non-compliance with, any * * of its terms. Licensee may be held legally responsible for any * * copyright infringement that is caused or encouraged by Licensee's * * failure to abide by the terms of this license. * * * * Comments and questions are welcome and can be sent to * * mosaic-x@ncsa.uiuc.edu. * ****************************************************************************/ #include "../config.h" #include #include #ifndef VMS #include #include #include #include #include #endif #include #include #ifndef VMS #include #include #include #include #endif #ifdef RS6000 #include #endif #ifdef VMS #include #include #include #include #include #include #include #include #include #define $NEW_DESCRIPTOR(name) \ struct dsc$descriptor_s name = { \ 0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0 \ } #endif #include "system.h" /* Use builtin strdup when appropriate -- code duplicated in tcp.h. PGE */ #if defined(ultrix) || defined(VMS) || defined(NeXT) extern char *strdup(char *str); #endif #ifndef VMS extern int errno; #endif #ifndef DISABLE_TRACE int nutTrace=0; #endif int sleep_interrupt=0; int my_system(char *cmd, char *retBuf, int bufsize); char *my_strerror(int errornum); char **buildArgv(char *cmd, int *new_argc); char *findProgram(char *pname,char *spath); int my_sleep(int length, int interrupt); /*#define STANDALONE /* */ #undef STANDALONE /* */ #ifdef STANDALONE #ifndef VMS /* Completely different tests needed under VMS. PGE */ char *userPath={"/bin:/usr/bin:/sbin:/usr/sbin"}; int main(int argc, char **argv) { int retValue; char *cmd, *fnam, *lpr; char buf[BUFSIZ]; if (argc==3) { if (my_sleep(atoi(argv[1]),atoi(argv[2]))) { printf("Interrupted\n"); } else { printf("Not Interrupted\n"); } exit(0); } lpr = (char *)malloc (50); strcpy(lpr,"dsfs/usr/ucb/lpr"); fnam = (char *)malloc (50); strcpy(fnam,"/sdlfjsdusr5/spowers/.cshrc"); cmd = (char *)malloc ((strlen (lpr) + strlen (fnam) + 24)); sprintf (cmd, "%s %s", lpr, fnam); printf("Executing '%s'.\n",cmd); if ((retValue=my_system(cmd,buf,BUFSIZ))!=SYS_SUCCESS) { printf("-----\nError Code [%d]\n-----\n",retValue); } if (buf && *buf) { printf("------\n%s-----\n",buf); } else { printf("------\nNo output.\n------\n"); } } #else /* Copied from mo-www.c PGE */ #if defined(ultrix) || defined(VMS) || defined(NeXT) || defined(M4310) || defined(vax) char *strdup(char *str) { char *dup; if(!str) return NULL; dup = (char *)malloc(strlen (str) + 1); if(!dup) return NULL; dup = strcpy(dup, str); return dup; } #endif int main(int argc, char **argv) { int retValue; char *home_dir; char buffer [256]; char **argv2; int argc2; retValue = get_home (&home_dir); printf ("Home = \"%s\"\n retValue = %d\n\n", home_dir, retValue); free (home_dir); if (file_exists ("sys$login:login.com")) printf ("The file sys$login:login.com exists\n"); else printf ("The file sys$login:login.com does not exist\n"); if (file_exists ("sys$login:ipserngipnfb.sadfghth")) printf ("The file sys$login:ipserngipnfb.sadfghth exists\n\n"); else printf ("The file sys$login:ipserngipnfb.sadfghth does not exist\n\n"); buffer [0] = '\0'; retValue = my_system ("kdshlkw", buffer, 256); printf ("my_system kdshlkw\n"); printf (" gave \"%s\"\n retValue = %d\n\n", buffer, retValue); buffer [0] = '\0'; retValue = my_system ("dir *.*;0", buffer, 256); printf ("my_system dir *.*;0\n"); printf (" gave \"%s\"\n retValue = %d\n\n", buffer, retValue); buffer [0] = '\0'; retValue = my_copy ("argjhsrghjajh", "oijfdgath", buffer, 256, TRUE); printf ("my_copy argjhsrghjajh to oijfdgath\n"); printf (" gave \"%s\"\n retValue = %d\n\n", buffer, retValue); buffer [0] = '\0'; retValue = my_copy ("sys$login:login.com", "sys$login:login.copy", buffer, 256, TRUE); printf ("my_copy sys$login:login.com to sys$login:login.copy\n"); printf (" gave \"%s\"\n retValue = %d\n\n", buffer, retValue); printf ("Starting 5 second sleep\n"); retValue = my_sleep (5, TRUE); printf ("Ending 5 second sleep\n retValue = %d\n\n", retValue); printf ("errno == 1 => \"%s\"\n\n", my_strerror (1)); argv2 = buildArgv("abc def", &argc2); printf ("\"abc def\" => argc %d, argv [0] \"%s\", argv [1] \"%s\"\n\n", argc2, argv2 [0], argv2 [1]); free (*argv); free (argv); buffer [0] = '\0'; retValue = my_move ("sys$login:login.copy", "sys$login:login.move", buffer, 256, TRUE); printf ("my_move sys$login:login.copy to sys$login:login.move\n"); printf (" gave %s\n retValue = %d\n\n", buffer, retValue); retValue = my_system ("diff sys$login:login.com sys$login:login.move", buffer, 256); retValue = my_system ("delete/log/noconf sys$login:login.move;*", buffer, 256); buffer [0] = '\0'; retValue = my_move ("sys$manager:sylogin.com", "sys$login:sylogin.move", buffer, 256, TRUE); printf ("my_move sys$manager:sylogin.com to sys$login:sylogin.move\n"); printf (" gave %s\n retValue = %d\n\n", buffer, retValue); retValue = my_system ("diff sys$manager:sylogin.com sys$login:sylogin.move", buffer, 256); retValue = my_system ("dir/full sys$login:sylogin.move", buffer, 256); retValue = my_system ("delete/log/noconf sys$login:sylogin.move;*", buffer, 256); } #endif /*!VMS*/ #else extern char *userPath; #endif /* * Written by: Scott Powers and Brad Viviano * * Takes a string command, executes the command, returns the output of * the command (if any) in retBuf (passed in and pre-allocated). * * Returns one of the following: * SYS_SUCCESS - The command executed without incident. Note, this does not * necessarily mean the command was successful...e.g. some systems have * a shell script for "lpr". In this case, the shell that runs "lpr" will * execute fine, but the command "lp" which "lpr" calls may still fail. * SYS_NO_COMMAND - There was no command provided. * SYS_FORK_FAIL - The fork failed. * SYS_PROGRAM_FAILED - The exec could not start the program. * SYS_NO_RETBUF - There was no retBuf allocated. * SYS_FCNTL_FAILED - The set of NON_BLOCK on the parent end of the pipe * failed. */ int my_system(char *cmd, char *retBuf, int bufsize) { #ifndef VMS /* PGE */ char **sys_argv=NULL; int sys_argc; pid_t pid; int status,statusloc; int fds[2]; char buf[BUFSIZ]; char *path=NULL; if (!retBuf) { return(SYS_NO_RETBUF); } *retBuf='\0'; if (!cmd || !*cmd) { return(SYS_NO_COMMAND); } pipe(fds); if (fcntl(fds[0],F_SETFL,O_NONBLOCK)==(-1)) { #ifndef DISABLE_TRACE if (nutTrace) { perror("fcntl-nonblock"); } #endif return(SYS_FCNTL_FAILED); } if ((pid=fork())==(-1)) { return(SYS_FORK_FAIL); } else if (pid==0) { /*in child -- so don't worry about frees*/ sys_argv=buildArgv(cmd, &sys_argc); dup2(fds[1],1); dup2(fds[1],2); if (sys_argv!=NULL) { if (sys_argv[0] && sys_argv[0][0] && sys_argv[0][0]=='/') { path=strdup(sys_argv[0]); } else { path=findProgram(sys_argv[0],userPath); } execv(path,sys_argv); #ifndef DISABLE_TRACE if (nutTrace) { fprintf(stderr,"Exec of %s failed!\n",cmd); perror("exec"); } #endif } else { #ifndef DISABLE_TRACE if (nutTrace) { fprintf(stderr,"Could not build argv for [%s].\n",cmd); } #endif } exit(1); /*child*/ } else { int n; /*in parent*/ status=wait(&statusloc); n=read(fds[0],retBuf,bufsize-1); if (n>0) { retBuf[n]='\0'; } else { *retBuf='\0'; } close(fds[0]); close(fds[1]); if (*retBuf) { return(SYS_PROGRAM_FAILED); } return(SYS_SUCCESS); } #else /* VMS -- PGE */ unsigned int status; unsigned int completion_status; if (!retBuf) { return(SYS_NO_RETBUF); } *retBuf='\0'; if (!cmd || !*cmd) { return(SYS_NO_COMMAND); } { $NEW_DESCRIPTOR (cmd_desc); $NEW_DESCRIPTOR (retBuf_desc); unsigned short int string_end; cmd_desc.dsc$w_length = strlen (cmd); cmd_desc.dsc$a_pointer = cmd; retBuf_desc.dsc$w_length = bufsize - 1; retBuf_desc.dsc$a_pointer = retBuf; status = lib$spawn (&cmd_desc, 0, 0, 0, 0, 0, &completion_status); if (status != 1) return(SYS_FORK_FAIL); if ((completion_status & 1) != 1) { status = sys$getmsg (completion_status, &string_end, &retBuf_desc, 15, 0); retBuf [string_end] = '\0'; } } return(SYS_SUCCESS); #endif } /* * Written by: Scott Powers * * findProgram takes a program name and a path and searches it until: * a) The program name is found, at which time the full path is returned. * b) The end of the search path comes about, at which time NULL is returned. * */ char *findProgram(char *pname,char *spath) { #ifndef VMS /* Always return NULL on VMS. PGE */ char *start=NULL,*ptr=NULL,*endptr=NULL; char tryit[BUFSIZ]; struct stat buf; if (!spath || !*spath || !pname || !*pname) { return(NULL); } start=spath; while (start && *start) { ptr=start; endptr=strchr(start,':'); if (endptr) { start=endptr+1; *endptr='\0'; } else { start=NULL; } sprintf(tryit,"%s/%s",ptr,pname); if (!stat(tryit,&buf)) { return(strdup(tryit)); } } #endif /* VMS, PGE */ return(NULL); } /* * Written by: Scott Powers * * This will effectively get rid of the problem with using "/bin/mv" as it * first tries to use "rename". If that fails, it stores the error report * and then tries to actually copy the file. If that fails, it stores the * error report. If the copy fails then we return an error as well as copying * both error reports into "retBuf" so they can be displayed to the user. * * If "overwrite" is true, the destination file will automatically be * overwritten. If it is false and the file exists, my_move will return * SYS_FILE_EXISTS. It is up to the programmer to tell the user this. * * Return Values: * SYS_NO_SRC_FILE -- There was no source filename specified. * SYS_NO_DEST_FILE -- There was no destination filename specified. * SYS_NO_RETBUF -- There was no retBuf specified (not allocated). * SYS_DEST_EXISTS -- Overwrite was off and the destination exists. * SYS_NO_MEMORY -- No memory to allocate with. * SYS_SRC_OPEN_FAIL -- Open failed on the source file. * SYS_DEST_OPEN_FAIL -- Open failed on the destination file. * SYS_READ_FAIL -- The read call failed. * SYS_WRITE_FAIL -- The write call failed. * SYS_SUCCESS -- Success. */ int my_move(char *src, char *dest, char *retBuf, int bufsize, int overwrite) { int status, n_src=1, n_dest=1, fd_src, fd_dest, ret; char *rename_error=NULL, *copy_error=NULL; struct stat dest_stat; if (!retBuf) { return(SYS_NO_RETBUF); } if (!src || !*src) { strcpy(retBuf,"There was no source file specified.\n"); return(SYS_NO_SRC_FILE); } if (!dest || !*dest) { strcpy(retBuf,"There was no destination file specified.\n"); return(SYS_NO_DEST_FILE); } *retBuf='\0'; if (!overwrite) { #if defined(MULTINET) && defined(__alpha) if (decc$stat(dest,&dest_stat)) { #else if (stat(dest,&dest_stat)) { #endif /* Alpha DEC C couldn't find it otherwise ?????, GEC */ sprintf(retBuf,"Stat [%s] error:\n File already exists.\n",dest); return(SYS_DEST_EXISTS); } } if ((status=rename(src,dest))==(-1)) { /*manual copy -- prolly accross partitions*/ rename_error=strdup(my_strerror(errno)); if (!rename_error) { strcpy(retBuf,"There was no enough memory allocate.\n"); return(SYS_NO_MEMORY); } #if 0 if ((fd_src=open(src,O_RDONLY))==(-1)) { copy_error=strdup(my_strerror(errno)); if (!copy_error) { free(rename_error); strcpy(retBuf,"There was no enough memory allocate.\n"); return(SYS_NO_MEMORY); } if (strlen(rename_error)>bufsize) { fprintf(stderr,"%s\n",rename_error); } else { sprintf(retBuf,"Rename([%s] to [%s]) error:\n %s\n\n",src,dest,rename_error); } free(rename_error); if (strlen(copy_error)>(bufsize-strlen(retBuf))) { fprintf(stderr,"%s\n",copy_error); } else { sprintf(retBuf,"%sCopy([%s] to [%s]) error:\n %s\n\n",retBuf,src,dest,copy_error); } free(copy_error); return(SYS_SRC_OPEN_FAIL); } if ((fd_dest=open(dest,O_WRONLY|O_CREAT,0644))==(-1)) { copy_error=strdup(my_strerror(errno)); if (!copy_error) { free(rename_error); strcpy(retBuf,"There was no enough memory allocate.\n"); return(SYS_NO_MEMORY); } if (strlen(rename_error)>bufsize) { fprintf(stderr,"%s\n",rename_error); } else { sprintf(retBuf,"Rename([%s] to [%s]) error:\n %s\n\n",src,dest,rename_error); } free(rename_error); if (strlen(copy_error)>(bufsize-strlen(retBuf))) { fprintf(stderr,"%s\n",copy_error); } else { sprintf(retBuf,"%sCopy([%s] to [%s]) error:\n %s\n\n",retBuf,src,dest,copy_error); } free(copy_error); close(fd_src); return(SYS_DEST_OPEN_FAIL); } /*both file open and ready*/ while (n_src>0) { n_src=read(fd_src,buf,BUFSIZ-1); if (n_src>0) { n_dest=write(fd_dest,buf,n_src); if (n_dest>0) { continue; } close(fd_src); close(fd_dest); sprintf(retBuf,"Write([%s]) error:\n %s\n\n",dest,my_strerror(errno)); return(SYS_WRITE_FAIL); } if (!n_src) { continue; } close(fd_src); close(fd_dest); sprintf(retBuf,"Read([%s]) error:\n %s\n\n",src,my_strerror(errno)); return(SYS_READ_FAIL); } close(fd_src); close(fd_dest); #endif if ((ret=my_copy(src, dest, retBuf, bufsize, overwrite))==SYS_SUCCESS) { /* Now get rid of previous file */ unlink(src); } return(ret); } /* Now get rid of previous file */ unlink(src); return(SYS_SUCCESS); } /* * Written by: Scott Powers * * Some systems do not have a "strerror" function. This covers all the bases. */ char *my_strerror(int errornum) { return(strerror(errornum)); } /* * Written by: Brad Viviano and Scott Powers * * Takes a 1d string and turns it into a 2d array of strings. * * Watch out for the frees! You must free(*argv) and then free(argv)! NOTHING * ELSE!! Do _NOT_ free the individual args of argv. */ char **buildArgv(char *cmd, int *new_argc) { char **new_argv=NULL; char *buf=NULL,*tmp=NULL; int i=0; if (!cmd && !*cmd) { *new_argc=0; return(NULL); } for(tmp=cmd; isspace(*tmp); tmp++); buf=strdup(tmp); if (!buf) { *new_argc=0; return(NULL); } tmp=buf; new_argv=(char **)calloc(1,sizeof(char *)); if (!new_argv) { free(buf); *new_argc=0; return(NULL); } new_argv[0]=NULL; while (*tmp) { if (!isspace(*tmp)) { /*found the begining of a word*/ new_argv[i]=tmp; for (; *tmp && !isspace(*tmp); tmp++); if (*tmp) { *tmp='\0'; tmp++; } i++; new_argv=(char **)realloc(new_argv,((i+1)*sizeof(char *))); new_argv[i]=NULL; } else { tmp++; } } *new_argc=i; return(new_argv); } /* * Written by: Scott Powers * * Takes an integer which is the number of seconds to sleep and an integer * which is a boolean for whether to interrupt the sleep or not. * * This function sleeps for X seconds. It is interruptable. * * Returns a 1 of interrupted (and allowed to interrupt) or 0 when done * sleeping. * * Note that this is not _really_ _truly_ _exact_ as it is does perform some * condition checking inbetween each 100 milliseconds. But...it's pretty * darn close. */ int my_sleep(int length, int interrupt) { int count=0; int num; #ifndef VMS /* PGE */ struct timeval timeout; #else unsigned char interval [8]; /* 64 bit VMS time */ char string_interval_data [] = "0 00:00:00.10"; /* 100msec. */ $NEW_DESCRIPTOR (string_interval); string_interval.dsc$w_length = strlen (string_interval_data); string_interval.dsc$a_pointer = string_interval_data; /* Convert string time into binary format. */ sys$bintim (&string_interval, &interval); #endif sleep_interrupt=0; length*=1000000; while (count(bufsize-strlen(retBuf))) { fprintf(stderr,"%s\n",copy_error); } else { sprintf(retBuf,"%sCopy([%s] to [%s]) error:\n %s\n\n",retBuf,src,dest,copy_error); } free(copy_error); return(SYS_SRC_OPEN_FAIL); } if ((fd_dest=open(dest,O_WRONLY|O_CREAT,0644))==(-1)) { copy_error=strdup(my_strerror(errno)); if (!copy_error) { strcpy(retBuf,"There was not enough memory allocate.\n"); return(SYS_NO_MEMORY); } if (strlen(copy_error)>(bufsize-strlen(retBuf))) { fprintf(stderr,"%s\n",copy_error); } else { sprintf(retBuf,"%sCopy([%s] to [%s]) error:\n %s\n\n",retBuf,src,dest,copy_error); } free(copy_error); close(fd_src); return(SYS_DEST_OPEN_FAIL); } /*both files open and ready*/ while (n_src>0) { n_src=read(fd_src,buf,BUFSIZ-1); if (n_src>0) { n_dest=write(fd_dest,buf,n_src); if (n_dest>0) { continue; } close(fd_src); close(fd_dest); sprintf(retBuf,"Write([%s]) error:\n %s\n\n",dest,my_strerror(errno)); return(SYS_WRITE_FAIL); } if (!n_src) { continue; } close(fd_src); close(fd_dest); sprintf(retBuf,"Read([%s]) error:\n %s\n\n",src,my_strerror(errno)); return(SYS_READ_FAIL); } close(fd_src); close(fd_dest); #else /* VMS, PGE */ cmd = malloc(sizeof(char) * (20 + strlen(src) + strlen(dest))); if(!cmd) return(SYS_NO_MEMORY); sprintf(cmd, "copy$$/noconf/nolog %s %s", src, dest); ret = my_system(cmd, retBuf, bufsize); free(cmd); return ret; #endif /* VMS, PGE */ return(SYS_SUCCESS); } /* * Written by: Tommy Reilly (originally by Scott Powers I think) * * This is a function that finds the users home directory. * * Return Values: * SYS_NO_MEMORY -- No memory to allocate with. * SYS_INTERNAL_FAIL -- Not an error that user would want to know about. * SYS_SUCCESS -- Success. */ int get_home(char **ret) { #ifndef VMS /* PGE */ char *home = NULL; struct passwd *pwdent; if(!(home = getenv("HOME"))) { if (!(pwdent=getpwuid(getuid()))) { fprintf(stderr, "Could not find home dir.\n"); *ret=NULL; return(SYS_INTERNAL_FAIL); } else { /* home = malloc(sizeof(char) * (strlen(pwdent->pw_dir) + 1)); if(!home) { *ret=NULL; return(SYS_NO_MEMORY); } strcpy(home, pwdent->pw_dir); */ home=strdup(pwdent->pw_dir); } } else { home=strdup(home); } if(home) *ret = home; /* he better free it */ else { *ret = NULL; return(SYS_INTERNAL_FAIL); } #else /* VMS, PGE */ typedef struct { unsigned short int length; unsigned short int code; char *buffer; unsigned short int *return_length; } ITEMLIST; int status; ITEMLIST item_list [2]; char translated_home_data [256]; unsigned short int translated_home_length; char logical_table_data [] = "LNM$FILE_DEV"; char home_data [] = "SYS$LOGIN"; $NEW_DESCRIPTOR (logical_table); $NEW_DESCRIPTOR (home_logical); /* Setup values to pass into sys$trnlnm */ logical_table.dsc$w_length = strlen(logical_table_data); logical_table.dsc$a_pointer = logical_table_data; home_logical.dsc$w_length = strlen(home_data); home_logical.dsc$a_pointer = home_data; /* Setup values to return from sys$trnlnm */ item_list[0].code = LNM$_STRING; item_list[0].length = 256; item_list[0].buffer = translated_home_data; item_list[0].return_length = &translated_home_length; item_list[1].code = 0; item_list[1].length = 0; /* translate SYS$LOGIN logical to DISK:[DIRECTORY] */ status = sys$trnlnm (0, &logical_table, &home_logical, 0, item_list); if (status != 1) { printf ("Status = %d", status); return(SYS_INTERNAL_FAIL); } /* Convert to null terminated C style string. */ translated_home_data [translated_home_length] = '\0'; *ret = strdup(translated_home_data); /* he better free it */ if(!(*ret)) return(SYS_NO_MEMORY); #endif /* VMS, PGE */ return(SYS_SUCCESS); }