ftp.nice.ch/pub/next/unix/hack/hackkit.2.N.bs.tar.gz#/freebies/source/nilist.c

This is nilist.c in view mode; [Download] [Up]

/*	nilist.c

	Turn the netinfo database into human-readable text.  Someday I
	hope there will be a parser for this to turn it back, or even
	better a new netinfo server that reads this format database.
	Being able to edit the database as text (with the abilities to
	search, compare, and copy arbitrary regions) is much more
	"user friendly" than the fanciest panels of buttons!

	Written by Bill Spitzak, May 1990.
	SPITZAK @ MCIMAIL.COM

============================================================================

	Syntax of the output file:
	(originally I hoped to make this compatable with the "slash"
	notation favored by the NeXT "niutil -read" program.  However
	this required extensive quoting of the pathnames that are very
	common field values.  So I dumped that for this notation.)

	... means repeat the last object zero or more times.

	comment: '#' <any character except newline>... <newline>

	tokencharacter:
		'a' .. 'z'
		'A' .. 'Z'
		'0' .. '9'
		'.'
		'/'
		'_'
		'-'
		(others may be added if common in field names)

	word: tokencharacter...

	quoted_string: '"' <normal C-string stuff>... '"'

	name:
		word
		quoted_string

	property: name

	value: name

	subdirectory: name

	entry:
		property value... ';'
		subdirectory '{' entry... '}'

	file: entry...

*/

#include <netinfo/ni.h>

printname(char *n) {
    char *p; int c;
    if (!n) return;
    /* search to see if any characters need to be quoted: */
    if (*n) for (p = n; ;) {
	c = *p++;
	if (!c) {printf("%s",n); return;}
	if (c>='a' && c<='z' || c>='A' && c<='Z' || c>='0' && c<='9'
	    || index("/._-",c));
	else break;
	}
    putchar('"');
    for (p = n; c = *p++;) {
	switch (c) {
	case '\b': c = 'b'; goto QUOTE;
	case '\t': c = 't'; goto QUOTE;
	case '\n': c = 'n'; goto QUOTE;
	case '\f': c = 'f'; goto QUOTE;
	case '\r': c = 'r'; goto QUOTE;
	case '\\':
	case '"':
	QUOTE: putchar('\\'); putchar(c); break;
	default:
	    if (c < ' ' || c >= 127) printf("\\%3o",c&255);
	    else putchar(c);
	    break;
	    }
	}
    putchar('"');
    }

void nli(int level) {	/* new line and indent */
    int x; putchar('\n'); for (x=0; x < level; x++) putchar('\t');
    }

listdirectory(void *handle, ni_id *dir,int level)
{
    int n,m;
    ni_proplist props;
    ni_idlist idlist;
    ni_id subdir;
    ni_property *prop;
    ni_namelist *list;
    int itemcount;
    int big;
    int sepflag;
    char *name;
    char namebuf[20];

    ni_read(handle,dir,&props);
    ni_children(handle,dir,&idlist);
    itemcount = props.ni_proplist_len + idlist.ni_idlist_len;

    name = 0;
    if (level) {
	/* get the name out of the property list.  If it is the only
	   name decrement the number of properties to print */
	name = 0;
	for (n = 0; n < props.ni_proplist_len; n++) {
	    prop = props.ni_proplist_val+n;
	    if (!strcmp(prop->nip_name,"name")) {
		if (!prop->nip_val.ni_namelist_len) break;
		name = prop->nip_val.ni_namelist_val[0];
		if (prop->nip_val.ni_namelist_len == 1) itemcount--;
		break;
		}
	    }
	if (name) printname(name); else printf("_%d",dir->nii_object);
	big = itemcount > 3 || itemcount>1 && idlist.ni_idlist_len;
	putchar(big ? ' ' : '\t'); putchar('{'); if (big) nli(level);
	}
    else big = 1;

    sepflag = 0;
    for (n = 0; n < props.ni_proplist_len; n++) {
	prop = props.ni_proplist_val+n;
	list = &prop->nip_val;
	if (list->ni_namelist_len==1 &&
	    list->ni_namelist_val[0] == name) continue;
	if (!big && sepflag++) putchar(' ');
	printname(prop->nip_name);
	for (m = 0; m < list->ni_namelist_len; m++) {
	    if (list->ni_namelist_val[m] == name) continue;
	    putchar(' ');
	    printname(list->ni_namelist_val[m]);
	    }
	putchar(';');
	if (big) nli(level);
	}
    for (n = 0; n < idlist.ni_idlist_len; n++) {
	subdir.nii_object = idlist.ni_idlist_val[n];
	subdir.nii_instance = 0;
	listdirectory(handle,&subdir,level+1);
	if (big) nli(level);
	}

    if (level) putchar('}');

    ni_proplist_free(&props);
    ni_idlist_free(&idlist);
    }

listdomain(void *handle) {
    ni_id dir;
    ni_root(handle,&dir);
    listdirectory(handle,&dir,0);
    }

main(int argc, char **argv)
{
    int n,status;
    void *handle;
    if (argc < 2) {argv[1] = "."; argc = 2;}
    for (n = 1; n < argc; n++) {
	handle = 0;
	status = ni_open(0, argv[n], &handle);
	if (status) printf("Error %d opening domain %s.\n",status,argv[n]);
	else {listdomain(handle); ni_free(handle);}
	}
    }

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.