home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
archiver
/
uucosr10
/
decode.c
next >
Wrap
C/C++ Source or Header
|
1991-06-01
|
9KB
|
440 lines
/*
* The uudecoding module, stripped and modified from Dumas' UUD
* with GEM routines added.
*/
#include <stdio.h>
#include <string.h>
#define MAXCHAR 256
#define LINELEN 256
#define FILELEN 128
#define NORMLEN 60 /* allows for 80 encoded chars per line */
#define MAXFILES 32
#define ifname if_name
#define ofname of_name
#define SEQMAX 'z'
#define SEQMIN 'a'
extern FILE *fopen();
extern char *strcpy();
extern char *strcat();
char *getnword();
char seqch;
int first, secnd, check, numl;
FILE *in, *out;
char *pos;
char *curarg;
char ifname[FILELEN], ofname[FILELEN];
int filenumber = 0;
char blank, partc = '\0';
int partn, lens;
int onedone = 0;
int chtbl[MAXCHAR], cdlen[NORMLEN + 3];
char lnbuf[128]; /* scratchpad for sprintf use */
int
decode(ifname) char *ifname;
{
int mode;
register int i, j;
char dest[FILELEN], buf[LINELEN];
if ((in = fopen(ifname, "r")) == NULL)
{
form_alert(1,"[1][Unable to open|the input file][ABORT]");
return;
}
disp_process(ifname);
/*
* Set up the default translation table.
*/
for (i = 0; i < ' '; i++) chtbl[i] = -1;
for (i = ' ', j = 0; i < ' ' + 64; i++, j++) chtbl[i] = j;
for (i = ' ' + 64; i < MAXCHAR; i++) chtbl[i] = -1;
chtbl['`'] = chtbl[' ']; /* common mutation */
chtbl['~'] = chtbl['^']; /* an other common mutation */
blank = ' ';
/*
* set up the line length table, to avoid computing lotsa * and / ...
*/
cdlen[0] = 1;
for (i = 1, j = 5; i <= NORMLEN; i += 3, j += 4)
cdlen[i] = (cdlen[i + 1] = (cdlen[i + 2] = j));
/*
* search for header or translation table line.
*/
for(;;)
{ /* master loop for multiple decodes in one file */
partn = 'a';
for(;;)
{
if (fgets(buf, sizeof buf, in) == NULL) /* end of file */
{
if(onedone)
{
return;
}
else
{
form_alert(1,"[1][Out of data...|No \"begin\" line][ABORT]");
return;
}
}
numl++;
if (strncmp(buf, "table", 5) == 0)
{
gettable();
continue;
}
if (strncmp(buf, "begin ", 6) == 0)
break;
if (strncmp(buf, "BEGIN", 5) == 0)
continue;
}
lens = strlen(buf);
if (lens) buf[--lens] = '\0';
if ((pos = getnword(buf, 3)))
{
strcpy(dest, pos);
}
else
{
form_alert(1,"[1][No filename|in \"begin\" line][ABORT]");
return;
}
/* NEED CODE HERE FOR USER TO EDIT DESTINATION LINE */
strcpy(ofname, dest);
if((out = fopen(ofname, "wb")) == NULL)
{
sprintf(lnbuf,"[1][Cannot open|output file|%s][ABORT]",
ofname);
form_alert(1,lnbuf);
return;
}
seqch = SEQMAX;
check = 1;
first = 1;
secnd = 0;
uudecode();
fclose(out);
onedone = 1;
} /* master loop for multiple decodes in one file */
}
/*
* Bring back a pointer to the start of the nth word.
*/
char *getnword(str, n) register char *str; register int n;
{
while((*str == '\t') || (*str == ' ')) str++;
if (! *str) return NULL;
while(--n)
{
while ((*str != '\t') && (*str != ' ') && (*str)) str++;
if (! *str) return NULL;
while((*str == '\t') || (*str == ' ')) str++;
if (! *str) return NULL;
}
return str;
}
/*
* Install the table in memory for later use.
*/
gettable()
{
char buf[LINELEN];
register int c, n = 0;
register char *cpt;
for (c = 0; c <= MAXCHAR; c++) chtbl[c] = -1;
for(;;)
{
if (fgets(buf, sizeof buf, in) == NULL)
{
form_alert(1,"[1][Unexpected EOF|in translation table][ABORT]");
return(-1);
}
numl++;
if (strncmp(buf, "begin", 5) == 0)
{
form_alert(1,"[1][Incomplete|translation table][ABORT]");
return(-1);
}
cpt = buf + strlen(buf) - 1;
*cpt = ' ';
while (*(cpt) == ' ')
{
*cpt = 0;
cpt--;
}
cpt = buf;
while (c = *cpt)
{
if (chtbl[c] != -1)
{
form_alert(1,"[1][Duplicate char|in translation table][ABORT]");
return(-1);
}
if (n == 0) blank = c;
chtbl[c] = n++;
if (n >= 64) return;
cpt++;
}
}
}
/*
* copy from in to out, decoding as you go along.
*/
uudecode()
{
char buf[LINELEN], outl[LINELEN];
register char *bp, *ut;
register int *trtbl = chtbl;
register int n, c, rlen;
register unsigned int len;
for(;;)
{
if (fgets(buf, sizeof buf, in) == NULL)
{
form_alert(1,"[1][EOF before end|of encoded data][ABORT]");
fclose(out);
return(-1);
}
numl++;
/*
* end of uuencoded file ?
*/
if (strncmp(buf, "END", 3) == 0)
{
for(;;)
{
/* look for another file */
if (fgets(buf, sizeof buf, in) == NULL)
{
fclose(out);
return(-1);
}
if (strncmp(buf, "BEGIN", 5) == 0) break;
}
if (fgets(buf, sizeof buf, in) == NULL)
{
form_alert(1,"[1][EOF right after BEGIN][ABORT]");
fclose(out);
return(-1);
}
}
len = strlen(buf);
if (len) buf[--len] = '\0';
/*
* Is it an unprotected empty line before the end line ?
*/
if (len == 0) continue;
/*
* Get the binary line length.
*/
n = trtbl[*buf];
if (n >= 0) goto decod;
/**********CHECK THE ABOVE; MOVE INTO MAIN LOOP?? ***********/
/*
* end of Dumas uuencoded file ?
*/
if (strncmp(buf, "end", 3) == 0) return;
/*
* end of current file ? : get next one.
*/
if (strncmp(buf, "include", 7) == 0)
{
if (getfile(buf) < 0)
{
sprintf(lnbuf,
"[1][Can't get data:|%s][ABORT]",
buf);
return(-1);
}
continue;
}
buf[20] = '\0'; /* limit length of line passed to GEM */
sprintf(lnbuf,"[1][Bad prefix|\"%s\"|in file:|%s][ABORT]",
buf, ifname);
form_alert(1,lnbuf);
return(-1);
/*
* Sequence checking ?
*/
decod: rlen = cdlen[n];
/*
* Is it the empty line before the end line ?
*/
if (n == 0) continue;
/*
* Pad with blanks.
*/
for (bp = &buf[c = len];
c < rlen; c++, bp++) *bp = blank;
/*
* All this just to check for uuencodes that append a 'z' to each line....
*/
if (secnd && check)
{
secnd = 0;
if (buf[rlen] == SEQMAX)
check = 0;
}
else if (first && check)
{
first = 0;
secnd = 1;
if (buf[rlen] != SEQMAX)
check = 0;
}
/*
* There we check.
*/
if (check)
{
if (buf[rlen] != seqch)
{
sprintf(lnbuf,"[1][Wrong sequence|line %d|in file:|%s][I know]",
numl, ifname);
form_alert(1,lnbuf);
}
seqch--;
if (seqch < SEQMIN) seqch = SEQMAX;
}
/*
* output a group of 3 bytes (4 input characters).
* the input chars are pointed to by p, they are to
* be output to file f.n is used to tell us not to
* output all of them at the end of the file.
*/
ut = outl;
len = n;
bp = &buf[1];
while (n > 0) {
*(ut++) = trtbl[*bp] << 2 | trtbl[bp[1]] >> 4;
n--;
if (n) {
*(ut++) = (trtbl[bp[1]] << 4) |
(trtbl[bp[2]] >> 2);
n--;
}
if (n) {
*(ut++) = trtbl[bp[2]] << 6 | trtbl[bp[3]];
n--;
}
bp += 4;
}
if ((n = fwrite(outl, 1, len, out)) <= 0)
{
form_alert(1,"[1][Error writing|decoded file][ABORT]");
return(-1);
}
}
}
/*
* Find the next needed file, if if exists, otherwise try further
* on next file.
*/
getfile(buf) register char *buf;
{
if ((pos = getnword(buf, 2)) == NULL)
{
form_alert(1,"[1][No include-file|name specified][ABORT]");
return(-1);
}
/* Some encoders are specifying filenames illegal for GEMdos */
/* The following transforms filename.arc.uab into filename.uab */
{
char *p, *q;
p = strchr(pos,'.');
q = strrchr(pos,'.');
if ((p != q) && p && q)
strcpy(p,q);
}
strcpy(ifname, pos);
if (exists(ifname))
{
if (freopen(ifname, "r", in) == in)
{
disp_process(ifname);
numl = 0;
}
else
{
sprintf(lnbuf,"[1][freopen failure|while attempting|%s][ABORT]",
ifname);
form_alert(1,lnbuf);
return(-1);
}
}
for(;;)
{
/* read lines, looking for table or begin */
if (fgets(buf, LINELEN, in) == NULL)
{
sprintf(lnbuf,"[1][No data in|%s][ABORT]",
ifname);
form_alert(1,lnbuf);
return(-1);
}
numl++;
if (strncmp(buf, "table", 5) == 0)
{
gettable();
continue;
}
if (strncmp(buf, "begin ", 6) == 0) break; /* found it! */
}
lens = strlen(buf);
if (lens) buf[--lens] = '\0'; /* I think this kills the newline */
/*
* Check the part suffix.
*/
if ((pos = getnword(buf, 3)) == NULL )
{
sprintf(lnbuf,"[1][Missing part name|in included file:|%s][ABORT]",
ifname);
form_alert(1,lnbuf);
return(-1);
}
else
{
partc = *pos;
partn++;
if (partn > 'z') partn = 'a';
if (partc != partn)
{
sprintf(lnbuf,"[1][Part suffix mismatch:|<%c> instead of <%c>][ABORT]",
partc, partn);
form_alert(1,lnbuf);
return(-1);
}
}
}