/* ldif_print_tree.exec - version 3                   */
/*                                                    */
/* Jim Dutton - 11 Sep 1998                           */
/* modified for Netscape DS specifics - 16 Mar 99     */
/* modified for Netscape LDIF specifics - 7 May 99    */
/*                                                    */
/* Dependencies:                                      */
/* REXX version: imc-beta-1.6c 4.00 10 Aug 1995 [Unix]*/
/* Unix commands (hostname, sort, rm, pipe)           */
/*                                                    */
/* Works with Netscape LDIF and UMich/OpenLDAP LDIF   */
/* Reads LDIF file and creates a pseudo "tree"        */
/* of RDN's listing RDN level and using indentation   */
/* and underscores to seperate and align RDN's        */
/*                                                    */
/* All RDN's are sorted in ascending alphabetical     */
/* (case insensitive) order. Only the RDN is          */
/* is printed. The true DN is determined by combining */
/* the printed RDN with all of its parent RDN's       */
/*                                                    */
/* Editing recommendation: set tab size to 2          */

Address 'COMMAND'; parse arg ldif_file .

failed = 2; at_eof = 0; null = ""; output_file = "/tmp/ldif_print_tree.dn"
dn_tag = "dn: "; offset = "    "; lastpart = ""; prev_lastpart = ""
true = 1; false = 0;NS_ldap_rdn = "cn=ldap://:389"; NS_schema_rdn = "cn=schema";

sorted_dn = "/tmp/ldif_print_tree.dn.sorted"
reverse_dn = "/tmp/ldif_print_tree.dn.reverse"; tree_file = "/tmp/ldif_dn_tree"
reverse_dn_sorted = "/tmp/ldif_print_tree.dn.reverse.sorted"

sort1_cmd = "sort -r -d -f -t, -o" reverse_dn_sorted output_file
sort2_cmd = "sort -d -f -t, -o" reverse_dn_sorted reverse_dn

If ldif_file = ""  then
  Do; say '*** Missing input LDIF file for "ldif_print_tree.exec"'; Exit 28; End
If open(ldif_file,r) = failed  then
	Do; say "*** Can't open '"ldif_file"' for input"; Exit 32; End
If open(output_file,w) = failed  then
	Do; say "*** Can't open '"output_file"' for output"; Exit 33; End

/* Netscape DS includes an entry for the IP host that the database */
/* is created on, using a DN syntax of all DC attributes           */
/* This particular object is not really important, so exclude it   */

duh = POPEN("hostname",R,pipe)
If duh = 0  then  parse value linein(pipe) with dc1"."dc2"."dc3"."dc4
Else  hostname = "unknown..."
duh = PCLOSE(pipe); ThisHostDN = "dc="dc1",dc="dc2",dc="dc3",dc="dc4

Call ON NOTREADY

parse value linein(ldif_file) with first_tag DN

Do until at_eof
	If pos(",",DN) > 0  then  parse var DN RDN",".
	Else  RDN = DN
	write_line = true

	Select
		When first_tag \= dn_tag  then  write_line = false;
		When DN  = null           then  write_line = false;
		When RDN = NS_ldap_rdn    then  write_line = false;
		When DN  = NS_schema_rdn  then  write_line = false;
		When DN  = ThisHostDN     then  write_line = false;
		Otherwise  /* read next line - may be DN continuation */
      nextline = substr(linein(ldif_file),2)
	   	parse var nextline firstword .
			If pos(":",firstword) = 0  then  DN = DN || nextline
	End

	If write_line = true  then  duh = lineout(output_file,DN)
  parse value linein(ldif_file) with first_tag DN
End

duh = close(ldif_file);  duh = close(output_file)

Address UNIX sort1_cmd
Address UNIX "rm" output_file

If open(reverse_dn_sorted,r) = failed  then
	Do; say "*** Can't open '"reverse_dn_sorted"' for input"; Exit 34; End
If open(reverse_dn,w) = failed  then
	Do; say "*** Can't open '"reverse_dn"' for output"; Exit 35; End

at_eof = 0; Call ON NOTREADY

input_line = reverse(linein(reverse_dn_sorted))
Do until at_eof
	output_line = null
	parse var input_line DNpart "," input_line; DNpart = strip(DNpart)
	If input_line \= null then
	  Do until (input_line = null)
			output_line = output_line || reverse(DNpart)","
			parse var input_line DNpart "," input_line; DNpart = strip(DNpart)
		End
	output_line = output_line || reverse(DNpart)
 	duh = lineout(reverse_dn,output_line)
	input_line = reverse(linein(reverse_dn_sorted))
End

duh = close(reverse_dn_sorted); duh = close(reverse_dn)

Address UNIX sort2_cmd
Address UNIX "rm" reverse_dn

If open(reverse_dn_sorted,r) = failed  then
	Do; say "*** Can't open '"reverse_dn_sorted"' for input"; Exit 36; End
If open(tree_file,w) = failed  then
	Do; say "*** Can't open '"tree_file"' for output"; Exit 37; End

at_eof = 0; Call ON NOTREADY

/* write final output to: ldif_dn_tree */

input_line = linein(reverse_dn_sorted); numlines = 0
parse var input_line firstlevel",".; duh = lineout(tree_file,firstlevel)
duh = lineout(tree_file,copies("-",length(firstlevel)))

Do until at_eof
	numlines = numlines + 1
	If pos(",",input_line) = 0  then
		Do
			duh = lineout(tree_file,input_line)
			duh = lineout(tree_file,copies("-",length(input_line)))
			prev_lastpart = input_line; indent = offset; prev_numparts = 1
		End
	Else
		Do
			mod_input_line = translate(input_line,"^"," ")
			mod_input_line = translate(mod_input_line," ",",")
			numparts = words(mod_input_line)
			Select
				When numparts > prev_numparts  then
					Do
						lastpart = word(mod_input_line,numparts)
						indent = copies(offset,prev_numparts)
						output_line = indent || lastpart
						output_line = translate(output_line," ","^")
						If numparts > 1  then
							output_line = overlay(numparts,output_line)
						duh = lineout(tree_file,output_line)
						output_line = indent || copies("-",length(lastpart))
						duh = lineout(tree_file,output_line)
						prev_numparts = numparts
					End
				When numparts = prev_numparts  then
					Do
						lastpart = word(mod_input_line,numparts)
						output_line = indent || lastpart
						output_line = translate(output_line," ","^")
						If numparts > 1  then
							output_line = overlay(numparts,output_line)
						duh = lineout(tree_file,output_line)
						output_line = indent || copies("-",length(lastpart))
						duh = lineout(tree_file,output_line)
					End
				Otherwise
						lastpart = word(mod_input_line,numparts)
						indent = copies(offset,numparts - 1)
						output_line = indent || lastpart
						output_line = translate(output_line," ","^")
						If numparts > 1  then
							output_line = overlay(numparts,output_line)
						duh = lineout(tree_file,output_line)
						output_line = indent || copies("-",length(lastpart))
						duh = lineout(tree_file,output_line)
						prev_numparts = numparts
			End
		End
	input_line = linein(reverse_dn_sorted)
End

duh = lineout(tree_file," ")
duh = lineout(tree_file,"[Number of DN's printed:"numlines"]")
duh = close(tree_file); duh = close(reverse_dn_sorted)
Address UNIX "rm" reverse_dn_sorted
Exit


NOTREADY:
	at_eof = 1
	Return
