11 #include <names_server.h>
12 #include <names_client.h>
19 #include <names_prototypes.h>
30 #define na_assert(cond) arb_assert(cond)
32 #define FULLNAME_LEN_MAX 64
33 #define NAME_LEN_MIN 2
42 inline void aisc_link(dll_public *dll, AN_shorts *shorts) {
aisc_link(reinterpret_cast<dllpublic_ext*>(dll), reinterpret_cast<dllheader_ext*>(shorts)); }
43 inline void aisc_link(dll_public *dll, AN_revers *revers) {
aisc_link(reinterpret_cast<dllpublic_ext*>(dll), reinterpret_cast<dllheader_ext*>(revers)); }
51 #define UPPERCASE(c) do { (c) = toupper(c); } while (0)
71 for (
int i = 0; str[i]; i++) {
72 str[i] = tolower(str[i]);
77 inline int an_strnicmp(
const char *s1,
const char *s2,
int len) {
80 for (
int i = 0; i<len; i++) {
81 cmp = tolower(s1[i])-tolower(s2[i]);
82 if (cmp || !s1[i])
break;
91 for (
int i = 0; ; i++) {
92 cmp = tolower(s1[i])-tolower(s2[i]);
93 if (cmp || !s1[i])
break;
102 AN_revers *an_reverse = (AN_revers*)
aisc_find_lib(&main->prevers, key);
114 AN_shorts *an_shorts = (AN_shorts*)
aisc_find_lib(&main->pnames, key);
139 if (elems<100) elems = 100;
154 static char buf[] =
"xxx";
170 const char *parsed_name,
const char *parsed_sym,
171 const char *shrt,
const char *acc,
const char *add_id)
173 AN_shorts *an_shorts;
174 AN_revers *an_revers;
177 if (strlen(parsed_sym)) {
178 ARB_calloc(full_name, strlen(parsed_name) + strlen(
" sym")+1);
179 sprintf(full_name,
"%s sym", parsed_name);
185 an_shorts = create_AN_shorts();
186 an_revers = create_AN_revers();
197 an_revers->full_name = full_name;
221 free(an_revers->mh.ident);
222 free(an_revers->full_name);
223 free(an_revers->acc);
229 free(an_shorts->mh.ident);
230 free(an_shorts->shrt);
231 free(an_shorts->full_name);
232 free(an_shorts->acc);
238 #if defined(DUMP_NAME_CREATION)
239 const char *org_str =
str;
240 #endif // DUMP_NAME_CREATION
248 if (isalpha(c)) buf[i++] = c;
252 #if defined(DUMP_NAME_CREATION)
253 printf(
"nas_string_2_name('%s') = '%s'\n", org_str, buf);
254 #endif // DUMP_NAME_CREATION
259 #if defined(DUMP_NAME_CREATION)
260 const char *org_str =
str;
261 #endif // DUMP_NAME_CREATION
269 if (!strchr(
"aeiouy", c)) {
275 #if defined(DUMP_NAME_CREATION)
276 printf(
"nas_remove_small_vocals('%s') = '%s'\n", org_str, buf);
277 #endif // DUMP_NAME_CREATION
282 int len = strlen(shrt);
285 char c = *rest_of_full++;
301 bool is_single_case =
true;
303 bool seen_upper_case =
false;
304 bool seen_lower_case =
false;
305 for (
int i = 0; str[i] && is_single_case; i++) {
308 if (islower(c)) seen_lower_case =
true;
309 else seen_upper_case =
true;
311 if (seen_lower_case == seen_upper_case) {
312 is_single_case =
false;
318 if (is_single_case) {
319 bool next_is_capital =
true;
321 for (
int i = 0; str[i]; i++) {
324 if (next_is_capital) {
326 next_is_capital =
false;
333 next_is_capital =
true;
353 look = (AN_shorts *)
aisc_find_lib((dllpublic_ext*)parent, full2);
367 strncpy(shrt, full2, 3);
373 len2 = strlen(full2);
381 len3 = strlen(full3);
383 for (p1=1; p1<(len3-1); p1++) {
385 for (p2=p1+1; p2<len3; p2++) {
397 len2 = strlen(full2);
398 for (p1=1; p1<(len2-1); p1++) {
400 for (p2=p1+1; p2<len2; p2++) {
412 for (p1=1; p1<len2; p1++) {
414 for (p2=0; p2<=9; p2++) {
426 for (p1=1; p1<=99; p1++) {
427 shrt[1] =
'0'+(p1/10);
428 shrt[2] =
'0'+(p1%10);
440 const char *allowed =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
443 for (p1=
'A'; p1<=
'Z'; p1++) {
445 for (p2 = 0; p2<len; p2++) {
446 shrt[1] = allowed[p2];
447 for (p3 = 0; p3<len; p3++) {
448 shrt[2] = allowed[p3];
464 if (result && result[0]) {
465 #if defined(DUMP_NAME_CREATION)
466 if (isdigit(result[0]) || isdigit(result[1])) {
467 printf(
"generated new short-name '%s' for full-name '%s' full2='%s' full3='%s'\n", shrt, full, full2, full3);
469 #endif // DUMP_NAME_CREATION
471 look = create_AN_shorts();
474 aisc_link((dllpublic_ext*)parent, (dllheader_ext*)look);
481 printf(
"ARB_name_server: Failed to find a unique short prefix for word '%s' (using '%s')\n", full, result);
497 const char *full_name;
518 void add_short(
const AN_local *locs,
const char *shrt)
const {
519 an_add_short(locs,
id, parsed_name, parsed_sym, shrt, parsed_acc, parsed_add_id);
524 bool nonalnum =
false;
525 for (
char c = *str++; c; c = *str++) {
537 char *newStr = ARB_alloc<char>(strlen(str)+1);
540 for (
int p = 0; str[p]; ++p) {
541 if (isalnum(str[p])) newStr[n++] = str[p];
549 char *newStr = ARB_alloc<char>(strlen(str)+1);
552 for (
int p = 0; str[p]; ++p) {
553 if (isalpha(str[p])) newStr[n++] = str[p];
560 #define assert_alphanumeric(s) na_assert(!contains_non_alphanumeric(s))
562 #define assert_alphanumeric(s)
566 full_name = locs->full_name;
571 "sp.=species:spec.=species:SP.=SPECIES:SPEC.=SPECIES:"
576 int leading_spaces = strspn(parsed_name,
" ");
577 int len = strlen(parsed_name)-leading_spaces;
578 memmove(parsed_name, parsed_name+leading_spaces, len);
580 char *first_space = strchr(parsed_name,
' ');
582 char *second_space = strchr(first_space+1,
' ');
592 if (strlen(parsed_sym)>1) freedup(parsed_sym,
"");
594 const char *add_id = locs->add_id[0] ? locs->add_id :
aisc_main->add_field_default;
599 rest_of_name =
make_alnum(parsed_name+strlen(first_name));
611 id = (strlen(parsed_acc)+strlen(parsed_add_id))
649 static char *shrt =
NULp;
657 bool recreate =
false;
662 else if (strcmp(an_shorts->full_name, default_full_name) == 0 &&
676 char *first_advice =
NULp;
677 char *second_advice =
NULp;
683 if (locs->advice[0]) {
687 if (strlen(advice) > 3) {
693 if (!first_advice) first_advice =
ARB_strdup(
"ZZZ");
694 if (!second_advice) second_advice =
ARB_strdup(
"ZZZZZ");
700 first_short = first_name[0]
706 if (first_short[0] == 0) {
707 freedup(first_short,
"ZZZ");
709 first_len = strlen(first_short);
712 char *second_short = ARB_calloc<char>(10);
716 int restlen = strlen(rest_of_name);
719 rest_of_name = second_advice;
720 restlen = strlen(rest_of_name);
722 rest_of_name =
"ZZZZZ";
729 if (restlen<5 && first_len>3) {
730 strcpy(second_short, first_short+3);
731 second_short[5-restlen] = 0;
734 char *strend = strchr(second_short, 0);
735 strncpy(strend, rest_of_name, 8);
736 second_len = strlen(second_short);
744 int both_len = first_len+second_len;
752 second_len = 8-first_len;
753 second_short[second_len] = 0;
758 sprintf(test_short,
"%s%s", first_short, second_short);
760 na_assert(
size_t(both_len) == strlen(test_short));
761 na_assert(second_len>=5 && second_len <= 8);
766 char *test_short_dup =
ARB_strdup(test_short);
772 const long NUMBERS = 100000;
774 int printOffset = both_len;
775 bool foundUnused =
false;
779 int digLimit[6] = { 0, 9, 99, 999, 9999, 99999 };
782 int limit = digLimit[
digits];
784 if (printOffset>maxOffset) printOffset = maxOffset;
786 char *printAt = test_short+printOffset;
792 for (; !foundUnused && count <= limit; ++count) {
804 const long base36_limit5 = 60466176;
805 const int64_t base36_limit7 = 78364164096LL;
807 bool store_in_nameModHash =
true;
811 strcpy(test_short, test_short_dup);
813 long count2 = count-NUMBERS;
814 char *printAt = test_short+3;
815 const char *
base36 =
"0123456789abcdefghijklmnopqrstuvwxyz";
819 for (; !foundUnused && count2<base36_limit5; ++count2) {
823 for (
int pos = 0; pos<5; ++pos) {
825 int rest = c-36*nextc;
827 printAt[4-pos] = base36[rest];
839 store_in_nameModHash =
false;
843 for (
int pc =
'a'; pc<=
'z' && !foundUnused; ++pc) {
844 char key[2] = {
char(pc), 0 };
849 printAt = test_short+1;
851 for (; !foundUnused && count3<base36_limit7; ++count3) {
855 for (
int pos = 0; pos<7; ++pos) {
856 int64_t nextc = c/36;
857 int rest = c-36*nextc;
859 printAt[6-pos] = base36[rest];
872 const int64_t names_limit = 26*base36_limit7;
882 count = count2+NUMBERS;
887 if (store_in_nameModHash) {
888 test_short_dup[7] = 0;
891 test_short_dup[6] = 0;
894 test_short_dup[5] = 0;
897 test_short_dup[4] = 0;
900 test_short_dup[3] = 0;
908 free(test_short_dup);
930 if (server_date>main->server_filedate) {
931 printf(
"Another nameserver changed '%s' - your changes are lost.\n", main->server_file);
934 char *sec_name = ARB_calloc<char>(strlen(main->server_file)+2);
935 sprintf(sec_name,
"%s%%", main->server_file);
936 printf(
"Saving '%s'..\n", main->server_file);
938 FILE *file = fopen(sec_name,
"w");
940 fprintf(stderr,
"ERROR cannot save file '%s'\n", sec_name);
943 save_AN_main(main, file);
944 if (fclose(file) == 0) {
947 else main->touched = 0;
951 fprintf(stderr,
"Error: %s\n", save_error);
960 printf(
"No changes to ARB_name_server data.\n");
966 #if defined(DEBUG) && 0
967 static void check_list(AN_shorts *
start) {
972 fprintf(stderr,
"<list has %i elements>\n", count);
977 fprintf(stderr,
"<ERROR - list is looped>\n");
986 bool case_error_occurred =
false;
987 int idents_changed = 0;
989 for (AN_shorts *shrt = main->shorts1; shrt;) {
990 AN_shorts *next = shrt->next;
993 fprintf(stderr,
"- Correcting error in name-database: '%s' equals '%s'\n",
994 found->shrt, shrt->shrt);
996 case_error_occurred =
true;
1002 for (AN_shorts *shrt = main->names; shrt;) {
1003 AN_shorts *next = shrt->next;
1006 if (found && (shrt->acc && found->acc &&
an_stricmp(shrt->acc, found->acc) != 0)) {
1007 fprintf(stderr,
"- Correcting error in name-database: '%s' equals '%s' (but acc differs)\n",
1008 found->mh.ident, shrt->shrt);
1011 case_error_occurred =
true;
1013 else if (found && (shrt->add_id && found->add_id &&
an_stricmp(shrt->add_id, found->add_id) != 0)) {
1014 fprintf(stderr,
"- Correcting error in name-database: '%s' equals '%s' (but add_id differs)\n",
1015 found->mh.ident, shrt->shrt);
1018 case_error_occurred =
true;
1028 case_error_occurred =
true;
1031 else if (self_find != shrt) {
1032 fprintf(stderr,
"- Correcting error in name-database: '%s' equals '%s' (case-difference in full_name or acc)\n",
1033 shrt->mh.ident, self_find->mh.ident);
1035 case_error_occurred =
true;
1042 if (case_error_occurred) {
1043 int regen_name_parts = 0;
1044 int deleted_names = 0;
1048 list<string> idents_to_recreate;
1050 for (AN_shorts *shrt = main->shorts1; shrt;) {
1054 if (strcmp(cap_name, shrt->shrt) != 0) {
1055 idents_to_recreate.push_back(shrt->mh.ident);
1059 AN_shorts *next = shrt->next;
1064 list<string>::const_iterator end = idents_to_recreate.end();
1065 for (list<string>::const_iterator i = idents_to_recreate.begin(); i != end; ++i) {
1066 const char *ident = i->c_str();
1067 free(
an_get_short(main->shorts1, &(main->pshorts1), ident));
1073 for (AN_shorts *shrt = main->names; shrt;) {
1074 AN_shorts *next = shrt->next;
1078 if (strcmp(cap_name, shrt->shrt) != 0) {
1086 if (idents_changed) fprintf(stderr,
"* Changed case of %i identifiers.\n", idents_changed);
1087 if (regen_name_parts) fprintf(stderr,
"* Regenerated %i prefix names.\n", regen_name_parts);
1088 if (deleted_names) fprintf(stderr,
"* Removed %i names with wrong case.\n"
1089 "=> This leads to name changes when generating new names (which is recommended now).\n", deleted_names);
1095 int illegal_names = 0;
1098 for (AN_shorts *shrt = main->shorts1; shrt;) {
1099 AN_shorts *next = shrt->next;
1101 fprintf(stderr,
"- Fixing illegal chars in '%s'\n", shrt->shrt);
1108 for (AN_shorts *shrt = main->names; shrt;) {
1109 AN_shorts *next = shrt->next;
1111 fprintf(stderr,
"- Fixing illegal chars in '%s'\n", shrt->shrt);
1118 if (illegal_names>0) {
1119 fprintf(stderr,
"* Removed %i names containing illegal characters.\n"
1120 "=> This leads to name changes when generating new names (which is recommended now).\n", illegal_names);
1127 if (main->add_field_default[0]) {
1132 for (AN_shorts *shrt = main->names; shrt;) {
1133 AN_shorts *next = shrt->next;
1134 if (!shrt->add_id[0]) {
1137 freedup(shrt->add_id, main->add_field_default);
1138 na_assert(strchr(shrt->mh.ident, 0)[-1] ==
'*');
1148 printf(
" Filled in default value '%s' for %li names\n", main->add_field_default, count);
1160 fprintf(stderr,
"Starting ARB_name_server..\n");
1162 file = fopen(main->server_file,
"r");
1167 fprintf(stderr,
"* Loading %s\n", main->server_file);
1168 int err_code = load_AN_main(main, file);
1170 error =
GBS_global_string(
"Error #%i while loading '%s'", err_code, main->server_file);
1175 fprintf(stderr,
"* Parsing data\n");
1177 for (shrt = main->names; shrt; shrt = shrt->next) {
1178 revers = create_AN_revers();
1180 revers->full_name =
ARB_strdup(shrt->full_name);
1187 int namesDBversion = main->dbversion;
1188 fprintf(stderr,
"* Loaded NAMEDB v%i (contains %li names)\n", namesDBversion, nameCount);
1190 if (namesDBversion < SERVER_VERSION) {
1191 if (namesDBversion<4) {
1192 fprintf(stderr,
"* Checking for case-errors\n");
1195 fprintf(stderr,
"* Checking for illegal characters\n");
1199 fprintf(stderr,
"* NAMEDB version upgrade %i -> %i\n", namesDBversion, SERVER_VERSION);
1203 if (namesDBversion > SERVER_VERSION) {
1204 error =
GBS_global_string(
"NAMEDB is from version %i, but your nameserver can only handle version %i",
1205 namesDBversion, SERVER_VERSION);
1208 fprintf(stderr,
"ARB_name_server is up.\n");
1213 main->server_filedate = -1;
1225 bool authorized = strcmp(passwd,
"ldfiojkherjkh") == 0;
1227 if (!authorized)
return 1;
1230 printf(
"\narb_name_server: I got the shutdown message.\n");
1236 printf(
"ARB_name_server: server shutdown by administrator\n");
1243 static int usage(
const char *exeName,
const char *err) {
1244 printf(
"ARB nameserver v%i\n"
1245 "Usage: %s command server-parameters\n"
1249 , SERVER_VERSION, exeName);
1251 if (err) printf(
"Error: %s\n", err);
1262 const char *executable = argv[0];
1265 return usage(executable,
"Missing default file");
1269 char flag[]=
"-look";
1275 return usage(executable,
"Too many parameters");
1298 if (!strcmp(argv[1],
"-look")) {
1299 printf(
"ARB_name_server: No client - terminating.\n");
1305 printf(
"There is another active nameserver. I try to kill it..\n");
1307 MAIN_SHUTDOWN,
"ldfiojkherjkh",
1315 printf(
"ARB_name_server: %s\n", error);
1319 if (((strcmp(argv[1],
"-kill") == 0)) ||
1320 ((argc==3) && (strcmp(argv[2],
"-kill")==0))) {
1321 printf(
"ARB_name_server: Now I kill myself!\n");
1329 printf(
"AN_SERVER: Gave up on opening the communication socket!\n");
1340 const char *field = params->
field;
1349 error =
GBS_global_string(
"Missing default value for add.field (option has to be -f%s=defaultValue)", field);
1356 printf(
"* add. field not defined yet -> using '%s'\n", field);
1359 fputs(
"* using no add. field\n", stdout);
1365 if (strcmp(
aisc_main->add_field, field) != 0) {
1370 error =
"This names-DB has to be started w/o -f option";
1377 char *field_default_alnum =
make_alnum(field_default);
1380 reassign(
aisc_main->add_field_default, field_default_alnum);
1385 if (strcmp(
aisc_main->add_field_default, field_default_alnum) != 0) {
1386 error =
GBS_global_string(
"Default for add.field previously was '%s' (called with '%s')\n"
1387 "If you really need to change this - delete the names DB",
1388 aisc_main->add_field_default, field_default_alnum);
1391 free(field_default_alnum);
1396 long accept_calls = accept_calls_init;
1397 bool isTimeout =
true;
1402 while (!error && accept_calls>0) {
1409 if (server_date == 0 &&
aisc_main->server_filedate != 0) {
1410 fprintf(stderr,
"ARB_name_server data has been deleted.\n");
1414 if (server_date>
aisc_main->server_filedate) {
1415 fprintf(stderr,
"ARB_name_server data changed on disc.\n");
1421 accept_calls = accept_calls_init;
1425 accept_calls = accept_calls_init;
1433 fprintf(stderr,
"%s\n", fullErrorMsg);
1435 if (error) fprintf(stderr,
"Error: %s\n", error);
1436 free(quotedErrorMsg);
1439 else if (accept_calls == 0) {
1445 printf(
"ARB_name_server terminating...\n");
1449 printf(
"Server terminates with code %i.\n", exitcode);
long aisc_find_lib(dll_public *dll, char *key)
const char * aisc_unlink(dllheader_ext *object)
GB_ERROR GBK_system(const char *system_command)
void GB_warning(const char *message)
static const char * an_make_prefix(const char *str)
int an_strnicmp(const char *s1, const char *s2, int len)
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
static const char * default_full_name
Hs_struct * open_aisc_server(const char *path, int timeout, int fork)
static GB_ERROR server_load(AN_main *main)
char * an_strlwr(char *str)
void aisc_server_shutdown(Hs_struct *&hs)
int aisc_close(aisc_com *link, AISC_Object &object)
static char * nas_remove_small_vocals(const char *str)
int main(int argc, char **argv)
void aisc_link(dll_public *dll, AN_shorts *shorts)
GB_ERROR GB_IO_error(const char *action, const char *filename)
char * ARB_strdup(const char *str)
const char * GBS_global_string(const char *templat,...)
static GB_HASH * an_get_prefix_hash()
int aisc_nput(aisc_com *link, int o_type, const AISC_Object &object,...)
static char * make_alnum(const char *str)
static void an_complete_shrt(char *shrt, const char *rest_of_full)
void GBK_terminatef(const char *templat,...)
char * GBS_string_eval(const char *insource, const char *icommand)
int del_short(const AN_local *locs)
void GBS_free_hash(GB_HASH *hs)
static int usage(const char *exeName, const char *err)
long GBS_write_hash_no_strdup(GB_HASH *hs, char *key, long val)
int server_shutdown(AN_main *, aisc_string passwd)
arb_params * arb_trace_argv(int *argc, const char **argv)
Hs_struct * server_communication
static HelixNrInfo * start
static char * nas_string_2_name(const char *str)
int an_stricmp(const char *s1, const char *s2)
void arb_print_server_params()
const char * GBS_read_arb_tcp(const char *env)
static char * an_get_short(AN_shorts *shorts, dll_public *parent, const char *full)
CONSTEXPR_INLINE int digits(int parts)
int ARB_main(int argc, char *argv[])
unsigned long GB_time_of_file(const char *path)
static struct AN_gl_struct AN_global
static void an_add_short(const AN_local *, const char *new_name, const char *parsed_name, const char *parsed_sym, const char *shrt, const char *acc, const char *add_id)
GB_ERROR GB_move_file(const char *oldpath, const char *newpath)
static void error(const char *msg)
static GB_HASH * nameModHash
const char * field_default
static int base36(int ch)
void ARB_sleep(int amount, TimeUnit tu)
int aisc_broadcast(Hs_struct *hs, int message_type, const char *message)
static bool contains_non_alphanumeric(const char *str)
#define NAME_SERVER_TIMEOUT
GB_ERROR GB_print_error()
#define AISC_MAGIC_NUMBER
fputs(TRACE_PREFIX, stderr)
TYPE * ARB_calloc(size_t nelem)
#define IF_ASSERTION_USED(x)
char * GBK_singlequote(const char *arg)
char * ARB_strndup(const char *start, int len)
const char * GBS_nameserver_tag(const char *add_field)
static size_t an_shorts_elems(AN_shorts *sin)
static void check_for_case_error(AN_main *main)
static void an_remove_short(AN_shorts *an_shorts)
static void check_for_illegal_chars(AN_main *main)
aisc_com * aisc_open(const char *path, AISC_Object &main_obj, long magic, GB_ERROR *error)
static AN_revers * lookup_an_revers(AN_main *main, const char *shortname)
static AN_shorts * an_find_shrt_prefix(const char *search)
#define NAME_SERVER_SLEEP
static void set_empty_addids(AN_main *main)
int server_save(AN_main *main, int)
aisc_string get_short(const AN_local *locs)
static AN_shorts * lookup_an_shorts(AN_main *main, const char *identifier)
static int info[maxsites+1]
Hs_struct * aisc_accept_calls(Hs_struct *hs)
#define assert_alphanumeric(s)
long GBS_read_hash(const GB_HASH *hs, const char *key)
static char * make_alpha(const char *str)
char * GBS_global_string_copy(const char *templat,...)
void GBS_optimize_hash(const GB_HASH *hs)
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
static void an_autocaps(char *str)