diff --git a/configure.ac b/configure.ac index 90164cfe0..6bfd89c95 100644 --- a/configure.ac +++ b/configure.ac @@ -466,6 +466,14 @@ PKG_CHECK_MODULES(E_THUMB, [ efreet >= ${efl_version} ]) +PKG_CHECK_MODULES(E_GRABBER, [ + eina >= ${efl_version} + ecore >= ${efl_version} + eet >= ${efl_version} + efreet >= ${efl_version} + ecore-x >= ${efl_version} +]) + efm_requires="\ ecore >= 1.2.0 \ ecore-file >= 1.2.0 \ diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am index 5772dc051..91dfc9b74 100644 --- a/src/bin/Makefile.am +++ b/src/bin/Makefile.am @@ -33,7 +33,8 @@ enlightenment_fm_op \ enlightenment_init \ enlightenment_sys \ enlightenment_thumb \ -enlightenment_alert +enlightenment_alert \ +enlightenment_static_grabber if HAVE_EEZE internal_bin_PROGRAMS += enlightenment_backlight @@ -426,6 +427,10 @@ enlightenment_open_SOURCES = e_open.c enlightenment_open_LDADD = @E_OPEN_LIBS@ enlightenment_open_CFLAGS = @E_OPEN_CFLAGS@ +enlightenment_static_grabber_SOURCES = e_static_grab.c +enlightenment_static_grabber_LDADD = @E_GRABBER_LIBS@ +enlightenment_static_grabber_CFLAGS = @E_GRABBER_CFLAGS@ + # HACK! why install-data-hook? install-exec-hook is run after bin_PROGRAMS # and before internal_bin_PROGRAMS are installed. install-data-hook is # run after both diff --git a/src/bin/e_static_grab.c b/src/bin/e_static_grab.c new file mode 100644 index 000000000..e3f5b41e1 --- /dev/null +++ b/src/bin/e_static_grab.c @@ -0,0 +1,465 @@ +#include +#include + +typedef struct _E_Static_Grab E_Static_Grab; +typedef struct _E_Static_Grab_Module E_Static_Grab_Module; + +struct _E_Static_Grab +{ + struct + { + int core_count; + int thread_count; + int bogo; + int model; + int family; + int stepping; + int cache_size; + int addr_space; + + const char *vendor; + const char *model_name; + + Eina_Bool fpu; + } cpu; + + struct + { + const char *name; + const char *release; + const char *os; + const char *kernel_release; + } distribution; + + struct { + struct + { + const char *vendor; + const char *renderer; + const char *version; + } gpu; + + const char *name; + const char *release_date; + const char *build_date; + + Eina_List *modules; + } x; +}; + +struct _E_Static_Grab_Module +{ + const char *name; + const char *vendor; + const char *compiled_for; + const char *version; + const char *class; + const char *ABI_class; + const char *ABI_version; +}; + +/* For /proc/cpuinfo */ +#define CPU_CORES "cpu cores" +#define CACHE_SIZE "cache size" +#define CPU_FAMILY "cpu family" +#define STEPPING "stepping" +#define SIBLINGS "siblings" +#define BOGOMIPS "bogomips" +#define MODEL "model" +#define MODEL_NAME "model name" +#define VENDOR_ID "vendor_id" +#define FPU "fpu" + +/* For /var/log/Xorg.0.log */ +#define RELEASE_DATE "Release Date" +#define BUILD_DATE "Build Date" +#define LOAD_MODULE "(II) LoadModule" +#define UNLOAD_MODULE "(II) UnloadModule" +#define MODULE_OF "(II) Module %s" +#define LOADING "(II) Loading" +#define VENDOR "vendor=\"" +#define COMPILED "compiled for " +#define MODULE_CLASS "Module class" +#define ABI_CLASS "ABI class" +#define VERSION ", version " + +static const char * +_e_static_grab_name(const char *line, const char *end, const char *name) +{ + size_t l; + + l = strlen(name); + if (line + l + 3 > end) return end; + if (strncmp(name, line, l)) return end; + + return line + l; +} + +static Eina_Bool +_e_static_grab_int(const char *line, const char *end, const char *txt, int *v) +{ + static const char *value = "0123456789"; + const char *over; + int r = 0; + + over = _e_static_grab_name(line, end, txt); + while (over < end) + { + if (strchr(value, *over)) break; + over++; + } + if (over == end) return EINA_FALSE; + + while (over < end) + { + const char *offset = strchr(value, *over); + + if (!offset) break; + r = r * 10 + (offset - value); + + over++; + } + + *v = r; + + return EINA_TRUE; +} + +static Eina_Bool +_e_static_grab_string(const char *line, const char *end, const char *txt, const char **s) +{ + static const char *value = " :\t"; + const char *over; + + over = _e_static_grab_name(line, end, txt); + while (over < end) + { + if (!strchr(value, *over)) break; + over++; + } + if (over == end) return EINA_FALSE; + + if (*over == '"' && *(end - 2) == '"') + { + over++; + end--; + } + + *s = eina_stringshare_add_length(over, end - over - 1); + return EINA_TRUE; +} + +static const char * +_e_static_grab_discard(const char *current, Eina_File_Line *line, int begin, int end) +{ + while (current < line->end && + strchr(" \t", *current)) + current++; + + if (*current != begin) return current; + + while (current < line->end && + *current != end) + current++; + + if (current == line->end) return current; + + for (current++; + current < line->end && strchr(" \t", *current); + current++) + ; + + return current; +} + +static void +_e_static_grab_cpu(E_Static_Grab *grab) +{ + char buf[4096]; + FILE *f; + const char *fpu = NULL; + int siblings = 0; + + grab->cpu.addr_space = sizeof (void*); + + f = fopen("/proc/cpuinfo", "r"); + if (!f) return ; + + while (!feof(f)) + { + char *end; + size_t length = 0; + size_t start = 0; + + fgets(buf, sizeof (buf), f); + length = strlen(buf); + end = buf + length; + + if (length < 3) continue ; + + switch (*buf) + { + case 'c': + if (_e_static_grab_int(buf, end, CPU_CORES, &grab->cpu.core_count)) break; + if (_e_static_grab_int(buf, end, CACHE_SIZE, &grab->cpu.cache_size)) break; + _e_static_grab_int(buf, end, CPU_FAMILY, &grab->cpu.family); + break; + case 's': + if (_e_static_grab_int(buf, end, STEPPING, &grab->cpu.stepping)) break; + _e_static_grab_int(buf, end, SIBLINGS, &siblings); + break; + case 'b': + _e_static_grab_int(buf, end, BOGOMIPS, &grab->cpu.bogo); + break; + case 'm': + if (_e_static_grab_string(buf, end, MODEL_NAME, &grab->cpu.model_name)) break; + _e_static_grab_int(buf, end, MODEL, &grab->cpu.model); + break; + case 'v': + _e_static_grab_string(buf, end, VENDOR_ID, &grab->cpu.vendor); + break; + case 'f': + _e_static_grab_string(buf, end, FPU, &fpu); + break; + } + } + fclose(f); + + if (siblings) grab->cpu.thread_count = siblings / grab->cpu.core_count; + if (fpu) + { + if (!strcmp(fpu, "yes")) grab->cpu.fpu = EINA_TRUE; + eina_stringshare_del(fpu); + } +} + +static void +_e_static_grab_x(E_Static_Grab *grab) +{ + Eina_Bool in_module = EINA_FALSE; + E_Static_Grab_Module *module; + Eina_File_Line *line; + Eina_Iterator *it; + Eina_File *f; + + module = calloc(1, sizeof (E_Static_Grab_Module)); + if (!module) return ; + + f = eina_file_open("/var/log/Xorg.0.log", EINA_FALSE); + if (!f) return ; + + it = eina_file_map_lines(f); + EINA_ITERATOR_FOREACH(it, line) + { + const char *current; + + current = _e_static_grab_discard(line->start, line, '[', ']'); + if (current >= line->end) continue ; + + if (!grab->x.name) + { + if (line->end - current - 1 <= 0) continue ; + grab->x.name = eina_stringshare_add_length(current, line->end - current - 1); + continue ; + } + + if (!in_module) + { + switch (*current) + { + case 'R': + if (_e_static_grab_string(current, line->end, RELEASE_DATE, &grab->x.release_date)) break; + break; + + case 'B': + if (_e_static_grab_string(current, line->end, BUILD_DATE, &grab->x.build_date)) break; + break; + + case '(': + { + E_Static_Grab_Module *md; + Eina_List *l; + const char *tmp; + + if (_e_static_grab_string(current, line->end, LOAD_MODULE, &module->name)) + { + EINA_LIST_FOREACH(grab->x.modules, l, md) + if (md->name == module->name) + { + eina_stringshare_del(module->name); + module->name = NULL; + break; + } + + if (module->name) in_module = EINA_TRUE; + break; + } + else if (_e_static_grab_string(current, line->end, UNLOAD_MODULE, &tmp)) + { + EINA_LIST_FOREACH(grab->x.modules, l, md) + if (md->name == tmp) + { + grab->x.modules = eina_list_remove_list(grab->x.modules, l); + + eina_stringshare_del(md->name); + eina_stringshare_del(md->vendor); + eina_stringshare_del(md->compiled_for); + eina_stringshare_del(md->version); + eina_stringshare_del(md->class); + eina_stringshare_del(md->ABI_class); + eina_stringshare_del(md->ABI_version); + free(md); + break; + } + eina_stringshare_del(tmp); + } + break; + } + } + } + else + { + char *buffer; + Eina_Bool found = EINA_FALSE; + + switch (*current) + { + case '(': + { + const char *vendor; + + if (strncmp(current, LOADING, strlen(LOADING)) == 0) + { + found = EINA_TRUE; + break; + } + + buffer = alloca(strlen(MODULE_OF) + strlen(module->name)); + sprintf(buffer, MODULE_OF, module->name); + + if (_e_static_grab_string(current, line->end, buffer, &vendor)) + { + if (strncmp(vendor, VENDOR, strlen(VENDOR)) == 0) + { + module->vendor = eina_stringshare_add_length(vendor + strlen(VENDOR), + eina_stringshare_strlen(vendor) - strlen(VENDOR) - 1); + found = EINA_TRUE; + } + eina_stringshare_del(vendor); + } + break; + } + case 'c': + if (strncmp(current, COMPILED, strlen(COMPILED)) == 0) + { + const char *lookup = current + strlen(COMPILED); + + while (lookup < line->end && *lookup != ',') + lookup++; + + module->compiled_for = eina_stringshare_add_length(current + strlen(COMPILED), + lookup - current - strlen(COMPILED)); + found = EINA_TRUE; + break; + } + break; + case 'M': + if (_e_static_grab_string(current, line->end, MODULE_CLASS, &module->class)) + { + found = EINA_TRUE; + break; + } + break; + case 'A': + { + const char *tmp; + + if (_e_static_grab_string(current, line->end, ABI_CLASS, &tmp)) + { + const char *lookup = strchr(tmp, ','); + + if (lookup) + { + module->ABI_class = eina_stringshare_add_length(tmp, lookup - tmp); + if (strncmp(lookup, VERSION, strlen(VERSION)) == 0) + { + module->ABI_version = eina_stringshare_add_length(lookup + strlen(VERSION), + eina_stringshare_strlen(tmp) - (lookup - tmp + strlen(VERSION) - 1)); + } + eina_stringshare_del(tmp); + } + else + { + module->ABI_class = tmp; + } + } + break; + } + } + + if (!found) + { + in_module = EINA_FALSE; + grab->x.modules = eina_list_append(grab->x.modules, module); + module = calloc(1, sizeof (E_Static_Grab_Module)); + } + } + } + + free(module); + + eina_iterator_free(it); + eina_file_close(f); +} + +int +main(int argc, char **argv) +{ + E_Static_Grab_Module *module; + Eina_List *l; + E_Static_Grab grab; + const char *output; + + if (argc != 2) exit(0); + +#if 0 + /* FIXME: Latter push information into an eet file when updated */ + if ((!strcmp(argv[1], "-h")) || + (!strcmp(argv[1], "-help")) || + (!strcmp(argv[1], "--help"))) + { + printf("This is an internal tool for Enlightenment.\n" + "do not use it.\n"); + exit(0); + } +#endif + + eina_init(); + eet_init(); + + output = argv[1]; + + memset(&grab, 0, sizeof (grab)); + _e_static_grab_cpu(&grab); /* FIXME: please provide patch for more Unix */ + _e_static_grab_x(&grab); + + fprintf(stderr, "%i core with %i thread running in %i bits at %i bogomips with %i cache from vendor %s with model %s\n", + grab.cpu.core_count, grab.cpu.thread_count, grab.cpu.addr_space * 8, grab.cpu.bogo, grab.cpu.cache_size, grab.cpu.vendor, grab.cpu.model_name); + fprintf(stderr, "X Server: '%s' released '%s' and build '%s'\n", + grab.x.name, grab.x.release_date, grab.x.build_date); + fprintf(stderr, "*** X Modules ***\n"); + EINA_LIST_FOREACH(grab.x.modules, l, module) + fprintf(stderr, "[%s - '%s' - '%s' - '%s' - '%s','%s' ]\n", + module->name, module->vendor, module->compiled_for, + module->class, module->ABI_class, module->ABI_version); + fprintf(stderr, "*** ***\n"); + + /* FIXME: Get information about what Unix (Linux, BSD, ...) it is run on */ + /* FIXME: run a mainloop and start gathering result from df, free, lspci and lsusb */ + /* FIXME: use xrandr to figure out the screen config */ + + eet_shutdown(); + eina_shutdown(); + + return 0; +}