#include "copyright2.h" #include #include #include #include "defs.h" #include INC_STRINGS #include "struct.h" #include "data.h" #include "packets.h" #ifdef FEATURE_PACKETS /* * Feature.c * * March, 1994. Joe Rumsey, Tedd Hadley * * most of the functions needed to handle SP_FEATURE/CP_FEATURE * packets. fill in the features list below for your server. * * feature packets look like: struct feature_spacket { char type; char feature_type; char arg1, arg2; int value; char name[80]; }; * type is SP_FEATURE, which is 60. feature_cpacket is identical. */ /* not the actual packets: this holds a list of features to report for */ /* this server. */ struct feature_var { char *name; int *var; /* local variable */ int *arg1; /* additional argument */ }; struct feature_var feature_vars[] = { {"FEATURE_PACKETS", &F_client_feature_packets, NULL}, {"WHY_DEAD", &why_dead, NULL}, {"SBHOURS", &SBhours, NULL}, {"SELF_8FLAGS", &F_self_8flags, NULL}, {"19FLAGS", &F_19flags, NULL}, #ifdef RCD { "RC_DISTRESS", &F_rc_distress, NULL}, /* xx */ #endif {"CLOAK_MAXWARP", &F_cloak_maxwarp, NULL}, {"SHIP_CAP", &F_ship_cap, NULL}, {"DEAD_WARP", &dead_warp, NULL}, {"SHOW_ALL_TRACTORS", &F_show_all_tractors, NULL}, {"SHOW_ARMY_COUNT", &F_show_army_count, NULL}, {"SHOW_OTHER_SPEED", &F_show_other_speed, NULL}, {"SHOW_CLOAKERS", &F_show_cloakers, NULL}, {"SP_GENERIC_32", &F_sp_generic_32, &A_sp_generic_32}, {"CHECK_PLANETS", &F_check_planets, NULL}, {"TURN_KEYS", &F_turn_keys, NULL}, {"SP_FLAGS_ALL", &F_flags_all, NULL}, {"WHY_DEAD_2", &F_why_dead_2, NULL}, {"FULL_DIRECTION_RESOLUTION", &F_full_direction_resolution, NULL}, {"FULL_WEAPON_RESOLUTION", &F_full_weapon_resolution, NULL}, {"SHOW_VISIBILITY_RANGE", &F_show_visibility_range, NULL}, {NULL, NULL, NULL}, }; /* file scope prototypes */ static int feature_cmp(char *f, char *s); /* * ------------------- NEW FEATURE STUFF */ static int num_features; static struct feature_spacket *features; static void freeFeatures(void) { free(features); } /* * Called once to read in feature strings */ void readFeatures(void) { register int i, sv, line=0; int a1,a2; char buf[512], value_string[64]; FILE *f; f = fopen(Feature_File, "r"); if(!f) return; num_features = 0; while(fgets(buf, 512, f)){ if(buf[0] == '#' || buf[0] == '\n') continue; /* old format. Ignore */ if(INDEX(buf, ':')) continue; num_features++; } fclose(f); features = (struct feature_spacket *) calloc(sizeof(struct feature_spacket) * num_features, 1); if(!features) { /* failsafe */ perror("calloc"); num_features = 0; return; } atexit(freeFeatures); f = fopen(Feature_File, "r"); i=0; while(fgets(buf, 511, f)){ line++; /* comment */ if(buf[0] == '#' || buf[0] == '\n') continue; /* old format. Ignore */ if(INDEX(buf, ':')) continue; *value_string = 0; a1 = 0; a2 = 0; sv = sscanf(buf, "%s %c %s %d %d", features[i].name, &features[i].feature_type, value_string, &a1, &a2); features[i].arg1 = a1; features[i].arg2 = a2; if(!sv) { fprintf(stderr, "%s:%d: syntax error on string %s", Feature_File, line, buf); continue; } switch(features[i].feature_type){ case 'C': case 'S': break; default: fprintf(stderr, "%s:%d: bad feature type in string %s", Feature_File, line, buf); continue; } /* value_string needs to be converted to an integer */ if(feature_cmp(value_string, "ON")) features[i].value = 1; else if(feature_cmp(value_string, "OFF")) features[i].value = 0; /* this probably won't be needed, but just in case ... */ else if(feature_cmp(value_string, "UNKNOWN")) features[i].value = 2; else if(!sscanf(value_string, "%d", &features[i].value)){ fprintf(stderr, "%s:%d: unknown value in string %s", Feature_File, line, buf); continue; } i++; } fclose(f); num_features = i; } void getFeature(struct feature_cpacket *cpack, /* client request */ struct feature_spacket *spack) /* server response */ { register int i; register struct feature_spacket *f; strcpy(spack->name, cpack->name); /* default is unknown feature */ spack->feature_type = 0; spack->value = -1; spack->arg1 = 0; spack->arg2 = 0; /* find the server's record of the feature */ for(i=0,f=features; iname, f->name)) { /* This is an evil hack, turn SAT on in obs mode */ if(Observer && !strcmp(f->name,"SHOW_ALL_TRACTORS")) f->value = 1; spack->feature_type = f->feature_type; spack->value = f->value; spack->arg1 = f->arg1; spack->arg2 = f->arg2; break; } } /* unknown feature name, return */ if(spack->value < 0) return; /* if it's a client option, no further processing needed. THe value and args specified in the feature file will already be in 'spack' */ if(spack->feature_type == 'C') return; /* server/client options that might need special variables */ for(i=0; feature_vars[i].name ; i++){ if(feature_cmp(cpack->name, feature_vars[i].name)) { if(feature_vars[i].var){ if(cpack->value == 1) *feature_vars[i].var = (spack->value == 1); else { spack->value = 0; *feature_vars[i].var = 0; } } else { /* xx: special features that don't have a single variable associated: */ /* client values mean nothing here */ spack->value = 1; } if (feature_vars[i].arg1) { *feature_vars[i].arg1 = cpack->arg1; } return; } } /* unimplemented server feature. We could be impolite and give a warning message here to get the server administrator to add it.. */ spack->value = -1; } /* this is exactly the same as (strcasecmp(f, s)==0), but some OS's don't have it */ static int feature_cmp(char *f, char *s) { while(*f && *s){ if((islower(*f)?toupper(*f):*f) != (islower(*s)?toupper(*s):*s)) return 0; f++; s++; } return !*f && !*s; } #endif