home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 9
/
MEDIASHARE_09.ISO
/
hamradio
/
7plus202.zip
/
7PL2SRC.LZH
/
UTILS.C
< prev
Wrap
C/C++ Source or Header
|
1992-06-11
|
21KB
|
1,122 lines
#include "7plus.h"
#include "globals.h"
#ifdef __unix__
#include <time.h>
#ifdef __M_XENIX__
struct utimbuf {
time_t actime;
time_t modtime;
};
extern time_t mktime (struct tm *utm);
#else
#include <utime.h>
#endif
#include <sys/stat.h>
#endif
static char no[] = NO, yes[] = YES, always[] = ALWAYS;
/*
*** get a line from file. don't care about type of line separator.
***
***
*/
char *my_fgets (char *string, register n, FILE *rein)
{
register in, i;
if (feof (rein))
return (NULL);
i = 0;
while ((in = fgetc (rein)) != EOF)
{
if (in == 0x0d)
{
if ((in = fgetc (rein)) != 0x0a)
if (in != EOF)
ungetc (in, rein);
in = 0x0a;
}
string[i++] = (char) in;
if (i == n || in == 0x0a)
break;
}
string[i] = EOS;
return (string);
}
/*
***
*** Write a byte to file.
***
*/
int my_putc (int outchar, FILE *out)
{
register x;
if ((x = putc ((char) outchar, out)) == EOF)
{
printf ("\007\nWrite error! Can't continue.\n");
exit (1);
}
return (x);
}
/*
*** Get crc and line number from code line.
***
***
*/
void crc_n_lnum (uint *crc, int *linenumber, char *line)
{
register ulong cs;
cs = 0xb640L * decode[(byte)line[66]] +
0xd8L * decode[(byte)line[65]] +
decode[(byte)line[64]];
*linenumber = (int) (cs >> 14); /* upper 9 bits are the line number */
*crc = (uint) (cs & 0x3fffL); /* lower 14 bits are the CRC */
}
/*
*** Get crc2 from code line.
***
***
*/
void crc2 (uint *crc, char *line)
{
*crc = 0xd8 * decode[(byte)line[68]] +
decode[(byte)line[67]];
}
/*
*** Whip up 2nd CRC
***
***
*/
void add_crc2 (char *line)
{
register uint crc;
register int i;
/* Whip up 2nd CRC */
crc = 0;
for (i=66;i>-1;i--)
crc = crctab[crc>>8] ^ (((crc&255)<<8) | (byte) line[i]);
crc &= 0x7fff;
i = 67;
line[i++] = code[crc % 0xd8];
line[i++] = code[crc / 0xd8];
line[i] = EOS;
}
/*
*** mini-crc for header. safe enough...
***
***
*/
int mcrc (char *line, int flag)
{
register int i, j;
register uint crc;
char test[3], *p;
sprintf (test, "\xb0\xb1");
if ((p = strstr (line, test)) == NULL)
return (0);
j = (int) (p - line) + 4;
for (i=crc=0; i<j; i++)
crc = crctab[crc>>8] ^ (((crc&255)<<8) | (byte)line[i]);
crc %= 216;
if (!flag)
{
if (crc == (uint) decode[(byte)line[j]])
return (1);
else
return (0);
}
else
line[j] = code[(byte)crc];
return (crc);
}
/*
*** read info from indexfile
***
***
*/
int read_index (FILE *ifile, struct m_index *index)
{
int j;
ulong i, begin, end;
#ifdef _CHSIZE_OK
fseek (ifile, -4L, SEEK_END);
fseek (ifile, read_ulong (ifile), SEEK_SET);
#endif
/* clear index */
for (j = 0;j < 8160; j++)
index->lines_ok[j] = 0;
my_fgets (index->full_name, 12, ifile);
if (strcmp(index->full_name, "7PLUS-index\x0a"))
{
printf ("\007No index info found.\n");
return (1);
}
my_fgets (index->filename, 13, ifile);
index->filename[(int)strlen(index->filename)-1] = EOS;
my_fgets (index->full_name, 257, ifile);
index->full_name[(int)strlen(index->full_name)-1] = EOS;
index->timestamp = read_ulong (ifile);
index->splitsize = read_uint (ifile);
index->lines_left= (long) read_ulong (ifile);
/* convert defect list into bitvektor */
while (1==1)
{
if ((begin = read_ulong (ifile)) == 0xffffffffUL)
break;
end = read_ulong (ifile);
if ((end>>4) > (begin>>4))
for (i = begin;i < ((begin |15UL) + 1UL); i++)
index->lines_ok[(int)i>>4] |= (1U << (uint)(i&15UL));
else
{
for (i = begin;i < end; i++)
index->lines_ok[(int)i>>4] |= (1U << (uint)(i&15UL));
continue;
}
for (i = (begin>>4) +1; i < (end>>4); i++)
index->lines_ok[(int)i] = 0xffffU;
if (end&15)
for (i = end &0xfffffff0UL; i < end; i++)
index->lines_ok[(int)i>>4] |= (1U << (uint)(i&15UL));
}
index->length = read_ulong (ifile);
#ifdef _CHSIZE_OK
fseek (ifile, 0UL, SEEK_SET);
#endif
return (0);
}
/*
*** write info to indexfile
***
***
*/
int write_index (FILE *ifile, struct m_index *index, int flag)
{
int j, part, prevpart, lines;
ulong i, begin, end;
part = prevpart = lines = 0;
begin = end = 0UL;
if (!flag)
{
#ifdef _CHSIZE_OK
fseek (ifile, index->length, SEEK_SET);
#endif
fprintf (ifile, "7PLUS-index\n");
fprintf (ifile, "%s\n", index->filename);
fprintf (ifile, "%s\n", index->full_name);
write_ulong (ifile, index->timestamp);
write_uint (ifile, index->splitsize);
write_ulong (ifile, (ulong) index->lines_left);
}
/* convert bitvektor into defect list */
i = 0UL;
j = 0;
while (1==1)
{
while (j < 8160 && !(index->lines_ok[j] &(uint)(1 << (i & 15UL))))
{
if (!(i&15UL) && index->lines_ok[j] == 0U)
{
j++;
i = (ulong) j<<4;
}
else
{
i++;
j = (int) i>>4;
}
}
if (j == 8160)
break;
begin = i;
do
{
if (!(i&15UL) && index->lines_ok[j] == 0xffffU)
{
j++;
i = (ulong) j<<4;
}
else
{
i++;
j = (int) i>>4;
}
}
while (j < 8160 && (index->lines_ok[j] &(uint)(1 << (i & 15UL))));
end = i;
if (!flag)
{
write_ulong (ifile, begin);
write_ulong (ifile, end);
}
else
{
for (i = begin; i < end; i++)
{
part = (int) i / index->splitsize +1;
if (part != prevpart)
{
if (prevpart)
{
if (!(lines % 18) && lines)
fprintf (ifile, delimit);
lines = 0;
fprintf (ifile, "FFF%s", delimit);
}
prevpart = part;
fprintf (ifile, "%02X%s", part, delimit);
}
lines++; /* Number of missing or corrupted lines in this part. */
fprintf (ifile, "%03X", i % index->splitsize);
if (!(lines % 18) && lines)
{
fprintf (ifile, delimit);
lines = 0;
}
else
fprintf (ifile, " ");
}
}
}
if (!flag)
{
write_ulong (ifile, 0xffffffffUL);
write_ulong (ifile, index->length);
#ifdef _CHSIZE_OK
chsize (fileno (ifile), ftell (ifile));
#endif
}
else
{
if (!(lines % 18) && lines)
fprintf (ifile, delimit);
fprintf (ifile, "FFF%s", delimit);
}
return (0);
}
/*
*** Reading/writing unsigned long(32bit)/int(16)
***
***
*/
ulong read_ulong (FILE *in)
{
return ((ulong)fgetc (in) +
((ulong)fgetc (in) <<8 ) +
((ulong)fgetc (in) <<16) +
((ulong)fgetc (in) <<24));
}
uint read_uint (FILE *in)
{
return ((uint)fgetc (in) +
((uint)fgetc (in) <<8 ));
}
void write_ulong (FILE *out, ulong val)
{
my_putc ((int) (val &0xffUL), out);
my_putc ((int)((val>>8 )&0xffUL), out);
my_putc ((int)((val>>16)&0xffUL), out);
my_putc ((int)((val>>24)&0xffUL), out);
}
void write_uint (FILE *out, uint val)
{
my_putc ((int) (val &0xffU), out);
my_putc ((int)((val>>8)&0xffU), out);
}
/*
*** read a file, search for s1, calculate CRC until s2 is found.
*** flag == 1: compare calculated an read CRC.
*** flag == 0: insert CRC into file.
*/
int crc_file (char *file, char *s1, char *s2, int flag)
{
char line[81], *p;
uint crc, cs;
int i, j, k;
FILE *in;
crc = cs = 0;
p = NULLCP;
if (!(in = fopen (file, OPEN_RANDOM_BINARY)))
{
printf (cant, file);
return (2);
}
i = (int) strlen (s1);
k = (int) strlen (s2);
j = 1;
do
{
if (my_fgets (line, 80, in) == NULL)
break;
j = strncmp (line, s1, i);
}
while (j);
if (j)
p = s1;
else
{
p = s2;
do
{
for (i=0;i!=(int)strlen(line);i++)
crc = crctab[crc>>8] ^ (((crc&255)<<8) | (byte)line[i]);
j = strncmp (line, s2, k);
if (!j)
continue;
if (my_fgets (line, 80, in) == NULL)
break;
}
while (j);
}
if (j)
{
printf ("\n\007Can't calculate CRC\n");
printf ("String '%s' not found in '%s'.\nBreak.\n", p, file);
return (7);
}
/* evaluate CRC */
if (flag)
{
my_fgets (line, 80, in);
fclose (in);
if (!line || strncmp ("CRC ", line, 4))
{
printf ("\n'%s': no CRC found.\n(File may be corrupted or from version \
earlier than 7PLUS v1.5)\n", file);
return (17);
}
cs = get_hex (line+4);
if (cs == crc)
return (0);
printf ("\007\n'%s' is corrupted. Break.\n", file);
return (7);
}
/* insert CRC into file */
fseek (in, ftell (in), SEEK_SET);
fprintf (in, "CRC %04X", crc);
fclose (in);
return (0);
}
/*
*** Copy a file.
***
***
*/
int copy_file (char *to, char *from, ulong timestamp)
{
FILE *_from, *_to;
int _char, stat;
stat = 0;
_from = fopen (from, OPEN_READ_BINARY);
_to = fopen (to, OPEN_WRITE_BINARY);
while ((_char = getc (_from)) != EOF)
if ((stat = putc (_char, _to)) == EOF)
break;
fclose (_from);
#ifdef _UXTIMESTAMP
fclose (_to);
if (timestamp)
set_uxfiletime (to, timestamp);
#else
if (timestamp)
set_filetime (_to, timestamp);
fclose (_to);
#endif
if (stat == EOF)
{
printf ("\007\nFatal error. Can't write '%s'! Break.\n", to);
exit (1);
}
return (0);
}
/*
*** Replace one file with another
***
***
*/
void replace (char *old, char *new, ulong timestamp)
{
unlink (old);
if (rename (new, old))
{
copy_file (old, new, timestamp);
unlink (new);
}
else
{
if (timestamp)
{
#ifdef _UXTIMESTAMP
set_uxfiletime (old, timestamp);
#else
FILE *_file;
_file = fopen (old, OPEN_APPEND_BINARY);
set_filetime (_file, timestamp);
fclose (_file);
#endif
}
}
}
/*
*** Kill all files that aren't needed any more
***
***
*/
void kill_em (char *name, char *inpath, char *one, char *two,
char *three, char *four, char *five)
{
char *p, newname[MAXPATH];
int i, j, k, len;
k = 0;
for (i = 0; i < 5; i++)
{
if (!i)
printf ("\n");
switch (i)
{
case 0: p = one;
break;
case 1: p = two;
break;
case 2: p = three;
break;
case 3: p = four;
break;
case 4: p = five;
default: p = NULLCP;
}
if (!p)
break;
len = strlen(p);
for (j = 1; j <256; j++)
{
if (len == 3)
sprintf (newname, "%s%s.%s", inpath, name, p);
else
sprintf (newname, "%s%s.%s%02x", inpath, name, p, j);
if (unlink (newname))
break;
k++;
printf ("Deleting: %s\r", newname);
fflush (stdout);
if (len == 3)
break;
}
}
if (k)
printf ("\n");
}
/*
***
***
***
*/
void kill_dest (FILE *in, FILE *out, char *name)
{
if (out)
fclose (out);
if (in)
fclose (in);
if (*name)
unlink (name);
}
/*
***
*** test if a file exists at all
***
*/
int test_exist (char *filename)
{
FILE *in = NULLFP;
if ((in = fopen (filename, OPEN_READ_TEXT)) != NULLFP)
{
fclose (in);
return (0);
}
return (1);
}
/*
*** test if outputfile already exists. prompt for overwrite or
*** new name.
***
*/
int test_file (FILE *in, char *destnam, int flag, int namsize)
{
FILE *out;
int i, ret;
ret = 0;
if (noquery)
return (ret);
/* Loop as long as file can be opened. */
while ((out = fopen (destnam, OPEN_READ_BINARY)) != NULLFP)
{
ret = 1;
printf ("\007\nOutputfile '%s' already exists, overwrite? [y/n/a] ", destnam);
do
{
i = toupper (getch());
if (i == 'N')
{
if (flag)
{
printf ("%s\n\nEnter new name (max %d chars)\n", no, namsize);
printf ("or simply press ENTER to break : ");
if (namsize == 12)
strlwr (destnam);
scanf ("%s", destnam);
destnam[namsize] = EOS;
}
else
*destnam = EOS;
if (!strlen (destnam))
{
if (!flag)
printf ("%s\n", no);
printf ("Break.\n");
if (in)
fclose (in);
exit (10);
}
i = 0xff; /* indicate, that new name has been specified */
}
}
while (i != 'Y' && i != 'A' && i != 0xff);
if (i != 0xff)
{
if (i == 'A')
{
printf ("%s\n", always);
noquery = 1;
}
else
printf ("%s\n", yes);
}
printf ("\n");
fclose (out);
if (i != 0xff)
break;
}
return (ret);
}
/*
*** initialize decoding table
***
***
*/
void init_decodetab (void)
{
register i;
register byte j;
for (i = 0; i < 256; i++)
decode[i] = 255;
j = 0;
for (i = 0x21; i < 0x2a; i++)
decode[i] = j++;
for (i = 0x2b; i < 0x7f; i++)
decode[i] = j++;
for (i = 0x80; i < 0x91; i++)
decode[i] = j++;
decode[0x92] = j++;
for (i = 0x94; i < 0xfd; i++)
decode[i] = j++;
}
/*
*** initialize encoding table
***
***
*/
void init_codetab (void)
{
register byte i, j;
j = 0;
for (i = 0x21; i < 0x2a; i++, j++)
code[j] = i;
for (i = 0x2b; i < 0x7f; i++, j++)
code[j] = i;
for (i = 0x80; i < 0x91; i++, j++)
code[j] = i;
code[j++] = 146;
for (i = 0x94; i < 0xfd; i++, j++)
code[j] = i;
}
/*
*** Tnx to DC4OX.
***
*** calculate CRC-table
***
*/
void init_crctab (void)
{
uint m, n, r, mask;
static uint bitrmdrs[] = { 0x9188,0x48C4,0x2462,0x1231,
0x8108,0x4084,0x2042,0x1021 };
for (n = 0; n < 256; ++n)
{
for (mask = 0x0080, r = 0, m = 0; m < 8; ++m, mask >>= 1)
if (n & mask)
r = bitrmdrs[m] ^ r;
crctab[n] = r;
}
}
/*
*** Create a MSDOS/ATARI compatible filename.
***
***
*/
void build_DOS_name (char *name)
{
char tmp[MAXFNAME];
register i, j;
i = j = 0;
strcpy (tmp, name);
strlwr (tmp);
if (*tmp)
{
do
{
tmp[i] &= 127;
if (strchr (" <>=,;:*?&[]()/.\\\"~+@", tmp[i]) == NULL)
name[j++] = tmp[i];
}
while (tmp[++i]);
name[j] = EOS;
}
}
#ifdef _UXTIMESTAMP
/*
* these functions have to convert a MS/DOS time to a UNIX time
* and vice versa.
* here comes the MS/DOS time structure
*/
struct ftime
{
unsigned ft_tsec : 5; /* 0..59 /2 (!) */
unsigned ft_min : 6; /* 0..59 */
unsigned ft_hour : 5; /* 0..23 */
unsigned ft_day : 5; /* 1..31 */
unsigned ft_month : 4; /* 1..12 */
unsigned ft_year : 7; /* Year minus 1980 */
};
/*
* Get UNIX file's timestamp and package it into a 32-bit word (MS_DOS-format)
*/
ulong get_uxfiletime (char *filename)
{
time_t atime;
struct ftime fti;
ulong *retval = (ulong *) &fti;
struct tm *utm;
struct stat fst;
*retval = 0UL;
/* get UNIX file status */
if (stat (filename, &fst) == 0)
{
/* get time of last modification and convert it to MS/DOS time */
utm = gmtime (&fst.st_mtime);
if (utm)
{
fti.ft_tsec = utm->tm_sec / 2;
fti.ft_min = utm->tm_min;
fti.ft_hour = utm->tm_hour;
fti.ft_day = utm->tm_mday;
fti.ft_month = utm->tm_mon + 1;
fti.ft_year = utm->tm_year - 80;
return (*retval);
}
}
/* error exit */
printf ("\007\nCan't get file's timestamp!\n");
return (*retval);
}
/*
* Set UNIX file's timestamp
*/
void set_uxfiletime (char *filename, ulong ftimestamp)
{
time_t atime;
struct utimbuf utim;
struct ftime *fti;
struct tm utm;
/* convert MS/DOS ftimestamp to UNIX atime */
fti = (struct ftime *) &ftimestamp;
utm.tm_sec = fti->ft_tsec * 2;
utm.tm_min = fti->ft_min;
utm.tm_hour = fti->ft_hour;
utm.tm_mday = fti->ft_day;
utm.tm_mon = fti->ft_month - 1;
utm.tm_year = fti->ft_year + 80;
utm.tm_wday = utm.tm_yday = utm.tm_isdst = 0;
atime = mktime (&utm);
if (atime != -1)
{
/* set access time and modification time */
utim.actime = atime;
utim.modtime = atime;
if (utime (filename, &utim) >= 0)
return;
}
/* error exit */
printf ("\007\nCan't set file's timestamp!");
return;
}
#else /* not UNIX */
/*
*** Get file's timestamp and package it into a 32-bit word (MS_DOS-format)
***
***
*/
ulong get_filetime (FILE *_file)
{
#ifdef _TIMESTAMP
ulong ftimestamp;
if (getftime (fileno(_file), (struct ftime *)&ftimestamp) == EOF)
printf ("\007\nCan't get file's timestamp!\n");
#ifdef __TOS__
ftimestamp = swapl(ftimestamp);
#endif
return (ftimestamp);
#else
/* This is the case with the AMIGA at this time */
printf ("\007\nWARNING: Function get_filetime() not yet implemented on this system!!\n");
return (0UL);
#endif _TIMESTAMP
}
/*
*** Set file's timestamp
***
***
*/
void set_filetime (FILE *_file, ulong ftimestamp)
{
#ifdef _TIMESTAMP
#ifdef __TOS__
ftimestamp = swapl(timestamp);
#endif
if (setftime (fileno(_file), (struct ftime *)&ftimestamp) == EOF)
printf ("\007\nCan't set file's timestamp!");
#else
/* This is the case with the AMIGA at this time */
printf ("\007\nWARNING: Function set_filetime() not yet implemented on this system!!\n");
#endif _TIMESTAMP
}
#endif
/*
*** get_hex: some compilers have real big trouble when reading hex values from
*** a file with fscanf() that have leading zeros! e.g. 00A will be
*** read as two separate values (0 and A)! grr!!
*** get_hex skips all leading zeros to eliminate the problem.
***
*/
uint get_hex (char *hex)
{
register i = 0;
uint ret = 0;
while (hex[i] == '0')
i++;
sscanf(hex+i, "%x", &ret);
return (ret);
}
#ifdef _FNSPLIT
/*
*** filenamesplit
*** (by DL1MEN, taken from SP-ST, modified for portability)
***
*** split filename up into drive, path, name and extension.
***
*/
void fnsplit(char *pth, char *dr, char *pa, char *fn, char *ft)
{
char drv[MAXDRIVE], pat[MAXDIR], fna[MAXFILE], fty[MAXEXT], tmp[MAXPATH];
char *p;
strcpy(tmp,pth);
if ((p = strchr(tmp,':')) != NULL)
{
*p++ = EOS;
strcpy(drv,tmp);
}
else
{
p = tmp;
drv[0] = EOS;
}
if ((pth = strrchr(p, PATHCHAR)) != NULL)
{
*pth++ = EOS;
strcpy(pat,p);
}
else
{
pth = p;
pat[0] = EOS;
}
if ((p = strchr(pth,'.')) != NULL)
{
strcpy(fty,p);
fty[MAXEXT-1] = EOS;
*p = EOS;
}
else
fty[0] = EOS;
strcpy(fna,pth);
fna[MAXFILE-1] = EOS;
if (dr)
{
strcpy(dr,drv);
if (drv[0])
strcat(dr,":");
}
if (pa)
{
strcpy(pa,pat);
if (pat[0])
strcat(pa, PATHSEP);
}
if (fn)
strcpy(fn,fna);
if (ft)
strcpy(ft,fty);
}
#endif /** _FNSPLIT **/
#ifdef _ICMP
/* The following functions are unfortunately not avialable on all compilers */
/*
*** strupr - convert string to upper case.
***
***
*/
char *strupr (char *string)
{
char *strcnvt (char *string, int flag);
return (strcnvt (string, 1));
}
/*
*** strlwr - convert string to lower case.
***
***
*/
char *strlwr (char *string)
{
char *strcnvt (char *string, int flag);
return (strcnvt (string, 0));
}
/*
*** strcnvt - convert string to upper (flag == 1) or lower (flag == 0) case.
***
***
*/
char *strcnvt (char *string, int flag)
{
register i = 0;
while (string[i])
{
string[i] = (flag)?toupper (string[i]):tolower (string[i]);
i++;
}
return (string);
}
/*
*** stricmp - same as strcmp(), but ignores case.
*** s1 and s2 are not modified.
***
*/
int stricmp (const char *s1, const char *s2)
{
return (strnicmp (s1, s2, (size_t) 80));
}
/*
*** strnicmp - same as strncmp(), but ignores case.
*** s1 and s2 are not modified.
***
*/
int strnicmp (const char *s1, const char *s2, size_t n)
{
char _s1[81], _s2[81];
strncpy (_s1, s1, 80);
strncpy (_s2, s2, 80);
strupr (_s1);
strupr (_s2);
return (strncmp (_s1, _s2, n));
}
#endif /** _ICMP **/