STATUS MO_classid_index(i4 msg, PTR cdata, i4 linstance, char *instance, PTR *instdata ) { STATUS stat = OK; MO_CLASS *cp; switch( msg ) { case MO_GET: if( OK == (stat = MO_getclass( instance, &cp ) ) ) *instdata = (PTR)cp; break; case MO_GETNEXT: if( OK == ( stat = MO_nxtclass( instance, &cp ) ) ) { *instdata = (PTR)cp; stat = MOstrout( MO_INSTANCE_TRUNCATED, cp->node.key, linstance, instance ); } break; default: stat = MO_BAD_MSG; break; } return( stat ); }
/*{ ** Name: MOset - set value associated with an instance ** ** Description: ** ** Attempts to set the value associated with the instance. ** ** If the call succeeds, it must also call the monitors for the ** class with the MO_SET event, the instance id, and the new value. ** Inputs: ** valid_perms ** the roles currently in effect, to be and-ed with object ** permissions to determine access rights. ** class ** the class whose value should be altered. ** instance ** the instance in question. ** val ** pointer to the string containing the new value. ** Outputs: ** none ** Returns: ** OK ** if the value was set ** MO_NO_INSTANCE ** if the class is not attached ** MO_NO_WRITE ** if the class may not be changed. ** other ** error status returned by a method. ** History: ** 23-sep-92 (daveb) ** documented ** 6-Apr-04 (gordy) ** Permit access if MO_ANY_WRITE attribute is set. ** 24-Oct-05 (toumi01) BUG 115449 ** Don't hold onto MO mutex if class' processing will try ** to take the mutex, and would thus deadlock on ourself. */ STATUS MOset(i4 valperms, char *classid, char *instance, char *val ) { STATUS stat = OK; MO_CLASS *cp; PTR idata; MO_once(); stat = MO_mutex(); if( stat != OK ) return( stat ); MO_nset++; /* get class and instance data */ if( OK == (stat = MO_getclass( classid, &cp ) ) ) { if( (cp->perms & MO_ANY_WRITE) != 0 || (valperms & MO_WRITE & cp->perms) != 0 ) stat = (*cp->idx)( MO_GET, cp->cdata, 0, instance, &idata ); else stat = MO_NO_WRITE; } if( stat == OK ) { if (cp->cflags & MO_NO_MUTEX) (VOID) MO_unmutex(); stat = (*cp->set)( cp->offset, 0, val, cp->size, idata ); if (cp->cflags & MO_NO_MUTEX) { stat = MO_mutex(); if( stat != OK ) return( stat ); } } if( stat == OK ) (VOID) MO_tell_class( cp, instance, val, MO_SET ); (VOID) MO_unmutex(); return( stat ); }
STATUS MOtell_monitor( char *classid, char *instance, char *value, i4 msg ) { MO_CLASS *cp; STATUS ret_val = OK; MO_once(); ret_val = MO_mutex(); if( ret_val == OK ) { ret_val = MO_getclass( classid, &cp ); if( ret_val == OK && cp->monitor != NULL ) ret_val = MO_tell_class( cp, instance, value, msg ); (VOID) MO_unmutex(); } return( ret_val ); }
MO_MON_BLOCK * MO_igetmon( char *instance ) { char classid[ 80 ]; MO_CLASS *cp; char *p; u_i4 mon_data_val; for( p = classid; *instance && *instance != '.' ; ) *p++ = *instance++; *p = EOS; cp = NULL; MO_getclass( classid, &cp ); if( *instance ) instance++; MO_str_to_uns( instance, &mon_data_val ); return( MO_getmon( cp, (PTR)mon_data_val ) ); }
STATUS MO_get(i4 valperms, char *classid, char *instance, i4 *lsbufp, char *sbuf, i4 *operms ) { STATUS stat; MO_CLASS *cp; PTR idata; MO_nget++; stat = OK; *sbuf = EOS; /* get class and instance data */ if( OK == (stat = MO_getclass( classid, &cp ) ) ) { if( (cp->perms & MO_ANY_READ) != 0 || (valperms & MO_READ & cp->perms) != 0 ) stat = (*cp->idx)( MO_GET, cp->cdata, 0, instance, &idata ); else stat = MO_NO_READ; } if( stat == OK ) stat = (*cp->get)( cp->offset, cp->size, idata, *lsbufp, sbuf ); if( stat == OK || stat == MO_VALUE_TRUNCATED ) { *operms = cp->perms; (VOID) MO_tell_class( cp, instance, sbuf, MO_GET ); } return( stat ); }
STATUS MOattach( i4 flags, char *classid, char *instance, PTR idata ) { MO_INSTANCE *ip; MO_CLASS *cp; STATUS stat; stat = OK; if( MO_disabled ) return( stat ); MO_once(); stat = MO_mutex(); if( stat == OK ) /* got mutex */ { do { if( stat != OK ) break; MO_nattach++; # ifdef xDEBUG SIprintf("attach %s:%s object %p\n", classid, instance, idata ); # endif /* check for special error cases */ ip = MO_getinstance( classid, instance ); if( ip != NULL ) { stat = MO_ALREADY_ATTACHED; break; } /* Get class, error if missing */ if( OK != MO_getclass( classid, &cp ) ) { stat = MO_NO_CLASSID; break; } /* Release mutex to prevent deadlock in MO_alloc call */ (VOID) MO_unmutex(); ip = (MO_INSTANCE *)MO_alloc( sizeof(*ip), &stat ); stat = MO_mutex(); if( NULL == ip ) break; ip->classdef = cp; ip->iflags = flags; if( (flags & MO_INSTANCE_VAR) == 0 ) { ip->instance = instance; } else { ip->instance = MO_defstring( instance, &stat ); if( ip->instance == NULL ) { MO_free( (PTR)ip, sizeof(*ip) ); break; } } ip->idata = idata; ip->node.key = (PTR)ip; (VOID) SPenq( &ip->node, MO_instances ); } while( FALSE ); (VOID) MO_unmutex(); /* Attach twin if needed */ if( stat == OK && cp->twin != NULL && !CMdigit( (char *)cp->node.key ) ) stat = MOattach( flags, cp->twin->node.key, instance, idata ); } # if xDEBUG if( stat != OK ) TRdisplay("attach (%s:%s) failed status %d\n", classid, instance, stat ); # endif if( stat == OK ) { if ( (stat = MO_mutex()) == OK) { (VOID) MO_tell_class( cp, instance, (char *)NULL, MO_ATTACH ); MO_unmutex (); } } return( stat ); }
STATUS MO_getnext(i4 valperms, i4 lclassid, i4 linstance, char *classid, char *instance, i4 *lsbufp, char *sbuf, i4 *operms ) { STATUS stat = OK; STATUS xstat = OK; MO_INSTANCE *ip; MO_CLASS *cp; /* this class */ PTR idata; MO_ngetnext++; # ifdef xDEBUG SIprintf("getnext entry: %s:%s\n", classid, instance ); # endif ip = NULL; cp = NULL; *sbuf = EOS; if( *instance != EOS ) { ip = MO_getinstance( classid, instance ); if( ip != NULL ) cp = ip->classdef; else if( OK != MO_getclass( classid, &cp ) ) stat = MO_NO_CLASSID; } else if( *classid != EOS && OK != MO_getclass( classid, &cp ) ) { stat = MO_NO_CLASSID; } /* ** Now do the real work: Given the starting point implied ** by ip and cp, find the next visible instance. */ if( stat == OK ) { if( cp == NULL ) /* start with first class */ { cp = (MO_CLASS *) SPfhead( MO_classes ); ip = NULL; } /* ** Loop over classes looking for the next valid instance. ** ** On exit, if cp != NULL, it's the class of the found instance; ** if NULL, then we never found a good instance. */ for( ; cp != NULL ; cp = (MO_CLASS *)SPnext( &cp->node, MO_classes ) ) { if( (cp->perms & MO_ANY_READ) != 0 || (valperms & MO_READ & cp->perms) != 0 ) { stat = (*cp->idx)( MO_GETNEXT, cp->cdata, linstance, instance, &idata ); if( stat == OK ) { stat = (*cp->get)( cp->offset, cp->size, idata, *lsbufp, sbuf ); if( stat == OK ) break; } } /* Now caller's ip and instance are bogus; set to search state */ ip = NULL; *instance = EOS; } if( cp == NULL ) stat = MO_NO_NEXT; if( stat == OK || MO_IS_TRUNCATED( stat ) ) xstat = MOstrout( MO_CLASSID_TRUNCATED, cp->node.key, lclassid, classid ); if( stat == OK ) stat = xstat; } *lsbufp = (i4)STlength( sbuf ); if( stat == OK || stat == MO_VALUE_TRUNCATED ) { *operms = cp->perms; (VOID) MO_tell_class( cp, instance, sbuf, MO_GET ); } # ifdef xDEBUG SIprintf("getnext exit: (%d) %s:%s - %s\n", stat, classid, instance, sbuf ); # endif return( stat ); }
STATUS MO_oid_set(i4 offset, i4 luserbuf, char *userbuf, i4 objsize, PTR object ) { STATUS cl_stat = OK; MO_CLASS *cp = (MO_CLASS *)object; MO_CLASS *twin_cp; MO_INSTANCE *ip; MO_INSTANCE *next_ip; MO_CLASS_DEF mo_class; do { /* if it has a twin already, error */ if( cp->twin != NULL ) { cl_stat = MO_NO_WRITE; break; } mo_class.flags = MO_CLASSID_VAR | cp->cflags; mo_class.classid = userbuf; mo_class.size = cp->size; mo_class.perms = cp->perms; mo_class.index = cp->index; mo_class.get = cp->get; mo_class.set = cp->set; mo_class.cdata = cp->cdata; mo_class.idx = cp->idx; if( OK != (cl_stat = MOclassdef( 1, &mo_class ) ) ) break; if( OK != (cl_stat = MO_getclass( userbuf, &twin_cp ) ) ) break; cp->twin = twin_cp; twin_cp->twin = cp; twin_cp->monitor = cp->monitor; /* now attach all objects of the class as twins */ for( ip = (MO_INSTANCE *)SPfhead( MO_instances ); ip != NULL ; ip = next_ip ) { next_ip = (MO_INSTANCE *)SPfnext( (SPBLK *)ip ); if( ip->classdef == cp ) { /* create one for the twin. */ cl_stat = MOattach( 0, twin_cp->node.key, ip->instance, ip->idata ); if( cl_stat != OK ) break; if( next_ip->classdef != cp ) break; } } } while( FALSE ); return( cl_stat ); }
STATUS MOset_monitor( char *classid, PTR mon_data, char *qual_regexp, MO_MONITOR_FUNC *monitor, MO_MONITOR_FUNC **old_monitor ) { MO_MON_BLOCK *mp; /* our monitor block */ MO_MON_BLOCK *fmp; /* first monitor block */ MO_MON_BLOCK *pmp; /* previous monitor block */ MO_CLASS *cp; /* class in question (not classid) */ char *saved_qual = NULL; STATUS ret_val = OK; STATUS mutex_stat; mutex_stat = MO_mutex(); do { if( mutex_stat != OK ) break; /* if we'll need it, save any qual_regexp string */ if( monitor != NULL && qual_regexp != NULL ) { saved_qual = MO_defstring( qual_regexp, &ret_val ); if( saved_qual == NULL ) break; /* FIXME maybe compile it here too? */ } /* locate the class def, we need it everywhere */ if( (ret_val = MO_getclass( classid, &cp )) != OK ) break; /* see if this is a replacement for an existing monitor */ mp = NULL; if( (mp = MO_getmon( cp, mon_data ) ) != NULL ) { /* yes, replace it with new values as appropriate */ *old_monitor = mp->monitor; if( monitor == NULL ) /* delete this monitor */ { MO_delmon( mp ); } else /* replace this one's values */ { mp->monitor = monitor; mp->mon_data = mon_data; /* delete old qual string */ if( mp->qual_regexp != NULL ) MO_delstring( mp->qual_regexp ); mp->qual_regexp = saved_qual; } } else if( monitor == NULL ) /* huh!? */ { ret_val = MO_BAD_MONITOR; break; } else /* make a new one and link it in. */ { *old_monitor = NULL; /* if it's an OID, get the class def instead */ if( CMdigit( (char *)cp->node.key ) && cp->twin != NULL ) cp = cp->twin; /* get a new monitor block */ mp = (MO_MON_BLOCK *)MO_alloc( sizeof( *mp ), &ret_val ); if( mp == NULL ) break; /* fill in the new block, and link in to the tree */ mp->node.key = (PTR)mp; mp->mo_class = cp; mp->monitor = monitor; mp->mon_data = mon_data; mp->qual_regexp = saved_qual; (void) SPenq( &mp->node, MO_monitors ); /* Fill in the class with first monitor for the class. The loop below goes backwards until pmp is null or doesn't have the same class definition. When it exits, fmp is at the first monitor block for the class */ for( fmp = mp; (pmp = (MO_MON_BLOCK *)SPfprev( &fmp->node )) != NULL && pmp->mo_class == cp; fmp = pmp ) continue; fmp->mo_class->monitor = fmp; if( cp->twin ) cp->twin->monitor = fmp; } } while ( FALSE ); if( mutex_stat != OK ) { ret_val = mutex_stat; } else { if( ret_val == OK ) MO_nset_monitor++; else if( saved_qual != NULL ) MO_delstring( saved_qual ); (void) MO_unmutex(); } return( ret_val ); }