DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T s

⟦4df9ef80a⟧ TextFile

    Length: 6414 (0x190e)
    Types: TextFile
    Names: »shrink.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/shrink/shrink.c« 

TextFile

/*
 *	Rename a file so's it will be unique under systems without
 *	extended filename size.
 *	The new name is written on the stardard output.
 *
 *	Example:
 *		To copy lots of files from a 4.?BSD system to a
 *		SystemV, SystemIII, 2.?BSD or V7 system, without
 *		having to worry about overlapping filenames
 *		(eg, so "what_a_long_filename.c" and "what_a_long_filename.h"
 *		don't get squished), just do
 *			for i in *
 *			do
 *				j=`shrink -m $i`
 *				uucp $j othersys!/stuff/$j  (or rcp, hhcp, ...)
 *			done
 *
 *	Bug:	It gets overenthusiastic and deletes characters
 *	    	unnecessarily if the filename begins with a "."
 *
 *	Author:
 *		Simon Brown
 *		Department of Computer Science, University of Edinburgh.
 */

#include <stdio.h>

/*
 *	maximum no. of "segments" allowed in a file 
 */
#define MAXSEGS 10

/*
 *	silly names for strchr/strrchr under non-usg unices
 */
#ifndef sysV
#define strchr	index
#define strrchr	rindex
#endif sysV

char *getsegment();
char *strchr(), *strrchr();

struct segment {
	char seg_string[63];
	char seg_sep;
} seg[MAXSEGS];

char defaults[] = "._+-,@~=";
char usagemsg[] = "Usage: %s [-<maxlength>] [-mnSv] [-s<separators>] filename ...\n";

int max = 14;			/* target length */
int nocheck = 0;		/* don't check for existance (-n flag) */
int chatty = 0;			/* talk a lot (-v flag) */
int silent = 0;			/* don't say anything (-s flag) */
int move = 0;			/* rename file (-m flag) */
char *file, *prefix;
int modified = 0;
char realname[512];
char *separators = defaults;

main(argc,argv)
char **argv;
{
	register int i, j;
	int nsegs, suflen, remainder, delete;
	int total;
	int zap = 0;
	register char *op;
	char *progname = argv[0];

	if (argv[1] == (char *)0){
		fprintf(stderr, usagemsg, progname);
		exit(1);
	}
	while (*++argv)		/* process command-line options... */
		if (**argv=='-')
			while (*++*argv)
				switch(**argv){
				   case '0': case '1': case '2':
				   case '3': case '4': case '5':
				   case '6': case '7': case '8':
				   case '9':	/* change target length */
					max = atoi(*argv);
					if (max<=0){
						fprintf(stderr,"%s: illegal length %s\n", argv[0], argv[1]);
						exit(1);
					}
					while (*++*argv);
					--*argv;
					break;
				   case 's':	/* change separator definition */
					separators = ++*argv;
					while (*++*argv);
					--*argv;
					break;
				   case 'n':	/* don't create a uniquely named file */
					nocheck=1;
					break;
				   case 'v':	/* talk a lot */
					chatty=1;
					break;
				   case 'm': 	/* move files */
					move=1;
					break;
				   case'S':	/* silent */
					silent=1;
					break;
				   default:
					fprintf(stderr,usagemsg,progname);
					exit(1);
				}
		else break;
	while (*argv){
		strcpy(realname, *argv);
		if (prefix=strrchr(*argv,'/')){		/* dir/.../file */
			file=prefix+1;
			*prefix = '\0';
			prefix = *argv;
		} else file = *argv;
		argv++;
		op=file;
		modified=0;
		/* split into logical parts */
		for (i=0; i<MAXSEGS && (op=getsegment(op,i)); i++);
		if (i==MAXSEGS){
			fprintf(stderr,"%s: too many segments\n", file);
			continue;
		}
		nsegs = i-1;
		if ((nsegs*2) >= max){
			fprintf(stderr,"%s: too many segments\n", file);
			continue;
		}
		suflen = strlen(seg[nsegs].seg_string);
		if (suflen>max-nsegs-1){
			if (chatty)
				fprintf(stderr,"warning: %s: suffix truncated\n", file);
			suflen = max-(2*nsegs)-1;
			seg[nsegs].seg_string[suflen-1] = '\0';
			modified=1;
		} else if (suflen+nsegs > max-nsegs-1){
			zap = nsegs - (max-suflen)/2;
			if (chatty && zap)
				fprintf(stderr,"warning: %s: %d segments removed\n", file, zap);
		}
		if (nsegs>=1){		/* complicated filename */
			for (i=zap+1; i<=nsegs; i++)
				if (seg[i].seg_sep) suflen++;
			if (seg[0].seg_sep) suflen++;
			remainder = max - suflen;
			delete = remainder/nsegs;
			total = suflen;
			for (i=zap+1; i<nsegs; i++){
				if (strlen(seg[i].seg_string) > delete)
					modified=1;
				seg[i].seg_string[delete] = '\0';
				total += delete;
			}
			if (strlen(seg[0].seg_string) > max-total)
				modified=1;
			seg[0].seg_string[max-total] = '\0';
		}
		unique(zap,nsegs,modified);
	}
}

