SMOLNET PORTAL home about changes
/********************************************************************
 * 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 <string.h> /* */
/* 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));
}


.
Response: text/plain
Original URLgopher://bitreich.org/0/gopher2007/2007-gopher-mirror/gop...
Content-Typetext/plain; charset=utf-8