18 #include <netinet/tcp.h>
21 #include <sys/socket.h>
27 # include <sys/sysctl.h>
65 fprintf(stderr,
"Cannot read data from client: len=%li (%s, errno %i)\n",
66 holding, strerror(errno), errno);
72 if (size>holding) size = holding;
83 if (readsize<=0)
return 0;
104 writesize = send(socket, ptr, leftsize, MSG_NOSIGNAL);
106 writesize = write(socket, ptr, leftsize);
112 "Client (pid=%i) terminating after failure to contact database (%s).",
113 getpid(), strerror(errno));
117 fprintf(stderr,
"Error sending data to client (%s).", strerror(errno));
122 leftsize -= writesize;
145 if (path && strcmp(path,
":") == 0) {
191 if (!socket)
return 1;
192 return gbcm_write(socket, (
const char *)ia,
sizeof(
long)*3);
205 size =
gbcm_read(socket, (
char *)&(ia[0]),
sizeof(
long)*3);
206 if (size !=
sizeof(
long) * 3) {
208 sizeof(
long) * 3, size, a);
230 size_t len = strlen(key);
261 gbcm_write(socket, (
char*)&data,
sizeof(data));
267 gbcm_read(socket, (
char*)&data,
sizeof(data));
281 while (EOF != (c = getc(in))) {
296 if (strcmp(path,
"-") == 0) {
303 FILE *in = fopen(epath,
"rt");
309 if (data_size >= 0) {
310 result = ARB_alloc<char>(data_size+1);
312 data_size = fread(result, 1, data_size, in);
313 result[data_size] = 0;
332 buffer = (
char*)mmap(
NULp, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fi, 0);
335 buffer = (
char*)mmap(
NULp, size, PROT_READ, MAP_SHARED, fi, 0);
337 if (buffer == MAP_FAILED) {
338 GB_export_errorf(
"GB_map_file: Error: Out of Memory: mmap failed (errno: %i)", errno);
347 in = fopen(path,
"r");
359 if (gettimeofday(&tp,
NULp))
return 0;
378 static const char *path =
NULp;
383 GB_informationf(
"Your PATH variable is empty - using '%s' as search path.", path);
387 if (!strstr(path, arbbin)) {
388 GB_warningf(
"Your PATH variable does not contain '%s'. Things may not work as expected.", arbbin);
410 va_start(args, description_of_executable);
421 va_start(args, description_of_executable);
422 while ((name = va_arg(args,
GB_CSTR))) {
423 if (!first) buf.
cat(
", ");
431 msg =
GBS_global_string_copy(
"Could not find a %s (looked for: %s)", description_of_executable, looked_for);
439 char *description =
GBS_global_string_copy(
"the %s derived from environment variable PATH", description_of_executable);
443 GB_informationf(
"Using %s '%s' ('%s')", description_of_executable, name, found);
470 if (!strncasecmp(exe_name,
"open", 4)) {
477 GB_warningf(
"Environment variable '%s' contains '%s' (which is not an executable)", envvar, exe_name);
481 char *description =
GBS_global_string_copy(
"the executable derived from environment variables '%s' and PATH", envvar);
503 char *description =
GBS_global_string_copy(
"the directory derived from environment variable '%s'", envvar);
509 GB_warningf(
"Environment variable '%s' should contain the path of an existing directory.\n"
510 "(current content '%s' has been ignored.)", envvar, dir_name);
516 static void GB_setenv(
const char *var,
const char *value) {
517 if (setenv(var, value, 1) != 0) {
518 GB_warningf(
"Could not set environment variable '%s'. This might cause problems in subprocesses.\n"
519 "(Reason: %s)", var, strerror(errno));
524 static const char *xterm =
NULp;
527 if (!xterm) xterm =
"xterm -sl 1000 -sb -geometry 150x60";
533 static const char *xcmd =
NULp;
546 static const char *user =
NULp;
552 if (user && strrchr(user,
'/')) user = strrchr(user,
'/')+1;
555 fprintf(stderr,
"WARNING: Cannot identify user: environment variables USER, LOGNAME and HOME not set\n");
556 user =
"UnknownUser";
564 static SmartCharPtr Home;
570 fprintf(stderr,
"WARNING: Cannot identify user's home directory: environment variable HOME not set\n"
571 "Using current directory (%s) as home.\n", home);
580 static SmartCharPtr Arbhome;
581 if (Arbhome.isNull()) {
584 fprintf(stderr,
"Fatal ERROR: Environment Variable ARBHOME not found !!!\n"
585 " Please set 'ARBHOME' to the installation path of ARB\n");
594 static const char *am =
NULp;
610 char *description =
GBS_global_string_copy(
"the default directory expanded from expression '%s'", defaultDirectory);
623 static SmartCharPtr ArbProps;
629 static SmartCharPtr ArbMacroHome;
631 return &*ArbMacroHome;
635 static SmartCharPtr ArbConfig;
641 static const char *gs =
NULp;
660 static const char *pdfview =
NULp;
669 pdfview =
GB_find_executable(
"PDF viewer",
"xreader",
"epdfview",
"xpdf",
"kpdf",
"acroread",
"gv",
NULp);
677 static const char *dp =
NULp;
687 static const char *dp =
NULp;
712 if (result)
return result;
714 if (strncmp(env,
"ARB", 3) == 0) {
760 static GB_ULONG physical_memsize = 0;
761 if (!physical_memsize) {
765 long pagesize = sysconf(_SC_PAGESIZE);
766 long pages = sysconf(_SC_PHYS_PAGES);
768 memsize = (pagesize/1024) * pages;
770 #elif defined(DARWIN)
771 #warning memsize detection needs to be tested for Darwin
780 sysctl(mib, 2, &bytes, &len,
NULp, 0);
782 memsize = bytes/1024;
787 "Warning: ARB is not prepared to detect the memory size on your system!\n"
788 " (it assumes you have %ul Mb, but does not use more)\n\n", memsize/1024);
791 GB_ULONG net_memsize = memsize - 10240;
794 GB_ULONG max_malloc_try = net_memsize*1024;
802 while ((tmp=(
void**)malloc(step_size))) {
805 max_malloc += step_size;
806 if (max_malloc >= max_malloc_try)
break;
809 }
while ((step_size=step_size/2) >
sizeof(
void*));
811 while (head) freeset(head, *(
void**)head);
815 physical_memsize =
std::min(net_memsize, max_malloc);
817 #if defined(DEBUG) && 0
818 printf(
"- memsize(real) = %20lu k\n", memsize);
819 printf(
"- memsize(net) = %20lu k\n", net_memsize);
820 printf(
"- memsize(max_malloc) = %20lu k\n", max_malloc);
827 return physical_memsize;
832 GB_ULONG num = strtoul(env_override, const_cast<char**>(&end), 10);
836 bool valid = num>0 || env_override[0] ==
'0';
838 const char *formatSpec = end;
841 switch (tolower(formatSpec[0])) {
855 default: valid =
false;
break;
858 if (valid)
return GB_ULONG(num*factor+0.5);
861 error =
"expected digits (optionally followed by k, M, G or %)";
869 if (!useable_memory) {
870 bool allow_fallback =
true;
871 const char *env_override =
GB_getenv(
"ARB_MEMORY");
872 const char *via_whom;
874 via_whom =
"via envar ARB_MEMORY";
878 env_override =
"90%";
879 via_whom =
"by internal default";
880 allow_fallback =
false;
888 GB_warningf(
"Ignoring invalid setting '%s' %s (%s)", env_override, via_whom, env_error);
889 if (allow_fallback)
goto FALLBACK;
894 if (!allow_fallback) {
895 GB_informationf(
"Note: Setting envar ARB_MEMORY will override that restriction (percentage or absolute memsize)");
897 useable_memory = env_memory;
900 return useable_memory;
921 system_call.
put(
'(');
922 system_call.
cat(xcmd);
931 bash_command.
cat(
"LD_LIBRARY_PATH=");
934 bash_command.
cat(dquoted_library_path);
935 free(dquoted_library_path);
937 bash_command.
cat(
";export LD_LIBRARY_PATH;");
943 bash_command.
cat(
"echo 'Warning: LD_LIBRARY_PATH is undefined';");
947 bash_command.
cat(
" (");
948 bash_command.
cat(cmd);
950 const char *wait_commands =
"echo; echo Press ENTER to close this window; read a";
951 if (wait_only_if_error) {
952 bash_command.
cat(
") || (");
953 bash_command.
cat(wait_commands);
955 else if (background) {
956 bash_command.
cat(
"; ");
957 bash_command.
cat(wait_commands);
959 bash_command.
put(
')');
961 system_call.
cat(
" bash -c ");
963 system_call.
cat(squoted_bash_command);
964 free(squoted_bash_command);
966 system_call.
cat(
" )");
967 if (background) system_call.
cat(
" &");
992 while (suffix[0] ==
'.') suffix++;
1011 else if (!anypath[0]) {
1018 if (anypath[0] ==
'~' && (!anypath[1] || anypath[1] ==
'/')) {
1025 result = realpath(anypath, path_buf[1-path_toggle]);
1031 char *dir, *fullname;
1034 const char *canonical_dir =
NULp;
1046 if (strcmp(fullname,
"..") == 0) {
1054 else if (strcmp(fullname,
".") == 0) {
1055 result = canonical_dir;
1080 if (anypath_right) {
1081 if (anypath_right[0] ==
'/') {
1084 else if (anypath_left && anypath_left[0]) {
1085 if (anypath_left[strlen(anypath_left)-1] ==
'/') {
1093 result = anypath_right;
1097 result = anypath_left;
1116 for (
int i = 0; name[i]; ++i) {
1117 if (isalnum(name[i]) || name[i] ==
'_')
continue;
1174 #define GB_PATH_TMP GB_path_in_arb_temp("tmp") // = "~/.arb_tmp/tmp" (used wherever '/tmp' was used in the past)
1192 bool write = strpbrk(fmode,
"wa");
1194 fp = fopen(file, fmode);
1197 if (fchmod(fileno(fp), S_IRUSR|S_IWUSR) != 0) {
1198 error =
GB_IO_error(
"changing permissions of", file);
1212 if (fp) { fclose(fp); fp =
NULp; }
1213 if (file) unlink(file);
1229 if (out) fclose(out);
1247 if (unlink(file) != 0) {
1248 fprintf(stderr,
"Warning: %s\n",
GB_IO_error(
"removing", file));
1252 if (files_to_remove_on_exit) {
1255 files_to_remove_on_exit =
NULp;
1261 if (!files_to_remove_on_exit) {
1268 void GB_split_full_path(
const char *fullpath,
char **res_dir,
char **res_fullname,
char **res_name_only,
char **res_suffix) {
1289 if (fullpath && fullpath[0]) {
1290 const char *lslash = strrchr(fullpath,
'/');
1291 const char *name_start = lslash ? lslash+1 : fullpath;
1292 const char *ldot = strrchr(lslash ? lslash : fullpath,
'.');
1293 const char *terminal = strchr(name_start, 0);
1299 if (!lslash && fullpath[0] ==
'.' && (fullpath[1] == 0 || (fullpath[1] ==
'.' && fullpath[2] == 0))) {
1300 if (res_dir) *res_dir =
ARB_strdup(fullpath);
1301 if (res_fullname) *res_fullname =
NULp;
1302 if (res_name_only) *res_name_only =
NULp;
1303 if (res_suffix) *res_suffix =
NULp;
1306 if (res_dir) *res_dir = lslash ?
ARB_strpartdup(fullpath, lslash == fullpath ? lslash : lslash-1) :
NULp;
1307 if (res_fullname) *res_fullname =
ARB_strpartdup(name_start, terminal-1);
1308 if (res_name_only) *res_name_only =
ARB_strpartdup(name_start, ldot ? ldot-1 : terminal-1);
1313 if (res_dir) *res_dir =
NULp;
1314 if (res_fullname) *res_fullname =
NULp;
1315 if (res_name_only) *res_name_only =
NULp;
1316 if (res_suffix) *res_suffix =
NULp;
1327 #define TEST_EXPECT_IS_CANONICAL(file) \
1329 char *dup = ARB_strdup(file); \
1330 TEST_EXPECT_EQUAL(GB_canonical_path(dup), dup); \
1334 #define TEST_EXPECT_CANONICAL_TO(not_cano,cano) \
1336 char *arb_not_cano = ARB_strdup(GB_concat_path(arbhome, not_cano)); \
1337 char *arb_cano = ARB_strdup(GB_concat_path(arbhome, cano)); \
1338 TEST_EXPECT_EQUAL(GB_canonical_path(arb_not_cano), arb_cano); \
1340 free(arb_not_cano); \
1343 static arb_test::match_expectation path_splits_into(
const char *path,
const char *Edir,
const char *Enameext,
const char *Ename,
const char *Eext) {
1347 char *Sdir,*Snameext,*Sname,*Sext;
1360 return all().ofgroup(expected);
1363 #define TEST_EXPECT_PATH_SPLITS_INTO(path,dir,nameext,name,ext) TEST_EXPECTATION(path_splits_into(path,dir,nameext,name,ext))
1364 #define TEST_EXPECT_PATH_SPLITS_INTO__BROKEN(path,dir,nameext,name,ext) TEST_EXPECTATION__BROKEN(path_splits_into(path,dir,nameext,name,ext))
1370 char *Sdir,*Snameext,*Sname,*Sext;
1381 return all().ofgroup(expected);
1384 #define TEST_SPLIT_REVERSIBILITY(path) TEST_EXPECTATION(path_splits_reversible(path))
1385 #define TEST_SPLIT_REVERSIBILITY__BROKEN(path) TEST_EXPECTATION__BROKEN(path_splits_reversible(path))
1396 TEST_EXPECT_PATH_SPLITS_INTO(
"dir/sub/.ext",
"dir/sub",
".ext",
"",
"ext");
1397 TEST_EXPECT_PATH_SPLITS_INTO(
"/root/sub/file.notext.ext",
"/root/sub",
"file.notext.ext",
"file.notext",
"ext");
1399 TEST_EXPECT_PATH_SPLITS_INTO(
"./file.ext",
".",
"file.ext",
"file",
"ext");
1400 TEST_EXPECT_PATH_SPLITS_INTO(
"/file",
"/",
"file",
"file",
NULp);
1401 TEST_EXPECT_PATH_SPLITS_INTO(
".",
".",
NULp,
NULp,
NULp);
1405 const char *prefix[] = {
1423 TEST_SPLIT_REVERSIBILITY(prefix[d]);
1434 const char* nosuchfile =
"nosuchfile";
1435 const char* somefile =
"arb_README.txt";
1446 TEST_EXPECT_IS_CANONICAL(somefile_in_arbhome);
1447 TEST_EXPECT_IS_CANONICAL(nosuchpath_in_arbhome);
1448 TEST_EXPECT_IS_CANONICAL(file_in_nosuchpath);
1450 TEST_EXPECT_IS_CANONICAL(
"/usr");
1451 #if !defined(DARWIN)
1453 TEST_EXPECT_IS_CANONICAL(
"/tmp/arbtest.fig");
1455 TEST_EXPECT_IS_CANONICAL(
"/arbtest.fig");
1457 TEST_EXPECT_CANONICAL_TO(
"./PARSIMONY/./../ARBDB/./arbdb.h",
"ARBDB/arbdb.h");
1458 TEST_EXPECT_CANONICAL_TO(
"INCLUDE/arbdb.h",
"ARBDB/arbdb.h");
1459 TEST_EXPECT_CANONICAL_TO(
"NAMES_COM/AISC/aisc.pa",
"AISC_COM/AISC/aisc.pa");
1460 TEST_EXPECT_CANONICAL_TO(
"./NAMES_COM/AISC/..",
"AISC_COM");
1462 TEST_EXPECT_CANONICAL_TO(
"./PARSIMONY/./../ARBDB/../nosuchpath",
"nosuchpath");
1464 TEST_EXPECT_CANONICAL_TO(
"./PARSIMONY/./../nosuchpath/../ARBDB",
"ARBDB");
1465 TEST_EXPECT_CANONICAL_TO(
"./nosuchpath/./../ARBDB",
"ARBDB");
1491 free(file_in_nosuchpath);
1492 free(somepath_in_arbhome);
1493 free(nosuchpath_in_arbhome);
1494 free(nosuchfile_in_arbhome);
1495 free(somefile_in_arbhome);
1507 bool open(
const char *mode) {
1508 FILE *out = fopen(name, mode);
1509 if (out) fclose(out);
1513 void unlink() { ::unlink(name); }
1515 TestFile(
const char *name_) : name(name_) { create(); }
1516 ~TestFile() {
if (exists()) unlink(); }
1517 const char *get_name()
const {
return name; }
1518 bool exists() {
return open(
"r"); }
1521 void TEST_GB_remove_on_exit() {
1524 TestFile file(
"test1");
1530 TestFile t(
"test1");
1541 void TEST_some_paths() {
1558 #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)
static void GB_setenv(const char *var, const char *value)
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)
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()
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,...)
char * GBK_doublequote(const char *arg)
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_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)
static GB_CSTR GB_getenvARB_XCMD()
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)
long GB_size_of_file(const char *path)
static GB_CSTR GB_getenvPATH()
#define ARRAY_ELEMS(array)
char buffer[MESSAGE_BUFFERSIZE]
NOT4PERL GB_ERROR GB_xcmd(const char *cmd, XCMD_TYPE exectype)
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)
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 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)
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_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)
static GB_HASH * files_to_remove_on_exit
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)
const char * get_data() const
GB_CSTR GB_getenvARBMACROHOME()
char * GB_map_file(const char *path, int writeable)
GB_CSTR GB_path_in_ARBHOME(const char *relative_path)
bool is_absolute_path(const char *path)
char * GB_read_fp(FILE *in)
#define TEST_EXPECT_EQUAL(expr, want)
char * release_memfriendly()
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)