*** support/tsapd.c	Tue Jun 16 13:40:21 1992
--- support/tsapd.c	Wed Jun 24 07:00:56 1992
***************
*** 332,340 ****
  		== NULL) {
  #else
      for (is = iae; is < iz; is++)
  	if (tsap_addr_cmp (&is -> is_addr, &ts -> ts_called) == OK)
  	    break;
! 
      if (is >= iz) {
  #endif
  	    (void) sprintf (buffer, "OSI service tsap/%s not found",
--- 332,349 ----
  		== NULL) {
  #else
      for (is = iae; is < iz; is++)
+ 	
+ #if 0
+ 	/* THIS doesn't work - JPO */
  	if (tsap_addr_cmp (&is -> is_addr, &ts -> ts_called) == OK)
  	    break;
! #else
!         if (is -> is_addr.ta_selectlen == ts -> ts_called.ta_selectlen
! 	    && bcmp (is -> is_addr.ta_selector,
! 		     ts -> ts_called.ta_selector,
! 		     is -> is_addr.ta_selectlen) == 0)
! 	    break;
! #endif
      if (is >= iz) {
  #endif
  	    (void) sprintf (buffer, "OSI service tsap/%s not found",
*** 9.0	1992/06/16 12:34:01
--- quipu/get_dsa_info.c	1992/07/20 14:16:31
***************
*** 235,241 ****
      */
  
      ent_res = &(on->on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry);
!     if((di_ent = cache_dsp_entry (ent_res)) == NULLENTRY)
      {
  	pslog (log_dsap,LLOG_EXCEPTIONS,
  	       "dsa_info_result_wakeup - cache_dsp_entry failure",
--- 235,241 ----
      */
  
      ent_res = &(on->on_resp.di_result.dr_res.dcr_dsres.res_rd.rdr_entry);
!     if((di_ent = cache_dsp_entry (ent_res,TRUE)) == NULLENTRY)
      {
  	pslog (log_dsap,LLOG_EXCEPTIONS,
  	       "dsa_info_result_wakeup - cache_dsp_entry failure",
*** 9.0	1992/06/16 12:34:01
--- quipu/ds_read.c	1992/07/20 14:16:26
***************
*** 39,45 ****
  Attr_Sequence dsa_eis_select ();
  extern Attr_Sequence entry_find_type();
  static cant_use_cache();
! static attribute_not_cached ();
  extern AttributeType at_control;
  extern unsigned bind_policy;
  extern unsigned strong_policy;
--- 39,45 ----
  Attr_Sequence dsa_eis_select ();
  extern Attr_Sequence entry_find_type();
  static cant_use_cache();
! static attribute_not_cache ();
  extern AttributeType at_control;
  extern unsigned bind_policy;
  extern unsigned strong_policy;
***************
*** 254,260 ****
  	if (dn == NULLDN) 
  		return FALSE;
  
! 	if ((ptr->e_data == E_DATA_MASTER) || (ptr->e_data == E_TYPE_SLAVE))
  		return FALSE;
  
  	/* see if more than cached data is required */	
--- 254,261 ----
  	if (dn == NULLDN) 
  		return FALSE;
  
! 	if ((ptr->e_data == E_DATA_MASTER) || (ptr->e_data == E_TYPE_SLAVE) ||
! 	    (ptr->e_complete == FALSE))
  		return FALSE;
  
  	/* see if more than cached data is required */	
*** 9.0	1992/06/16 12:34:01
--- quipu/oper_result.c	1992/07/20 14:16:31
***************
*** 73,79 ****
  
  	/* If we have the arguments we could do more caching here. */
  	if (dr->dr_res.dcr_dsres.result_type == OP_READ)
! 	       (void) cache_dsp_entry (&dr->dr_res.dcr_dsres.res_rd.rdr_entry);
  
  	ds_res_free (&dr->dr_res.dcr_dsres);
  	oper_extract(on);
--- 73,79 ----
  
  	/* If we have the arguments we could do more caching here. */
  	if (dr->dr_res.dcr_dsres.result_type == OP_READ)
! 	       (void) cache_dsp_entry (&dr->dr_res.dcr_dsres.res_rd.rdr_entry,TRUE);
  
  	ds_res_free (&dr->dr_res.dcr_dsres);
  	oper_extract(on);
*** 9.0	1992/06/16 12:34:01
--- quipu/dsp_cache.c	1992/07/20 14:16:32
***************
*** 43,50 ****
  extern AttributeType at_acl;
  extern AttributeType at_objectclass;
  
! Entry cache_dsp_entry (ptr)
  EntryInfo      *ptr;
  {
  	/* assumes entry passed is complete */
  
--- 43,51 ----
  extern AttributeType at_acl;
  extern AttributeType at_objectclass;
  
! Entry cache_dsp_entry (ptr,complete)
  EntryInfo      *ptr;
+ char * complete;
  {
  	/* assumes entry passed is complete */
  
***************
*** 89,95 ****
  			as_free (eptr->e_attributes);
  			as_write_files(ptr->ent_attr,edbtmp_path);
  			eptr->e_attributes = as_cpy(ptr->ent_attr);
! 			eptr->e_complete = TRUE;
  			eptr->e_data = E_TYPE_CACHE_FROM_MASTER;
  			eptr->e_age = timenow;
  			if (eptr->e_inherit)
--- 90,96 ----
  			as_free (eptr->e_attributes);
  			as_write_files(ptr->ent_attr,edbtmp_path);
  			eptr->e_attributes = as_cpy(ptr->ent_attr);
! 			eptr->e_complete = complete;
  			eptr->e_data = E_TYPE_CACHE_FROM_MASTER;
  			eptr->e_age = timenow;
  			if (eptr->e_inherit)
***************
*** 103,109 ****
  			return NULLENTRY;
  		local_cache_size++;
  		eptr->e_name = rdn_cpy (dnptr->dn_rdn);
! 		eptr->e_complete = TRUE;
  		eptr->e_data = E_TYPE_CACHE_FROM_MASTER;
  		as_write_files(ptr->ent_attr,edbtmp_path);
  		eptr->e_attributes = as_cpy(ptr->ent_attr);
--- 104,110 ----
  			return NULLENTRY;
  		local_cache_size++;
  		eptr->e_name = rdn_cpy (dnptr->dn_rdn);
! 		eptr->e_complete = complete;
  		eptr->e_data = E_TYPE_CACHE_FROM_MASTER;
  		as_write_files(ptr->ent_attr,edbtmp_path);
  		eptr->e_attributes = as_cpy(ptr->ent_attr);
***************
*** 147,153 ****
  
      switch(arg->arg_type) {    
      case OP_READ:
! 	entryptr = cache_dsp_entry (&res->res_rd.rdr_entry);
  	if (ctx == DS_CTX_X500_DAP)
  	   if (entryptr != NULLENTRY) {
  	    
--- 157,163 ----
  
      switch(arg->arg_type) {    
      case OP_READ:
! 	entryptr = cache_dsp_entry (&res->res_rd.rdr_entry,TRUE);
  	if (ctx == DS_CTX_X500_DAP)
  	   if (entryptr != NULLENTRY) {
  	    
***************
*** 174,180 ****
  	break;
      case OP_SEARCH:
  	for (ptr = res->res_sr.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next) 
!  			(void) cache_dsp_entry (ptr);
       	break;
      case OP_LIST:
  	if (ctx == DS_CTX_QUIPU_DSP)
--- 184,190 ----
  	break;
      case OP_SEARCH:
  	for (ptr = res->res_sr.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next) 
!  			(void) cache_dsp_entry (ptr,FALSE);
       	break;
      case OP_LIST:
  	if (ctx == DS_CTX_QUIPU_DSP)
*** 9.2	1992/07/21 17:20:55
--- quipu/dsp_cache.c	1992/07/22 07:21:05
***************
*** 54,60 ****
  
  Entry cache_dsp_entry (ptr,complete)
  EntryInfo      *ptr;
! char * complete;
  {
  	/* assumes entry passed is complete */
  
--- 54,60 ----
  
  Entry cache_dsp_entry (ptr,complete)
  EntryInfo      *ptr;
! char complete;
  {
  	/* assumes entry passed is complete */
  
***************
*** 163,168 ****
--- 163,169 ----
  EntryInfo *ptr;
  Entry entryptr;
  Attr_Sequence as, eis_select (), attr_eis_select ();
+ char cache_search = FALSE;
  
      switch(arg->arg_type) {    
      case OP_READ:
***************
*** 192,199 ****
  	   }
  	break;
      case OP_SEARCH:
  	for (ptr = res->res_sr.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next) 
!  			(void) cache_dsp_entry (ptr,FALSE);
       	break;
      case OP_LIST:
  	if (ctx == DS_CTX_QUIPU_DSP)
--- 193,204 ----
  	   }
  	break;
      case OP_SEARCH:
+         if ((arg->arg_sr.sra_eis.eis_allattributes == TRUE) &&
+             (arg->arg_sr.sra_eis.eis_infotypes == EIS_ATTRIBUTESANDVALUES)) 
+ 		cache_search = TRUE;
+ 
  	for (ptr = res->res_sr.CSR_entries; ptr != NULLENTRYINFO; ptr = ptr->ent_next) 
!  			(void) cache_dsp_entry (ptr,cache_search);
       	break;
      case OP_LIST:
  	if (ctx == DS_CTX_QUIPU_DSP)
*** 9.0	1992/06/16 12:34:01
--- quipu/update.c	1992/07/28 11:57:07
***************
*** 65,70 ****
--- 65,88 ----
  static edb_start ();
  static edb_continue ();
  
+ #ifdef USE_DSA_WAIT
+ 
+ /*
+ dsa_wait() causes problems sometimes -> it is not re-entrant.
+ If the connection we are serving fails, then we free the oper struct
+ we are currently using.
+ Easiest solution is to remove the dsa_wait() calls.
+ But eventually need to work out	how to put them back.  Without then the 
+ blocking during an EDB update will be worse.
+ 
+ Also need to look as dsa_wait() calls in ds_search().
+ 
+ */
+ 
+ 
+ #endif
+ 
+ 
  char * edbtmp_path = NULLCP;
  
  #ifndef TURBO_DISK
***************
*** 411,418 ****
  		if(dn || isroot)
  		    break;
  
  		(void) dsa_wait (0);	/* accept any results of previous ops */
! 
  	}
  	avs_free (avs_head);
  
--- 429,437 ----
  		if(dn || isroot)
  		    break;
  
+ #ifdef USE_DSA_WAIT
  		(void) dsa_wait (0);	/* accept any results of previous ops */
! #endif
  	}
  	avs_free (avs_head);
  
***************
*** 702,709 ****
  	}
  
  
  	(void) dsa_wait (0);	/* progress any other connections before writing EDB */
! 
  	if (eptr->e_children == NULLAVL)
  		slave_edbs++;
  
--- 721,729 ----
  	}
  
  
+ #ifdef USE_DSA_WAIT
  	(void) dsa_wait (0);	/* progress any other connections before writing EDB */
! #endif
  	if (eptr->e_children == NULLAVL)
  		slave_edbs++;
  
***************
*** 916,923 ****
  	}
  
  	/* This is a slow process, take a look at the network... */
  	(void) dsa_wait (0);
! 
  	/* write PE to file */
  
  	/* Make file name - this is where we could be clever an pick up
--- 936,944 ----
  	}
  
  	/* This is a slow process, take a look at the network... */
+ #ifdef USE_DSA_WAIT
  	(void) dsa_wait (0);
! #endif
  	/* write PE to file */
  
  	/* Make file name - this is where we could be clever an pick up
***************
*** 1010,1016 ****
--- 1031,1039 ----
  	edbops = nextop;
  
  	/* This is a slow process, take a look at the network... */
+ #ifdef USE_DSA_WAIT
  	(void) dsa_wait (0);
+ #endif
  
  	pe_free (pe);
  
***************
*** 1284,1290 ****
--- 1307,1315 ----
  
  	pe_free(pe);
  
+ #ifdef USE_DSA_WAIT
  	(void) dsa_wait (0);	/* accept any results of previous ops */
+ #endif
  
  	return TRUE;
  }
*** 9.0	1992/06/16 12:23:11
--- h/quipu/oid.h	1992/07/30 11:31:37
***************
*** 79,84 ****
--- 79,85 ----
  
  	/* NON leaf object class */
  #define QUIPU_DSA	"0.9.2342.19200300.99.3.1"
+ #define QUIPUOBJECT	"0.9.2342.19200300.99.3.2"
  #define NONLEAFOBJECT	"0.9.2342.19200300.99.3.6"
  #define EXTERNOBJECT	"0.9.2342.19200300.99.3.9"
  
*** 9.1	1992/07/21 17:23:02
--- quipu/ds_add.c	1992/07/30 11:31:34
***************
*** 70,75 ****
--- 70,78 ----
  int authp;
  extern int read_only;
  extern int	entry_cmp();
+ char add_edbinfo = FALSE;
+ Attr_Sequence newas;
+ 		
  
  	DLOG (log_dsap,LLOG_TRACE,("ds_add"));
  
***************
*** 241,246 ****
--- 243,253 ----
  	ptr->e_name = rdn_cpy (dn->dn_rdn);
  	ptr->e_attributes = as_cpy (arg->ada_entry);
   
+ 	/* Add QUIPU object to object class -> may not be a QUIPU DUA ! */
+ 	newas = as_comp_new (AttrT_cpy(at_objectclass),
+ 		 str2avs(QUIPUOBJECT,at_objectclass),NULLACL_INFO);
+ 	ptr->e_attributes = as_merge (ptr->e_attributes,newas);
+ 
  	modify_attr (ptr,binddn);
  
  	DLOG (log_dsap,LLOG_TRACE,("add - unravel"));
***************
*** 297,304 ****
  		/* Turn leaf into non leaf, and add child */
  		/* Temporary until managemnet tools do it */
  
- 		Attr_Sequence newas;
- 		
  		if (entryptr->e_data != E_DATA_MASTER) {
  			DN dn_found;
  			struct dn_seq	* dn_stack = NULLDNSEQ;
--- 304,309 ----
*** 9.0	1992/06/16 12:35:39
--- quipu/dish/modify.c	1992/08/27 14:51:11
***************
*** 81,86 ****
--- 81,87 ----
  	DN		moddn;
  	char	       *home;
  	RDN		new_rdn;
+ 	char		force_del_draft = FALSE;
  
  struct  list_element   *start = 0 ;
  struct  list_element   *last ;
***************
*** 247,252 ****
--- 248,263 ----
  	entry_ptr->e_attributes = get_attributes (fd);
  #endif
  
+ 	/* Fix ref count of all file attrs */
+ 	for (as = entry_ptr->e_attributes;as != NULLATTR; as = as->attr_link) {
+ 	   AV_Sequence avs;
+            for (avs = as->attr_value; avs != NULLAV; avs=avs->avseq_next)
+ 	       if (avs->avseq_av.av_syntax == AV_FILE) {
+ 		 ((struct file_syntax *)(avs->avseq_av.av_struct)) -> fs_ref++;
+ 		 force_del_draft = TRUE;
+ 	       }
+         }
+ 		
  	(void) fclose (fd);
  	if (parse_status != 0)
  		return;
***************
*** 354,359 ****
--- 365,372 ----
  	while (ds_modifyentry (&mod_arg, &error) != DS_OK) {
  		if (dish_error (OPT, &error) == 0) {
  			entry_free (entry_ptr);
+ 			if (force_del_draft)
+ 				make_old (fname,draft_flag);
  			return;
  		}
  		mod_arg.mea_object = error.ERR_REFERRAL.DSE_ref_candidates->cr_name;
*** 9.0	1992/06/16 12:34:01
--- quipu/schema.c	1992/09/01 14:49:21
***************
*** 108,113 ****
--- 108,130 ----
  		}
  	}
  
+ 	/* check the each attribute has at least one value */
+ 	for (at = eptr->e_attributes; at!=NULLATTR; at=at->attr_link)
+ 		if (at->attr_value == NULLAV) {
+ 			error->dse_type = DSE_ATTRIBUTEERROR;
+ 			error->ERR_ATTRIBUTE.DSE_at_name = 
+ 				get_copy_dn (eptr);
+ 			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =
+ 				DSE_AT_CONSTRAINTVIOLATION;
+ 			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = 
+ 				AttrT_cpy (at->attr_type);
+ 			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = 
+ 				NULLAttrV;
+ 			error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = 
+ 				DSE_AT_NOPROBLEM;
+ 			return (DS_ERROR_REMOTE);
+ 		}
+ 
  	/* now check 'must contain' attributes */
  	for (; avs != NULLAV; avs = avs->avseq_next) {
  	    oc = (objectclass *) avs->avseq_av.av_struct;
*** 9.0	1992/06/16 12:34:01
--- quipu/ds_modify.c	1992/09/01 14:45:32
***************
*** 268,290 ****
  		}
  	}
  
- 	/* check the last value of an attribute has not been removed */
- 	for (as = entryptr->e_attributes; as!=NULLATTR; as=as->attr_link)
- 		if (as->attr_value == NULLAV) {
- 			error->dse_type = DSE_ATTRIBUTEERROR;
- 			error->ERR_ATTRIBUTE.DSE_at_name = 
- 				get_copy_dn (entryptr);
- 			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =
- 				DSE_AT_CONSTRAINTVIOLATION;
- 			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = 
- 				AttrT_cpy (as->attr_type);
- 			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = 
- 				NULLAttrV;
- 			error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = 
- 				DSE_AT_NOPROBLEM;
- 			entry_free (entryptr);
- 			return (DS_ERROR_REMOTE);
- 		}
  	
  	DATABASE_HEAP;
  	modify_attr (entryptr,binddn);
--- 268,273 ----
*** 9.0	1992/06/16 12:17:57
--- h/psap.h	1992/09/01 09:10:44
***************
*** 541,549 ****
--- 544,556 ----
  extern struct qbuf *Fqb;
  extern struct qbuf *Qb;
  
+ #ifdef USE_QBUF2PE_FAST
+ 	/*  This is a faster version of qbuf2pe, but it has a memory leak. */
  #define qbuf2pe(qb, len, result) (Byteno = 0, Hqb = qb, \
                                          Fqb = (Qb = (qb) -> qb_forw), \
                                          qbuf2pe_f (result))
+ #endif
+ 
  PE	qbuf2pe_f ();
  char   *qb2str ();
  struct qbuf *str2qb ();
*** 9.0	1992/06/16 12:34:01
--- quipu/entry_load.c	1992/07/08 09:13:57
***************
*** 198,205 ****
          free (cp);
  
          nptr = (aps->ps_base + strlen (mapdir));
-         aps->ps_ptr = nptr;
  #endif /* TEMPNAM */
  
  	DLOG(log_dsap,LLOG_DEBUG,("mapped name %s",aps->ps_base));
  
--- 198,206 ----
          free (cp);
  
          nptr = (aps->ps_base + strlen (mapdir));
  #endif /* TEMPNAM */
+ 
+ 	aps->ps_ptr = aps->ps_base + strlen(aps->ps_base);
  
  	DLOG(log_dsap,LLOG_DEBUG,("mapped name %s",aps->ps_base));
  
*** tsap/tp0ts.c.dist	Wed Jul  8 15:54:35 1992
--- tsap/tp0ts.c	Wed Jul  8 15:54:47 1992
***************
*** 1041,1048 ****
  	        != qb -> qb_len) {
  	    if (nc == NOTOK) {
  		if (errno != EWOULDBLOCK) {
! 		    result = tsaplose (td, DR_NETWORK, "failed",
! 				      "write to network");
  		    goto out;
  		}
  
--- 1041,1050 ----
  	        != qb -> qb_len) {
  	    if (nc == NOTOK) {
  		if (errno != EWOULDBLOCK) {
! 		    (void) tpktlose (tb, td, DR_NETWORK, "failed",
! 			"write to network");
! 		    result = NOTOK;
! 
  		    goto out;
  		}
  
