BSD 4_3_Net_2 development
[unix-history] / usr / src / contrib / isode / others / quipu / uips / pod / modify.c
#include <sys/types.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include "quipu/util.h"
#include "quipu/common.h"
#include "quipu/entry.h"
#include "quipu/modify.h"
#include "quipu/name.h"
#include "sequence.h"
#include "dir_entry.h"
#include "defs.h"
#include "util.h"
#define AS_SYNTAX(attrSeq) attrSeq->attr_type->oa_syntax
#define AS_STROID(attrSeq) attrSeq->attr_type->oa_ot.ot_stroid
#define FOREACH(a) for (eptr = a; eptr != NULLATTR; eptr=eptr->attr_link)
extern bool photo_on;
char *modify_error();
Attr_Sequence as_sort();
void char_map(), char_unmap();
static Attr_Sequence eptr;
#ifndef NO_STATS
extern LLog *log_stat;
#endif
struct entrymod * ems_append (a,b)
struct entrymod *a;
struct entrymod *b;
{
struct entrymod *ptr;
if ((ptr = a) == NULLMOD)
return b;
for ( ; ptr->em_next != NULLMOD; ptr = ptr->em_next)
;
ptr->em_next = b;
return a;
}
dsErrorStruct modify_entry(mods)
dirEntry mods;
{
struct ds_modifyentry_arg mod_arg;
dsErrorStruct mod_error;
struct DSError error;
struct entrymod *curr_mod = 0, *entrymods = 0;
AttributeType attr_type = 0;
AttributeValue attr_val = 0;
AV_Sequence attrVal_seq = 0;
register modVals curr_val;
dirAttrs attrs;
char err_buf[STRINGLEN], attr_val_buf[STRINGLEN];
short attr_removed;
if (get_default_service(&mod_arg.mea_common) != 0) {
mod_error.error = serviceerror;
mod_error.err_mess = strdup("Directory Service Error!\n");
}
mod_arg.mea_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN;
mod_arg.mea_object = str2dn(mods->entry_name);
for (attrs = mods->attrs; attrs; attrs = attrs->next) {
if (attrs->mod_flag) {
attr_type = str2AttrT(attrs->attr_name);
for (curr_val = attrs->val_seq;
curr_val && curr_val->mod_flag;
curr_val = curr_val->next)
;
if (!curr_val) {
if (attrs->in_flag) {
curr_mod = em_alloc();
curr_mod->em_next = NULLMOD;
curr_mod->em_type = EM_REMOVEATTRIBUTE;
curr_mod->em_what = NULLATTR;
curr_mod->em_what = as_comp_new(attr_type, NULLAV, NULLACL_INFO);
entrymods = ems_append(entrymods, curr_mod);
}
curr_mod = em_alloc();
curr_mod->em_next = NULLMOD;
curr_mod->em_type = EM_ADDATTRIBUTE;
curr_mod->em_what = NULLATTR;
for (curr_val = attrs->val_seq; curr_val; curr_val = curr_val->next) {
char_unmap(attr_val_buf, curr_val->new_value);
if (attr_val_buf[0] != '\0') {
attr_val = str2AttrV(attr_val_buf, attr_type->oa_syntax);
if (attr_val) {
if (attrVal_seq)
attrVal_seq = avs_merge(attrVal_seq, avs_comp_new(attr_val));
else
attrVal_seq = avs_comp_new(attr_val);
} else {
if (entrymods) ems_free(entrymods);
AttrT_free(attr_type);
mod_error.error = attributerror;
(void) sprintf(err_buf,
"Attribute Error!\nInvalid syntax for value %s type %s.",
curr_val->new_value, attrs->attr_name);
mod_error.err_mess = strdup(err_buf);
return mod_error;
}
}
}
if (attrVal_seq) {
curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
attrVal_seq,
NULLACL_INFO);
entrymods = ems_append(entrymods, curr_mod);
attrVal_seq = 0;
curr_mod = 0;
AttrT_free(attr_type);
}
} else {
if (attrs->in_flag) {
for (curr_val = attrs->val_seq;
curr_val;
curr_val = curr_val->next) {
char_unmap(attr_val_buf, curr_val->value);
if (curr_val->mod_flag && attr_val_buf[0] != '\0') {
attrVal_seq = avs_comp_new(str2AttrV(attr_val_buf,
attr_type->
oa_syntax));
curr_mod = em_alloc();
curr_mod->em_next = NULLMOD;
curr_mod->em_type = EM_REMOVEVALUES;
curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
attrVal_seq,
NULLACL_INFO);
entrymods = ems_append(entrymods, curr_mod);
}
}
for (curr_val = attrs->val_seq;
curr_val;
curr_val = curr_val->next) {
char_unmap(attr_val_buf, curr_val->new_value);
if (curr_val->mod_flag && attr_val_buf[0] != '\0') {
attr_val = str2AttrV(attr_val_buf,
attr_type->oa_syntax);
if (attr_val) {
if (attrVal_seq)
attrVal_seq = avs_merge(attrVal_seq,
avs_comp_new(attr_val));
else
attrVal_seq = avs_comp_new(attr_val);
} else {
if (entrymods) ems_free(entrymods);
AttrT_free(attr_type);
mod_error.error = attributerror;
(void) sprintf(err_buf,
"Attribute Error!\nInvalid syntax for value %s type %s.",
curr_val->new_value, attrs->attr_name);
mod_error.err_mess = strdup(err_buf);
return mod_error;
}
curr_mod = em_alloc();
curr_mod->em_next = NULLMOD;
curr_mod->em_type = EM_ADDVALUES;
curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
attrVal_seq,
NULLACL_INFO);
entrymods = ems_append(entrymods, curr_mod);
}
}
} else {
curr_mod = em_alloc();
curr_mod->em_next = NULLMOD;
curr_mod->em_type = EM_ADDATTRIBUTE;
for (curr_val = attrs->val_seq;
curr_val;
curr_val = curr_val->next) {
char_unmap(attr_val_buf, curr_val->new_value);
if (attr_val_buf[0] != '\0') {
attr_val = str2AttrV(attr_val_buf,
attr_type->oa_syntax);
if (attr_val) {
if (attrVal_seq)
attrVal_seq = avs_merge(attrVal_seq,
avs_comp_new(attr_val));
else
attrVal_seq = avs_comp_new(attr_val);
} else {
if (entrymods) ems_free(entrymods);
AttrT_free(attr_type);
mod_error.error = attributerror;
(void) sprintf(err_buf,
"Attribute Error!\nInvalid syntax for value %s type %s.",
curr_val->new_value, attrs->attr_name);
mod_error.err_mess = strdup(err_buf);
return mod_error;
}
}
}
if (attrVal_seq) {
curr_mod->em_what = as_comp_new(AttrT_cpy(attr_type),
attrVal_seq,
NULLACL_INFO);
entrymods = ems_append(entrymods, curr_mod);
attrVal_seq = 0;
curr_mod = 0;
AttrT_free(attr_type);
}
}
}
}
}
if (entrymods) {
mod_arg.mea_changes = entrymods;
if (ds_modifyentry(&mod_arg, &error) != DS_OK) {
mod_error.err_mess = modify_error(&error);
switch (error.dse_type) {
case DSE_LOCALERROR:
mod_error.error = duaerror;
if (!mod_error.err_mess) {
mod_error.err_mess =
strdup("Internal Error, No modifications made. Sorry!");
}
break;
case DSE_REMOTEERROR:
mod_error.error = localdsaerror;
break;
case DSE_ATTRIBUTEERROR:
mod_error.error = attributerror;
if (!mod_error.err_mess) {
mod_error.err_mess =
strdup("Attribute Error! No Modifications made.");
}
break;
case DSE_REFERRAL:
case DSE_DSAREFERRAL:
mod_error.error = remotedsaerror;
if (!mod_error.err_mess) {
mod_error.err_mess =
strdup("Referral Error! No Modifications made.");
}
break;
case DSE_SECURITYERROR:
mod_error.error = security;
if (!mod_error.err_mess) {
mod_error.err_mess = strdup("Security Error! Check access rights.");
}
break;
case DSE_NAMEERROR:
mod_error.error = namerror;
if (!mod_error.err_mess) {
switch (error.dse_un.dse_un_name.DSE_na_problem) {
case DSE_NA_NOSUCHOBJECT:
mod_error.err_mess =
strdup("Name Error! No such object.");
break;
case DSE_NA_ALIASPROBLEM:
case DSE_NA_ALIASDEREFERENCE:
mod_error.err_mess = strdup("Error! Alias problem.");
break;
case DSE_NA_INVALIDATTRIBUTESYNTAX:
mod_error.err_mess =
strdup("Name Error! Invalid attribute syntax.");
break;
}
}
break;
case DSE_SERVICEERROR:
mod_error.error = serviceerror;
break;
case DSE_UPDATEERROR:
mod_error.error = updaterror;
break;
default:
mod_error.error = localdsaerror;
break;
}
ds_error_free(&error);
dn_free(mod_arg.mea_object);
return mod_error;
} else {
ems_free(entrymods);
delete_cache(mod_arg.mea_object);
}
} else {
mod_error.error = updaterror;
mod_error.err_mess = strdup("No modifications to make!");
dn_free(mod_arg.mea_object);
return mod_error;
}
for (attrs = mods->attrs; attrs; attrs = attrs->next) {
if (attrs->mod_flag == TRUE && attrs->in_flag == FALSE)
attrs->in_flag = TRUE;
attrs->mod_flag = FALSE;
attr_removed = TRUE;
for (curr_val = attrs->val_seq; curr_val; curr_val = curr_val->next) {
if (curr_val->new_value != NULLCP) {
if (curr_val->value != NULLCP) free(curr_val->value);
curr_val->value = curr_val->new_value;
curr_val->new_value = NULLCP;
attr_removed = FALSE;
}
if (curr_val->value && *curr_val->value != '\0' && !curr_val->mod_flag)
attr_removed = FALSE;
curr_val->mod_flag = FALSE;
}
if (attr_removed) attrs->in_flag = FALSE;
}
mod_error.error = Okay;
dn_free(mod_arg.mea_object);
return mod_error;
}
void make_template(entry_name, attrs)
char *entry_name;
dirAttrs *attrs;
{
static char buffer[RESBUF];
PS ps;
extern AttributeType at_objectclass;
struct ds_read_arg read_arg;
struct ds_read_result result;
struct DSError error;
Entry read_entry;
Attr_Sequence as, read_attrs;
Attr_Sequence nas = 0, tas = 0, templ_as, make_template_as();
buffer[0] = '\0';
*attrs = 0;
if (*entry_name == '\0') return;
if ((ps = ps_alloc(str_open)) == NULLPS) return;
if (str_setup(ps, buffer, RESBUF, 1) == NOTOK) return;
if (get_default_service (&read_arg.rda_common) != 0) return;
read_arg.rda_common.ca_servicecontrol.svc_options = SVC_OPT_PREFERCHAIN;
read_arg.rda_eis.eis_allattributes = TRUE;
read_arg.rda_eis.eis_infotypes = EIS_ATTRIBUTESANDVALUES;
read_arg.rda_object = str2dn(entry_name);
photo_on = FALSE;
if ((read_entry = local_find_entry(read_arg.rda_object, FALSE))
!= NULLENTRY &&
read_entry->e_data != E_TYPE_CONSTRUCTOR) {
read_attrs = read_entry->e_attributes;
} else {
if (ds_read(&read_arg, &error, &result) != DS_OK) {
photo_on = TRUE;
return;
}
if (result.rdr_entry.ent_attr == NULLATTR) {
photo_on = TRUE;
return;
}
read_attrs = result.rdr_entry.ent_attr;
}
for (as = read_attrs; as != NULLATTR; as = as->attr_link)
if (as->attr_type == at_objectclass)
break;
templ_as = make_template_as(as->attr_value);
for (as = read_attrs;
as != NULLATTR;
as = as->attr_link)
if (!(AS_SYNTAX(as) == str2syntax("schema") ||
AS_SYNTAX(as) == str2syntax("objectclass") ||
AS_SYNTAX(as) == str2syntax("acl") ||
AS_SYNTAX(as) == str2syntax("edbinfo") ||
AS_SYNTAX(as) == str2syntax("octetstring") ||
!strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.23") ||
!strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.24"))) {
nas = as_comp_new(AttrT_cpy(as->attr_type),
avs_cpy(as->attr_value),
NULLACL_INFO);
if (tas) tas = as_merge(tas, nas);
else tas = nas;
}
as = templ_as;
nas = templ_as = 0;
for (; as != NULLATTR; as = as->attr_link)
if (!(AS_SYNTAX(as) == str2syntax("schema") ||
AS_SYNTAX(as) == str2syntax("objectclass") ||
AS_SYNTAX(as) == str2syntax("acl") ||
AS_SYNTAX(as) == str2syntax("edbinfo") ||
AS_SYNTAX(as) == str2syntax("octetstring") ||
!strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.23") ||
!strcmp(AS_STROID(as), "0.9.2342.19200300.100.1.24"))) {
nas = as_comp_new(AttrT_cpy(as->attr_type), NULLAV, NULLACL_INFO);
if (templ_as) templ_as = as_merge(templ_as, nas);
else templ_as = nas;
}
as = as_merge(tas, templ_as);
as = as_sort(as);
my_as_print(ps, as, READOUT);
*--ps->ps_ptr = NULL, ps->ps_cnt++;
photo_on = TRUE;
ps_free(ps);
as_free(as);
make_attr_sequence(buffer, attrs);
}
make_attr_sequence(entry_string, attrs)
char *entry_string;
dirAttrs *attrs;
{
register char *str, *sptr;
char save, buffer[RESBUF];
modVals curr_val = 0;
dirAttrs curr_attr = 0;
AttributeType curr_attr_type;
int count = 0;
str = sptr = entry_string;
while (1) {
str = index(sptr, '-');
if (!str || str == sptr) return;
while (!isalpha(*str)) {
if (str < sptr) return;
else --str;
}
str++;
save = *str;
*str = '\0';
if (curr_attr) {
if (strcmp(curr_attr->attr_name, sptr)) {
curr_val = 0;
curr_attr->next = (dirAttrs) malloc(sizeof(dir_attrs));
curr_attr = curr_attr->next;
curr_attr->next = 0;
curr_attr->val_seq = 0;
curr_attr->mod_flag = FALSE;
curr_attr->in_flag = TRUE;
curr_attr->attr_name = strdup(sptr);
curr_attr_type = str2AttrT(curr_attr->attr_name);
if (!strcmp(curr_attr_type->oa_ot.ot_stroid, "2.5.4.35"))
curr_attr->hidden_flag = TRUE;
else
curr_attr->hidden_flag = FALSE;
AttrT_free(curr_attr_type);
}
} else {
curr_attr = (dirAttrs) malloc(sizeof(dir_attrs));
*attrs = curr_attr;
curr_attr->next = 0;
curr_attr->val_seq = (modVals) 0;
curr_attr->mod_flag = FALSE;
curr_attr->in_flag = TRUE;
curr_attr->attr_name = strdup(sptr);
curr_attr_type = str2AttrT(curr_attr->attr_name);
if (!strcmp(curr_attr_type->oa_ot.ot_stroid, "2.5.4.35"))
curr_attr->hidden_flag = TRUE;
else
curr_attr->hidden_flag = FALSE;
AttrT_free(curr_attr_type);
}
*str = save;
while ((isspace(*str) || (*str == '-')) && *str != '\n' && *str != '\0')
str++;
sptr = str;
count = 0;
while (1) {
while (*str != '\n' && *str != '\0') {
buffer[count++] = *str;
str++;
}
if (*str != '\0' && *(str + 1) == '\t') {
buffer[count++] = '\n';
while (isspace(*str)) str++;
} else break;
}
buffer[count] = '\0';
save = *str;
*str = '\0';
if (curr_val) {
curr_val->next = (modVals) malloc(sizeof(struct mod_vals));
curr_val = curr_val->next;
} else {
curr_val = (modVals) malloc(sizeof(struct mod_vals));
curr_attr->val_seq = curr_val;
if (!count) curr_attr->in_flag = FALSE;
}
curr_val->attr = curr_attr;
curr_val->next = 0;
curr_val->mod_flag = FALSE;
curr_val->new_value = 0;
curr_val->text_widg = 0;
curr_val->value = strdup(buffer);
char_map(buffer, curr_val->value);
free(curr_val->value);
curr_val->value = strdup(buffer);
*str = save;
if (*str == '\0' || *++str == '\0') return;
sptr = str;
}
}
void char_map(buffer, value)
char *buffer, *value;
{
if (value != NULLCP && *value != '\0') {
while (*value != '\0') {
switch (*value) {
case '$':
*buffer = '\n';
break;
case '\\':
if (*((char *) (value + 1)) == '4' &&
*((char *) (value + 2)) == '0') {
*buffer = '@';
value += 2;
}
break;
default:
*buffer = *value;
}
value++;
buffer++;
}
}
*buffer = '\0';
}
void char_unmap(buffer, value)
char *buffer, *value;
{
if (value != NULLCP && *value != '\0') {
while (*value != '\0') {
switch (*value) {
case '\n':
*buffer = '$';
break;
default:
*buffer = *value;
}
value++;
buffer++;
}
}
*buffer = '\0';
}
Attr_Sequence make_template_as(oc)
AV_Sequence oc;
{
AV_Sequence avs;
Attr_Sequence newas;
Attr_Sequence as = NULLATTR;
table_seq optr;
AttributeType at;
objectclass * ocp;
for (avs = oc; avs != NULLAV; avs = avs->avseq_next) {
ocp = (objectclass *) avs->avseq_av.av_struct;
for (optr = ocp->oc_must; optr != NULLTABLE_SEQ; optr = optr->ts_next) {
at = optr->ts_oa;
newas = as_comp_new(at, NULLAV, NULLACL_INFO);
as = as_merge(as, newas);
}
}
for (avs = oc; avs != NULLAV; avs = avs->avseq_next) {
ocp = (objectclass *) avs->avseq_av.av_struct;
for (optr = ocp->oc_may; optr != NULLTABLE_SEQ; optr = optr->ts_next) {
at = optr->ts_oa;
newas = as_comp_new(at, NULLAV, NULLACL_INFO);
as = as_merge(as, newas);
}
}
return(as);
}
/*Big Bodge!*/
char *modify_error(error)
struct DSError *error;
{
PS ps;
char buffer[RESBUF];
char *str, *message;
if ((ps = ps_alloc(str_open)) == NULLPS) {
return NULLCP;
}
if (str_setup(ps, buffer, RESBUF, 1) == NOTOK) {
return NULLCP;
}
ds_error(ps, error);
*ps->ps_ptr = 0;
ps_free(ps);
str = buffer;
if (*str != '\0') {
message = strdup(str);
} else message = NULLCP;
return message;
}
my_as_comp_print (ps,as,format)
PS ps;
Attr_Sequence as;
int format;
{
AV_Sequence avs;
char buffer[RESBUF];
extern int oidformat;
if (as!=NULLATTR) {
if (format == READOUT)
(void) sprintf(buffer,"%s",attr2name (as->attr_type, 1));
else
(void) sprintf (buffer,"%s",attr2name_aux (as->attr_type));
if (split_attr (as)) {
if ((as->attr_value == NULLAV) && (format != READOUT))
ps_printf (ps, "%s=\n", buffer);
else {
if (as->attr_value == NULLAV) {
ps_printf(ps, "%-21s - \n", buffer);
} else {
for (avs = as->attr_value; avs != NULLAV; avs = avs->avseq_next) {
if (format == READOUT)
ps_printf (ps, "%-21s - ", buffer);
else
ps_printf (ps, "%s= ", buffer);
avs_comp_print (ps, avs, EDBOUT);
ps_print (ps, "\n");
}
}
}
} else {
if (format == READOUT)
ps_printf (ps, "%-21s - ", buffer);
else
ps_printf (ps, "%s= ", buffer);
avs_print (ps, as->attr_value, format);
}
}
}
my_as_print (ps,as,format)
Attr_Sequence as;
PS ps;
int format;
{
if (as != NULLATTR)
FOREACH(as)
my_as_comp_print(ps,eptr,format);
}
Attr_Sequence as_sort(as)
Attr_Sequence as;
{
Attr_Sequence with_vals = NULLATTR, without_vals = NULLATTR, next_as;
if (as == NULLATTR) return as;
while (as != NULLATTR) {
next_as = as->attr_link;
as->attr_link = NULLATTR;
if (as->attr_value) with_vals = as_merge(with_vals, as);
else without_vals = as_merge(without_vals, as);
as = next_as;
}
as = with_vals;
if (as != NULLATTR)
for (; as->attr_link != NULLATTR; as = as->attr_link)
;
else return without_vals;
as->attr_link = without_vals;
return with_vals;
}