/* * archive.c * * archive file accessing module */ #include "fd.h" #include "func.h" #include "kanji.h" #ifndef _NOARCHIVE #ifndef _NOORIGSHELL #include "system.h" #endif #if MSDOS extern char *unixgetcurdir __P_((char *, int)); #endif extern int mark; #if FD >= 2 extern int sorttype; #endif extern int stackdepth; #ifndef _NOTRADLAYOUT extern int tradlayout; #endif extern int sizeinfo; extern off_t marksize; extern namelist filestack[]; extern char fullpath[]; #ifndef _NOCOLOR extern int ansicolor; #endif extern int win_x; extern int win_y; extern char *deftmpdir; extern int hideclock; extern int n_args; #if FD >= 2 static char *form_lha[] = { #if MSDOS "%*f\\n%s %x %x %y-%m-%d %t %a", /* MS-DOS (-v) */ "%1x %12f %s %x %x %y-%m-%d %t %a", /* MS-DOS (-l) */ #else "%a %u/%g %s %x %m %d %{yt} %*f", /* >=1.14 */ "%9a %u/%g %s %x %m %d %{yt} %*f", /* traditional */ #endif NULL }; static char *ign_lha[] = { #if MSDOS "Listing of archive : *", " Name Original *", "--------------*", # if defined (FAKEMETA) || !defined (BSPATHDELIM) "* files * ???.?% ?\077-?\077-?? ??:??:??", /* avoid trigraph */ # else "* files * ???.?%% ?\077-?\077-?? ??:??:??", /* avoid trigraph */ # endif "", #else /* !MSDOS */ " PERMSSN * UID*GID *", "----------*", " Total * file* ???.*%*", #endif /* !MSDOS */ NULL }; static char *form_tar[] = { #if MSDOS "%a %u/%g %s %m %d %t %y %*f", /* traditional */ "%a %u/%g %s %y-%m-%d %t %*f", /* GNU >=1.12 */ "%a %u/%g %s %m %d %y %t %*f", /* kmtar */ #else /* !MSDOS */ "%a %u/%g %s %m %d %t %y %*f", /* SVR4 */ "%a %u/%g %s %y-%m-%d %t %*f", /* GNU >=1.12 */ "%a %l %u %g %s %m %d %{yt} %*f", /* pax */ "%10a %u/%g %s %m %d %t %y %*f", /* tar (UXP/DS) */ "%9a %u/%g %s %m %d %t %y %*f", /* traditional */ "%a %u %g %s %m %d %t %y %*f", /* AIX */ "%a %u/%g %m %d %t %y %*f", /* IRIX */ #endif /* !MSDOS */ NULL }; #define PM_LHA form_lha, ign_lha, NULL, 0, 0 #define PM_TAR form_tar, NULL, NULL, 0, 0 #define PM_NULL NULL, NULL, NULL, 0, 0 #define LINESEP '\n' #define MAXSCORE 256 #define isarchbr(l) ((l) -> format) #else /* FD < 2 */ #if MSDOS #define PM_LHA 5, 2, \ {255, 255, 255, 1, 4, 4, 4, 5, 0}, \ {0, 0, 0, 0, 0, '-', 128 + 6, 0, 0}, \ {0, 0, 0, 0, '-', '-', 0, 0, 0}, \ {255, 255, 255}, 2 #define PM_TAR 0, 0, \ {0, 1, 1, 2, 5, 3, 4, 6, 7}, \ {0, 0, '/', 0, 0, 0, 0, 0, 0}, \ {0, '/', 0, 0, 0, 0, 0, 0, 0}, \ {255, 255, 255}, 1 #else /* !MSDOS */ #define PM_LHA 2, 2, \ {0, 1, 1, 2, 6, 4, 5, 6, 7}, \ {0, 0, '/', 0, 0, 0, 0, 0, 0}, \ {128 + 9, '/', 0, 0, 0, 0, 0, 0, 0}, \ {9, 255, 255}, 1 # ifdef UXPDS #define PM_TAR 0, 0, \ {0, 1, 1, 2, 6, 3, 4, 5, 7}, \ {0, 0, '/', 0, 0, 0, 0, 0, 0}, \ {128 + 10, '/', 0, 0, 0, 0, 0, 0, 0}, \ {10, 255, 255}, 1 # else /* !UXPDS */ # ifdef TARFROMPAX #define PM_TAR 0, 0, \ {0, 2, 3, 4, 7, 5, 6, 7, 8}, \ {0, 0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0, 0}, \ {255, 255, 255}, 1 # else /* !TARFROMPAX */ # ifdef TARUSESPACE #define PM_TAR 0, 0, \ {0, 1, 1, 2, 6, 3, 4, 5, 7}, \ {0, 0, '/', 0, 0, 0, 0, 0, 0}, \ {0, '/', 0, 0, 0, 0, 0, 0, 0}, \ {255, 255, 255}, 1 # else /* !TARUSESPACE */ #define PM_TAR 0, 0, \ {0, 1, 1, 2, 6, 3, 4, 5, 7}, \ {0, 0, '/', 0, 0, 0, 0, 0, 0}, \ {128 + 9, '/', 0, 0, 0, 0, 0, 0, 0}, \ {9, 255, 255}, 1 # endif /* !TARUSESPACE */ # endif /* !TARFROMPAX */ # endif /* !UXPDS */ #endif /* !MSDOS */ #define PM_NULL 255, 0, \ {0, 0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0, 0}, \ {0, 0, 0, 0, 0, 0, 0, 0, 0}, \ {255, 255, 255}, 1 #define LINESEP '\t' #define isarchbr(l) (((l) -> topskip) < (u_char)255) #endif /* FD < 2 */ #define IGNORETYPESYM "-VMNLhC" #define SYMLINKSTR "->" #define GNULINKSTR "link to" #ifndef _NOBROWSE static VOID NEAR copyargvar __P_((int, char *CONST *)); static VOID NEAR pushbrowsevar __P_((CONST char *)); static VOID NEAR popbrowsevar __P_((VOID_A)); #endif static VOID NEAR pusharchdupl __P_((VOID_A)); static VOID NEAR poparchdupl __P_((VOID_A)); static int NEAR readattr __P_((namelist *, CONST char *)); #if FD >= 2 static char *NEAR checkspace __P_((CONST char *, int *)); # ifdef _NOKANJIFCONV #define readfname strndup2 # else static char *NEAR readfname __P_((CONST char *, int)); # endif # ifndef NOSYMLINK static char *NEAR readlinkname __P_((CONST char *, CONST char *)); # endif static int NEAR readfileent __P_((namelist *, CONST char *, CONST char *, int)); #else /* FD < 2 */ static int NEAR countfield __P_((CONST char *, CONST u_char [], int, int *)); static char *NEAR getfield __P_((char *, CONST char *, int, launchtable *, int)); static int NEAR readfileent __P_((namelist *, CONST char *, launchtable *, int)); #endif /* FD < 2 */ static int NEAR dircmp __P_((CONST char *, CONST char *)); static int NEAR dirmatchlen __P_((CONST char *, CONST char *)); static char *NEAR pseudodir __P_((namelist *)); static VOID NEAR Xwaitmes __P_((VOID_A)); #if FD >= 2 static char **NEAR decodevar __P_((char *CONST *)); static int NEAR matchlist __P_((CONST char *, char *CONST *)); #endif static int NEAR parsearchive __P_((FILE *, launchtable *, namelist *, int *)); static VOID NEAR unpackerror __P_((VOID_A)); static int NEAR readarchive __P_((CONST char *, launchtable *, int)); static char *NEAR searcharcdir __P_((CONST char *, int)); static char *NEAR archoutdir __P_((VOID_A)); static int NEAR undertmp __P_((CONST char *)); #ifdef _NODOSDRIVE static char *NEAR genfullpath __P_((char *, CONST char *, CONST char *)); #else static char *NEAR genfullpath __P_((char *, CONST char *, CONST char *, CONST char *)); static int NEAR archdostmpdir __P_((char *, char **, CONST char *)); #endif #ifndef NOSYMLINK static int NEAR archrealpath __P_((char *, char *)); static int NEAR unpacklink __P_((namelist *, CONST char *)); #endif int maxlaunch = 0; int maxarchive = 0; launchtable launchlist[MAXLAUNCHTABLE] = { #if MSDOS {"*.lzh", "lha v %S", PM_LHA, 0}, {"*.tar", "tar tvf %S", PM_TAR, 0}, {"*.tar.Z", "gzip -cd %S|tar tvf -", PM_TAR, 0}, {"*.tar.gz", "gzip -cd %S|tar tvf -", PM_TAR, 0}, {"*.tar.bz2", "bzip2 -cd %S|tar tvf -", PM_TAR, 0}, {"*.taz", "gzip -cd %S|tar tvf -", PM_TAR, 0}, {"*.tgz", "gzip -cd %S|tar tvf -", PM_TAR, 0}, #else /* !MSDOS */ {"*.lzh", "lha l", PM_LHA, 0}, {"*.tar", "tar tvf", PM_TAR, 0}, {"*.tar.Z", "zcat %C|tar tvf -", PM_TAR, 0}, {"*.tar.gz", "gzip -cd %C|tar tvf -", PM_TAR, 0}, {"*.tar.bz2", "bzip2 -cd %C|tar tvf -", PM_TAR, 0}, # ifndef CYGWIN {"*.taZ", "zcat %C|tar tvf -", PM_TAR, 0}, # endif {"*.taz", "gzip -cd %C|tar tvf -", PM_TAR, 0}, {"*.tgz", "gzip -cd %C|tar tvf -", PM_TAR, 0}, #endif /* !MSDOS */ {NULL, NULL, PM_NULL, 0} }; archivetable archivelist[MAXARCHIVETABLE] = { #if MSDOS {"*.lzh", "lha a %S %TA", "lha x %S %TA", 0}, {"*.tar", "tar cf %C %T", "tar xf %C %TA", 0}, {"*.tar.Z", "tar cf - %T|compress -c > %C", "gzip -cd %S|tar xf - %TA", 0}, {"*.tar.gz", "tar cf - %T|gzip -c > %C", "gzip -cd %S|tar xf - %TA", 0}, {"*.tar.bz2", "tar cf - %T|bzip2 -c > %C", "bzip2 -cd %S|tar xf - %TA", 0}, {"*.taz", "tar cf - %T|compress -c > %C", "gzip -cd %S|tar xf - %TA", 0}, {"*.tgz", "tar cf - %T|gzip -c > %C", "gzip -cd %S|tar xf - %TA", 0}, #else /* !MSDOS */ {"*.lzh", "lha aq %C %TA", "lha xq %C %TA", 0}, {"*.tar", "tar cf %C %T", "tar xf %C %TA", 0}, {"*.tar.Z", "tar cf - %T|compress -c > %C", "zcat %C|tar xf - %TA", 0}, {"*.tar.gz", "tar cf - %T|gzip -c > %C", "gzip -cd %C|tar xf - %TA", 0}, {"*.tar.bz2", "tar cf - %T|bzip2 -c > %C", "bzip2 -cd %C|tar xf - %TA", 0}, # ifndef CYGWIN {"*.taZ", "tar cf - %T|compress -c > %C", "zcat %C|tar xf - %TA", 0}, # endif {"*.taz", "tar cf - %T|gzip -c > %C", "gzip -cd %C|tar xf - %TA", 0}, {"*.tgz", "tar cf - %T|gzip -c > %C", "gzip -cd %C|tar xf - %TA", 0}, #endif /* !MSDOS */ {NULL, NULL, NULL, 0} }; char archivedir[MAXPATHLEN]; #ifndef _NOBROWSE char **browsevar = NULL; #endif #ifndef NOSYMLINK static CONST strtable linklist[] = { {strsize(SYMLINKSTR), SYMLINKSTR}, {strsize(GNULINKSTR), GNULINKSTR}, }; #define LINKLISTSIZ arraysize(linklist) #endif /* !NOSYMLINK */ #if FD >= 2 static CONST char *autoformat[] = { # if MSDOS "%*f\n%s %x %x %y-%m-%d %t %a", /* LHa (v) */ " %*f\n%s %x %x %d-%m-%y %t %a", /* RAR (v) */ "%a %u/%g %s %m %d %t %y %*f", /* tar (traditional) */ "%a %u/%g %s %y-%m-%d %t %*f", /* tar (GNU >=1.12) */ "%a %l %u %g %s %m %d %{yt} %*f", /* ls or pax */ "%a %u/%g %s %m %d %y %t %*f", /* tar (kmtar) */ " %s %y-%m-%d %t %*f", /* zip */ " %s %x %x %x %y-%m-%d %t %*f", /* pkunzip */ " %s %x %x %d %m %y %t %*f", /* zoo */ "%1x %12f %s %x %x %y-%m-%d %t %a", /* LHa (l) */ " %f %s %x %x %d-%m-%y %t %a", /* RAR (l) */ # else /* !MSDOS */ " %*f\n%s %x %x %d-%m-%y %t %a", /* RAR (v) */ "%a %u/%g %s %m %d %t %y %*f", /* tar (SVR4) */ "%a %u/%g %s %y-%m-%d %t %*f", /* tar (GNU >=1.12) */ "%a %l %u %g %s %m %d %{yt} %*f", /* ls or pax */ "%a %u/%g %s %x %m %d %{yt} %*f", /* LHa (1.14<=) */ " %s %m-%d-%y %t %*f", /* zip */ " %s %x %x %d %m %y %t %*f", /* zoo */ "%10a %u/%g %s %m %d %t %y %*f", /* tar (UXP/DS) */ "%9a %u/%g %s %m %d %t %y %*f", /* tar (traditional) */ "%9a %u/%g %s %x %m %d %{yt} %*f", /* LHa */ "%a %u/%g %m %d %t %y %*f", /* tar (IRIX) */ " %f %s %x %x %d-%m-%y %t %a", /* RAR (l) */ # endif /* !MSDOS */ }; #define AUTOFORMATSIZ arraysize(autoformat) #endif /* FD >= 2 */ #ifndef _NOBROWSE static VOID NEAR copyargvar(argc, argv) int argc; char *CONST *argv; { int i; if (argvar && argvar[0]) for (i = 1; argvar[i]; i++) free(argvar[i]); argvar = (char **)realloc2(argvar, (argc + 2) * sizeof(char *)); for (i = 0; i < argc; i++) argvar[i + 1] = strdup2(argv[i]); argvar[i + 1] = NULL; } static VOID NEAR pushbrowsevar(s) CONST char *s; { int i; i = countvar(browsevar); browsevar = (char **)realloc2(browsevar, (i + 2) * sizeof(char *)); if (!i) browsevar[1] = NULL; else memmove((char *)&(browsevar[1]), (char *)&(browsevar[0]), (i + 1) * sizeof(char *)); browsevar[0] = strdup2(s); copyargvar(i + 1, browsevar); } static VOID NEAR popbrowsevar(VOID_A) { int i; i = countvar(browsevar); if (i <= 0) return; free(browsevar[0]); memmove((char *)&(browsevar[0]), (char *)&(browsevar[1]), i * sizeof(char *)); copyargvar(i - 1, browsevar); } #endif /* !_NOBROWSE */ static VOID NEAR pusharchdupl(VOID_A) { winvartable *new; new = (winvartable *)malloc2(sizeof(winvartable)); new -> v_archduplp = archduplp; new -> v_archivedir = NULL; new -> v_archivefile = archivefile; new -> v_archtmpdir = archtmpdir; new -> v_launchp = launchp; new -> v_arcflist = arcflist; new -> v_maxarcf = maxarcf; #ifndef _NODOSDRIVE new -> v_archdrive = archdrive; #endif #ifndef _NOBROWSE new -> v_browselist = browselist; new -> v_browselevel = browselevel; #endif #ifndef _NOTREE new -> v_treepath = treepath; #endif new -> v_fullpath = NULL; new -> v_findpattern = findpattern; new -> v_filelist = filelist; new -> v_maxfile = maxfile; new -> v_maxent = maxent; new -> v_filepos = filepos; new -> v_sorton = sorton; archduplp = new; } VOID escapearch(VOID_A) { #ifndef _NOBROWSE if (!archduplp) return; if (browselist) popbrowsevar(); #endif poparchdupl(); } static VOID NEAR poparchdupl(VOID_A) { #ifndef _NODOSDRIVE int drive; #endif winvartable *old; char *cp, *dir; int i; if (!(old = archduplp)) return; cp = archivefile; dir = archtmpdir; #ifndef _NODOSDRIVE drive = archdrive; #endif if (arcflist) { for (i = 0; i < maxarcf; i++) { free(arcflist[i].name); #ifndef NOSYMLINK if (arcflist[i].linkname) free(arcflist[i].linkname); #endif } free(arcflist); } archduplp = old -> v_archduplp; if (!(old -> v_archivedir)) *archivedir = '\0'; else { strcpy(archivedir, old -> v_archivedir); free(old -> v_archivedir); } archivefile = old -> v_archivefile; archtmpdir = old -> v_archtmpdir; launchp = old -> v_launchp; arcflist = old -> v_arcflist; maxarcf = old -> v_maxarcf; #ifndef _NODOSDRIVE archdrive = old -> v_archdrive; #endif #ifndef _NOBROWSE browselevel = old -> v_browselevel; #endif #ifndef _NOTREE treepath = old -> v_treepath; #endif if (findpattern) free(findpattern); findpattern = old -> v_findpattern; filepos = old -> v_filepos; sorton = old -> v_sorton; free(filelist); filelist = old -> v_filelist; maxfile = old -> v_maxfile; maxent = old -> v_maxent; #ifndef _NOBROWSE if (browselist) { if (!(old -> v_browselist)) { freebrowse(browselist); browselist = NULL; } } else #endif #ifndef _NODOSDRIVE if (drive > 0) { strcpy(fullpath, old -> v_fullpath); free(old -> v_fullpath); removetmp(dir, cp); } else #endif if (archivefile) { strcpy(fullpath, old -> v_fullpath); free(old -> v_fullpath); removetmp(dir, NULL); } free(cp); free(old); } static int NEAR readattr(tmp, buf) namelist *tmp; CONST char *buf; { int i, len; u_int n, mode; len = strlen(buf); if (len < 9) { mode = (tmp -> st_mode & S_IFMT) | S_IREAD_ALL | S_IWRITE_ALL; while (--len >= 0) { if ((n = getfmode(buf[len])) != (u_int)-1) { mode &= ~S_IFMT; mode |= n; } else switch (tolower2(buf[len])) { case 'a': mode |= S_ISVTX; break; case 'h': mode &= ~S_IREAD_ALL; break; case 'r': case 'o': mode &= ~S_IWRITE_ALL; break; case 'w': case '-': case '.': case ' ': break; case 'v': mode &= ~S_IFMT; mode |= S_IFIFO; break; default: return(0); /*NOTREACHED*/ break; } } if ((mode & S_IFMT) == S_IFDIR) mode |= S_IEXEC_ALL; } else { mode = tmp -> st_mode & S_IFMT; i = len - 9; if (buf[i] == 'r' || buf[i] == 'R') mode |= S_IRUSR; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'w' || buf[i] == 'W') mode |= S_IWUSR; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'x' || buf[i] == 'X') mode |= S_IXUSR; else if (buf[i] == 's') mode |= (S_IXUSR | S_ISUID); else if (buf[i] == 'S') mode |= S_ISUID; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'r' || buf[i] == 'R') mode |= S_IRGRP; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'w' || buf[i] == 'W') mode |= S_IWGRP; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'x' || buf[i] == 'X') mode |= S_IXGRP; else if (buf[i] == 's') mode |= (S_IXGRP | S_ISGID); else if (buf[i] == 'S') mode |= S_ISGID; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'r' || buf[i] == 'R') mode |= S_IROTH; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'w' || buf[i] == 'W') mode |= S_IWOTH; else if (buf[i] != '-') return(0); i++; if (buf[i] == 'x' || buf[i] == 'X') mode |= S_IXOTH; else if (buf[i] == 't') mode |= (S_IXOTH | S_ISVTX); else if (buf[i] == 'T') mode |= S_ISVTX; else if (buf[i] != '-') return(0); if (len >= 10 && !strchr(IGNORETYPESYM, buf[len - 10])) { n = getfmode(buf[len - 10]); if (n == (u_int)-1) return(0); mode &= ~S_IFMT; mode |= n; } } tmp -> st_mode = mode; return(len); } #if FD >= 2 static char *NEAR checkspace(s, scorep) CONST char *s; int *scorep; { int i, len; if (isblank2(*s)) { (*scorep)++; s = skipspace(&(s[1])); } for (i = 0; s[len = i]; i++) { if (isblank2(s[i])) { (*scorep)++; for (i++; isblank2(s[i]); i++); if (!s[i]) break; *scorep += 4; } } return(strndup2(s, len)); } # ifndef _NOKANJIFCONV static char *NEAR readfname(s, len) CONST char *s; int len; { char *cp, *tmp; cp = strndup2(s, len); tmp = newkanjiconv(cp, fnamekcode, DEFCODE, L_FNAME); if (tmp != cp) free(cp); return(tmp); } # endif /* !_NOKANJIFCONV */ # ifndef NOSYMLINK static char *NEAR readlinkname(s, eol) CONST char *s, *eol; { int i; for (i = 0; i < LINKLISTSIZ; i++) { if (&(s[linklist[i].no]) > eol) continue; if (!strncmp(s, linklist[i].str, linklist[i].no)) { s += linklist[i].no; return(skipspace(s)); } } return(NULL); } # endif /* !NOSYMLINK */ static int NEAR readfileent(tmp, line, form, skip) namelist *tmp; CONST char *line, *form; int skip; { # ifndef NOUID uidtable *up; gidtable *gp; uid_t uid; gid_t gid; # endif # ifndef NOSYMLINK CONST char *line2, *lname; # endif time_t now; struct tm tm, *tp; off_t n; int i, ch, l, len, hit, err, err2, score; CONST char *s; char *cp, *buf, *eol, *rawbuf; if (skip && skip > strlen(form)) return(-1); tmp -> name = NULL; tmp -> st_mode = 0644; tmp -> st_nlink = 1; # ifndef NOUID tmp -> st_uid = (uid_t)-1; tmp -> st_gid = (gid_t)-1; tmp -> linkname = NULL; # endif tmp -> st_size = (off_t)0; tmp -> flags = 0; tmp -> tmpflags = F_STAT; tm.tm_year = tm.tm_mon = tm.tm_mday = -1; tm.tm_hour = tm.tm_min = tm.tm_sec = 0; score = 0; while (*form) if (isblank2(*form)) { line = skipspace(line); form++; } else if (*form == '\n') { if (*line != *(form++)) score += 20; else line++; line = skipspace(line); } else if (*form != '%' || *(++form) == '%') { ch = *(form++); if (skip) { skip--; continue; } if (*line != ch) score += 10; else line++; } else { ch = '\0'; if (*form == '*') { form++; for (i = 0; line[i]; i++) if (line[i] == '\n') break; len = i; } else if (!(cp = sscanf2(form, "%+d", &len))) len = -1; else { form = cp; for (i = 0; i < len; i++) if (!line[i]) break; len = i; ch = -1; } if (*form != '{') { l = 1; s = form++; } else { s = ++form; form = strchr2(s, '}'); if (!form || form <= s) { if (tmp -> name) free(tmp -> name); # ifndef NOSYMLINK if (tmp -> linkname) free(tmp -> linkname); # endif return(-1); } l = form++ - s; } if (skip) { skip--; continue; } if (len < 0) { if (!isblank2(*form) && (*form != '%' || *(form + 1) == '%')) ch = *form; for (len = 0; line[len]; len++) { if (ch) { if (ch == line[len]) break; } else if (isblank2(line[len])) break; } } rawbuf = strndup2(line, len); hit = err = err2 = 0; buf = checkspace(rawbuf, &err); while (l--) switch (s[l]) { case 'a': if (readattr(tmp, buf)) hit++; break; case 'l': if ((i = atoi2(buf)) < 0) break; tmp -> st_nlink = i; hit++; break; case 'u': # ifndef NOUID cp = sscanf2(buf, "%-<*d%$", sizeof(uid_t), &uid); if (cp) tmp -> st_uid = uid; else if ((up = finduid(0, buf))) tmp -> st_uid = up -> uid; # endif hit++; break; case 'g': # ifndef NOUID cp = sscanf2(buf, "%-<*d%$", sizeof(gid_t), &gid); if (cp) tmp -> st_gid = gid; else if ((gp = findgid(0, buf))) tmp -> st_gid = gp -> gid; # endif hit++; break; case 's': if (!(cp = sscanf2(buf, "%qd", &n))) break; if (*cp) err2++; tmp -> st_size = n; hit++; break; case 'y': if ((i = atoi2(buf)) < 0) break; tm.tm_year = i; hit++; break; case 'm': if (!strncmp(buf, "Jan", 3)) tm.tm_mon = 0; else if (!strncmp(buf, "Feb", 3)) tm.tm_mon = 1; else if (!strncmp(buf, "Mar", 3)) tm.tm_mon = 2; else if (!strncmp(buf, "Apr", 3)) tm.tm_mon = 3; else if (!strncmp(buf, "May", 3)) tm.tm_mon = 4; else if (!strncmp(buf, "Jun", 3)) tm.tm_mon = 5; else if (!strncmp(buf, "Jul", 3)) tm.tm_mon = 6; else if (!strncmp(buf, "Aug", 3)) tm.tm_mon = 7; else if (!strncmp(buf, "Sep", 3)) tm.tm_mon = 8; else if (!strncmp(buf, "Oct", 3)) tm.tm_mon = 9; else if (!strncmp(buf, "Nov", 3)) tm.tm_mon = 10; else if (!strncmp(buf, "Dec", 3)) tm.tm_mon = 11; else if ((i = atoi2(buf)) >= 1 && i <= 12) tm.tm_mon = i - 1; else break; hit++; break; case 'd': if ((i = atoi2(buf)) < 1 || i > 31) break; tm.tm_mday = i; hit++; break; case 't': if (!(cp = sscanf2(buf, "%d", &i)) || i > 23) break; tm.tm_hour = i; hit++; if (!(cp = sscanf2(cp, ":%d", &i)) || i > 59) { tm.tm_min = tm.tm_sec = 0; err2++; break; } tm.tm_min = i; if (!sscanf2(cp, ":%d%$", &i) || i > 59) { tm.tm_sec = 0; break; } tm.tm_sec = i; break; case 'f': eol = &(rawbuf[len]); # ifndef NOSYMLINK lname = NULL; # endif for (i = 0; i < len; i++) { cp = &(rawbuf[i]); # if MSDOS # ifdef BSPATHDELIM if (*cp == '/') *cp = _SC_; # else if (*cp == '\\') *cp = _SC_; if (iskanji1(rawbuf, i)) { i++; continue; } # endif # endif /* MSDOS */ if (!isblank2(*cp)) continue; cp = skipspace(&(cp[1])); if (cp >= eol) { if (!ch) i = len; break; } # ifndef NOSYMLINK if ((lname = readlinkname(cp, eol))) break; # endif } # ifndef NOSYMLINK line2 = &(line[i]); # endif if (isdelim(rawbuf, i - 1)) { tmp -> st_mode &= ~S_IFMT; tmp -> st_mode |= S_IFDIR; while (i > 1) if (!isdelim(rawbuf, --i - 1)) break; } if (tmp -> name) free(tmp -> name); tmp -> name = readfname(rawbuf, i); hit++; err = 0; # ifndef NOSYMLINK if (!lname) break; line2 = skipspace(line2); if (ch && line2 >= &(line[len])) break; lname = &(line[lname - rawbuf]); for (i = 0; lname[i]; i++) if (isblank2(lname[i])) break; if (i) { if (tmp -> linkname) free(tmp -> linkname); tmp -> linkname = readfname(lname, i); i = &(lname[i]) - line; if (i > len) len = i; } # endif break; case 'x': hit++; err = 0; break; default: hit = -1; break; } free(buf); free(rawbuf); if (hit < 0) { if (tmp -> name) free(tmp -> name); # ifndef NOSYMLINK if (tmp -> linkname) free(tmp -> linkname); # endif return(hit); } if (!hit) score += 5; else if (hit <= err2) score += err2; score += err; line += len; if (!ch) line = skipspace(line); } if (score >= MAXSCORE || !(tmp -> name) || !*(tmp -> name)) { if (tmp -> name) free(tmp -> name); # ifndef NOSYMLINK if (tmp -> linkname) free(tmp -> linkname); # endif return(MAXSCORE); } if (!(tmp -> st_mode & S_IFMT)) tmp -> st_mode |= S_IFREG; if (s_isdir(tmp)) tmp -> flags |= F_ISDIR; else if (s_islnk(tmp)) tmp -> flags |= F_ISLNK; if (tm.tm_year < 0) { now = time2(); # ifdef DEBUG _mtrace_file = "localtime(start)"; tp = localtime(&now); if (_mtrace_file) _mtrace_file = NULL; else { _mtrace_file = "localtime(end)"; malloc(0); /* dummy malloc */ } # else tp = localtime(&now); # endif tm.tm_year = tp -> tm_year; if (tm.tm_mon < 0 || tm.tm_mday < 0) tm.tm_year = 1970 - 1900; else if (tm.tm_mon > tp -> tm_mon || (tm.tm_mon == tp -> tm_mon && tm.tm_mday > tp -> tm_mday)) tm.tm_year--; } else { if (tm.tm_year < 1900 && (tm.tm_year += 1900) < 1970) tm.tm_year += 100; tm.tm_year -= 1900; } if (tm.tm_mon < 0) tm.tm_mon = 0; if (tm.tm_mday < 0) tm.tm_mday = 1; tmp -> st_mtim = timelocal2(&tm); tmp -> flags |= # ifdef NOUID logical_access(tmp -> st_mode); # else logical_access(tmp -> st_mode, tmp -> st_uid, tmp -> st_gid); # endif return(score); } #else /* FD < 2 */ static int NEAR countfield(line, sep, field, eolp) CONST char *line; CONST u_char sep[]; int field, *eolp; { int i, j, f, s, sp; f = -1; s = 1; sp = (int)sep[0]; for (i = j = 0; line[i]; i++) { if (sp < 255 && i >= sp) { j++; sp = (j < MAXLAUNCHSEP) ? (int)sep[j] : 255; for (; sp == 255 || i < sp; i++) if (!isblank2(line[i])) break; if (f < 0) f = 1; else f++; s = 0; } else if (isblank2(line[i])) s = 1; else if (s) { f++; s = 0; } if (field < 0) continue; else if (f > field) return(-1); else if (f == field) { if (eolp) { for (j = i; line[j]; j++) { if ((sp < 255 && j >= sp) || isblank2(line[j])) break; } *eolp = j; } return(i); } } return((field < 0) ? f : -1); } static char *NEAR getfield(buf, line, skip, list, no) char *buf; CONST char *line; int skip; launchtable *list; int no; { CONST char *cp; char *tmp; int i, f, eol; *buf = '\0'; f = (list -> field[no] < 255) ? (int)(list -> field[no]) - skip : -1; if (f < 0 || (i = countfield(line, list -> sep, f, &eol)) < 0) return(buf); cp = &(line[i]); i = (int)(list -> delim[no]); if (i >= 128) { i -= 128; if (&(cp[i]) < &(line[eol])) cp += i; else return(buf); } else if (i && (!(cp = strchr2(cp, i)) || ++cp >= &(line[eol]))) return(buf); i = (int)(list -> width[no]); if (i >= 128) i -= 128; else if (i) { if ((tmp = strchr2(cp, i))) i = tmp - cp; else i = &(line[eol]) - cp; } if (!i || &(cp[i]) > &(line[eol])) i = &(line[eol]) - cp; strncpy2(buf, cp, i); return(buf); } static int NEAR readfileent(tmp, line, list, max) namelist *tmp; CONST char *line; launchtable *list; int max; { # ifndef NOUID uidtable *up; gidtable *gp; uid_t uid; gid_t gid; # endif time_t now; struct tm tm, *tp; off_t n; int i, skip; char *cp, *buf; i = countfield(line, list -> sep, -1, NULL); skip = (max > i) ? max - i : 0; buf = malloc2(strlen(line) + 1); tmp -> flags = 0; tmp -> tmpflags = F_STAT; tmp -> st_mode = 0; tmp -> st_nlink = 1; # ifndef NOSYMLINK tmp -> linkname = NULL; # endif getfield(buf, line, skip, list, F_NAME); if (!*buf) { free(buf); return(-1); } # if MSDOS # ifdef BSPATHDELIM for (i = 0; buf[i]; i++) if (buf[i] == '/') buf[i] = _SC_; # else for (i = 0; buf[i]; i++) { if (buf[i] == '\\') buf[i] = _SC_; if (iskanji1(buf, i)) i++; } # endif # endif /* MSDOS */ if (isdelim(buf, i = (int)strlen(buf) - 1)) { if (i > 0) buf[i] = '\0'; tmp -> st_mode |= S_IFDIR; } tmp -> name = strdup2(buf); getfield(buf, line, skip, list, F_MODE); readattr(tmp, buf); if (!(tmp -> st_mode & S_IFMT)) tmp -> st_mode |= S_IFREG; if (s_isdir(tmp)) tmp -> flags |= F_ISDIR; else if (s_islnk(tmp)) tmp -> flags |= F_ISLNK; # ifndef NOUID getfield(buf, line, skip, list, F_UID); if (sscanf2(buf, "%-<*d%$", sizeof(uid_t), &uid)) tmp -> st_uid = uid; else tmp -> st_uid = ((up = finduid(0, buf))) ? up -> uid : (uid_t)-1; getfield(buf, line, skip, list, F_GID); if (sscanf2(buf, "%-<*d%$", sizeof(gid_t), &gid)) tmp -> st_gid = gid; else tmp -> st_gid = ((gp = findgid(0, buf))) ? gp -> gid : (gid_t)-1; # endif getfield(buf, line, skip, list, F_SIZE); tmp -> st_size = (sscanf2(buf, "%qd%$", &n)) ? n : (off_t)0; getfield(buf, line, skip, list, F_MON); if (!strncmp(buf, "Jan", 3)) tm.tm_mon = 0; else if (!strncmp(buf, "Feb", 3)) tm.tm_mon = 1; else if (!strncmp(buf, "Mar", 3)) tm.tm_mon = 2; else if (!strncmp(buf, "Apr", 3)) tm.tm_mon = 3; else if (!strncmp(buf, "May", 3)) tm.tm_mon = 4; else if (!strncmp(buf, "Jun", 3)) tm.tm_mon = 5; else if (!strncmp(buf, "Jul", 3)) tm.tm_mon = 6; else if (!strncmp(buf, "Aug", 3)) tm.tm_mon = 7; else if (!strncmp(buf, "Sep", 3)) tm.tm_mon = 8; else if (!strncmp(buf, "Oct", 3)) tm.tm_mon = 9; else if (!strncmp(buf, "Nov", 3)) tm.tm_mon = 10; else if (!strncmp(buf, "Dec", 3)) tm.tm_mon = 11; else if ((i = atoi2(buf)) >= 1 && i < 12) tm.tm_mon = i - 1; else tm.tm_mon = 0; getfield(buf, line, skip, list, F_DAY); tm.tm_mday = ((i = atoi2(buf)) >= 1 && i < 31) ? i : 1; getfield(buf, line, skip, list, F_YEAR); if (!*buf) tm.tm_year = 1970; else if ((i = atoi2(buf)) >= 0) tm.tm_year = i; else if (list -> field[F_YEAR] == list -> field[F_TIME] && strchr(buf, ':')) { now = time2(); # ifdef DEBUG _mtrace_file = "localtime(start)"; tp = localtime(&now); if (_mtrace_file) _mtrace_file = NULL; else { _mtrace_file = "localtime(end)"; malloc(0); /* dummy malloc */ } # else tp = localtime(&now); # endif tm.tm_year = tp -> tm_year; if (tm.tm_mon > tp -> tm_mon || (tm.tm_mon == tp -> tm_mon && tm.tm_mday > tp -> tm_mday)) tm.tm_year--; } else tm.tm_year = 1970; if (tm.tm_year < 1900 && (tm.tm_year += 1900) < 1970) tm.tm_year += 100; tm.tm_year -= 1900; getfield(buf, line, skip, list, F_TIME); if (!(cp = sscanf2(buf, "%d", &i)) || i > 23) tm.tm_hour = tm.tm_min = tm.tm_sec = 0; else { tm.tm_hour = i; if (!(cp = sscanf2(cp, ":%d", &i)) || i > 59) tm.tm_min = tm.tm_sec = 0; else { tm.tm_min = i; if (!sscanf2(cp, ":%d%$", &i) || i > 59) tm.tm_sec = 0; else tm.tm_sec = i; } } tmp -> st_mtim = timelocal2(&tm); tmp -> flags |= # ifdef NOUID logical_access(tmp -> st_mode); # else logical_access(tmp -> st_mode, tmp -> st_uid, tmp -> st_gid); # endif free(buf); return(0); } #endif /* FD < 2 */ VOID archbar(file, dir) CONST char *file, *dir; { char *arch; int len; #ifndef _NOBROWSE if (browselist) { int i; if (!browsevar) arch = strdup2(nullstr); else { len = 0; for (i = 0; browsevar[i]; i++) len += strlen(browsevar[i]) + 1; arch = malloc2(len + 1); len = 0; for (i--; i >= 0; i--) { strcpy(&(arch[len]), browsevar[i]); len += strlen(browsevar[i]); if (i > 0) arch[len++] = '>'; } arch[len] = '\0'; } } else #endif /* !_NOBROWSE */ { arch = malloc2(strlen(fullpath) + strlen(file) + strlen(dir) + 3); strcpy(strcpy2(strcatdelim2(arch, fullpath, file), ":"), dir); } #ifndef _NOTRADLAYOUT if (istradlayout()) { Xlocate(0, TL_PATH); Xputterm(L_CLEAR); Xlocate(TC_PATH, TL_PATH); Xputterm(T_STANDOUT); # ifndef _NOBROWSE if (browselist) { Xcputs2(TS_BROWSE); len = TD_BROWSE; } else # endif { Xcputs2(TS_ARCH); len = TD_ARCH; } Xputterm(END_STANDOUT); cputstr(len, arch); free(arch); Xlocate(TC_MARK, TL_PATH); Xcprintf2("%<*d", TD_MARK, mark); Xputterm(T_STANDOUT); Xcputs2(TS_MARK); Xputterm(END_STANDOUT); Xcprintf2("%<'*qd", TD_SIZE, marksize); Xtflush(); return; } #endif /* !_NOTRADLAYOUT */ Xlocate(0, L_PATH); Xputterm(L_CLEAR); Xlocate(C_PATH, L_PATH); Xputterm(T_STANDOUT); #ifndef _NOBROWSE if (browselist) { Xcputs2(S_BROWSE); len = D_BROWSE; } else #endif { Xcputs2(S_ARCH); len = D_ARCH; } Xputterm(END_STANDOUT); cputstr(len, arch); free(arch); Xtflush(); } static int NEAR dircmp(s1, s2) CONST char *s1, *s2; { int i, j; for (i = j = 0; s2[j]; i++, j++) { if (s1[i] == s2[j]) { #ifdef BSPATHDELIM if (iskanji1(s1, i) && (s1[++i] != s2[++j] || !s2[j])) return(s1[i] - s2[j]); #endif continue; } if (s1[i] != _SC_ || s2[j] != _SC_) return(s1[i] - s2[j]); while (s1[i + 1] == _SC_) i++; while (s2[j + 1] == _SC_) j++; } return(s1[i]); } static int NEAR dirmatchlen(s1, s2) CONST char *s1, *s2; { int i, j; for (i = j = 0; s1[i]; i++, j++) { if (s1[i] == s2[j]) { #ifdef BSPATHDELIM if (iskanji1(s1, i)) { if (s1[++i] != s2[++j]) return(0); if (s1[i]) continue; if (s2[j]) j++; break; } #endif continue; } if (s1[i] != _SC_ || s2[j] != _SC_) return(0); while (s1[i + 1] == _SC_) i++; while (s2[j + 1] == _SC_) j++; } if (s2[j] && s2[j] != _SC_) { for (j = 0; s1[j] == _SC_; j++); return((i == j) ? 1 : 0); } if (i && s2[j]) while (s2[j + 1] == _SC_) j++; return(j); } static char *NEAR pseudodir(namep) namelist *namep; { char *cp, *next; int i, len; u_short ent; for (cp = namep -> name; (next = strdelim(cp, 0)); cp = ++next) { while (*(next + 1) == _SC_) next++; if (!*(next + 1)) break; len = next - namep -> name; if (!len) len++; for (i = 0; i < maxfile; i++) { if (isdir(&(filelist[i])) && len == dirmatchlen(filelist[i].name, namep -> name)) break; } if (i >= maxfile) return(strndup2(namep -> name, len)); if (strncmp(filelist[i].name, namep -> name, len)) { filelist[i].name = realloc2(filelist[i].name, len + 1); strncpy2(filelist[i].name, namep -> name, len); } } if (isdir(namep) && !isdotdir(namep -> name)) for (i = 0; i < maxfile; i++) { if (isdir(&(filelist[i])) && !dircmp(filelist[i].name, namep -> name)) { cp = filelist[i].name; ent = filelist[i].ent; memcpy((char *)&(filelist[i]), (char *)namep, sizeof(namelist)); filelist[i].name = cp; filelist[i].ent = ent; return(NULL); } } return(namep -> name); } static VOID NEAR Xwaitmes(VOID_A) { int x, y; x = win_x; y = win_y; win_x = win_y = -1; waitmes(); win_x = x; win_y = y; } #if FD >= 2 static char **NEAR decodevar(argv) char *CONST *argv; { char **new; int n, max; max = countvar(argv); new = (char **)malloc2((max + 1) * sizeof(char *)); for (n = 0; n < max; n++) new[n] = decodestr(argv[n], NULL, 0); new[n] = NULL; return(new); } static int NEAR matchlist(s, argv) CONST char *s; char *CONST *argv; { # ifndef PATHNOCASE int duppathignorecase; # endif reg_t *re; CONST char *s1, *s2; char *new; int i, len, ret; if (!argv) return(0); # ifndef PATHNOCASE duppathignorecase = pathignorecase; pathignorecase = 0; # endif ret = 0; for (i = 0; !ret && argv[i]; i++) { s1 = argv[i]; s2 = s; if (!isblank2(s1[0])) s2 = skipspace(s2); len = strlen(s1); if (!len || isblank2(s1[len - 1])) new = strdup2(s2); else { len = strlen(s2); for (len--; len >= 0; len--) if (!isblank2(s2[len])) break; new = strndup2(s2, ++len); } re = regexp_init(s1, -1); ret = regexp_exec(re, new, 0); free(new); regexp_free(re); } # ifndef PATHNOCASE pathignorecase = duppathignorecase; # endif return(ret); } #endif /* FD >= 2 */ static int NEAR parsearchive(fp, list, namep, linenop) FILE *fp; launchtable *list; namelist *namep; int *linenop; { #if FD >= 2 static char **formlist = NULL; static char **lign = NULL; static char **lerr = NULL; namelist tmp; CONST char *form; char *form0, *form2; short *scorelist; int nf, na, ret, skip; #else int max; #endif static char **lvar = NULL; char *cp; int i, score, len, nline, needline; if (!fp) { freevar(lvar); lvar = NULL; #if FD >= 2 freevar(formlist); freevar(lign); freevar(lerr); if (!list || !(list -> format)) formlist = lign = lerr = NULL; else { formlist = decodevar(list -> format); lign = decodevar(list -> lignore); lerr = decodevar(list -> lerror); } #endif return(0); } #if FD >= 2 if (!formlist || !*formlist) return(-3); #endif if (!(nline = countvar(lvar))) { lvar = (char **)realloc2(lvar, (nline + 2) * sizeof(char *)); if (!(lvar[nline] = fgets2(fp, 0))) return(-1); lvar[++nline] = NULL; } if (isttyiomode && intrkey(K_ESC)) return(-2); #if FD >= 2 if (matchlist(lvar[0], lign)) { free(lvar[0]); memmove((char *)(&(lvar[0])), (char *)(&(lvar[1])), nline * sizeof(char *)); (*linenop)++; return(0); } if (matchlist(lvar[0], lerr)) return(-3); #endif /* FD >= 2 */ #if FD >= 2 nf = countvar(formlist); scorelist = (short *)malloc2(nf * sizeof(short)); for (i = 0; i < nf; i++) scorelist[i] = MAXSCORE; nf = na = skip = 0; form0 = NULL; ret = 1; #else /* FD < 2 */ max = 0; for (i = 0; i < MAXLAUNCHFIELD; i++) if (list -> field[i] < 255 && (int)(list -> field[i]) > max) max = (int)(list -> field[i]); #endif /* FD < 2 */ namep -> name = NULL; #ifndef NOSYMLINK namep -> linkname = NULL; #endif needline = 0; for (;;) { #if FD >= 2 # ifdef FAKEUNINIT form2 = NULL; /* fake for -Wuninitialized */ # endif if (formlist[nf]) form = form2 = formlist[nf]; else if (scorelist[0] < MAXSCORE) { ret = scorelist[0] + 1; score = 0; break; } else if (na < AUTOFORMATSIZ) form = autoformat[na++]; else { if (!form0) form0 = decodestr(list -> format[0], NULL, 0); form = form0; skip++; } needline = 1; for (i = 0; form[i]; i++) if (form[i] == '\n') needline++; #else needline = list -> lines; #endif if (nline < needline) { lvar = (char **)realloc2(lvar, (needline + 1) * sizeof(char *)); for (; nline < needline; nline++) if (!(lvar[nline] = fgets2(fp, 0))) break; lvar[nline] = NULL; if (nline < needline) { #if FD >= 2 if (needline > 1 && na < AUTOFORMATSIZ) { if (!formlist[nf]) continue; free(formlist[nf]); for (i = nf; formlist[i]; i++) formlist[i] = formlist[i + 1]; continue; } if (namep -> name) free(namep -> name); namep -> name = NULL; # ifndef NOSYMLINK if (namep -> linkname) free(namep -> linkname); namep -> linkname = NULL; # endif if (form0) free(form0); free(scorelist); #endif *linenop += nline; return(-1); } } for (i = len = 0; i < needline; i++) len += strlen(lvar[i]) + 1; cp = malloc2(len + 1); for (i = len = 0; i < needline; i++) { strcpy(&(cp[len]), lvar[i]); len += strlen(lvar[i]); cp[len++] = LINESEP; } if (len > 0) len--; cp[len] = '\0'; #if FD >= 2 score = readfileent(&tmp, cp, form, skip); free(cp); if (score < 0) { if (formlist[nf]) { free(formlist[nf]); for (i = nf; formlist[i]; i++) formlist[i] = formlist[i + 1]; } else if (na >= AUTOFORMATSIZ) break; continue; } if (!formlist[nf]) { if (score < scorelist[0]) i = 0; } else { for (i = 0; i < nf; i++) if (score < scorelist[i]) { memmove((char *)(&(formlist[i + 1])), (char *)(&(formlist[i])), (nf - i) * sizeof(char *)); memmove((char *)(&(scorelist[i + 1])), (char *)(&(scorelist[i])), (nf - i) * sizeof(short)); break; } scorelist[i] = score; formlist[i] = form2; nf++; } if (score >= MAXSCORE); else if (!i) { if (namep -> name) free(namep -> name); # ifndef NOSYMLINK if (namep -> linkname) free(namep -> linkname); # endif memcpy((char *)namep, (char *)&tmp, sizeof(tmp)); } else { if (tmp.name) free(tmp.name); # ifndef NOSYMLINK if (tmp.linkname) free(tmp.linkname); # endif } if (!score) break; #else /* FD < 2 */ score = readfileent(namep, cp, list, max); free(cp); break; /*NOTREACHED*/ #endif /* FD < 2 */ } #if FD >= 2 if (score < 0) { if (namep -> name) free(namep -> name); namep -> name = NULL; # ifndef NOSYMLINK if (namep -> linkname) free(namep -> linkname); namep -> linkname = NULL; # endif } #endif /* FD >= 2 */ if (lvar) { for (i = 0; i < needline; i++) free(lvar[i]); if (nline + 1 > needline) memmove((char *)(&(lvar[0])), (char *)(&(lvar[needline])), (nline - needline + 1) * sizeof(char *)); } *linenop += needline; #if FD >= 2 if (form0) free(form0); free(scorelist); return((score) ? 0 : ret); #else return((score) ? 0 : 1); #endif } static VOID NEAR unpackerror(VOID_A) { if (!isttyiomode) { kanjifputs(UNPNG_K, stderr); fputnl(stderr); } else { Xlocate(0, n_line - 1); Xcputnl(); hideclock = 1; warning(0, UNPNG_K); } } static int NEAR readarchive(file, list, flags) CONST char *file; launchtable *list; int flags; { namelist tmp; FILE *fp; char *cp, *dir; int i, no, max, wastty; wastty = isttyiomode; if (!(fp = popenmacro(list -> comm, file, flags))) return(-1); if (wastty) Xwaitmes(); for (i = 0; i < (int)(list -> topskip); i++) { if (!(cp = fgets2(fp, 0))) break; free(cp); } maxfile = 0; addlist(); filelist[0].name = strdup2(parentpath); #ifndef NOSYMLINK filelist[0].linkname = NULL; #endif filelist[0].flags = (F_ISEXE | F_ISRED | F_ISWRI | F_ISDIR); filelist[0].tmpflags = F_STAT; maxfile++; #ifdef HAVEFLAGS tmp.st_flags = (u_long)0; #endif no = 0; max = -1; parsearchive(NULL, list, NULL, NULL); for (;;) { i = parsearchive(fp, list, &tmp, &no); if (i < 0) { if (i == -1) break; pclose2(fp); if (i == -3) unpackerror(); parsearchive(NULL, NULL, NULL, NULL); for (i = 0; i < maxfile; i++) { free(filelist[i].name); #ifndef NOSYMLINK if (filelist[i].linkname) free(filelist[i].linkname); #endif } return(-1); } if (!i) continue; else if (max < 0) max = i; else if (i > max) continue; while ((dir = pseudodir(&tmp)) && dir != tmp.name) { addlist(); memcpy((char *)&(filelist[maxfile]), (char *)&tmp, sizeof(namelist)); filelist[maxfile].st_mode &= ~S_IFMT; filelist[maxfile].st_mode |= S_IFDIR; filelist[maxfile].st_size = 0; filelist[maxfile].flags |= F_ISDIR; filelist[maxfile].name = dir; #ifndef NOSYMLINK filelist[maxfile].linkname = NULL; #endif filelist[maxfile].ent = no; maxfile++; } if (!dir) { free(tmp.name); #ifndef NOSYMLINK if (tmp.linkname) free(tmp.linkname); #endif continue; } addlist(); memcpy((char *)&(filelist[maxfile]), (char *)&tmp, sizeof(namelist)); filelist[maxfile].ent = no; maxfile++; } parsearchive(NULL, NULL, NULL, NULL); no -= (int)(list -> bottomskip); for (i = maxfile - 1; i > 0; i--) { if (filelist[i].ent <= no) break; free(filelist[i].name); #ifndef NOSYMLINK if (filelist[i].linkname) free(filelist[i].linkname); #endif } maxfile = i + 1; for (i = 0; i < maxfile; i++) filelist[i].ent = i; if (maxfile <= 1) { maxfile = 0; free(filelist[0].name); filelist[0].name = (char *)NOFIL_K; #ifndef NOSYMLINK if (filelist[0].linkname) { free(filelist[0].linkname); filelist[0].linkname = NULL; } #endif filelist[0].st_nlink = -1; filelist[0].flags = 0; filelist[0].tmpflags = F_STAT; } if ((i = pclose2(fp))) { if (i > 0) unpackerror(); for (i = 0; i < maxfile; i++) { free(filelist[i].name); #ifndef NOSYMLINK if (filelist[i].linkname) free(filelist[i].linkname); #endif } return(-1); } return(maxfile); } VOID copyarcf(re, arcre) CONST reg_t *re; CONST char *arcre; { char *cp, *tmp; int i, j, n, len, parent; parent = (*archivedir) ? 0 : -1; /* omit filelist[0] as pseudo ".." */ for (i = 1; i < maxarcf; i++) { if (!*archivedir) len = 0; else if (!(len = dirmatchlen(archivedir, arcflist[i].name))) continue; cp = &(arcflist[i].name[len]); if (*cp && len > 0 && (len > 1 || *archivedir != _SC_)) cp++; if (!*cp) { parent = i; continue; } if (!(tmp = strdelim(cp, 0))) len = strlen(cp); else { len = (tmp == cp) ? 1 : tmp - cp; while (*(++tmp) == _SC_); } if (parent <= 0 && len == 2 && cp[0] == '.' && cp[1] == '.') parent = i; if ((tmp && *tmp) || (re && !regexp_exec(re, cp, 1))) continue; if (arcre) { if (!(n = searcharc(arcre, arcflist, maxarcf, i))) continue; if (n < 0) break; } for (j = 0; j < stackdepth; j++) if (!strcmp(cp, filestack[j].name)) break; if (j < stackdepth) continue; memcpy((char *)&(filelist[maxfile]), (char *)&(arcflist[i]), sizeof(namelist)); filelist[maxfile].name = cp; #ifndef NOSYMLINK filelist[maxfile].linkname = arcflist[i].linkname; #endif maxfile++; } if (parent < 0) return; for (i = 0; i < maxfile; i++) if (isdotdir(filelist[i].name) == 1) return; memmove((char *)&(filelist[1]), (char *)&(filelist[0]), maxfile++ * sizeof(namelist)); memcpy((char *)&(filelist[0]), (char *)&(arcflist[parent]), sizeof(namelist)); filelist[0].name = arcflist[0].name; #ifndef NOSYMLINK filelist[0].linkname = NULL; #endif } static char *NEAR searcharcdir(file, flen) CONST char *file; int flen; { char *cp, *tmp; int i, len; errno = ENOENT; for (i = 0; i < maxarcf; i++) { if (!*archivedir) len = 0; else if (!(len = dirmatchlen(archivedir, arcflist[i].name))) continue; cp = &(arcflist[i].name[len]); if (*cp && len > 0 && (len > 1 || *archivedir != _SC_)) cp++; if (!*cp) { if (file) continue; } else { if (!file) continue; if (!(tmp = strdelim(cp, 0))) len = strlen(cp); else { len = (tmp == cp) ? 1 : tmp - cp; while (*(++tmp) == _SC_); } if (!*file && len == 2 && cp[0] == '.' && cp[1] == '.') return(arcflist[0].name); if ((tmp && *tmp) || len != flen || strnpathcmp(file, cp, flen)) continue; if (!isdir(&(arcflist[i]))) { errno = ENOTDIR; continue; } } return(arcflist[i].name); } return(NULL); } static char *NEAR archoutdir(VOID_A) { char *cp, *file; if (!*archivedir) return((char *)-1); if (!(file = searcharcdir(NULL, 0))) return(NULL); cp = &(file[(int)strlen(file) - 1]); while (cp > file && *cp == _SC_) cp--; #ifdef BSPATHDELIM if (onkanji1(file, cp - file)) cp++; #endif cp = strrdelim2(file, cp); if (!cp) *archivedir = '\0'; else { if (cp == file) copyrootpath(archivedir); else strncpy2(archivedir, file, cp - file); file = ++cp; } return(file); } CONST char *archchdir(path) CONST char *path; { CONST char *cp, *file; char *tmp, duparcdir[MAXPATHLEN]; int len; if (findpattern) free(findpattern); findpattern = NULL; #ifndef _NOBROWSE if (browselist) { int i, n, flags, dupfilepos; if (!path || !*path) path = parentpath; if ((cp = strdelim(path, 0))) { for (i = 1; cp[i]; i++) if (cp[i] != _SC_) break; if (cp[i]) { errno = ENOENT; return(NULL); } strncpy2(duparcdir, path, (cp - path)); path = duparcdir; } n = browselevel; cp = browselist[n].ext; flags = (F_NOCONFIRM | F_ARGSET | F_NOADDOPT | F_IGNORELIST); dupfilepos = filepos; if (path == filelist[filepos].name) i = filepos; else for (i = 0; i < maxfile; i++) if (!strcmp(path, filelist[i].name)) break; if (i < maxfile && isdir(&(filelist[i]))) filepos = i; else if (!isdotdir(path)) { errno = ENOENT; return(NULL); } pushbrowsevar(path); if (cp && !(browselist[n].flags & LF_DIRNOPREP)) execusercomm(cp, path, flags); if (isdotdir(path)) { filepos = dupfilepos; popbrowsevar(); return((path[1]) ? (char *)-1 : path); } if (browselist[n + 1].comm && !(browselist[n].flags & LF_DIRLOOP)) n++; if (dolaunch(&(browselist[n]), flags) < 0 || !isarchbr(&(browselist[n]))) { popbrowsevar(); return(path); } browselevel = n; return(parentpath); } #endif /* !_NOBROWSE */ if (!path) return(archoutdir()); strcpy(duparcdir, archivedir); do { if (*path == _SC_) len = 1; else if ((cp = strdelim(path, 0))) len = cp - path; else len = strlen(path); cp = path; if (len == 2 && path[0] == '.' && path[1] == '.') cp = nullstr; if (searcharcdir(cp, len)) { if (*(tmp = archivedir)) tmp = strcatdelim(archivedir); strncpy2(tmp, path, len); file = parentpath; } else if (*cp || !(file = archoutdir())) { strcpy(archivedir, duparcdir); errno = ENOENT; return(NULL); } else if (file == (char *)-1) break; path += len; while (*path == _SC_) path++; } while (*path); return(file); } #ifndef _NOCOMPLETE int completearch(path, flen, argc, argvp) CONST char *path; int flen, argc; char ***argvp; { CONST char *cp, *file; char *tmp, *new, dir[MAXPATHLEN], duparcdir[MAXPATHLEN]; int i, len, parent; # ifdef _USEDOSPATH if (_dospath(path)) return(argc); # endif strcpy(duparcdir, archivedir); if (!(file = strrdelim(path, 0))) file = path; # ifndef _NOBROWSE else if (browselist) return(argc); # endif else { strncpy2(dir, path, (file == path) ? 1 : file - path); if (!(cp = archchdir(dir)) || cp == (char *)-1) { strcpy(archivedir, duparcdir); return(argc); } flen -= ++file - path; } /* omit filelist[0] as pseudo ".." */ for (i = 1; i < maxarcf; i++) { if (!*archivedir) len = 0; else if (!(len = dirmatchlen(archivedir, arcflist[i].name))) continue; cp = &(arcflist[i].name[len]); if (*cp && len > 0 && (len > 1 || *archivedir != _SC_)) cp++; if (!*cp) continue; if (!(tmp = strdelim(cp, 0))) len = strlen(cp); else { len = (tmp == cp) ? 1 : tmp - cp; while (*(++tmp) == _SC_); } parent = 0; if (len == 2 && cp[0] == '.' && cp[1] == '.') parent++; else if (tmp && *tmp) continue; if (strnpathcmp(file, cp, flen)) continue; new = malloc2(len + 1 + 1); strncpy(new, cp, len); if (parent || isdir(&(arcflist[i]))) new[len++] = _SC_; new[len] = '\0'; if (finddupl(new, argc, *argvp)) { free(new); continue; } *argvp = (char **)realloc2(*argvp, (argc + 1) * sizeof(char *)); (*argvp)[argc++] = new; } strcpy(archivedir, duparcdir); return(argc); } #endif /* !_NOCOMPLETE */ int dolaunch(list, flags) launchtable *list; int flags; { #ifndef _NODOSDRIVE int drive; #endif CONST char *cp; char *tmpdir; int i; tmpdir = NULL; #ifndef _NODOSDRIVE drive = 0; #endif if (flags & F_ARGSET) /*EMPTY*/; else if (archivefile) { if (!(tmpdir = tmpunpack(1))) { Xputterm(T_BELL); return(-1); } } #ifndef _NODOSDRIVE else if ((drive = tmpdosdupl(nullstr, &tmpdir, 1)) < 0) { Xputterm(T_BELL); return(-1); } #endif if (!isarchbr(list)) { ptyusercomm(list -> comm, filelist[filepos].name, flags); if (flags & F_ARGSET) /*EMPTY*/; #ifndef _NODOSDRIVE else if (drive) removetmp(tmpdir, filelist[filepos].name); #endif else if (archivefile) removetmp(tmpdir, NULL); return(1); } pusharchdupl(); if (flags & F_ARGSET) /*EMPTY*/; #ifndef _NODOSDRIVE else if (drive) { archduplp -> v_fullpath = strdup2(fullpath); strcpy(fullpath, tmpdir); } #endif else if (archivefile) { archduplp -> v_fullpath = strdup2(fullpath); strcpy(fullpath, tmpdir); if (*archivedir) { strcpy(strcatdelim(fullpath), archivedir); archduplp -> v_archivedir = strdup2(archivedir); } } cp = (filelist && filepos < maxfile) ? filelist[filepos].name : NULL; if (!cp) cp = nullstr; archivefile = strdup2(cp); *archivedir = '\0'; archtmpdir = tmpdir; #ifndef _NODOSDRIVE archdrive = drive; #endif #ifndef _NOTREE treepath = NULL; #endif findpattern = NULL; launchp = list; filelist = NULL; maxent = 0; #if FD >= 2 if (sorttype < 200) sorton = 0; #else sorton = 0; #endif if (readarchive(archivefile, launchp, flags) < 0) { arcflist = NULL; poparchdupl(); return(-1); } arcflist = (namelist *)malloc2(((maxfile) ? maxfile : 1) * sizeof(namelist)); for (i = 0; i < maxfile; i++) memcpy((char *)&(arcflist[i]), (char *)&(filelist[i]), sizeof(namelist)); maxarcf = maxfile; maxfile = 0; filepos = -1; return(1); } int launcher(VOID_A) { reg_t *re; int i, n; #ifndef _NOBROWSE if (browselist) { char *cp; int flags; n = browselevel; cp = browselist[n].ext; flags = (F_NOCONFIRM | F_ARGSET | F_NOADDOPT | F_IGNORELIST); pushbrowsevar(filelist[filepos].name); if (cp && !(browselist[n].flags & LF_FILENOPREP)) execusercomm(cp, filelist[filepos].name, flags); if (browselist[n + 1].comm && !(browselist[n].flags & LF_FILELOOP)) n++; if (dolaunch(&(browselist[n]), flags) < 0 || !isarchbr(&(browselist[n]))) { popbrowsevar(); return(-1); } browselevel = n; return(1); } #endif /* !_NOBROWSE */ for (i = 0; i < maxlaunch; i++) { #ifndef PATHNOCASE if (launchlist[i].flags & LF_IGNORECASE) pathignorecase++; #endif re = regexp_init(launchlist[i].ext, -1); n = regexp_exec(re, filelist[filepos].name, 0); regexp_free(re); #ifndef PATHNOCASE if (launchlist[i].flags & LF_IGNORECASE) pathignorecase--; #endif if (n) break; } if (i >= maxlaunch) return(0); return(dolaunch(&(launchlist[i]), F_NOCONFIRM | F_IGNORELIST)); } static int NEAR undertmp(path) CONST char *path; { winvartable *wvp; char *full, rpath[MAXPATHLEN], dir[MAXPATHLEN]; full = fullpath; realpath2(path, rpath, 1); for (wvp = archduplp; wvp; wvp = wvp -> v_archduplp) { if (!(wvp -> v_fullpath)) continue; realpath2(full, dir, 1); if (underpath(rpath, dir, -1)) return(1); full = wvp -> v_fullpath; } return(0); } #ifdef _NODOSDRIVE static char *NEAR genfullpath(path, file, full) char *path; CONST char *file, *full; #else static char *NEAR genfullpath(path, file, full, tmpdir) char *path; CONST char *file, *full, *tmpdir; #endif { #if MSDOS char *tmp; int drive; #endif CONST char *cp; cp = file; #if MSDOS if ((drive = _dospath(cp))) cp += 2; #endif #ifdef _USEDOSEMU if (_dospath(cp)) cp += 2; #endif #ifndef _NODOSDRIVE if (tmpdir) strcpy(path, tmpdir); else #endif if (*cp == _SC_) { strcpy(path, file); return(path); } else if (!full || !*full) { errno = ENOENT; return(NULL); } #if MSDOS else if (drive) { tmp = gendospath(path, drive, _SC_); drive = toupper2(drive); if (drive == toupper2(*full)) strcpy(tmp, &(full[3])); else if (!unixgetcurdir(tmp, drive - 'A' + 1)) return(NULL); } #endif else strcpy(path, full); strcpy(strcatdelim(path), cp); return(path); } #ifndef _NODOSDRIVE static int NEAR archdostmpdir(path, dirp, full) char *path, **dirp; CONST char *full; { char *cp, dupfullpath[MAXPATHLEN]; int drive; strcpy(dupfullpath, fullpath); if (full != fullpath) { strcpy(fullpath, full); if (_chdir2(fullpath) < 0) full = NULL; } drive = dospath2(path); strcpy(fullpath, dupfullpath); if (full != fullpath && _chdir2(fullpath) < 0) { lostcwd(fullpath); return(-1); } if (!drive) return(0); cp = path; if (_dospath(cp)) cp += 2; if (full) strcpy(fullpath, full); else if (*cp != _SC_) return(-1); realpath2(path, path, 1); strcpy(fullpath, dupfullpath); if (!(cp = dostmpdir(drive))) return(-1); *dirp = cp; return(1); } #endif /* !_NODOSDRIVE */ int pack(arc) CONST char *arc; { #ifndef _NODOSDRIVE char *dest, *tmpdest; int drive; #endif winvartable *wvp; reg_t *re; char *tmpdir, *full, *duparchivefile, path[MAXPATHLEN]; int i, n, ret; for (i = 0; i < maxarchive; i++) { if (!archivelist[i].p_comm) continue; #ifndef PATHNOCASE if (archivelist[i].flags & AF_IGNORECASE) pathignorecase++; #endif re = regexp_init(archivelist[i].ext, -1); n = regexp_exec(re, arc, 0); regexp_free(re); #ifndef PATHNOCASE if (archivelist[i].flags & AF_IGNORECASE) pathignorecase--; #endif if (n) break; } if (i >= maxarchive) return(-1); full = fullpath; for (wvp = archduplp; wvp; wvp = wvp -> v_archduplp) if (wvp -> v_fullpath) full = wvp -> v_fullpath; ret = 1; tmpdir = NULL; #ifndef _NODOSDRIVE tmpdest = NULL; drive = 0; strcpy(path, arc); if ((dest = strrdelim(path, 1))) *(++dest) = '\0'; else copycurpath(path); if ((n = archdostmpdir(path, &tmpdest, full)) < 0) { warning(ENOENT, arc); return(0); } if (n) dest = strdup2(path); #endif /* !_NODOSDRIVE */ if (archivefile) { if (!(tmpdir = tmpunpack(0))) { #ifndef _NODOSDRIVE free(dest); #endif return(0); } } #ifndef _NODOSDRIVE else if ((drive = tmpdosdupl(nullstr, &tmpdir, 0)) < 0) { free(dest); return(0); } #endif #ifdef _NODOSDRIVE if (!genfullpath(path, arc, full)) warning(-1, arc); #else if (!genfullpath(path, arc, full, tmpdest)) warning(-1, arc); #endif else { duparchivefile = archivefile; archivefile = NULL; Xwaitmes(); ret = execusercomm(archivelist[i].p_comm, path, F_ARGSET | F_ISARCH | F_NOADDOPT); if (ret > 0) { if (ret < 127) { hideclock = 1; warning(0, HITKY_K); } rewritefile(1); } archivefile = duparchivefile; } #ifndef _NODOSDRIVE if (tmpdest) { if (!ret) { if (_chdir2(tmpdest) < 0) ret = 1; else VOID_C forcemovefile(dest); } free(dest); removetmp(tmpdest, NULL); } if (drive) removetmp(tmpdir, NULL); else #endif /* !_NODOSDRIVE */ if (archivefile) removetmp(tmpdir, NULL); return((ret) ? 0 : 1); } /*ARGSUSED*/ int unpack(arc, dir, arg, tr, flags) CONST char *arc, *dir, *arg; int tr, flags; { #ifndef _NODOSDRIVE winvartable *wvp; namelist alist[1], *dupfilelist; char *full, *dest, *tmpdest; int drive, dupmaxfile, dupfilepos; #endif reg_t *re; char *cp, *new, *tmpdir, path[MAXPATHLEN]; int i, n, ret; #ifndef _NOBROWSE if (browselist) { warning(0, UNPNG_K); return(0); } #endif for (i = 0; i < maxarchive; i++) { if (!archivelist[i].u_comm) continue; #ifndef PATHNOCASE if (archivelist[i].flags & AF_IGNORECASE) pathignorecase++; #endif re = regexp_init(archivelist[i].ext, -1); n = regexp_exec(re, arc, 0); regexp_free(re); #ifndef PATHNOCASE if (archivelist[i].flags & AF_IGNORECASE) pathignorecase--; #endif if (n) break; } if (i >= maxarchive) return(-1); if (dir) strcpy(path, dir); else for (;;) { #ifndef _NOTREE if (tr) dir = new = tree(0, NULL); else #endif /* !_NOTREE */ { if (arg && *arg) new = strdup2(arg); else new = inputstr(UNPAC_K, 1, -1, NULL, HST_PATH); dir = new = evalpath(new, 0); } if (!dir) return(0); if (!*dir) copycurpath(path); else { cp = strcpy2(path, dir); #ifdef _USEDOSPATH if (_dospath(dir) && !dir[2]) copycurpath(cp); #endif } free(new); dir = NULL; if (!undertmp(path)) break; Xlocate(0, L_CMDLINE); Xputterm(L_CLEAR); Xcprintf2("[%.*s]", n_column - 2, path); if (yesno(UNPTM_K)) break; } ret = 1; cp = path; tmpdir = NULL; #ifndef _NODOSDRIVE tmpdest = NULL; full = fullpath; for (wvp = archduplp; wvp; wvp = wvp -> v_archduplp) if (wvp -> v_fullpath) full = wvp -> v_fullpath; if ((n = archdostmpdir(path, &tmpdest, full)) < 0) { warning(ENOENT, path); return(0); } if (n) { dest = strdup2(path); cp = tmpdest; } # ifdef FAKEUNINIT else dest = NULL; /* fake for -Wuninitialized */ # endif dupfilelist = filelist; dupmaxfile = maxfile; dupfilepos = filepos; alist[0].name = (char *)arc; # ifndef NOSYMLINK alist[0].linkname = NULL; # endif alist[0].st_mode = 0700; filelist = alist; maxfile = 1; filepos = 0; drive = tmpdosdupl(arc, &tmpdir, 0); filelist = dupfilelist; maxfile = dupmaxfile; filepos = dupfilepos; if (drive < 0) warning(-1, arc); else #endif /* !_NODOSDRIVE */ if ((!dir && preparedir(path) < 0) || _chdir2(cp) < 0) warning(-1, path); #ifdef _NODOSDRIVE else if (!genfullpath(path, arc, fullpath)) warning(-1, arc); #else else if (!genfullpath(path, arc, fullpath, tmpdir)) warning(-1, arc); #endif else { Xwaitmes(); ret = execusercomm(archivelist[i].u_comm, path, flags); if (ret > 0) { if (ret < 127) { hideclock = 1; warning(0, HITKY_K); } rewritefile(1); } } #ifndef _NODOSDRIVE if (tmpdest) { if (!ret) VOID_C forcemovefile(dest); free(dest); removetmp(tmpdest, NULL); } if (tmpdir) removetmp(tmpdir, arc); else #endif /* !_NODOSDRIVE */ if (_chdir2(fullpath) < 0) lostcwd(fullpath); return((ret) ? 0 : 1); } #ifndef NOSYMLINK static int NEAR archrealpath(path, resolved) char *path, *resolved; { char *cp, tmp[MAXPATHLEN]; int n; if (!*path || (n = isdotdir(path)) == 2) /*EMPTY*/; else if (n == 1) { cp = strrdelim(resolved, 0); if (!cp) return(-1); *cp = '\0'; } else if ((cp = strdelim(path, 0))) { strncpy2(tmp, path, cp - path); if (archrealpath(tmp, resolved) < 0) return(-1); if (archrealpath(++cp, resolved) < 0) return(-1); } else { cp = strcatdelim(resolved); strncpy2(cp, path, MAXPATHLEN - 1 - (cp - resolved)); } return(0); } static int NEAR unpacklink(list, dir) namelist *list; CONST char *dir; { namelist duplist; char *cp, path[MAXPATHLEN], duparcdir[MAXPATHLEN]; int i, ret; if (!(list -> linkname)) return(0); if (!islink(list)) cp = list -> linkname; else { strcatdelim2(duparcdir, archivedir, list -> linkname); cp = duparcdir; } *path = '\0'; if (archrealpath(cp, path) < 0) return(-1); for (i = 0; i < maxarcf; i++) { *duparcdir = '\0'; if (archrealpath(arcflist[i].name, duparcdir) < 0) continue; if (!strcmp(path, duparcdir)) break; } if (i >= maxarcf) return(-1); if (unpacklink(&(arcflist[i]), dir) < 0) return(-1); strcpy(duparcdir, archivedir); memcpy(&duplist, &(filelist[filepos]), sizeof(namelist)); memcpy(&(filelist[filepos]), &(arcflist[i]), sizeof(namelist)); if (!(cp = strrdelim(filelist[filepos].name, 0))) *archivedir = '\0'; else { strncpy2(archivedir, filelist[filepos].name, cp - filelist[filepos].name); filelist[filepos].name = ++cp; } ret = unpack(archivefile, dir, NULL, 0, F_ARGSET | F_ISARCH | F_NOADDOPT); memcpy(&(filelist[filepos]), &duplist, sizeof(namelist)); strcpy(archivedir, duparcdir); return(ret); } #endif /* !NOSYMLINK */ char *tmpunpack(single) int single; { #ifdef _USEDOSEMU char tmp[MAXPATHLEN]; #endif winvartable *wvp; char *subdir, *tmpdir, path[MAXPATHLEN]; int i, ret, dupmark; for (i = 0, wvp = archduplp; wvp; i++, wvp = wvp -> v_archduplp); strcpy(path, ARCHTMPPREFIX); if (mktmpdir(path) < 0) { warning(-1, path); return(NULL); } tmpdir = strdup2(path); for (i = 0; i < maxfile; i++) if (ismark(&(filelist[i]))) filelist[i].tmpflags |= F_WSMRK; dupmark = mark; if (single) { mark = 0; #ifndef NOSYMLINK VOID_C unpacklink(&(filelist[filepos]), path); #endif } ret = unpack(archivefile, path, NULL, 0, F_ARGSET | F_ISARCH | F_NOADDOPT); mark = dupmark; for (i = 0; i < maxfile; i++) { if (wasmark(&(filelist[i]))) filelist[i].tmpflags |= F_ISMRK; filelist[i].tmpflags &= ~F_WSMRK; } subdir = archivedir; while (*subdir == _SC_) subdir++; if (ret < 0) Xputterm(T_BELL); else if (!ret) /*EMPTY*/; else if (_chdir2(path) < 0) { hideclock = 1; warning(-1, path); } else if (*subdir && _chdir2(subdir) < 0) { hideclock = 1; warning(-1, subdir); } else if (single || mark <= 0) { if (Xaccess(fnodospath(tmp, filepos), F_OK) >= 0) return(tmpdir); hideclock = 1; warning(-1, filelist[filepos].name); } else { for (i = 0; i < maxfile; i++) { if (!ismark(&(filelist[i]))) continue; if (Xaccess(fnodospath(tmp, i), F_OK) < 0) { hideclock = 1; warning(-1, filelist[i].name); break; } } if (i >= maxfile) return(tmpdir); } removetmp(tmpdir, NULL); return(NULL); } int backup(dev) CONST char *dev; { macrostat st; char *tmp; int i; waitmes(); if (!filelist) n_args = 0; else { for (i = 0; i < maxfile; i++) { if (ismark(&(filelist[i]))) filelist[i].tmpflags |= F_ISARG; else filelist[i].tmpflags &= ~F_ISARG; } n_args = mark; } st.flags = 0; if (!(tmp = evalcommand("tar cf %C %TA", dev, &st))) return(0); #ifdef _NOEXTRAMACRO if (filelist) for (;;) { system2(tmp, -1); free(tmp); if (!(st.flags & F_REMAIN) || !(tmp = evalcommand("tar rf %C %TA", dev, NULL))) break; } else #endif { system2(tmp, -1); free(tmp); } if (filelist) { for (i = 0; i < maxfile; i++) filelist[i].tmpflags &= ~(F_ISARG | F_ISMRK); mark = 0; marksize = (off_t)0; } return(1); } int searcharc(regstr, flist, maxf, n) CONST char *regstr; namelist *flist; int maxf, n; { namelist tmp; launchtable *list; namelist *dupfilelist; reg_t *re; FILE *fp; char *cp, *next, *tmpdir, *file; int i, c, no, match, dupmaxfile, dupfilepos; if (n < 0) { file = flist -> name; if (isdir(flist)) return(0); } else { file = flist[n].name; if (isdir(&(flist[n]))) return(0); } for (i = 0; i < maxlaunch; i++) { if (!isarchbr(&(launchlist[i]))) continue; #ifndef PATHNOCASE if (launchlist[i].flags & LF_IGNORECASE) pathignorecase++; #endif re = regexp_init(launchlist[i].ext, -1); c = regexp_exec(re, file, 0); regexp_free(re); #ifndef PATHNOCASE if (launchlist[i].flags & LF_IGNORECASE) pathignorecase--; #endif if (c) break; } if (i >= maxlaunch) return(0); list = &(launchlist[i]); if (n >= 0) { dupfilelist = filelist; dupmaxfile = maxfile; dupfilepos = filepos; filelist = flist; maxfile = maxf; filepos = n; tmpdir = tmpunpack(1); filelist = dupfilelist; maxfile = dupmaxfile; filepos = dupfilepos; if (!tmpdir) return(0); } #ifdef FAKEUNINIT else tmpdir = NULL; /* fake for -Wuninitialized */ #endif Xlocate(0, n_line - 1); Xtflush(); if (!(fp = popenmacro(list -> comm, file, F_IGNORELIST))) { if (n >= 0) removetmp(tmpdir, file); return(0); } Xlocate(0, L_MESLINE); Xputterm(L_CLEAR); Xputterm(T_STANDOUT); Xkanjiputs(SEACH_K); Xputterm(END_STANDOUT); Xkanjiputs(file); Xtflush(); for (i = 0; i < (int)(list -> topskip); i++) { if (!(cp = fgets2(fp, 0))) break; free(cp); } no = match = 0; re = regexp_init(regstr, -1); parsearchive(NULL, list, NULL, NULL); for (;;) { if (match && match <= no - (int)(list -> bottomskip)) break; i = parsearchive(fp, list, &tmp, &no); if (i < 0) { if (i == -1) break; pclose2(fp); parsearchive(NULL, NULL, NULL, NULL); regexp_free(re); if (n >= 0) removetmp(tmpdir, file); return(-1); } if (!i) continue; cp = tmp.name; while (cp) { if ((next = strdelim(cp, 0))) *(next++) = '\0'; if (regexp_exec(re, cp, 1)) break; cp = next; } if (cp) match = no; free(tmp.name); #ifndef NOSYMLINK if (tmp.linkname) free(tmp.linkname); #endif } parsearchive(NULL, NULL, NULL, NULL); regexp_free(re); if (n >= 0) removetmp(tmpdir, file); if ((i = pclose2(fp))) return((i > 0) ? -1 : 0); if (match > no - (int)(list -> bottomskip)) match = 0; return(match); } #endif /* !_NOARCHIVE */