/******************************************************************** * wilkinson * 3.18VMS * 1995/09/25 14:40 * gopher_root1:[gopher.g2.vms2_13.gopherd]special.c,v * Exp * * Paul Lindner, University of Minnesota CIS. * * Copyright 1991, 1992 by the Regents of the University of Minnesota * see the file "Copyright" in the distribution for conditions of use. ********************************************************************* * MODULE: special.c * routines to deal with special types of files, compressed, scripts, etc. ********************************************************************* * Revision History: * special.c,v * Revision 3.18VMS 1995/09/25 14:40 wilkinson * Consolodate VMS/Unix source code for server as well as client * * Revision 3.18 1994/07/21 04:08:29 lindner * Bulletproofing for shell scripts * * Revision 3.17 1994/04/25 20:49:11 lindner * Fix for debug code * * Revision 3.16 1994/04/14 15:48:54 lindner * Fix for files with single quotes * * Revision 3.15 1993/11/03 03:32:52 lindner * Test shell scripts for exec bit * * Revision 3.14 1993/08/19 20:52:30 lindner * Mitra comments * * Revision 3.13 1993/08/11 22:47:11 lindner * Don't let the security stuff trap ask blocks * * Revision 3.12 1993/08/06 14:30:49 lindner * Fixes for better security logging * * Revision 3.11 1993/08/04 22:14:54 lindner * Mods to use Gpopen * * Revision 3.10 1993/08/04 22:12:51 lindner * Mods to use Gpopen * * Revision 3.9 1993/07/27 05:27:59 lindner * Mondo Debug overhaul from Mitra * * Revision 3.8 1993/07/25 02:56:51 lindner * Fixed iscompressed() to return NULL * * Revision 3.7 1993/07/23 03:18:13 lindner * Mods for using decoder:'s * * Revision 3.6 1993/07/07 19:35:36 lindner * removed extra args to popen() * * Revision 3.5 1993/06/22 06:58:53 lindner * Added a little debug code.. * * Revision 3.4 1993/06/11 16:46:50 lindner * Support for gzipped files * * Revision 3.3 1993/04/09 15:00:19 lindner * Fixes for ask shell scripts, ensure that they're run in the current * directory of the script. * * Revision 3.2 1993/03/24 20:24:23 lindner * Addition for compressed file support rfopenz() * * Revision 3.1.1.1 1993/02/11 18:02:53 lindner * Gopher+1.2beta release * * Revision 1.3 1993/02/09 22:15:36 lindner * additions for askfile * * Revision 1.2 1993/01/30 23:57:44 lindner * Additions for ASK block support. * * Revision 1.1 1992/12/10 23:13:27 lindner * gopher 1.1 release * * *********************************************************************/ #ifdef VMS_SERVER #define GSGOPHEROBJ_C /* Right now, DEC C v5.0 seems to ignore the angle brackets and pull in [-.object]string.h instead of the system version of string.h, which we need here. But all we need it for is a prototype of strchr(), so we'll put that in by hand to get around this for now */ #include /* */ /* char *strchr (const char *__s, int __c); /* */ #endif #include "gopherd.h" #ifdef VMS_SERVER #undef GSGOPHEROBJ_C #include "serverutil.h" #endif #include "ext.h" #include "Debug.h" char *iscompressed(); /* Check to see if this file needs special treatment before heading * back to the client... We will check for: * Encoded files execute decoder... * Shellscript if so, "do it" * (add ask block params if exists..) * Note: it would be somewhat non-portable to check of a binary * (we'd need to check for so many different magic numbers; the * shell script designation should be sufficient, since the script * can call an executable anyway * Recognized elsewhere: * .snd needs special processing on client * uuencoded needs special processing on client * Other filetypes we could check for: * GIF -> Bring up GIF previewer * Postscript -> Bring up Postscript previewer */ static int ispipe; #ifdef VMS_SERVER /* Provide a VMS way of doing popen() */ FILE * vms_popen(char *cmd, char *mode) { int vms_pipe_status; FILE *fopen_VMSopt(char *, char *, char *, char *); if (((vms_pipe_status = VMS$system(cmd)) &1)==1) return(fopen_VMSopt(vms_pipe_file,mode,"","")); if (access(vms_pipe_file, 0) == 0) unlink(vms_pipe_file); vms_pipe_file[0] = '\0'; return((FILE *)(0)); } /* Provide a VMS way of doing pclose() */ int vms_pclose(FILE *fp) { int vms_pipe_status; vms_pipe_status = fclose(fp); if (strlen(vms_pipe_file)!=0) unlink(vms_pipe_file); vms_pipe_file[0] = '\0'; return(vms_pipe_status); } #endif FILE * specialfile(sockfd, fp, pathname) int sockfd; FILE *fp; char *pathname; { FILE *pp; static char buf[256]; char s[256], *cp; long i; char *decoder; #ifdef VMS_SERVER char *VMS$Validate_Filespec(char *); #endif ispipe = 0; /* Keep track of where we are */ i = ftell(fp); rewind(fp); /* Grab the first line or 254 bytes, and rewind */ if (fgets(s, 255, fp) == NULL) return (FILE *)0; fseek(fp, i, 0); /* Compressed? */ if ((decoder = iscompressed(pathname)) != NULL) { #ifndef VMS_SERVER dequote1(pathname); if (dochroot) sprintf(buf, "%s '%s'", decoder, pathname); else sprintf(buf, "%s '%s/%s'", decoder, Data_Dir, pathname); #else /* Need to set up buf & vms_pipe_file for VMS decoding here */ #endif Debug("Executing decoder %s\n",buf); pp = popen(buf, "r"); if (!pp) return (FILE *)0; ispipe = 1; return pp; } /* Script? */ #ifndef VMS_SERVER if (isshellscript(s) && isexec(fileno(fp))) { dequote1(pathname); s[strlen(s)-1] = '\0'; if (dochroot) sprintf(buf, "\"%s\" %s", pathname, (EXECargs == NULL) ? "" : EXECargs); else sprintf(buf, "\"%s/%s\" %s", Data_Dir, pathname, (EXECargs == NULL) ? "" : EXECargs); if (ASKfile != NULL) { /* Ick this is a global*/ strcat(buf, " < "); strcat(buf, ASKfile); } else strcat(buf, " < /dev/null "); /* * Okay, let's change our working directory for the benefit of * shell script writers everywhere :-) */ strcpy(s, pathname); cp = strrchr(s, '/'); if (cp != NULL && cp > s) { *cp = '\0'; ; } else strcpy(s, "/"); rchdir(s); #else if (isshellscript(s, pathname)) { strcpy(vms_pipe_file, pathname); if ((cp=strchr(vms_pipe_file,' '))!=NULL) *cp = '\0'; if (VMS$Validate_Filespec(vms_pipe_file)==NULL) { vms_pipe_file[0] = '\0'; return (FILE *)(ispipe=0); } strcpy(vms_pipe_file, cp=tempnam(GDCgetScratchDir(Config),NULL)); free(cp); sprintf(buf, "$ @%s/output=%s", pathname, vms_pipe_file); if (ASKfile != NULL) { strcat(buf, "/input="); /** JLW - I know this won't work */ strcat(buf, ASKfile); /** just a placeholder, really **/ } if (EXECargs != NULL) { strcat(buf, " \""); strcat(buf, EXECargs); strcat(buf, "\""); } #endif Debug("Executing %s\n", buf); if (EXECargs) { if (! (pp = Gpopen(sockfd, buf, "r"))) return (FILE *)0; } else { if (! (pp = popen(buf, "r"))) return (FILE *)0; } ispipe = 1; Debugmsg("Zcat/popen is okay\n"); return pp; } return (FILE *)0; } char * iscompressed(pathname) char *pathname; { static Extobj *ext = NULL; if (pathname == NULL || strlen(pathname)==0) return(NULL); if (ext == NULL) ext = EXnew(); if (EXAcasedSearch(Config->Extensions, ext, pathname, EXT_DECODER)) return(EXgetDecoder(ext)); return(NULL); } /* * Is this a shell script? */ #ifndef VMS_SERVER int isshellscript(s) char *s; { if (! strncmp(s, "#!", 2)) return 1; else return 0; } #else int isshellscript(char *s, char *path) { if (strncasecmp(path+strlen(path)-strlen(".SCRIPT"),".SCRIPT")!=0) return 0; if (! strncmp(s, "$!", 2)) return 1; else return 0; } #endif #ifndef VMS_SERVER /* * Are the exec bits set? */ int isexec(fd) int fd; { STATSTR sb; if (fstat(fd, &sb) == -1) return 0; if (sb.st_mode & S_IXUSR) return 1; else return 0; } #endif int Specialclose(fp) FILE *fp; { if (ASKfile != NULL) /* Ick this is a global*/ unlink(ASKfile); if (ispipe) return(pclose(fp)); else return(fclose(fp)); } .