18 #include <netinet/tcp.h>
21 #include <sys/socket.h>
27 # include <sys/sysctl.h>
66 fprintf(stderr,
"Cannot read data from client: len=%li (%s, errno %i)\n",
67 holding, strerror(errno), errno);
73 if (size>holding) size = holding;
84 if (readsize<=0)
return 0;
105 writesize = send(socket, ptr, leftsize, MSG_NOSIGNAL);
107 writesize = write(socket, ptr, leftsize);
113 "Client (pid=%i) terminating after failure to contact database (%s).",
114 getpid(), strerror(errno));
118 fprintf(stderr,
"Error sending data to client (%s).", strerror(errno));
123 leftsize -= writesize;
146 if (path && strcmp(path,
":") == 0) {
192 if (!socket)
return 1;
193 return gbcm_write(socket, (
const char *)ia,
sizeof(
long)*3);
206 size =
gbcm_read(socket, (
char *)&(ia[0]),
sizeof(
long)*3);
207 if (size !=
sizeof(
long) * 3) {
209 sizeof(
long) * 3, size, a);
231 size_t len = strlen(key);
262 gbcm_write(socket, (
char*)&data,
sizeof(data));
268 gbcm_read(socket, (
char*)&data,
sizeof(data));
282 while (EOF != (c = getc(in))) {
297 if (strcmp(path,
"-") == 0) {
304 FILE *in = fopen(epath,
"rt");
310 if (data_size >= 0) {
311 result = ARB_alloc<char>(data_size+1);
313 data_size = fread(result, 1, data_size, in);
314 result[data_size] = 0;
333 buffer = (
char*)mmap(
NULp, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fi, 0);
336 buffer = (
char*)mmap(
NULp, size, PROT_READ, MAP_SHARED, fi, 0);
338 if (buffer == MAP_FAILED) {
339 GB_export_errorf(
"GB_map_file: Error: Out of Memory: mmap failed (errno: %i)", errno);
348 in = fopen(path,
"r");
360 if (gettimeofday(&tp,
NULp))
return 0;
379 static const char *path =
NULp;
384 GB_informationf(
"Your PATH variable is empty - using '%s' as search path.", path);
388 if (!strstr(path, arbbin)) {
389 GB_warningf(
"Your PATH variable does not contain '%s'. Things may not work as expected.", arbbin);
411 va_start(args, description_of_executable);
422 va_start(args, description_of_executable);
423 while ((name = va_arg(args,
GB_CSTR))) {
424 if (!first) buf.
cat(
", ");
432 msg =
GBS_global_string_copy(
"Could not find a %s (looked for: %s)", description_of_executable, looked_for);
440 char *description =
GBS_global_string_copy(
"the %s derived from environment variable PATH", description_of_executable);
444 GB_informationf(
"Using %s '%s' ('%s')", description_of_executable, name, found);
471 if (!strncasecmp(exe_name,
"open", 4)) {
478 GB_warningf(
"Environment variable '%s' contains '%s' (which is not an executable)", envvar, exe_name);
482 char *description =
GBS_global_string_copy(
"the executable derived from environment variables '%s' and PATH", envvar);
504 char *description =
GBS_global_string_copy(
"the directory derived from environment variable '%s'", envvar);
510 GB_warningf(
"Environment variable '%s' should contain the path of an existing directory.\n"
511 "(current content '%s' has been ignored.)", envvar, dir_name);
518 if (setenv(var, value, 1) != 0) {
519 GB_warningf(
"Could not set environment variable '%s'. This might cause problems in subprocesses.\n"
520 "(Reason: %s)", var, strerror(errno));
525 static const char *xterm =
NULp;
528 if (!xterm) xterm =
"xterm -sl 1000 -sb -geometry 150x60";
534 static const char *xcmd =
NULp;
547 static const char *user =
NULp;
553 if (user && strrchr(user,
'/')) user = strrchr(user,
'/')+1;
556 fprintf(stderr,
"WARNING: Cannot identify user: environment variables USER, LOGNAME and HOME not set\n");
557 user =
"UnknownUser";
565 static SmartCharPtr Home;
571 fprintf(stderr,
"WARNING: Cannot identify user's home directory: environment variable HOME not set\n"
572 "Using current directory (%s) as home.\n", home);
581 static SmartCharPtr Arbhome;
582 if (Arbhome.isNull()) {
585 fprintf(stderr,
"Fatal ERROR: Environment Variable ARBHOME not found !!!\n"
586 " Please set 'ARBHOME' to the installation path of ARB\n");
595 static const char *am =
NULp;
611 char *description =
GBS_global_string_copy(
"the default directory expanded from expression '%s'", defaultDirectory);
624 static SmartCharPtr ArbProps;
630 static SmartCharPtr ArbMacroHome;
632 return &*ArbMacroHome;
636 static SmartCharPtr ArbConfig;
642 static const char *gs =
NULp;
661 static const char *pdfview =
NULp;
670 pdfview =
GB_find_executable(
"PDF viewer",
"xreader",
"epdfview",
"xpdf",
"kpdf",
"acroread",
"gv",
NULp);
678 static const char *dp =
NULp;
688 static const char *dp =
NULp;
713 if (result)
return result;
715 if (strncmp(env,
"ARB", 3) == 0) {
761 static GB_ULONG physical_memsize = 0;
762 if (!physical_memsize) {
766 long pagesize = sysconf(_SC_PAGESIZE);
767 long pages = sysconf(_SC_PHYS_PAGES);
769 memsize = (pagesize/1024) * pages;
771 #elif defined(DARWIN)
772 #warning memsize detection needs to be tested for Darwin
781 sysctl(mib, 2, &bytes, &len,
NULp, 0);
783 memsize = bytes/1024;
788 "Warning: ARB is not prepared to detect the memory size on your system!\n"
789 " (it assumes you have %ul Mb, but does not use more)\n\n", memsize/1024);
792 GB_ULONG net_memsize = memsize - 10240;
795 GB_ULONG max_malloc_try = net_memsize*1024;
803 while ((tmp=(
void**)malloc(step_size))) {
806 max_malloc += step_size;
807 if (max_malloc >= max_malloc_try)
break;
810 }
while ((step_size=step_size/2) >
sizeof(
void*));
812 while (head) freeset(head, *(
void**)head);
816 physical_memsize =
std::min(net_memsize, max_malloc);
818 #if defined(DEBUG) && 0
819 printf(
"- memsize(real) = %20lu k\n", memsize);
820 printf(
"- memsize(net) = %20lu k\n", net_memsize);
821 printf(
"- memsize(max_malloc) = %20lu k\n", max_malloc);
828 return physical_memsize;
833 GB_ULONG num = strtoul(env_override, const_cast<char**>(&end), 10);
837 bool valid = num>0 || env_override[0] ==
'0';
839 const char *formatSpec = end;
842 switch (tolower(formatSpec[0])) {
856 default: valid =
false;
break;
859 if (valid)
return GB_ULONG(num*factor+0.5);
862 error =
"expected digits (optionally followed by k, M, G or %)";
870 if (!useable_memory) {
871 bool allow_fallback =
true;
872 const char *env_override =
GB_getenv(
"ARB_MEMORY");
873 const char *via_whom;
875 via_whom =
"via envar ARB_MEMORY";
879 env_override =
"90%";
880 via_whom =
"by internal default";
881 allow_fallback =
false;
889 GB_warningf(
"Ignoring invalid setting '%s' %s (%s)", env_override, via_whom, env_error);
890 if (allow_fallback)
goto FALLBACK;
895 if (!allow_fallback) {
896 GB_informationf(
"Note: Setting envar ARB_MEMORY will override that restriction (percentage or absolute memsize)");
898 useable_memory = env_memory;
901 return useable_memory;
912 gb_sync_data =
GBT_create(gb_main,
"sync_data", 0);
983 while (suffix[0] ==
'.') suffix++;
1002 else if (!anypath[0]) {
1009 if (anypath[0] ==
'~' && (!anypath[1] || anypath[1] ==
'/')) {
1016 result = realpath(anypath, path_buf[1-path_toggle]);
1022 char *dir, *fullname;
1025 const char *canonical_dir =
NULp;
1037 if (strcmp(fullname,
"..") == 0) {
1045 else if (strcmp(fullname,
".") == 0) {
1046 result = canonical_dir;
1071 if (anypath_right) {
1072 if (anypath_right[0] ==
'/') {
1075 else if (anypath_left && anypath_left[0]) {
1076 if (anypath_left[strlen(anypath_left)-1] ==
'/') {
1084 result = anypath_right;
1088 result = anypath_left;
1107 for (
int i = 0; name[i]; ++i) {
1108 if (isalnum(name[i]) || name[i] ==
'_')
continue;
1165 #define GB_PATH_TMP GB_path_in_arb_temp("tmp") // = "~/.arb_tmp/tmp" (used wherever '/tmp' was used in the past)
1183 bool write = strpbrk(fmode,
"wa");
1185 fp = fopen(file, fmode);
1188 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) != 0) {
1189 error =
GB_IO_error(
"changing permissions of", file);
1203 if (fp) { fclose(fp); fp =
NULp; }
1204 if (file) unlink(file);
1220 if (out) fclose(out);
1238 if (unlink(file) != 0) {
1239 fprintf(stderr,
"Warning: %s\n",
GB_IO_error(
"removing", file));
1243 if (files_to_remove_on_exit) {
1246 files_to_remove_on_exit =
NULp;
1252 if (!files_to_remove_on_exit) {
1259 void GB_split_full_path(
const char *fullpath,
char **res_dir,
char **res_fullname,
char **res_name_only,
char **res_suffix) {
1280 if (fullpath && fullpath[0]) {
1281 const char *lslash = strrchr(fullpath,
'/');
1282 const char *name_start = lslash ? lslash+1 : fullpath;
1283 const char *ldot = strrchr(lslash ? lslash : fullpath,
'.');
1284 const char *terminal = strchr(name_start, 0);
1290 if (!lslash && fullpath[0] ==
'.' && (fullpath[1] == 0 || (fullpath[1] ==
'.' && fullpath[2] == 0))) {
1291 if (res_dir) *res_dir =
ARB_strdup(fullpath);
1292 if (res_fullname) *res_fullname =
NULp;
1293 if (res_name_only) *res_name_only =
NULp;
1294 if (res_suffix) *res_suffix =
NULp;
1297 if (res_dir) *res_dir = lslash ?
ARB_strpartdup(fullpath, lslash == fullpath ? lslash : lslash-1) :
NULp;
1298 if (res_fullname) *res_fullname =
ARB_strpartdup(name_start, terminal-1);
1299 if (res_name_only) *res_name_only =
ARB_strpartdup(name_start, ldot ? ldot-1 : terminal-1);
1304 if (res_dir) *res_dir =
NULp;
1305 if (res_fullname) *res_fullname =
NULp;
1306 if (res_name_only) *res_name_only =
NULp;
1307 if (res_suffix) *res_suffix =
NULp;
1318 #define TEST_EXPECT_IS_CANONICAL(file) \
1320 char *dup = ARB_strdup(file); \
1321 TEST_EXPECT_EQUAL(GB_canonical_path(dup), dup); \
1325 #define TEST_EXPECT_CANONICAL_TO(not_cano,cano) \
1327 char *arb_not_cano = ARB_strdup(GB_concat_path(arbhome, not_cano)); \
1328 char *arb_cano = ARB_strdup(GB_concat_path(arbhome, cano)); \
1329 TEST_EXPECT_EQUAL(GB_canonical_path(arb_not_cano), arb_cano); \
1331 free(arb_not_cano); \
1334 static arb_test::match_expectation path_splits_into(
const char *path,
const char *Edir,
const char *Enameext,
const char *Ename,
const char *Eext) {
1338 char *Sdir,*Snameext,*Sname,*Sext;
1351 return all().ofgroup(expected);
1354 #define TEST_EXPECT_PATH_SPLITS_INTO(path,dir,nameext,name,ext) TEST_EXPECTATION(path_splits_into(path,dir,nameext,name,ext))
1355 #define TEST_EXPECT_PATH_SPLITS_INTO__BROKEN(path,dir,nameext,name,ext) TEST_EXPECTATION__BROKEN(path_splits_into(path,dir,nameext,name,ext))
1361 char *Sdir,*Snameext,*Sname,*Sext;
1372 return all().ofgroup(expected);
1375 #define TEST_SPLIT_REVERSIBILITY(path) TEST_EXPECTATION(path_splits_reversible(path))
1376 #define TEST_SPLIT_REVERSIBILITY__BROKEN(path) TEST_EXPECTATION__BROKEN(path_splits_reversible(path))
1387 TEST_EXPECT_PATH_SPLITS_INTO(
"dir/sub/.ext",
"dir/sub",
".ext",
"",
"ext");
1388 TEST_EXPECT_PATH_SPLITS_INTO(
"/root/sub/file.notext.ext",
"/root/sub",
"file.notext.ext",
"file.notext",
"ext");
1390 TEST_EXPECT_PATH_SPLITS_INTO(
"./file.ext",
".",
"file.ext",
"file",
"ext");
1391 TEST_EXPECT_PATH_SPLITS_INTO(
"/file",
"/",
"file",
"file",
NULp);
1392 TEST_EXPECT_PATH_SPLITS_INTO(
".",
".",
NULp,
NULp,
NULp);
1396 const char *prefix[] = {
1414 TEST_SPLIT_REVERSIBILITY(prefix[d]);
1425 const char* nosuchfile =
"nosuchfile";
1426 const char* somefile =
"arb_README.txt";
1437 TEST_EXPECT_IS_CANONICAL(somefile_in_arbhome);
1438 TEST_EXPECT_IS_CANONICAL(nosuchpath_in_arbhome);
1439 TEST_EXPECT_IS_CANONICAL(file_in_nosuchpath);
1441 TEST_EXPECT_IS_CANONICAL(
"/usr");
1442 #if !defined(DARWIN)
1444 TEST_EXPECT_IS_CANONICAL(
"/tmp/arbtest.fig");
1446 TEST_EXPECT_IS_CANONICAL(
"/arbtest.fig");
1448 TEST_EXPECT_CANONICAL_TO(
"./PARSIMONY/./../ARBDB/./arbdb.h",
"ARBDB/arbdb.h");
1449 TEST_EXPECT_CANONICAL_TO(
"INCLUDE/arbdb.h",
"ARBDB/arbdb.h");
1450 TEST_EXPECT_CANONICAL_TO(
"NAMES_COM/AISC/aisc.pa",
"AISC_COM/AISC/aisc.pa");
1451 TEST_EXPECT_CANONICAL_TO(
"./NAMES_COM/AISC/..",
"AISC_COM");
1453 TEST_EXPECT_CANONICAL_TO(
"./PARSIMONY/./../ARBDB/../nosuchpath",
"nosuchpath");
1455 TEST_EXPECT_CANONICAL_TO(
"./PARSIMONY/./../nosuchpath/../ARBDB",
"ARBDB");
1456 TEST_EXPECT_CANONICAL_TO(
"./nosuchpath/./../ARBDB",
"ARBDB");
1482 free(file_in_nosuchpath);
1483 free(somepath_in_arbhome);
1484 free(nosuchpath_in_arbhome);
1485 free(nosuchfile_in_arbhome);
1486 free(somefile_in_arbhome);
1498 bool open(
const char *mode) {
1499 FILE *out = fopen(name, mode);
1500 if (out) fclose(out);
1504 void unlink() { ::unlink(name); }
1506 TestFile(
const char *name_) : name(name_) { create(); }
1507 ~TestFile() {
if (exists()) unlink(); }
1508 const char *get_name()
const {
return name; }
1509 bool exists() {
return open(
"r"); }
1512 void TEST_GB_remove_on_exit() {
1515 TestFile file(
"test1");
1521 TestFile t(
"test1");
1532 void TEST_some_paths() {
1550 const char *db_save_name =
"saved_after_sync.arb";
1560 TEST_EXPECT_RESULT__NOERROREXPORTED(value =
GB_read_sync_value(gb_main,
"neverUsedId"));
1563 #define SYNCID "myId"
1602 #endif // UNIT_TESTS
static GB_CSTR GB_getenvARB_PROP()
char * gbcm_read_string(int socket)
GB_CSTR GB_path_in_HOME(const char *relative_path)
GB_ULONG GB_get_usable_memory()
GB_ERROR GBK_system(const char *system_command)
long GB_size_of_FILE(FILE *in)
GB_CSTR GB_unfold_in_directory(const char *relative_directory, const char *path)
GBDATA * GB_open(const char *path, const char *opent)
static GBDATA * find_or_create_sync_value(GBDATA *gb_main, const char *id)
GBCM_ServerResult gbcm_write_flush(int socket)
GB_CSTR GB_concat_full_path(const char *anypath_left, const char *anypath_right)
void GB_warning(const char *message)
#define TEST_EXPECT_CONTAINS__BROKEN(str, part)
GB_CSTR GB_unfold_path(const char *pwd_envar, const char *path)
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
void GB_split_full_path(const char *fullpath, char **res_dir, char **res_fullname, char **res_name_only, char **res_suffix)
static GB_ULONG get_physical_memory()
GB_ERROR GB_write_string(GBDATA *gbd, const char *s)
GBDATA * GB_searchOrCreate_string(GBDATA *gb_container, const char *fieldpath, const char *default_value)
NOT4PERL gb_getenv_hook GB_install_getenv_hook(gb_getenv_hook hook)
const char * GBS_global_string_to_buffer(char *buffer, size_t bufsize, const char *templat,...)
GB_CSTR GB_getenvHTMLDOCPATH()
void ARB_warn_about_unwanted_chars(const char *path, const char *path_description)
char * GB_read_file(const char *path)
const char * arb_gethostname()
GB_CSTR GB_path_in_ARBLIB(const char *relative_path)
int ARB_stricmp(const char *s1, const char *s2)
#define ASSERT_RESULT(Type, Expected, Expr)
const char * ARB_getenv_ignore_empty(const char *envvar)
GB_ERROR GB_delete_database(GB_CSTR filename)
GB_ERROR GB_IO_error(const char *action, const char *filename)
char * ARB_strdup(const char *str)
static GB_CSTR GB_getenvARBCONFIG()
void GB_internal_errorf(const char *templat,...)
GB_ERROR arb_open_socket(const char *name, bool do_connect, int *fd, char **filename_out)
GB_CSTR GB_getenvARBHOME()
const char * GBS_global_string(const char *templat,...)
GB_CSTR GB_getenv(const char *env)
GB_ERROR GB_textprint(const char *path)
static void exit_remove_file(const char *file, long, void *)
static char * getenv_executable(GB_CSTR envvar)
void GBS_free_hash(GB_HASH *hs)
void cat(const char *from)
GBCM_ServerResult gbcm_write(int socket, const char *ptr, long size)
char * ARB_strpartdup(const char *start, const char *end)
GB_ERROR GB_create_parent_directory(const char *path)
GBCM_ServerResult gbcm_write_long(int socket, long data)
void GB_setenv(const char *var, const char *value)
long GB_size_of_file(const char *path)
static GB_CSTR GB_getenvPATH()
#define ARRAY_ELEMS(array)
char buffer[MESSAGE_BUFFERSIZE]
static char * getenv_autodirectory(const char *envvar, const char *defaultDirectory)
static char path_buf[2][ARB_PATH_MAX]
GB_ULONG GB_time_of_day()
char * ARB_executable(const char *exe_name, const char *path)
#define TEST_EXPECT_CONTAINS(str, part)
GB_ERROR GB_export_error(const char *error)
static long gbcm_read_buffered(int socket, char *ptr, long size)
GB_ERROR GB_await_error()
#define TEST_EXPECT(cond)
const char * GBS_read_arb_tcp(const char *env)
GBCM_ServerResult gbcm_read_two(int socket, long a, long *b, long *c)
void GB_warningf(const char *templat,...)
GB_CSTR GB_append_suffix(const char *name, const char *suffix)
static char * use_other_path_buf()
static GB_CSTR GB_getenvHOME()
void GBS_hash_do_const_loop(const GB_HASH *hs, gb_hash_const_loop_type func, void *client_data)
GB_CSTR GB_read_sync_value(GBDATA *gb_main, const char *id)
void GBK_terminate(const char *error) __ATTR__NORETURN
char * GB_unique_filename(const char *name_prefix, const char *suffix)
long gbcm_read(int socket, char *ptr, long size)
GB_ERROR GB_save_as(GBDATA *gbd, const char *path, const char *savetype)
GB_ERROR GB_write_sync_value(GBDATA *gb_main, const char *id, const char *value)
GB_ERROR gbcm_open_socket(const char *path, bool do_connect, int *psocket, char **unix_name)
const char * GBS_readable_size(unsigned long long size, const char *unit_suffix)
static char * GB_find_executable(GB_CSTR description_of_executable,...)
#define TEST_REJECT(cond)
void GB_atexit(void(*exitfun)())
long gbcm_read_long(int socket)
static void error(const char *msg)
expectation_group & add(const expectation &e)
char * GB_create_tempfile(const char *name)
GB_CSTR GB_getenvARBMACRO()
static GB_CSTR GB_path_in_arb_temp(const char *relative_path)
GB_CSTR GB_concat_path(GB_CSTR anypath_left, GB_CSTR anypath_right)
bool is_name_of_envvar(const char *name)
static char * getenv_existing_directory(GB_CSTR envvar)
static GB_CSTR GB_concat_path_in_ARBHOME(const char *relative_path_left, const char *anypath_right)
GBCM_ServerResult gbcm_write_string(int socket, const char *key)
bool GB_host_is_local(const char *hostname)
const char *(* gb_getenv_hook)(const char *varname)
static gb_getenv_hook getenv_hook
CONSTEXPR_INLINE bool valid(SpeciesCreationMode m)
static GBDATA * find_or_create_sync_data(GBDATA *gb_main)
long gbcm_write_two(int socket, long a, long c)
FILE * GB_fopen_tempfile(const char *filename, const char *fmode, char **res_fullname)
void GBS_reuse_buffer(const char *global_buffer)
GB_CSTR GB_getenvDOCPATH()
GB_CSTR GB_getenvARB_GS()
GB_ERROR GB_set_temporary(GBDATA *gbd) __ATTR__USERESULT
GB_ERROR GB_export_errorf(const char *templat,...)
void GB_internal_error(const char *message)
GB_CSTR GB_getenvARB_XTERM()
TYPE * ARB_calloc(size_t nelem)
static void exit_removal()
char * GBK_singlequote(const char *arg)
GB_CSTR GB_concat_path_in_ARBLIB(const char *relative_path_left, const char *anypath_right)
void GB_remove_on_exit(const char *filename)
bool GB_is_directory(const char *path)
char ARB_path_contains_unwanted_chars(const char *path)
GB_ERROR GB_failedTo_error(const char *do_something, const char *special, GB_ERROR error)
char * GB_map_FILE(FILE *in, int writeable)
GB_CSTR GB_canonical_path(const char *anypath)
GBDATA * GBT_create(GBDATA *father, const char *key, long delete_level)
static GB_HASH * files_to_remove_on_exit
#define TEST_EXPECT_NO_ERROR(call)
char * GBS_eval_env(GB_CSTR p)
static export_environment expenv
void GB_informationf(const char *templat,...)
gbcmc_comm * gbcmc_open(const char *path)
bool ARB_strBeginsWith(const char *str, const char *with)
static GB_ULONG parse_env_mem_definition(const char *env_override, GB_ERROR &error)
GB_CSTR GB_getenvARBMACROHOME()
char * GB_map_file(const char *path, int writeable)
GB_transaction ta(gb_var)
GB_CSTR GB_path_in_ARBHOME(const char *relative_path)
bool is_absolute_path(const char *path)
GB_CSTR GB_read_char_pntr(GBDATA *gbd)
GB_CSTR GB_getenvARB_XCMD()
char * GB_read_fp(FILE *in)
GBDATA * GBT_find_or_create_item_rel_item_data(GBDATA *gb_item_data, const char *itemname, const char *id_field, const char *id, bool markCreated)
#define TEST_EXPECT_EQUAL(expr, want)
char * release_memfriendly()
GBDATA * GB_entry(GBDATA *father, const char *key)
GB_ERROR GB_create_directory(const char *path)
long gbcms_close(gbcmc_comm *link)
char * GBS_global_string_copy(const char *templat,...)
void GB_close(GBDATA *gbd)
GB_CSTR GB_getenvARB_PDFVIEW()
GB_CSTR GB_path_in_arbprop(const char *relative_path)
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)