+ } else if ((feat = feature_desc(from, fields[0]))) { /* find feature */
+ if (feat->set && (i = (*feat->set)(from, fields + 1, count - 1))) {
+ if (i > 0) /* call the set callback and do marking */
+ feat->flags |= FEAT_MARK;
+ else /* i < 0 */
+ feat->flags &= ~FEAT_MARK;
+ } else /* Ok, it's a value we can fiddle with */
+ switch (feat->flags & FEAT_MASK) {
+ case FEAT_INT: /* an integer value */
+ if (count < 2) { /* reset value */
+ feat->v_int = feat->def_int;
+ feat->flags &= ~FEAT_MARK;
+ } else { /* ok, figure out the value and whether to mark it */
+ feat->v_int = atoi(fields[1]);
+ if (feat->v_int == feat->def_int)
+ feat->flags &= ~FEAT_MARK;
+ else
+ feat->flags |= FEAT_MARK;
+ }
+ break;
+
+ case FEAT_BOOL: /* it's a boolean value--true or false */
+ if (count < 2) { /* reset value */
+ feat->v_int = feat->def_int;
+ feat->flags &= ~FEAT_MARK;
+ } else { /* figure out the value and whether to mark it */
+ if (!ircd_strncmp(fields[1], "TRUE", strlen(fields[1])))
+ feat->v_int = 1;
+ else if (!ircd_strncmp(fields[1], "YES", strlen(fields[1])))
+ feat->v_int = 1;
+ else if (!ircd_strncmp(fields[1], "FALSE", strlen(fields[1])))
+ feat->v_int = 0;
+ else if (!ircd_strncmp(fields[1], "NO", strlen(fields[1])))
+ feat->v_int = 0;
+ else if (from) /* report an error... */
+ return send_reply(from, ERR_BADFEATVALUE, fields[1], feat->type);
+ else {
+ log_write(LS_CONFIG, L_ERROR, 0, "Bad value \"%s\" for feature %s",
+ fields[1], feat->type);
+ return 0;
+ }
+
+ if (feat->v_int == feat->def_int) /* figure out whether to mark it */
+ feat->flags &= ~FEAT_MARK;
+ else
+ feat->flags |= FEAT_MARK;
+ }
+ break;
+
+ case FEAT_STR: /* it's a string value */
+ if (count < 2 ||
+ !(feat->flags & FEAT_CASE ? strcmp(fields[1], feat->def_str) :
+ ircd_strcmp(fields[1], feat->def_str))) { /* reset to default */
+ if (feat->v_str && feat->v_str != feat->def_str)
+ MyFree(feat->v_str); /* free old value */
+ feat->v_str = feat->def_str; /* very special... */
+
+ feat->flags &= ~FEAT_MARK; /* unmark it */
+ } else {
+ if (!*fields[1]) { /* empty string translates to NULL */
+ if (feat->flags & FEAT_NULL) { /* permitted? */
+ if (feat->v_str && feat->v_str != feat->def_str)
+ MyFree(feat->v_str); /* free old value */
+ feat->v_str = 0; /* set it to NULL */
+ } else if (from) /* hmmm...not permitted; report error */
+ return send_reply(from, ERR_BADFEATVALUE, "NULL", feat->type);
+ else {
+ log_write(LS_CONFIG, L_ERROR, 0,
+ "Bad value \"NULL\" for feature %s", feat->type);
+ return 0;
+ }
+ } else if ((feat->flags & FEAT_CASE ?
+ strcmp(fields[1], feat->v_str) :
+ ircd_strcmp(fields[1], feat->v_str))) { /* new value */
+ if (feat->v_str && feat->v_str != feat->def_str)
+ MyFree(feat->v_str); /* free old value */
+ DupString(feat->v_str, fields[1]); /* store new value */
+ }
+
+ feat->flags |= FEAT_MARK; /* mark it as having been touched */
+ }
+ break;
+ }
+ }