/*
 *	get a segment from a filename.
 *	returns pointer to remainder of filename, or 0 at end of filename
 */
char *
getsegment(cp,i)
char *cp;
{
	register char *xp = seg[i].seg_string;
	while (*cp && strchr(separators,*cp)==0)
		*xp++ = *cp++;
	*xp = '\0';
	seg[i].seg_sep = *cp;
	if (*cp) cp++;
	if (seg[i].seg_string[0] || seg[i].seg_sep) return(cp);
	else return((char *)0);
}

	
/*
 *	print out the current filename in a unique form
 */
unique(zap,n,mod)
{
	register int i, j;
	int jmax[MAXSEGS];
	int xstart, xstop;

	if (ok(zap,zap||mod)) return;
	xstart = (n==0)? 0 : 1;
	xstop = (n==0)? 1 : n;
    more:
	if (xstop <= xstart){
		xstart=0;
		xstop = n+1;
	}
	for (i=xstart; i<xstop; i++)
		jmax[i] = strlen(seg[i].seg_string);
	for (j=0; j<5; j++){
		for (i=xstart; i<xstop; i++){
			if (j >= jmax[i]) continue;
			increment(seg[i].seg_string,j);
			if (ok(zap,1)) return;
		}
	}
	if (xstart>0 || xstop<n+1){	/* Desparation time: try _any_ segment! */
		xstop = -1;
		goto more;
	}
	fprintf(stderr,"Can't generate unique name for %s\n", file);
}

/*
 *	modify a character in a string (stupid algorithm)
 */
increment(str,ind)
char *str;
{
	char ch = str[ind];

	if (ch>='a' && ch<='z') ch += ('A'-'a');
	else if (ch>='A' && ch<='Z') ch += ('a'-'A');
	str[ind] = ch;
}


/*
 *	see if a filename is reasonable, and if so print it out
 *	and return 1.
 *	otherwise return 0.
 */
ok(zap,changed)
{
	char buffer[512];
	register char *cp = buffer;
	register char *xp;
	register int i;

	if (prefix){
		for (xp=prefix; *xp; )
			*cp++ = *xp++;
		*cp++ = '/';
	}
	for (xp=seg[0].seg_string; *xp; )	/* copy initial segment */
		*cp++ = *xp++;
	if (seg[0].seg_sep){
		*cp++ = seg[0].seg_sep;
		for (i=zap+1; ; i++){		/* copy rest of segments */
			for (xp=seg[i].seg_string; *xp; )
				*cp++ = *xp++;
			if (seg[i].seg_sep) *cp++ = seg[i].seg_sep;
			else if (seg[i].seg_string[0] == '\0') break;
		}
	}
	*cp = '\0';
	if (changed && nocheck==0 && access(buffer,0)==0){
		if (chatty)
			fprintf(stderr,"warning: %s already exists - trying again\n",buffer);
		return(0);
	} else {
		if (silent==0) printf("%s\n", buffer);
		if (move && strcmp(realname,buffer)){
			if (link(realname,buffer)==-1 || unlink(realname)==-1)
				fprintf(stderr,"%s: link/unlink failure\n", realname);
		}
		return(1);
	}
}