ftp.nice.ch/pub/next/tools/archiver/Opener.3.4b.Utils.s.tar.gz#/Opener.3.4a.Utils.s/mpack/arcos.c

This is arcos.c in view mode; [Download] [Up]

/* (C) Copyright 1993,1994 by Carnegie Mellon University
 * All Rights Reserved.
 *
 * Permission to use, copy, modify, distribute, and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of Carnegie
 * Mellon University not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.  Carnegie Mellon University makes no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */
/* Based on dosos.c */
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include "xmalloc.h"
#include "common.h"

char *getParam();

int overwrite_files = 0;
int didchat;

/* The name of the file we're writing */
static char *output_fname = 0;

/* Characters that can be in filenames */
#define GOODCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_!'()+/=?[]`{|}~" /* some of those symbols are a tad dubious */

static unsigned long load, exec, acc;
static fLoad, fExec, fAcc; /* flags to say if each set */

/* RISC OS needs this to find filetype, etc */
/* Quite likely to be an empty function for many ports */
/* no longer a hook function - rework at some point */
os_parameterhook(contentParams)
params contentParams;
{
    fLoad=fExec=fAcc=0;
    if (contentParams) {
        char *p;
        p = getParam(contentParams, "load");
        if (p) {
            if (*p=='&')
                p++;
            load=strtoul(p,NULL,16);
            fLoad=1;
        }
        p = getParam(contentParams, "exec");
        if (p) {
            if (*p=='&')
                p++;
            exec=strtoul(p,NULL,16);
            fExec=1;
        }
        p = getParam(contentParams, "access");
        if (p) {
            if (*p=='&')
                p++;
            acc=strtoul(p,NULL,16);
            fAcc=1;
        }
    }
}

static char *dir=NULL;
static int offset[10];
static int fFirst=0;

os_boundaryhookopen(depth)
int depth;
{
/*    printf("((( %d '%s'\n",depth,dir?dir:"(null)"); */
    if (dir) {
        offset[depth]=strlen(dir);
    } else {
        offset[depth]=0;
    }
    if (depth>1)
        fFirst=1;
}

os_boundaryhookclose(depth)
int depth;
{
/*    printf("))) %d '%s'\n",depth,dir?dir:"(null)"); */
    if (dir) {
        dir[offset[depth+1]]='\0';
    }
}

/* Generate a message-id */
char *os_genid()
{
    static time_t curtime;
    static char *hostname;
    char *result;

    if (curtime == 0) {
	time(&curtime);

	hostname = getenv("HOSTNAME");
	if (!hostname) hostname="random-arc";
    }

    result = xmalloc(25+strlen(hostname));
    sprintf(result, "%lu@%s", curtime++, hostname);
    return result;
}

/* Create and return directory for a message-id */
char *os_idtodir(id)
char *id;
{
    static char buf[256];
    int len = 0;
    char *p;

    if (p = getenv("Wimp$ScrapDir")) {
	strncpy(buf, p, 201);
	buf[200] = '\0';		/* Ensure sufficiently short */
    }
    else {
	strcpy(buf, "/tmp");
	(void)mkdir(buf);
    }
    strcat(buf, "/mimeparts");
    (void)mkdir(buf);

    p = buf + strlen(buf);
    *p++ = '/';

    while (*id && len < 10) {
	if (strchr(GOODCHARS, *id)) {
/*	    if (len++ == 8) *p++ = '.'; */
	    *p++ = *id;
	}
	id++;
    }
    *p = '\0';
    if (mkdir(buf) == -1 && errno != EACCES) {
	perror(buf);
	return 0;
    }
    *p++ = '/';
    *p = '\0';
    return buf;
}

/*
 * We are done with the directory returned by os_idtodir()
 * Remove it
 */
os_donewithdir(dir)
char *dir;
{
    char *p;

    /* Remove trailing slash */
    p = dir + strlen(dir) - 1;
    *p = '\0';

    rmdir(dir);
}

/*
 * Create a new file, with suggested filename "fname".
 * "fname" may have come from an insecure source, so clean it up first.
 * It may also be null.
 * "contentType" is passed in for use by systems that have typed filesystems.
 * "flags" contains a bit pattern describing attributes of the new file.
 */
