archie/prospero/user/vls.c
2024-05-27 16:13:40 +02:00

396 lines
12 KiB
C

/*
* Copyright (c) 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <usc-license.h>
*/
#include <usc-license.h>
#include <stdio.h>
#include <pfs.h>
#include <perrno.h>
char *prog;
int pfs_debug = 0;
PATTRIB pget_at();
static const char *sequence_separator = " ; "; /* should be changed at some
point? */
static void
display_link(VLINK l, int dmagic,int verbose, int pretty_flag, int show_at,
char *at_name, int nesting);
void
main(argc,argv)
int argc;
char *argv[];
{
VDIR_ST dir_st;
VDIR dir= &dir_st;
VLINK l;
VLINK replica;
int flags = 0;
int verbose = 0;
int dmagic = 0;
int show_failed = 0;
int show_invisible = 0;
int show_at = 0;
int replica_flag = 0;
int pretty_flag = 0;
int conflict_flag = 0;
int dirflag = 0;
int tmp;
char *at_name = NULL; /* will point to allocated memory */
char *progname = argv[0];
prog = progname;
p_initialize("ufP", 0, (struct p_initialize_st *) NULL);
flags = RVD_LREMEXP;
vdir_init(dir);
argc--;argv++;
while (argc > 0 && **argv == '-') {
switch ((*argv)[1]) {
case 'a': /* Right now, just shows object attributes. */
/* SHOULD show object and link attributes both. */
show_at = 1;
verbose = 1;
tmp = qsscanf(argv[0],"-a%&s", &at_name);
if(tmp < 1) at_name = stcopy("#ALL");
break;
case 'A': /* Show only link attributes */
show_at = 2; /* Show only link attributes */
verbose = 1;
tmp = qsscanf(argv[0],"-A%&s", &at_name);
if(tmp < 1) at_name = stcopy("#ALL");
break;
case 'c': /* Show conflicting links */
conflict_flag++;
break;
case 'd': /* If target specified, treat it as a link even
if it's a directory. This is just like the -d
flag in UNIX ls. */
dirflag++;
break;
case 'D': /* Debug level */
pfs_debug = 1; /* Default debug level */
sscanf(argv[0],"-D%d",&pfs_debug);
break;
case 'f': /* Show failed links */
show_failed++;
break;
case 'i': /* Show invisible links */
show_invisible++;
break;
case 'm': /* Display magic number */
dmagic++;
break;
case 'N': /* ARDP priority level */
sscanf(argv[0],"-N%d",&ardp_priority);
break;
case 'P': /* Pretty flag -- truncate if too much. */
pretty_flag++;
break;
case 'r': /* Show replicas */
replica_flag++;
break;
case 'u': /* Do not expand union links */
flags = RVD_UNION;
break;
case 'v': /* Display link on more than one line (verbose) */
verbose = 1;
break;
default: {
usage:
fprintf(stderr,
"Usage: vls [-a,-A,-c,-r,-u,-v,-d] \
[<file or directory name>]\n");
exit(1);
}
}
argc--, argv++;
}
if(show_at) flags |= RVD_ATTRIB;
if (dirflag) flags |= RVD_DFILE_ONLY;
if (argc > 1) goto usage;
ardp_abort_on_int();
tmp = rd_vdir((argc == 1 ? argv[0] : ""), (char *) NULL, dir,flags);
if(tmp && (tmp != DIRSRV_NOT_DIRECTORY)) {
fprintf(stderr,"%s",progname);
perrmesg(" failed: ", tmp, NULL);
exit(1);
}
if(pwarn) pwarnmesg("WARNING: ",0,NULL);
l = dir->links;
while(l) {
if (show_invisible || l->linktype != 'I')
display_link(l,dmagic,verbose,pretty_flag,show_at,at_name, 0);
replica = l->replicas;
while(replica) {
if((replica_flag && (l->f_magic_no != 0) &&
(l->f_magic_no == replica->f_magic_no)) || conflict_flag)
if (show_invisible || l->linktype != 'I')
display_link(replica,
(dmagic || (l->f_magic_no != replica->f_magic_no)),
verbose, pretty_flag, show_at,at_name, 0);
replica = replica->next;
}
l = l->next;
}
l = dir->ulinks;
if((tmp != DIRSRV_NOT_DIRECTORY) || show_failed) {
while(l) {
if((l->expanded == FALSE) || (l->expanded == FAILED))
display_link(l,dmagic,verbose, pretty_flag, show_at,at_name, 0);
l = l->next;
}
}
vllfree(dir->links);
exit(0);
}
static void display_fil(FILTER fil, int nesting);
static void display_nesting(int nesting);
static void
display_link(VLINK l, int dmagic,int verbose, int pretty_flag, int show_at,
char *at_name, int nesting)
{
/* check if a string is a null pointer. If it is, return an empty string. */
#define chknl(s) ((s) ? (s) : "")
FILTER fil;
PATTRIB ap;
if(l->linktype == '-') return;
if (verbose) {
if (!nesting) putchar('\n');
display_nesting(nesting);
printf(" Name: %s\n",chknl(l->name));
display_nesting(nesting);
printf(" Target: %s\n",chknl(l->target));
display_nesting(nesting);
printf(" LinkType: %s\n",
((l->linktype == 'U') ? "Union" :
(l->linktype == 'I' ? "Invisible" : "Standard")));
if (l->hosttype && !strequal(l->hosttype, "") &&
!strequal(l->hosttype, "INTERNET-D")) {
display_nesting(nesting);
printf(" HostType: %s\n",chknl(l->hosttype));
}
display_nesting(nesting);
printf(" Host: %s\n",chknl(l->host));
if (l->hsonametype && !strequal(l->hsonametype, "") &&
!strequal(l->hsonametype, "ASCII")) {
display_nesting(nesting);
printf(" NameType: %s\n",chknl(l->hsonametype));
}
display_nesting(nesting);
printf(" Hsoname: %s\n",chknl(l->hsoname));
if(l->version) {
display_nesting(nesting);
printf(" Version: %ld\n",l->version);
}
if(dmagic || l->f_magic_no) {
display_nesting(nesting);
printf(" RemoteID: %ld\n",l->f_magic_no);
}
if(show_at) {
/* If only link attributes, then use l->lattrib */
/* otherwise get attribues for object. */
if(show_at == 2) ap = l->lattrib;
else {
/* Eventually we will merge the link attributes with */
/* the object attribues based on the precedence field,*/
/* but for now, if attributes are returned for the */
/* object we use them, otherwise we use those associated */
/* with the link */
ap = pget_at(l,at_name);
if(!ap) ap = l->lattrib; /* This really needs fixing soon. */
}
if(ap) {
display_nesting(nesting);
printf("Attributes:\n");
if (!nesting) putchar('\n');
while(ap) {
display_nesting(nesting);
printf("%15s: ",ap->aname);
if(ap->avtype == ATR_SEQUENCE) {
TOKEN tk;
int first_token_output = 0;
for (tk = ap->value.sequence; tk; tk = tk->next) {
if (first_token_output++)
fputs(sequence_separator, stdout);
/* if (tk->token) */
fputs(tk->token, stdout);
/* else fputs("''", stdout); */
}
putchar('\n');
} else if(ap->avtype == ATR_LINK) {
#if 1
puts("LINK valued attribute:");
/* Display the link WITH subattributes. */
/* Downgrade the show_at to not retrieving
OBJECT attributes from the sublinks, though. */
display_link(l, dmagic, verbose, pretty_flag,
show_at? 1 : 0,
at_name, nesting + 1);
#else
/* Display the link without subattributes */
VLINK vl = ap->value.link;
printf("%s %s %s %d %d\n",
vl->name, vl->host, vl->hsoname, vl->version,
vl->f_magic_no);
#endif
} else if (ap->avtype == ATR_FILTER)
display_fil(ap->value.filter, nesting);
else printf("<unknown-type %d>\n",ap->avtype);
ap = ap->next;
}
if(l->filters) printf("\n");
}
atlfree(ap);
}
if(l->filters) {
display_nesting(nesting);
printf(" Filters:\n");
for(fil = l->filters; fil; fil = fil->next) {
display_nesting(nesting);
display_fil(fil, nesting);
}
}
putchar('\n');
}
/* First character is determined by l->target and l->linktype.
U for a union link (always to a DIRECTORY or DIRECTORY+FILE)
I for an invisible link (only shown if -i flag specified)
(could be to a FILE, DIRECTORY, or DIRECTORY+FILE).
If a normal link, determined by l->target:
blank (' ') if a normal link to a FILE.
S for SYMBOLIC
E for EXTERNAL
N for NULL (returned if inadequate permissions),
D for DIRECTORY
B (Both) for DIRECTORY+FILE
O for OBJECT
Second character is F if expanding the union link failed. */
else {
char linkname[MAX_VPATH];
if(dmagic) sprintf(linkname,"%s#%ld",chknl(l->name),l->f_magic_no);
else strcpy(linkname,chknl(l->name));
printf((pretty_flag ? "%c%c %-20.20s %c%-15.15s %-38.38s\n"
: "%c%c %-20s %c%-15s %s\n"),
((l->linktype != 'L') ? l->linktype :
(l->target && strequal(l->target, "DIRECTORY+FILE")) ? 'B' :
(l->target && !strequal(l->target, "FILE")) ? *l->target
: ' '),
(l->expanded ? 'F' : ' '),
chknl(linkname),
(l->filters ? '*' : ' '),
chknl(l->host),chknl(l->hsoname));
}
}
static void
display_fil(FILTER fil, int nesting)
{
display_nesting(nesting);
if (fil->name)
printf("Predefined Filter: %s\n", fil->name);
else
/* Should we display link filters the same way we display other links?
Should we allow them to have subattributes? */
printf("Link Filter: %s %s %s %ld %ld\n", chknl(fil->link->name),
chknl(fil->link->host),
chknl(fil->link->hsoname), fil->link->version, fil->link->f_magic_no);
display_nesting(nesting);
switch(fil->type) {
case FIL_DIRECTORY:
printf(" DIRECTORY");
break;
case FIL_HIERARCHY:
printf(" HIERARCHY");
break;
case FIL_OBJECT:
printf(" OBJECT");
break;
case FIL_UPDATE:
printf(" UPDATE");
break;
default:
internal_error("unknown fil->type value.");
}
switch(fil->execution_location) {
case FIL_SERVER:
printf(" SERVER");
break;
case FIL_CLIENT:
printf(" CLIENT");
break;
default:
internal_error("unknown fil->execution_location");
}
switch(fil->pre_or_post) {
case FIL_PRE:
printf(" PRE");
break;
case FIL_POST:
printf(" POST");
break;
default:
internal_error("unknown fil->pre_or_post");
}
if (fil->args) {
TOKEN tk;
printf(" ARGS");
for (tk = fil->args; tk; tk = tk->next)
printf(" %s", tk->token);
}
putchar('\n');
}
static void
display_nesting(int nesting)
{
assert(nesting >= 0);
while (nesting--)
putchar('>');
}