home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 1999 mARCH
/
PCWK3A99.iso
/
Archiwiz
/
Tar320
/
SOURCES.ZIP
/
READOPT.C
< prev
next >
Wrap
Text File
|
1994-12-31
|
15KB
|
513 lines
#include "modern.h"
#ifdef MODERN
# include <stdlib.h>
# include <string.h>
# ifdef ZMEM
# define MEMCPY(d,s,n) strcpy(d,s)
# endif
# ifdef NOMEMCPY
# define MEMCPY(d,s,n) strcpy(d,s)
# endif
# ifndef MEMCPY
# define MEMCPY(d,s,n) memcpy(d,s,n)
# endif
# ifdef __TURBOC__
# include <io.h>
# endif
#else
# define MEMCPY(d,s,n) strcpy(d,s)
char *strcpy(), *getenv(), *malloc(), *realloc();
int strlen();
#endif
#include <stdio.h>
#include "define.h"
#include "lzwbits.h"
#ifdef MSDOS
# define switchar(c) ((c)=='-' || (c)=='/')
#else
# define switchar(c) ((c)=='/')
#endif
void revector(argc, argv, n)
char ***argv;
{
register i;
/* create new argument vector */
i = (int)((argc + n) * sizeof(char *));
if (argvector) {
free(argvector);
if ((argvector=(char**)realloc(argvector, i)) == NULL) outmem(stderr);
} else {
argvector = (char **)salloc(i);
/* copy origin arguments */
for (i=0; i<argc; i++) argvector[i] = (*argv)[i];
}
*argv = argvector;
}
int buildarg(argc, argv, buf)
char ***argv, *buf;
{
register c;
register i, n;
i = 0; n = 0;
while (buf[i]) { /* count number of words in responce file */
while ((c=buf[i])!='\0' && space(c)) ++i;
if (buf[i]) ++n; /* next word found */
while ((c=buf[i])!='\0' && !space(c)) ++i;
}
revector(argc, argv, n);
i = argc; n = 0;
while (buf[n]) {/* append new arguments */
while ((c=buf[n])!='\0' && space(c)) buf[n++] = '\0';
if (buf[n]) argvector[i++] = buf+n; /* next word found */
while ((c=buf[n])!='\0' && !space(c)) ++n;
}
return i;
}
#define INDMAX 32760
#define INDMIN 1024
#define INDLOW 1023
int argfile(argc, argv, fname, buf)
char ***argv, *fname, **buf;
{
register i;
register l = 0;
register char *p;
if (fname[0] == '-' && fname[1] == '\0') {
/* standard input */ i = 0;
} else if ((i = open(fname, O_RDONLY)) < 0 || fstat(i, &st) < 0) {
(void)fprintf(stderr, "Tar: can\'t process \'%s\'\n", fname);
done(ERRARG);
}
if ((st.st_mode & S_IFMT) == S_IFREG) {
if (st.st_size >= INDMAX) {
(void)fprintf(stderr, "Tar: \'%s\' exceeds limit in size\n", fname);
done(ERRARG);
}
p = salloc((l = (int)st.st_size) + 1);
/* Note: effective text file size differs from the real one under MS-DOS */
if ((l = read(i, p, l)) < 1) {
(void)fprintf(stderr, "Tar: can\'t read \'%s\'\n", fname);
done(ERRARG);
}
(void)close(i);
} else if ((st.st_mode & S_IFMT) == S_IFCHR || /* character device */
(st.st_mode & S_IFMT) == S_IFIFO) { /* pipe */
int j, m; long s;
for (s=0, m=INDMAX+1; m>=INDMIN; ) {
if ((p = malloc(m)) != NULL) goto ok;
m = ((m+INDLOW) & ~INDLOW) / 2;
}
outmem(stderr);
ok:
s = 0;
do {
l = (int)s;
j = read(i, p+l, m-l);
s += j;
} while (j>0 && s<m);
if (j < 0) {
(void)fprintf(stderr, "Tar: error reading \'%s\'\n", fname);
done(ERRARG);
}
if (s >= m) {
if (m < INDMAX) {
outmem(stderr);
} else {
(void)fprintf(stderr,"Tar: \'%s\' exceeds limit in size\n",fname);
done(ERRARG);
}
}
if (l+1 < m) {
free(p);
if ((p = realloc(p, l+1)) == NULL) {
(void)fprintf(stderr, "Tar: error shrinking memory block\n");
done(ERRARG);
}
}
} else {
(void)fprintf(stderr, "Tar: \'%s\' not a file\n", fname);
done(ERRARG);
}
p[l] = '\0';
return buildarg(argc, argv, (*buf=p));
}
int envbuild(argc, argv)
char ***argv;
{
register i;
register char *p;
if ((p = getenv("TARCMD")) == NULL) return 0;
i = strlen(p); if (!i) return 0;
#ifdef UNIX
# define ARGFILE
if (p[0] == '/')
#endif
#ifdef MSDOS
# define ARGFILE
if (((p[0] <= 'A' && p[0] >= 'Z') || (p[0] <= 'a' && p[0] >= 'z')) &&
p[1] == ':' && p[2] == '\\' || p[0]=='\\')
#endif
#ifdef ARGFILE
return argfile(argc, argv, p, &tarcmd);
#endif
#if 0 /*ndef MSDOS*/
/* Make a copy of environment variable to avoid protection problems */
tarcmd = salloc(i+1); (void)MEMCPY(tarcmd, p, i+1); p = tarcmd;
#endif
return buildarg(argc, argv, p);
}
/* ARGSUSED */ static void readblk(p, argv, i)
char **p, **argv; int *i;
{
register char *s;
register n;
if (cblock) {
(void)fprintf(stderr, "Tar: blocksize multiply defined\n");
done(ERRARG);
}
s = argv[++*i];
for (cblock=0,n=0; digit(*s) && n<3; ++n,s++) cblock = *s-'0' + 10*cblock;
if (n>0 && n<=2) {
if (*s == 'k' || *s == 'K') { cblock *= 2; s++; }
else if (*s == 'b' || *s == 'B') s++;
if (*s=='\0' && cblock>0 && cblock<=MAXBLOCK) /* blocksize ok */ return;
}
(void)fprintf(stderr, "Tar: bad blocksize (max is %d)\n", MAXBLOCK);
done(ERRARG);
#ifdef __TURBOC__
(void)p;
#endif
}
#ifdef MSDOS
static void readvol(p, argv, i)
char **p, **argv; int *i;
{
register char *s;
register n;
if (k_flag || tapename) {
(void)fprintf(stderr, "Tar: tape device multiply defined\n");
done(ERRARG);
}
k_flag = TRUE;
s = argv[++*i];
for (volume=0, n=0; digit(*s) && n<7; ++n,s++) volume = *s-'0' + 10*volume;
if (n>0 && n<=6) {
if (*s == 'm' || *s == 'M') { volume <<= 11; ++s; }
else if (*s == 'k' || *s == 'K') { volume += volume; ++s; }
else if (*s == 'b' || *s == 'B') ++s;
else volume += volume;
if ((volume & ~0x7FFE) == 0)
if (*s=='\0' && argdisk((int)volume >> 1) == 0)
/* diskette size ok */ return;
}
(void)fprintf(stderr, "Tar: Invalid diskette size\n");
done(ERRARG);
#ifdef __TURBOC__
(void)p;
#endif
}
#endif
/* ARGSUSED */ static void readpk(p, argv, i)
char **p, **argv; int *i;
{
register c;
c = (*p)[0]; if (c>='A' && c<='Z') c += 'z'-'Z';
if (pktype != PKNONE) {
(void)fprintf(stderr,"Tar: compression method multiply defined\n");
done(ERRARG);
}
if (c == 'z' || c == ',') {
pktype = c==',' ? PKpLZW : PKfLZW;
lzwbits = BITS;
if ((*p)[1] == '9') {
*p += 1; lzwbits = 9;
} else if ((*p)[1] == '1') {
*p += 2; lzwbits = 10 + **p - '0';
if (lzwbits < 10 || lzwbits > BITS) {
(void)fprintf(stderr, "Tar: Invalid bits factor\n");
done(ERRARG);
}
}
} else {
pktype = c=='.' ? PKZIP : PKDEF;
ziplevel = 6; /* default */
if (digit((*p)[1])) {
*p += 1; ziplevel = **p - '0';
}
}
#ifdef __TURBOC__
(void)argv; (void)i;
#endif
}
#ifdef MSDOS
/* ARGSUSED */ static void devno(p, argv, i)
char **p, **argv; int *i;
{
ndrive = **p & 7; setdrive = TRUE;
#ifdef __TURBOC__
(void)argv; (void)i;
#endif
}
#endif
static void readxcl(p, argv, i)
char **p, **argv; int *i;
{
if (xcnt >= XMAX) {
(void)fprintf(stderr,"Tar: too many \'%s\'s\n", **p ? "#" : argv[*i]);
done(ERRARG);
}
xarg[xcnt++] = argv[++*i];
}
#define TO_APP '\377'
#define TO_INC '\376'
#define TO_REM '\375'
#define TO_CALL '\374'
#define MAXOPT 8
#ifdef MODERN
# ifdef __MEDIUM__
# define NF void far *
# else
# define NF void *
# endif
#endif
static struct {
union {
#ifdef NF
NF __dummy__;
#endif
char *flag; char **str;
void (*fun) __ARGS__((char**, char**, int*));
} p;
char longop[MAXOPT], shortop;
char optype, xflag;
} oplist[] = {
{ &a_flag, "append", 'a', TRUE, 0},
{ &a_flag, "append", 'r', TRUE, 0},
{ &c_flag, "create", 'c', TRUE, 0},
{ &x_flag, "extract", 'x', TRUE, 0},
{ &t_flag, "list", 't', TO_INC, 0},
{ &y_flag, "move", 'y', TRUE, 0},
{ &u_flag, "update", 'u', TRUE, 0},
{ &d_flag, "delete", 'd', TRUE, 0},
{ &v_flag, "verbose", 'v', TO_INC, 0},
{ &w_flag, "interact",'w', TRUE, 0},
{ &i_flag, "inhibit", 'i', TRUE, 0},
{ &s_flag, "strict", 's', TRUE, 0},
{ &m_flag, "modifica",'m', TRUE, 0},
{ &j_flag, "comment", 'j', TRUE, 0},
{ &nonest, "nonest", 'n', TRUE, 0},
{ &o_flag, "", 'o', TRUE, 0},
#ifdef UNIX
{ &dslash, "", '/', TRUE, 0},
{ &l_flag, "link-war",'l', TRUE, 0},
{ &p_flag, "permissi",'p', TRUE, 0},
{ &ndrive, "", '0', 0, 0},
{ &ndrive, "", '1', 1, 0},
{ &ndrive, "", '2', 2, 0},
{ &ndrive, "", '3', 3, 0},
{ &ndrive, "", '4', 4, 0},
{ &ndrive, "", '5', 5, 0},
{ &ndrive, "", '6', 6, 0},
{ &ndrive, "", '7', 7, 0},
#endif
#ifdef MSDOS
{ &dslash, "", '\\',TRUE, 0},
{ &l_flag, "link-cop",'l', TRUE, 0},
{ readvol, "", 'k', TO_CALL, 0},
{ &deldrv, "", ':', TRUE, 0},
{ devno, "", '0', TO_CALL, 0},
{ devno, "", '1', TO_CALL, 0},
{ devno, "", '2', TO_CALL, 0},
{ devno, "", '3', TO_CALL, 0},
#endif
{ &tapename,"file", 'f', TO_REM, 0},
{ readblk, "block-si",'b', TO_CALL, 0},
{ NULL, "", '@', TO_APP, 0},
{ readxcl, "exclude", '#', TO_CALL, 0},
{ readpk, "", ',', TO_CALL, 0},
{ readpk, "", '.', TO_CALL, 0},
{ readpk, "", 'e', TO_CALL, 0},
{ readpk, "", 'z', TO_CALL, 0},
{ &pktype, "compress", 0, PKpLZW, 0},
{ &pktype, "zip-arch", 0, PKZIP, 0},
{ &pktype, "zip-file", 0, PKDEF, 0},
{ &gnuzip, "gzip", 0, TRUE, 0},
{ &gnuzip, "gnu", 0, TRUE, 0},
};
void cleanopt()
{
register i;
for (i=0; i<dimof(oplist); i++) {
switch (oplist[i].optype) {
case TO_REM: *(oplist[i].p.str) = NULL;
case TO_CALL: break;
default: *(oplist[i].p.flag) = 0;
}
oplist[i].xflag = 0;
}
}
static void cmpflags __ARGS__((char**, int, int));
static void cmpflags(fl, n, to_break)
char *fl[];
{
register i;
register x0, x1;
for (x0=x1=0, i=0; i<n; i++) {
if (*(fl[i])) { if (*(fl[i]) & OPTFLAG) ++x1; else ++x0; }
}
if (x0 == 1) {
for (i=0; i<n; i++) if (*(fl[i]) & OPTFLAG) *(fl[i]) = 0;
} else if (x0>1 || x1>1) {
(void)fprintf(stderr, "Tar: ambiguous options\n");
if (to_break) done(ERRARG);
}
}
int readopt(argc, argv, aux)
int *argc; char ***argv;
{
register c;
register j, k;
char lex[MAXOPT];
char *p;
int i;
char *fl[5];
if (*argc < 1) {
(void)fprintf(stderr, "Tar: no options to read\n");
done(ERRARG);
}
for (i=0; i<*argc; i++) {
p = (*argv)[i];
if (switchar(*p)) {
if (p[1] == '\0') goto end;
if (p[1] != '-' || p[0] != '-') ++p;
} else if (*p != '+' && i) goto end;
if (p[0]!='+' && (p[0]!='-' || p[1]!='-')) {
for (;*p; p++) {
c = *p; if (switchar(c)) goto end;
if (c>='A' && c<='Z') c += 'z'-'Z';
for (k=0; k<dimof(oplist); k++) {
if (c == oplist[k].shortop) goto sfound;
}
(void)fprintf(stderr, "Tar: bad option \'%c\'\n", *p);
done(ERRARG);
sfound: switch (oplist[k].optype) {
case TO_APP:
if (aux) {
appname = (*argv)[++i];
} else {
*argc = argfile(*argc, argv, (*argv)[++i], &responce);
}
break;
case TO_REM:
if (*(oplist[k].p.str) && oplist[k].xflag == aux) {
(void)fprintf(stderr, "Tar: duplicate \'%c\'\n", *p);
done(ERRARG);
}
*(oplist[k].p.str) = (*argv)[++i];
break;
case TO_CALL:
(*(oplist[k].p.fun))(&p, (*argv), &i);
break;
case TO_INC:
if (oplist[k].xflag != aux) *(oplist[k].p.flag) = 0;
*(oplist[k].p.flag) = aux | (1 + *(oplist[k].p.flag));
break;
default:
if (*(oplist[i].p.flag) && oplist[k].xflag == aux) {
(void)fprintf(stderr, "Tar: duplicate \'%c\'\n", *p);
done(ERRARG);
}
*(oplist[k].p.flag) = aux | oplist[k].optype;
}
oplist[k].xflag = aux;
}
} else {
if (p[0] == '+') p += 1; else p += 2;
for (j=0; *p; p++) {
if (j < MAXOPT) {
c = *p; if (c>='A' && c<='Z') c += 'z'-'Z';
lex[j++] = c;
}
}
if (!j) goto end;
for (k=0; k<dimof(oplist); k++) {
if (oplist[k].longop[0] &&
0 == strncmp(oplist[k].longop, lex, j)) goto lfound;
}
(void)fprintf(stderr, "Tar: bad option \'%s\'\n", (*argv)[i]);
done(ERRARG);
lfound: switch (oplist[k].optype) {
case TO_APP:
if (aux) {
appname = (*argv)[++i];
} else {
*argc = argfile(*argc, argv, (*argv)[++i], &responce);
}
break;
case TO_REM:
if (*(oplist[k].p.str) && oplist[k].xflag == aux) {
(void)fprintf(stderr, "Tar: duplicate \'%s\'\n", (*argv)[i]);
done(ERRARG);
}
*(oplist[k].p.str) = (*argv)[++i];
break;
case TO_CALL:
(*(oplist[k].p.fun))(&p, (*argv), &i);
break;
case TO_INC:
if (oplist[k].xflag != aux) *(oplist[k].p.flag) = 0;
*(oplist[k].p.flag) = aux | (1 + *(oplist[k].p.flag));
break;
default:
if (*(oplist[k].p.flag) && oplist[k].xflag == aux) {
(void)fprintf(stderr, "Tar: duplicate \'%s\'\n", argv[i]);
done(ERRARG);
}
*(oplist[k].p.flag) = oplist[k].optype;
}
oplist[k].xflag = aux;
}
}
end:
fl[0] = &c_flag; fl[1] = &u_flag; cmpflags(fl, 2, TRUE);
fl[0] = &a_flag; fl[1] = &x_flag; fl[2] = &t_flag; cmpflags(fl, 3, TRUE);
fl[0] = &d_flag; fl[3] = &c_flag; cmpflags(fl, 4, TRUE);
fl[0] = &d_flag; fl[1] = &i_flag; cmpflags(fl, 2, TRUE);
if (c_flag && !a_flag) a_flag = c_flag;
if (u_flag && !a_flag && !x_flag) a_flag = u_flag;
if (a_flag && !c_flag) {
fl[0] = &a_flag; fl[1] = &i_flag; cmpflags(fl, 2, TRUE);
}
fl[0] = &u_flag; fl[1] = &m_flag; cmpflags(fl, 2, FALSE);
return i;
}