FILE *os_newtypedfile(fname, contentType, flags, contentParams)
char *fname;
char *contentType;
int flags;
params contentParams;
{
    char *p, *q;
    int len, sawdot;
    static int filesuffix=0;
    char buf[128], *descfname=0;
    FILE *outfile = 0;
    int fRISCOS=0;
    extern int __uname_control;
    int uname_control_old;

    os_parameterhook(contentParams);

    if (!fname) fname = "";
    len=strlen(fname);

    if (cistrcmp(contentType,"APPLICATION/RISCOS")==0) {
        fRISCOS=1; /* It's definitely RISC OS */
        /* check for directory */
        if (len>5) {
            if (strcmp(fname+len-5,",1000")==0 ||
                strcmp(fname+len-5,",2000")==0) {
                /* OK -- it's a RISC OS directory */
                int lendir=0;
                fname[len-5]='\0';
                if (dir) {
                    lendir=strlen(dir);
                    dir=xrealloc(dir,lendir+len-3);
                    if (lendir)
                        dir[lendir++]='.';
                    strcpy(dir+lendir,fname);
                } else {
                    dir=xmalloc(len);
                    strcpy(dir,fname);
                }
                {
                    int r[6];
                    r[4]=0;
                    if (os_file (0x08, dir, r)) {
                        printf("couldn't create '%s'\n",dir);
                    }
                }
/*                printf("&&& just mkdir(%s)-ed -- fFirst=%d\n",dir,fFirst); */
                if (!fFirst) {
                    if (lendir) lendir--;
                    dir[lendir]='\0';
                }
                fFirst=0;
                return NULL; /* ignore dummy message body */
            }
        }
    }
/*    printf("*** file '%s'\n*** type '%s'\n",fname,contentType?contentType:"(null)"); */
    fFirst=0;
    /* Turn of UnixLib name mangling as it goes wrong for "foo.c.bar" */
    uname_control_old=__uname_control;
    __uname_control|=1;

    /* lose any RISC OS filetype (3 hex digits) appended after a ',' */
    if (len>4 && fname[len-4]==',') {
        int x;
        fRISCOS=1;
        for( x=len-3 ; x<len ; x++ )
            if (!isxdigit(fname[x]))
                fRISCOS=0;
        if (fRISCOS)
            fname[len-4]='\0';
    }
    if (!fRISCOS) {
        /* Chop off any drive specifier, convert \ to / */
        if (*fname && fname[1] == ':') fname +=2;
        for (p = fname; *p; p++) if (*p == '\\') *p = '/';

        /* If absolute path name, chop to tail */
        if (*fname == '/') {
            p = strrchr(fname, '/');
            fname = p+1;
        }
    }
    /* similarly for RISC OS pathnames */
    if (strchr(fname,'$') || strchr(fname,'&') || strchr(fname,':')) {
        fRISCOS=1;
	p = strrchr(fname, '.');
	fname = p+1;
    }

    if (fRISCOS && dir && *dir) {
        char *p;
        p=xmalloc(strlen(fname)+strlen(dir)+2);
        strcpy(p,dir);
        strcat(p,".");
        strcat(p,fname);
        fname=p;
    }

    if (!fRISCOS) {
    /* Clean out bad characters, create directories along path */
    for (p=q=fname, len=sawdot=0; *p; p++) {
	if (*p == '/') {
	    if (!strncmp(p, "/../", 4)) {
		p[1] = p[2] = 'X';
	    }
	    *q = '\0';
	    (void) mkdir(fname);
	    *q++ = '/';
	    len = sawdot = 0;
	}
	else if (*p == '.' && !sawdot) {
	    *q++ = '.';
	    sawdot++;
	    len = 0;
	}
	else if (/*len < (sawdot ? 3 : 8) &&*/ strchr(GOODCHARS, *p)) {
	    *q++ = *p;
	    len++;
	}
    }
    *q = '\0';
    }

    if (!fname[0]) {
	do {
	    if (outfile) fclose(outfile);
	    sprintf(buf, "part%d", ++filesuffix);
	} while (outfile = fopen(buf, "r"));
	fname = buf;
    }
    else if (!overwrite_files && (outfile = fopen(fname, "r"))) {
	/* chop off suffix */
	p = strrchr(fname, '/');
	if (!p) p = fname;
	p = strchr(p, '.');
	if (p) *p = '\0';

	/* append unique number */
	do {
	    fclose(outfile);
	    sprintf(buf, "%s/%d", fname, ++filesuffix);

	} while (outfile = fopen(buf, "r"));
	fname = buf;
    }

    outfile = fopen(fname, (flags & FILE_BINARY) ? "wb" : "w");
    if (!outfile) {
        printf("++++ wouldn't open!!!!\n");
	perror(fname);
    }

    if (output_fname) free(output_fname);
    output_fname = strsave(fname);

    if (strlen(fname) > sizeof(buf)-6) {
	descfname = xmalloc(strlen(fname)+6);
    }
    else {
	descfname = buf;
    }
    strcpy(descfname, fname);

    p = strrchr(descfname, '/');
    if (!p) p = descfname;
    if (p = strrchr(p, '.')) *p = '\0';

    strcat(descfname, "/dsc");
    (void) rename(TEMPFILENAME, descfname);
    if (descfname != buf) free(descfname);

    fprintf(stdout, "%s (%s)\n", output_fname, contentType);
    didchat = 1;

    __uname_control=uname_control_old;
    return outfile;
}

/*
 * Close a file opened by os_newTypedFile()
 */
os_closetypedfile(outfile)
FILE *outfile;
{
    fclose(outfile);

    if (fLoad || fExec || fAcc) {
        unsigned long args[6];
        char *p;
        args[2]=load;
        args[3]=exec;
        args[5]=acc;
        if (fLoad && fExec && fAcc) {
/*            printf("%x %x %x\n",load,exec,acc); */
            p=(char*)os_file(1,output_fname,args);
            if (p) printf("Failed to set file type/date/access '%s'\n",p+4);
        } else {
            if (fLoad) {
                p=(char*)os_file(2,output_fname,args);
                if (p) printf("Failed to set file load addr '%s'\n",p+4);
            }
            if (fExec) {
                p=(char*)os_file(3,output_fname,args);
                if (p) printf("Failed to set file exec addr '%s'\n",p+4);
            }
            if (fAcc) {
                p=(char*)os_file(5,output_fname,args);
                if (p) printf("Failed to set file access perms '%s'\n",p+4);
            }
        }
    }
}

/*
 * (Don't) Handle a BinHex'ed file
 */
int
os_binhex(inpart, part, nparts)
struct part *inpart;
int part;
int nparts;
{
    return 1;
}

/*
 * Warn user that the MD5 digest of the last file created by os_newtypedfile()
 * did not match that supplied in the Content-MD5: header.
 */
os_warnMD5mismatch()
{
    char *warning;

    warning = xmalloc(strlen(output_fname) + 100);
    sprintf(warning, "%s was corrupted in transit",
	    output_fname);
    warn(warning);
    free(warning);
}

/*
 * Report an error (in errno) concerning a filename
 */
os_perror(file)
char *file;
{
    perror(file);
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.