summaryrefslogtreecommitdiff
path: root/default.c
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-12-07 02:53:31 -0800
committerAnas Nashif <anas.nashif@intel.com>2012-12-07 02:53:31 -0800
commitcbb6286cb92020dd7ae88798ed831ed76fd2130e (patch)
tree782a01c00d5e064aa67ea3f9241a8ef1de1060c6 /default.c
downloadlinks-cbb6286cb92020dd7ae88798ed831ed76fd2130e.tar.gz
links-cbb6286cb92020dd7ae88798ed831ed76fd2130e.tar.bz2
links-cbb6286cb92020dd7ae88798ed831ed76fd2130e.zip
Imported Upstream version 2.6upstream/2.6upstream
Diffstat (limited to 'default.c')
-rw-r--r--default.c2069
1 files changed, 2069 insertions, 0 deletions
diff --git a/default.c b/default.c
new file mode 100644
index 0000000..db1d815
--- /dev/null
+++ b/default.c
@@ -0,0 +1,2069 @@
+/* default.c
+ * (c) 2002 Mikulas Patocka, Petr 'Brain' Kulhavy
+ * This file is a part of the Links program, released under GPL
+ *
+ * Does the configuration file.
+ */
+
+#include "links.h"
+
+unsigned char system_name[MAX_STR_LEN];
+
+static void get_system_name(void)
+{
+#ifdef OS2
+ if (!os_get_system_name(system_name))
+ return;
+#endif
+#if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
+ {
+ struct utsname name;
+ int rs;
+ memset(&name, 0, sizeof name);
+ EINTRLOOP(rs, uname(&name));
+ if (!rs) {
+ unsigned char *str = init_str();
+ int l = 0;
+ add_to_str(&str, &l, name.sysname);
+ add_to_str(&str, &l, " ");
+ add_to_str(&str, &l, name.release);
+ add_to_str(&str, &l, " ");
+ add_to_str(&str, &l, name.machine);
+ if (l >= MAX_STR_LEN) str[MAX_STR_LEN - 1] = 0;
+ strcpy(system_name, str);
+ mem_free(str);
+ return;
+ }
+ }
+#endif
+#ifdef HAVE_POPEN
+ if (0) {
+ FILE *f;
+ unsigned char *p;
+ memset(system_name, 0, MAX_STR_LEN);
+ ENULLLOOP(f, popen("uname -srm", "r"));
+ if (!f) goto fail;
+ if (fread(system_name, 1, MAX_STR_LEN - 1, f) <= 0) {
+ pclose(f);
+ goto fail;
+ }
+ pclose(f);
+ for (p = system_name; *p; p++) if (*p < ' ') {
+ *p = 0;
+ break;
+ }
+ if (system_name[0]) return;
+ }
+ fail:
+#endif
+ strcpy(system_name, SYSTEM_NAME);
+}
+
+unsigned char compiler_name[MAX_STR_LEN];
+
+static void get_compiler_name(void)
+{
+#if defined(__BORLANDC__)
+
+ int w = __BORLANDC__+0;
+ int v1 = w / 0x100;
+ int v2 = w / 0x10 % 0x10;
+ int v3 = w % 0x10;
+ if (v1 == 4 && v2 < 5) v1 = 3;
+ if (v1 == 4 && v2 == 5) v2 = 0;
+
+ if (!v3) sprintf(compiler_name, "Borland C %d.%d", v1, v2);
+ else sprintf(compiler_name, "Borland C %d.%d.%d", v1, v2, v3);
+
+#elif defined(__clang__)
+
+#if !defined(__clang_major__) || !defined(__clang_minor__)
+ sprintf(compiler_name, "LLVM/Clang");
+#else
+ int v1 = __clang_major__+0;
+ int v2 = __clang_minor__+0;
+#ifdef __clang_patchlevel__
+ int v3 = __clang_patchlevel__+0;
+#else
+ int v3 = 0;
+#endif
+ if (v3 > 0) sprintf(compiler_name, "LLVM/Clang %d.%d.%d", v1, v2, v3);
+ else sprintf(compiler_name, "LLVM/Clang %d.%d", v1, v2);
+#endif
+
+#elif defined(__COMO_VERSION__)
+
+ int w = __COMO_VERSION__+0;
+ int v1 = w / 100;
+ int v2 = w % 100;
+ if (!(v2 % 10)) sprintf(compiler_name, "Comeau C %d.%d", v1, v2 / 10);
+ else sprintf(compiler_name, "Comeau C %d.%02d", v1, v2);
+
+#elif defined(__convexc__)
+
+ sprintf(compiler_name, "Convex C");
+
+#elif defined(_CRAYC)
+
+#if !defined(_RELEASE) || !defined(_RELEASE_MINOR)
+ sprintf(compiler_name, "Cray C");
+#else
+ int v1 = _RELEASE+0;
+ int v2 = _RELEASE_MINOR+0;
+ sprintf(compiler_name, "Cray C %d.%d", v1, v2);
+#endif
+
+#elif defined(__DCC__)
+
+#ifndef __VERSION_NUMBER__
+ sprintf(compiler_name, "Diab C");
+#else
+ int w = __VERSION_NUMBER__+0;
+ int v1 = w / 1000;
+ int v2 = w / 100 % 10;
+ int v3 = w % 100;
+ sprintf(compiler_name, "Diab C %d.%d.%02d", v1, v2, v3);
+#endif
+
+#elif defined(__DMC__)
+
+ int w = __DMC__+0;
+ int v1 = w / 0x100;
+ int v2 = w / 0x10 % 0x10;
+ int v3 = w % 0x10;
+ if (!v3) sprintf(compiler_name, "Digital Mars C %d.%d", v1, v2);
+ else sprintf(compiler_name, "Digital Mars C %d.%d.%d", v1, v2, v3);
+
+#elif defined(__DECC_VER)
+
+ int w = __DECC_VER+0;
+ int v1 = w / 10000000;
+ int v2 = w / 100000 % 100;
+ int v3 = w % 10000;
+ if (!(v2 % 10)) sprintf(compiler_name, "DEC C %d.%d-%d", v1, v2 / 10, v3);
+ else sprintf(compiler_name, "DEC C %d.%02d-%d", v1, v2, v3);
+
+#elif defined(__ghs__)
+
+#ifndef __GHS_VERSION_NUMBER__
+ sprintf(compiler_name, "Green Hill C");
+#else
+ int w = __GHS_VERSION_NUMBER__+0;
+ int v1 = w / 100;
+ int v2 = w / 10 % 10;
+ int v3 = w % 10;
+ sprintf(compiler_name, "Green Hill C %d.%d.%d", v1, v2, v3);
+#endif
+
+#elif defined(__HIGHC__)
+
+ sprintf(compiler_name, "MetaWare High C");
+
+#elif defined(__HP_cc)
+
+ int w = __HP_cc+0;
+ int v1 = w / 10000;
+ int v2 = w / 100 % 100;
+ int v3 = w % 100;
+ if (w <= 1) sprintf(compiler_name, "HP CC");
+ else sprintf(compiler_name, "HP CC %d.%02d.%02d", v1, v2, v3);
+
+#elif defined(__xlc__)
+
+ int w = __xlc__+0;
+ int v1 = w / 0x100;
+ int v2 = w % 0x100;
+ sprintf(compiler_name, "IBM XL C %X.%X", v1, v2);
+
+#elif defined(__IBMC__) && defined(__COMPILER_VER__)
+
+ unsigned w = __COMPILER_VER__+0;
+ int v0 = w / 0x10000000;
+ int v1 = w / 0x1000000 % 0x10;
+ int v2 = w / 0x10000 % 0x100;
+ int v3 = w % 0x10000;
+ unsigned char *os = !v0 ? "S/370" : v0 == 1 ? "OS/390" : v0 == 4 ? "z/OS" : "";
+ sprintf(compiler_name, "IBM%s%s XL C %X.%0X.%X", *os ? " " : "", os, v1, v2, v3);
+
+#elif defined(__ICC)
+
+ int w = __ICC+0;
+ int v1 = w / 100;
+ int v2 = w % 100;
+ if (!(v2 % 10)) sprintf(compiler_name, "Intel C %d.%d", v1, v2 / 10);
+ else sprintf(compiler_name, "Intel C %d.%02d", v1, v2);
+
+#elif defined(__LCC__)
+
+ sprintf(compiler_name, "LCC");
+
+#elif defined(__NDPC__)
+
+ sprintf(compiler_name, "Microway NDP C");
+
+#elif defined(_MSC_VER)
+
+ int w = _MSC_VER+0;
+ int v1 = w / 100;
+ int v2 = w % 100;
+ unsigned char *visual = "";
+ if (v1 >= 8) {
+ v1 -= 6;
+ if (v1 == 2) v1 = 1;
+ visual = "Visual ";
+ }
+ if (!(v2 % 10)) sprintf(compiler_name, "Microsoft %sC %d.%d", visual, v1, v2 / 10);
+ else sprintf(compiler_name, "Microsoft %sC %d.%02d", visual, v1, v2);
+
+#elif defined(__MWERKS__)
+
+ int w = __MWERKS__+0;
+ int v1 = w / 0x1000;
+ int v2 = w / 0x100 % 0x10;
+ int v3 = w % 0x100;
+ if (w <= 1) sprintf(compiler_name, "Metrowerks CodeWarrior");
+ sprintf(compiler_name, "Metrowerks CodeWarrior %x.%x.%x", v1, v2, v3);
+
+#elif defined(__NWCC__)
+
+ sprintf(compiler_name, "NWCC");
+
+#elif defined(__OPEN64__)
+
+ unsigned char *n = "Open64 " __OPEN64__;
+ if (strlen(n) >= sizeof(compiler_name)) n = "Open64";
+ strcpy(compiler_name, n);
+
+#elif defined(__PATHSCALE__)
+
+ unsigned char *n = "PathScale " __PATHSCALE__;
+ if (strlen(n) >= sizeof(compiler_name)) n = "PathScale";
+ strcpy(compiler_name, n);
+
+#elif defined(__PCC__)
+
+ int v1 = __PCC__+0;
+#ifdef __PCC_MINOR__
+ int v2 = __PCC_MINOR__+0;
+#else
+ int v2 = 0;
+#endif
+#ifdef __PCC_MINORMINOR__
+ int v3 = __PCC_MINORMINOR__+0;
+#else
+ int v3 = 0;
+#endif
+ sprintf(compiler_name, "PCC %d.%d.%d", v1, v2, v3);
+
+#elif defined(__PGI) || defined(__PGIC__)
+
+#if !defined(__PGIC__) || !defined(__PGIC_MINOR__)
+ sprintf(compiler_name, "The Portland Group C");
+#else
+ int v1 = __PGIC__+0;
+ int v2 = __PGIC_MINOR__+0;
+#ifdef __PGIC_PATCHLEVEL__
+ int v3 = __PGIC_PATCHLEVEL__+0;
+#else
+ int v3 = 0;
+#endif
+ if (v3 > 0) sprintf(compiler_name, "The Portland Group C %d.%d.%d", v1, v2, v3);
+ else sprintf(compiler_name, "The Portland Group C %d.%d", v1, v2);
+#endif
+
+#elif defined(__SASC__)
+
+ int w = __SASC__+0;
+ int v1 = w / 100;
+ int v2 = w % 100;
+ sprintf(compiler_name, "SAS C %d.%02d", v1, v2);
+
+#elif (defined(__sgi) && defined(_COMPILER_VERSION)) || defined(_SGI_COMPILER_VERSION)
+
+#ifdef _SGI_COMPILER_VERSION
+ int w = _SGI_COMPILER_VERSION;
+#else
+ int w = _COMPILER_VERSION;
+#endif
+ int v1 = w / 100;
+ int v2 = w / 10 % 10;
+ int v3 = w % 10;
+ sprintf(compiler_name, "MIPSpro %d.%d.%d", v1, v2, v3);
+
+#elif defined(__SUNPRO_C)
+
+ int w = __SUNPRO_C+0;
+ int div = w >= 0x1000 ? 0x1000 : 0x100;
+ int v2_digits = w >= 0x1000 ? 2 : 1;
+ int v1 = w / div;
+ int v2 = w % div / 0x10;
+ int v3 = w % 0x10;
+ if (!v3) sprintf(compiler_name, "Sun C %X.%0*X", v1, v2_digits, v2);
+ else sprintf(compiler_name, "Sun C %X.%0*X.%X", v1, v2_digits, v2, v3);
+
+#elif defined(__SYSC__) && defined(__SYSC_VER__)
+
+ int w = __SYSC_VER__+0;
+ int v1 = w / 10000;
+ int v2 = w / 100 % 100;
+ int v3 = w % 100;
+ sprintf(compiler_name, "Dignus Systems C %d.%02d.%02d", v1, v2, v3);
+
+#elif defined(__TenDRA__)
+
+ sprintf(compiler_name, "TenDRA C");
+
+#elif defined(__TINYC__)
+
+ sprintf(compiler_name, "Tiny C");
+
+#elif defined(_UCC)
+
+#if !defined(_MAJOR_REV) || !defined(_MINOR_REV)
+ sprintf(compiler_name, "Ultimate C");
+#else
+ int v1 = _MAJOR_REV+0;
+ int v2 = _MAJOR_REV+0;
+ sprintf(compiler_name, "Ultimate C %d.%d", v1, v2);
+#endif
+
+#elif defined(__USLC__)
+
+ sprintf(compiler_name, "USL C");
+
+#elif defined(__VAXC)
+
+ sprintf(compiler_name, "VAX C");
+
+#elif defined(__VOSC__)
+
+ sprintf(compiler_name, "Stratus VOS C");
+
+#elif defined(__WATCOMC__)
+
+ int w = __WATCOMC__+0;
+ int v1 = w / 100;
+ int v2 = w % 100;
+ unsigned char *op = "";
+ if (v1 >= 12) {
+ v1 -= 11;
+ op = "Open";
+ }
+ if (!(v2 % 10)) sprintf(compiler_name, "%sWatcom C %d.%d", op, v1, v2 / 10);
+ else sprintf(compiler_name, "%sWatcom C %d.%02d", op, v1, v2);
+
+#elif defined(__GNUC__)
+
+ int v1 = __GNUC__+0;
+#ifdef __GNUC_MINOR__
+ int v2 = __GNUC_MINOR__+0;
+#else
+ int v2 = 0;
+#endif
+#ifdef __GNUC_PATCHLEVEL__
+ int v3 = __GNUC_PATCHLEVEL__+0;
+#else
+ int v3 = 0;
+#endif
+#if defined(__llvm__)
+ unsigned char *prefix = "LLVM/";
+#else
+ unsigned char *prefix = "";
+#endif
+ if (v1 == 2 && (v2 >= 90 && v2 <= 91)) sprintf(compiler_name, "%sEGCS 1.%d", prefix, v2 - 90);
+ else if (v3 > 0) sprintf(compiler_name, "%sGNU C %d.%d.%d", prefix, v1, v2, v3);
+ else sprintf(compiler_name, "%sGNU C %d.%d", prefix, v1, v2);
+
+#else
+
+ sprintf(compiler_name, "unknown compiler");
+
+#endif
+}
+
+struct option {
+ int p;
+ unsigned char *(*rd_cmd)(struct option *, unsigned char ***, int *);
+ unsigned char *(*rd_cfg)(struct option *, unsigned char *);
+ void (*wr_cfg)(struct option *, unsigned char **, int *);
+ int min, max; /* for double min and max are in 1/100's (e.g. 0.1 is min==10) */
+ void *ptr;
+ unsigned char *cfg_name;
+ unsigned char *cmd_name;
+};
+
+static unsigned char *p_arse_options(int argc, unsigned char *argv[], struct option **opt)
+{
+ unsigned char *e, *u = NULL;
+ while (argc) {
+ int i;
+ argv++, argc--;
+ if (argv[-1][0] == '-') {
+ struct option *options;
+ struct option **op;
+ for (op = opt; (options = *op); op++) for (i = 0; options[i].p; i++)
+ if (options[i].rd_cmd && options[i].cmd_name &&
+ !strcasecmp(options[i].cmd_name, &argv[-1][1])) {
+ if ((e = options[i].rd_cmd(&options[i], &argv, &argc))) {
+ if (e[0]) fprintf(stderr, "Error parsing option %s: %s\n", argv[-1], e);
+ return NULL;
+ }
+ goto found;
+ }
+ uu:
+#ifdef GRDRV_DIRECTFB
+ if (!strncmp(argv[-1], "--dfb:", 6))
+ goto found;
+#endif
+ fprintf(stderr, "Unknown option %s\n", argv[-1]);
+ return NULL;
+ } else if (!u) u = argv[-1];
+ else goto uu;
+ found:;
+ }
+ if (u) return u;
+ return "";
+}
+
+static unsigned char *get_token(unsigned char **line)
+{
+ unsigned char *s = NULL;
+ int l = 0;
+ int escape = 0;
+ int quote = 0;
+
+ while (**line == ' ' || **line == 9) (*line)++;
+ if (**line) {
+ for (s = init_str(); **line; (*line)++) {
+ if (escape)
+ escape = 0;
+ else if (**line == '\\') {
+ escape = 1;
+ continue;
+ }
+ else if (**line == '"') {
+ quote = !quote;
+ continue;
+ }
+ else if ((**line == ' ' || **line == 9) && !quote)
+ break;
+ add_chr_to_str(&s, &l, **line);
+ }
+ }
+ return s;
+}
+
+static void parse_config_file(unsigned char *name, unsigned char *file, struct option **opt)
+{
+ struct option *options;
+ struct option **op;
+ int err = 0;
+ int line = 0;
+ unsigned char *e;
+ int i;
+ unsigned char *n, *p;
+ unsigned char *tok;
+ int nl, pl;
+ while (file[0]) {
+ line++;
+ while (file[0] && (file[0] == ' ' || file[0] == 9)) file++;
+ n = file;
+ while (file[0] && file[0] > ' ') file++;
+ if (file == n) {
+ if (file[0]) file++;
+ continue;
+ }
+ nl = file - n;
+ while (file[0] == 9 || file[0] == ' ') file++;
+ p = file;
+ while (file[0] && file[0] != 10 && file[0] != 13) file++;
+ pl = file - p;
+ if (file[0]) {
+ if ((file[1] == 10 || file[1] == 13) && file[0] != file[1]) file++;
+ file++;
+ }
+ tok = NULL;
+ if (n[0] == '#') goto f;
+ if (!(tok = get_token(&n))) goto f;
+ nl = strlen(tok);
+ for (op = opt; (options = *op); op++)
+ for (i = 0; options[i].p; i++) if (options[i].cfg_name && (size_t)nl == strlen(options[i].cfg_name) && !casecmp(tok, options[i].cfg_name, nl)) {
+ unsigned char *o = memacpy(p, pl);
+ if ((e = options[i].rd_cfg(&options[i], o))) {
+ if (e[0]) fprintf(stderr, "Error parsing config file %s, line %d: %s\n", name, line, e), err = 1;
+ }
+ mem_free(o);
+ goto f;
+ }
+ fprintf(stderr, "Unknown option in config file %s, line %d\n", name, line);
+ err = 1;
+ f:
+ if (tok) mem_free(tok);
+ }
+ if (err) fprintf(stderr, "\007"), sleep(1);
+}
+
+static unsigned char *create_config_string(struct option *options)
+{
+ unsigned char *s = init_str();
+ int l = 0;
+ int i;
+ add_to_str(&s, &l, "# This file is automatically generated by Links -- please do not edit.");
+ for (i = 0; options[i].p; i++) if (options[i].wr_cfg)
+ options[i].wr_cfg(&options[i], &s, &l);
+ add_to_str(&s, &l, NEWLINE);
+ return s;
+}
+
+#define FILE_BUF 1024
+
+static unsigned char cfg_buffer[FILE_BUF];
+
+unsigned char *read_config_file(unsigned char *name)
+{
+ int h, r;
+ int l = 0;
+ unsigned char *s;
+ int rs;
+ EINTRLOOP(h, open(name, O_RDONLY | O_NOCTTY));
+ if (h == -1) return NULL;
+ set_bin(h);
+ s = init_str();
+ while ((r = hard_read(h, cfg_buffer, FILE_BUF)) > 0) {
+ int i;
+ for (i = 0; i < r; i++) if (!cfg_buffer[i]) cfg_buffer[i] = ' ';
+ add_bytes_to_str(&s, &l, cfg_buffer, r);
+ }
+ if (r == -1) mem_free(s), s = NULL;
+ EINTRLOOP(rs, close(h));
+ return s;
+}
+
+int write_to_config_file(unsigned char *name, unsigned char *c)
+{
+ int rr;
+ int r;
+ int h, w;
+ int count = 0;
+ int tmp_namel;
+ unsigned char *tmp_name;
+ int rs;
+try_new_count:
+ tmp_namel = 0;
+ tmp_name = init_str();
+ add_to_str(&tmp_name, &tmp_namel, name);
+ add_to_str(&tmp_name, &tmp_namel, ".tmp.");
+ add_num_to_str(&tmp_name, &tmp_namel, count);
+ EINTRLOOP(h, open(tmp_name, O_WRONLY | O_NOCTTY | O_CREAT | O_TRUNC | O_EXCL, 0600));
+ if (h == -1) {
+ if (errno == EEXIST && count < MAXINT) {
+ count++;
+ mem_free(tmp_name);
+ goto try_new_count;
+ }
+ mem_free(tmp_name);
+ return get_error_from_errno(errno);
+ }
+ set_bin(h);
+ rr = strlen(c);
+ r = rr;
+ while (r > 0) {
+ if ((w = hard_write(h, c + rr - r, r)) <= 0) {
+ int err = !w ? ENOSPC : errno;
+ EINTRLOOP(rs, close(h));
+ EINTRLOOP(rs, unlink(tmp_name));
+ mem_free(tmp_name);
+ return get_error_from_errno(err);
+ }
+ r -= w;
+ }
+ EINTRLOOP(rs, close(h));
+#ifndef RENAME_OVER_EXISTING_FILES
+ EINTRLOOP(rs, unlink(name));
+#endif
+ EINTRLOOP(rs, rename(tmp_name, name));
+ if (rs) {
+ int err = errno;
+ EINTRLOOP(rs, unlink(tmp_name));
+ mem_free(tmp_name);
+ return get_error_from_errno(err);
+ }
+ mem_free(tmp_name);
+ return 0;
+}
+
+static unsigned char *get_home(int *n)
+{
+ struct stat st;
+ int rs;
+ unsigned char *home = NULL;
+ unsigned char *home_links;
+ unsigned char *config_dir = stracpy(getenv("CONFIG_DIR"));
+
+ if (n) *n = 1;
+#ifdef WIN32
+ if (!home) {
+ home = stracpy(getenv("APPDATA"));
+#ifdef HAVE_CYGWIN_CONV_PATH
+ /*
+ * Newer Cygwin complains about windows-style path, so
+ * we have to convert it.
+ */
+ if (home) {
+ unsigned char *new_path;
+ ssize_t sz = cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, home, NULL, 0);
+ if (sz < 0)
+ goto skip_path_conv;
+ new_path = mem_alloc(sz);
+ sz = cygwin_conv_path(CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, home, new_path, sz);
+ if (sz < 0) {
+ mem_free(new_path);
+ goto skip_path_conv;
+ }
+ mem_free(home);
+ home = new_path;
+skip_path_conv:;
+ }
+#endif
+ if (home) {
+ EINTRLOOP(rs, stat(home, &st));
+ if (rs || !S_ISDIR(st.st_mode)) {
+ mem_free(home);
+ home = NULL;
+ }
+ }
+ }
+#endif
+ if (!home) home = stracpy(getenv("HOME"));
+#ifdef WIN32
+/* When we run in Cygwin without Cygwin environment, it reports home "/".
+ Unfortunatelly, it can't write anything to that directory */
+ if (home && !strcmp(home, "/")) {
+ mem_free(home);
+ home = NULL;
+ }
+#endif
+ if (!home) {
+ int i;
+ home = stracpy(path_to_exe);
+ if (!home) {
+ if (config_dir) mem_free(config_dir);
+ return NULL;
+ }
+ for (i = strlen(home) - 1; i >= 0; i--) if (dir_sep(home[i])) {
+ home[i + 1] = 0;
+ goto br;
+ }
+ home[0] = 0;
+ br:;
+ }
+ while (home[0] && dir_sep(home[strlen(home) - 1])) home[strlen(home) - 1] = 0;
+ if (home[0]) add_to_strn(&home, "/");
+ home_links = stracpy(home);
+ if (config_dir)
+ {
+ add_to_strn(&home_links, config_dir);
+ while (home_links[0] && dir_sep(home_links[strlen(home_links) - 1])) home_links[strlen(home_links) - 1] = 0;
+ EINTRLOOP(rs, stat(home_links, &st));
+ if (!rs && S_ISDIR(st.st_mode)) {
+ add_to_strn(&home_links, "/links");
+ } else {
+ fprintf(stderr, "CONFIG_DIR set to %s. But directory %s doesn't exist.\n\007", config_dir, home_links);
+ sleep(3);
+ mem_free(home_links);
+ home_links = stracpy(home);
+ add_to_strn(&home_links, ".links");
+ }
+ mem_free(config_dir);
+ } else add_to_strn(&home_links, ".links");
+ EINTRLOOP(rs, stat(home_links, &st));
+ if (rs) {
+#ifdef HAVE_MKDIR
+ EINTRLOOP(rs, mkdir(home_links, 0700));
+ if (!rs) goto home_creat;
+#endif
+ if (config_dir) goto failed;
+ goto first_failed;
+ }
+ if (S_ISDIR(st.st_mode)) goto home_ok;
+ /* This is a Cygwin hack! Cygwin reports stat for "links" if no
+ "links" exists and only "links.exe" does. So try to create directory
+ anyway. */
+#ifdef HAVE_MKDIR
+ EINTRLOOP(rs, mkdir(home_links, 0700));
+ if (!rs) goto home_creat;
+#endif
+ first_failed:
+ mem_free(home_links);
+ home_links = stracpy(home);
+ add_to_strn(&home_links, "links");
+ EINTRLOOP(rs, stat(home_links, &st));
+ if (rs) {
+#ifdef HAVE_MKDIR
+ EINTRLOOP(rs, mkdir(home_links, 0700));
+ if (!rs) goto home_creat;
+#else
+ mem_free(home_links);
+ home_links = stracpy(home);
+ goto home_ok;
+#endif
+ goto failed;
+ }
+ if (S_ISDIR(st.st_mode)) goto home_ok;
+#ifdef HAVE_MKDIR
+ EINTRLOOP(rs, mkdir(home_links, 0700));
+ if (!rs) goto home_creat;
+#endif
+ failed:
+ mem_free(home_links);
+ mem_free(home);
+ return NULL;
+
+ home_ok:
+ if (n) *n = 0;
+ home_creat:
+#ifdef HAVE_CHMOD
+ EINTRLOOP(rs, chmod(home_links, 0700));
+#endif
+ add_to_strn(&home_links, "/");
+ mem_free(home);
+ return home_links;
+}
+
+void init_home(void)
+{
+ get_system_name();
+ get_compiler_name();
+ links_home = get_home(&first_use);
+ if (!links_home) {
+ fprintf(stderr, "Unable to find or create links config directory. Please check, that you have $HOME variable set correctly and that you have write permission to your home directory.\n\007");
+ sleep(3);
+ return;
+ }
+}
+
+/* prefix: directory
+ * name: name of the configuration file (typ. links.cfg)
+ */
+static int write_config_data(unsigned char *prefix, unsigned char *name, struct option *o, struct terminal *term)
+{
+ int err;
+ unsigned char *c, *config_file;
+ if (!(c = create_config_string(o))) return -1;
+ config_file = stracpy(prefix);
+ if (!config_file) {
+ mem_free(c);
+ return -1;
+ }
+ add_to_strn(&config_file, name);
+ if ((err = write_to_config_file(config_file, c))) {
+ if (term) msg_box(term, NULL, TEXT_(T_CONFIG_ERROR), AL_CENTER | AL_EXTD_TEXT, TEXT_(T_UNABLE_TO_WRITE_TO_CONFIG_FILE), ": ", get_err_msg(err), NULL, NULL, 1, TEXT_(T_CANCEL), NULL, B_ENTER | B_ESC);
+ mem_free(c);
+ mem_free(config_file);
+ return -1;
+ }
+ mem_free(c);
+ mem_free(config_file);
+ return 0;
+}
+
+static void add_nm(struct option *o, unsigned char **s, int *l)
+{
+ if (*l) add_to_str(s, l, NEWLINE);
+ add_to_str(s, l, o->cfg_name);
+ add_to_str(s, l, " ");
+}
+
+static void add_quoted_to_str(unsigned char **s, int *l, unsigned char *q)
+{
+ add_chr_to_str(s, l, '"');
+ while (*q) {
+ if (*q == '"' || *q == '\\') add_chr_to_str(s, l, '\\');
+ add_chr_to_str(s, l, *q);
+ q++;
+ }
+ add_chr_to_str(s, l, '"');
+}
+
+static unsigned char *num_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *tok = get_token(&c);
+ unsigned char *end;
+ long l;
+ if (!tok) return "Missing argument";
+ l = strtolx(tok, &end);
+ if (*end) {
+ mem_free(tok);
+ return "Number expected";
+ }
+ if (l < o->min || l > o->max) {
+ mem_free(tok);
+ return "Out of range";
+ }
+ *(int *)o->ptr = l;
+ mem_free(tok);
+ return NULL;
+}
+
+static void num_wr(struct option *o, unsigned char **s, int *l)
+{
+ add_nm(o, s, l);
+ add_knum_to_str(s, l, *(int *)o->ptr);
+}
+
+static unsigned char *dbl_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *tok = get_token(&c);
+ unsigned char *end;
+ double d;
+
+ if (!tok) return "Missing argument";
+ d = strtod(tok, (char **)(void *)&end);
+
+ if (*end) {
+ mem_free(tok);
+ return "Number expected";
+ }
+ if (100*d < o->min || 100*d > o->max) {
+ mem_free(tok);
+ return "Out of range";
+ }
+ *(double *)o->ptr = d;
+ mem_free(tok);
+ return NULL;
+}
+
+static void dbl_wr(struct option *o, unsigned char **s, int *l)
+{
+ unsigned char number[80];
+ snprintf(number, sizeof number, "%.4f", *(double*)o->ptr);
+
+ add_nm(o, s, l);
+ add_to_str(s, l, number);
+}
+
+static unsigned char *str_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *tok = get_token(&c);
+ unsigned char *e = NULL;
+ if (!tok) return NULL;
+ if (strlen(tok) + 1 > (size_t)o->max) e = "String too long";
+ else strcpy(o->ptr, tok);
+ mem_free(tok);
+ return e;
+}
+
+static void str_wr(struct option *o, unsigned char **s, int *l)
+{
+ add_nm(o, s, l);
+ if (strlen(o->ptr) + 1 > (size_t)o->max) {
+ unsigned char *s1 = init_str();
+ int l1 = 0;
+ add_bytes_to_str(&s1, &l1, o->ptr, o->max - 1);
+ add_quoted_to_str(s, l, s1);
+ mem_free(s1);
+ }
+ else add_quoted_to_str(s, l, o->ptr);
+}
+
+static unsigned char *cp_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *tok = get_token(&c);
+ unsigned char *e = NULL;
+ int i;
+ if (!tok) return "Missing argument";
+ if ((i = get_cp_index(tok)) == -1) e = "Unknown codepage";
+#ifndef ENABLE_UTF8
+ else if (o->min == 1 && i == utf8_table) e = "UTF-8 can't be here";
+#endif
+ else *(int *)o->ptr = i;
+ mem_free(tok);
+ return e;
+}
+
+static void cp_wr(struct option *o, unsigned char **s, int *l)
+{
+ unsigned char *n = get_cp_mime_name(*(int *)o->ptr);
+ add_nm(o, s, l);
+ add_to_str(s, l, n);
+}
+
+static unsigned char *lang_rd(struct option *o, unsigned char *c)
+{
+ int i;
+ unsigned char *tok = get_token(&c);
+ if (!tok) return "Missing argument";
+ for (i = 0; i < n_languages(); i++)
+ if (!(strcasecmp(language_name(i), tok))) {
+ set_language(i);
+ mem_free(tok);
+ return NULL;
+ }
+ mem_free(tok);
+ return "Unknown language";
+}
+
+static void lang_wr(struct option *o, unsigned char **s, int *l)
+{
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, language_name(current_language));
+}
+
+static int getnum(unsigned char *s, int *n, int r1, int r2)
+{
+ unsigned char *e;
+ long l = strtol(s, (char **)(void *)&e, 10);
+ if (*e || !*s) return -1;
+ if (l < r1 || l >= r2) return -1;
+ *n = (int)l;
+ return 0;
+}
+
+static unsigned char *type_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *err = "Error reading association specification";
+ struct assoc new;
+ unsigned char *w;
+ int n = 0; /* against warning */
+ memset(&new, 0, sizeof(struct assoc));
+ if (!(new.label = get_token(&c))) goto err;
+ if (!(new.ct = get_token(&c))) goto err;
+ if (!(new.prog = get_token(&c))) goto err;
+ if (!(w = get_token(&c))) goto err;
+ if (getnum(w, &n, 0, 128)) goto err_f;
+ mem_free(w);
+ new.cons = !!(n & 1);
+ new.xwin = !!(n & 2);
+ new.ask = !!(n & 4);
+ if ((n & 8) || (n & 16)) new.block = !!(n & 16);
+ else new.block = !new.xwin || new.cons;
+ new.accept_http = !!(n & 32);
+ new.accept_ftp = !!(n & 64);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '9') goto err_f;
+ new.system = w[0] - '0';
+ mem_free(w);
+ update_assoc(&new);
+ err = NULL;
+ err:
+ if (new.label) mem_free(new.label);
+ if (new.ct) mem_free(new.ct);
+ if (new.prog) mem_free(new.prog);
+ return err;
+ err_f:
+ mem_free(w);
+ goto err;
+}
+
+static unsigned char *block_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *err = "Error reading image block specification";
+ unsigned char* url;
+
+ if(!(url = get_token(&c)))
+ return err;
+
+ block_add_URL_fn(NULL, url);
+
+ mem_free(url);
+
+ return NULL;
+}
+
+static void block_wr(struct option *o, unsigned char **s, int *l)
+{
+ struct block *a;
+ foreachback(a, blocks) {
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, a->url);
+ }
+}
+
+static void type_wr(struct option *o, unsigned char **s, int *l)
+{
+ struct assoc *a;
+ foreachback(a, assoc) {
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, a->label);
+ add_to_str(s, l, " ");
+ add_quoted_to_str(s, l, a->ct);
+ add_to_str(s, l, " ");
+ add_quoted_to_str(s, l, a->prog);
+ add_to_str(s, l, " ");
+ add_num_to_str(s, l, (!!a->cons) + (!!a->xwin) * 2 + (!!a->ask) * 4 + (!a->block) * 8 + (!!a->block) * 16 + (!!a->accept_http) * 32 + (!!a->accept_ftp) * 64);
+ add_to_str(s, l, " ");
+ add_num_to_str(s, l, a->system);
+ }
+}
+
+static unsigned char *ext_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *err = "Error reading extension specification";
+ struct extension new;
+ memset(&new, 0, sizeof(struct extension));
+ if (!(new.ext = get_token(&c))) goto err;
+ if (!(new.ct = get_token(&c))) goto err;
+ update_ext(&new);
+ err = NULL;
+ err:
+ if (new.ext) mem_free(new.ext);
+ if (new.ct) mem_free(new.ct);
+ return err;
+}
+
+static void ext_wr(struct option *o, unsigned char **s, int *l)
+{
+ struct extension *a;
+ foreachback(a, extensions) {
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, a->ext);
+ add_to_str(s, l, " ");
+ add_quoted_to_str(s, l, a->ct);
+ }
+}
+
+static unsigned char *prog_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *err = "Error reading program specification";
+ unsigned char *prog, *w;
+ if (!(prog = get_token(&c))) goto err_1;
+ if (!(w = get_token(&c))) goto err_2;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '9') goto err_3;
+ update_prog(o->ptr, prog, w[0] - '0');
+ err = NULL;
+ err_3:
+ mem_free(w);
+ err_2:
+ mem_free(prog);
+ err_1:
+ return err;
+}
+
+static void prog_wr(struct option *o, unsigned char **s, int *l)
+{
+ struct protocol_program *a;
+ foreachback(a, *(struct list_head *)o->ptr) {
+ if (!*a->prog) continue;
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, a->prog);
+ add_to_str(s, l, " ");
+ add_num_to_str(s, l, a->system);
+ }
+}
+
+static unsigned char *term_rd(struct option *o, unsigned char *c)
+{
+ struct term_spec *ts;
+ unsigned char *w;
+ int i;
+ if (!(w = get_token(&c))) goto err;
+ if (!(ts = new_term_spec(w))) {
+ mem_free(w);
+ goto end;
+ }
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '4') goto err_f;
+ ts->mode = w[0] - '0';
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '3') goto err_f;
+ ts->m11_hack = (w[0] - '0') & 1;
+ ts->braille = !!((w[0] - '0') & 2);
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '7') goto err_f;
+ ts->col = (w[0] - '0') & 1;
+ ts->restrict_852 = !!((w[0] - '0') & 2);
+ ts->block_cursor = !!((w[0] - '0') & 4);
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if ((i = get_cp_index(w)) == -1) goto err_f;
+#ifndef ENABLE_UTF8
+ if (i == utf8_table) {
+ i = 0;
+ }
+#endif
+ ts->charset = i;
+ mem_free(w);
+ end:
+ return NULL;
+ err_f:
+ mem_free(w);
+ err:
+ return "Error reading terminal specification";
+}
+
+static unsigned char *term2_rd(struct option *o, unsigned char *c)
+{
+ struct term_spec *ts;
+ unsigned char *w;
+ int i;
+ if (!(w = get_token(&c))) goto err;
+ if (!(ts = new_term_spec(w))) {
+ mem_free(w);
+ goto end;
+ }
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '3') goto err_f;
+ ts->mode = w[0] - '0';
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '1') goto err_f;
+ ts->m11_hack = w[0] - '0';
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '1') goto err_f;
+ ts->restrict_852 = w[0] - '0';
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if (strlen(w) != 1 || w[0] < '0' || w[0] > '1') goto err_f;
+ ts->col = w[0] - '0';
+ mem_free(w);
+ if (!(w = get_token(&c))) goto err;
+ if ((i = get_cp_index(w)) == -1) goto err_f;
+#ifndef ENABLE_UTF8
+ if (i == utf8_table) {
+ i = 0;
+ }
+#endif
+ ts->charset = i;
+ mem_free(w);
+ end:
+ return NULL;
+ err_f:
+ mem_free(w);
+ err:
+ return "Error reading terminal specification";
+}
+
+static void term_wr(struct option *o, unsigned char **s, int *l)
+{
+ struct term_spec *ts;
+ foreachback(ts, term_specs) {
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, ts->term);
+ add_to_str(s, l, " ");
+ add_num_to_str(s, l, ts->mode);
+ add_to_str(s, l, " ");
+ add_num_to_str(s, l, !!ts->m11_hack + !!ts->braille * 2);
+ add_to_str(s, l, " ");
+ add_num_to_str(s, l, !!ts->col + !!ts->restrict_852 * 2 + !!ts->block_cursor * 4);
+ add_to_str(s, l, " ");
+ add_to_str(s, l, get_cp_mime_name(ts->charset));
+ }
+}
+
+static struct list_head driver_params = { &driver_params, &driver_params };
+
+struct driver_param *get_driver_param(unsigned char *n)
+{
+ struct driver_param *dp;
+ foreach(dp, driver_params) if (!strcasecmp(dp->name, n)) return dp;
+ dp = mem_calloc(sizeof(struct driver_param) + strlen(n) + 1);
+ dp->codepage = get_cp_index("iso-8859-1");
+ strcpy(dp->name, n);
+ dp->shell = mem_calloc(1);
+ dp->nosave = 1;
+ add_to_list(driver_params, dp);
+ return dp;
+}
+
+static unsigned char *dp_rd(struct option *o, unsigned char *c)
+{
+ int cc;
+ unsigned char *n, *param, *cp, *shell;
+ struct driver_param *dp;
+ if (!(n = get_token(&c))) goto err;
+ if (!(param = get_token(&c))) {
+ mem_free(n);
+ goto err;
+ }
+ if (!(shell = get_token(&c))){
+ mem_free(n);
+ mem_free(param);
+ goto err;
+ }
+ if (!(cp = get_token(&c))) {
+ mem_free(n);
+ mem_free(param);
+ mem_free(shell);
+ goto err;
+ }
+ if ((cc=get_cp_index(cp)) == -1) {
+ mem_free(n);
+ mem_free(param);
+ mem_free(shell);
+ mem_free(cp);
+ goto err;
+ }
+ dp=get_driver_param(n);
+ dp->codepage=cc;
+ if (dp->param) mem_free(dp->param);
+ dp->param=param;
+ if (dp->shell) mem_free(dp->shell);
+ dp->shell=shell;
+ dp->nosave = 0;
+ mem_free(cp);
+ mem_free(n);
+ return NULL;
+ err:
+ return "Error reading driver mode specification";
+}
+
+static void dp_wr(struct option *o, unsigned char **s, int *l)
+{
+ struct driver_param *dp;
+ foreachback(dp, driver_params) {
+ if ((!dp->param || !*dp->param) && !dp->codepage && !*dp->shell) continue;
+ if (dp->nosave) continue;
+ add_nm(o, s, l);
+ add_quoted_to_str(s, l, dp->name);
+ add_to_str(s, l, " ");
+ add_quoted_to_str(s, l, dp->param ? dp->param : (unsigned char*)"");
+ add_to_str(s, l, " ");
+ add_quoted_to_str(s, l, dp->shell);
+ add_to_str(s, l, " ");
+ add_to_str(s, l, get_cp_mime_name(dp->codepage));
+ }
+}
+
+static unsigned char *ip_rd(struct option *o, unsigned char *c)
+{
+ unsigned char *e;
+ e = str_rd(o, c);
+ if (e) return e;
+ if (*(unsigned char *)o->ptr && numeric_ip_address(o->ptr, NULL) == -1) return "Invalid IP address";
+ return NULL;
+}
+
+static unsigned char *gen_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ unsigned char *e;
+ int l;
+ unsigned char *r;
+ if (!*argc) return "Parameter expected";
+ e = init_str();
+ l = 0;
+ add_quoted_to_str(&e, &l, **argv);
+ r = o->rd_cfg(o, e);
+ mem_free(e);
+ if (r) return r;
+ (*argv)++; (*argc)--;
+ return NULL;
+}
+
+static unsigned char *lookup_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ ip__address addr;
+ unsigned char *p = (unsigned char *)&addr;
+ if (!*argc) return "Parameter expected";
+ if (*argc >= 2) return "Too many parameters";
+ (*argv)++; (*argc)--;
+ if (do_real_lookup(*(*argv - 1), &addr)) {
+#if defined(HAVE_GETHOSTBYNAME) && defined(HAVE_HERROR)
+ herror("error");
+#else
+ fprintf(stderr, "error: host not found\n");
+#endif
+ return "";
+ }
+ printf("%d.%d.%d.%d\n", (int)p[0], (int)p[1], (int)p[2], (int)p[3]);
+ fflush(stdout);
+ return "";
+}
+
+static unsigned char *version_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ printf("Links " VERSION_STRING "\n");
+ fflush(stdout);
+ return "";
+}
+
+static unsigned char *set_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ *(int *)o->ptr = 1;
+ return NULL;
+}
+
+static unsigned char *unset_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ *(int *)o->ptr = 0;
+ return NULL;
+}
+
+static unsigned char *setstr_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ if (!*argc) return "Parameter expected";
+ safe_strncpy(o->ptr, **argv, o->max);
+ (*argv)++; (*argc)--;
+ return NULL;
+}
+
+static unsigned char *dump_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+ if (dmp != o->min && dmp) return "Can't use both -dump and -source";
+ dmp = o->min;
+ no_connect = 1;
+ return NULL;
+}
+
+static unsigned char *printhelp_cmd(struct option *o, unsigned char ***argv, int *argc)
+{
+/* Changed and splited - translation is much easier.
+ * Print to stdout instead stderr (,,links -help | more''
+ * is much better than ,,links -help 2>&1 | more'').
+ */
+fprintf(stdout, "%s%s%s%s%s%s\n",
+
+("links [options] URL\n"
+"Options are:\n"
+"\n"
+" -g\n"
+" Run in graphics mode.\n"
+"\n"
+" -no-g\n"
+" Run in text mode (overrides previous -g).\n"
+"\n"
+" -driver <driver name>\n"
+" Graphics driver to use. Drivers are: x, svgalib, fb, directfb, pmshell,\n"
+" atheos.\n"
+" List of drivers will be shown if you give it an unknown driver.\n"
+" Available drivers depend on your operating system and available libraries.\n"
+"\n"
+" -mode <graphics mode>\n"
+" Graphics mode. For SVGALIB it is in format COLUMNSxROWSxCOLORS --\n"
+" for example 640x480x256, 800x600x64k, 960x720x16M, 1024x768x16M32\n"
+" List of modes will be shown if you give it an unknown videomode.\n"
+" For framebuffer it is number of pixels in border --- LEFT,TOP,RIGHT,BOTTOM\n"
+" other 3 values are optional --- i.e. -mode 10 will set all borders to 10,\n"
+" -mode 10,20 will set left & right border to 10 and top & bottom to 20.\n"
+" For Xwindow it is size of a window in format WIDTHxHEIGHT.\n"
+"\n"
+" -display <x-display>\n"
+" Set Xwindow display.\n"
+"\n"
+" -force-html\n"
+" Treat files with unknown type as html rather than text.\n"
+" (can be toggled with '\\' key)\n"
+"\n"
+" -source <url>\n"
+" Write unformatted data stream to stdout.\n"
+"\n"
+" -dump <url>\n"
+" Write formatted document to stdout.\n"
+"\n"
+" -width <number>\n"
+" For dump, document will be formatted to this screen width (but it can still\n"
+" exceed it if lines can't be broken).\n"
+"\n"
+" -codepage <codepage>\n"
+" For dump, convert output to specified character set --\n"
+" for eaxmple iso-8859-2, windows-1250.\n"
+"\n"
+" -anonymous\n"
+" Restrict links so that it can run on an anonymous account.\n"
+" No local file browsing. No downloads. Executing viewers\n"
+" is allowed, but user can't add or modify entries in\n"
+" association table.\n"
+"\n"
+" -no-connect\n"
+" Runs links as a separate instance - instead of connecting to\n"
+" existing instance.\n"
+"\n"
+" -max-connections <max>\n"
+" Maximum number of concurrent connections.\n"
+" (default: 10)\n"
+"\n"),
+(" -max-connections-to-host <max>\n"
+" Maximum number of concurrent connection to a given host.\n"
+" (default: 2)\n"
+"\n"
+" -retries <retry>\n"
+" Number of retries.\n"
+" (default: 3)\n"
+"\n"
+" -receive-timeout <sec>\n"
+" Timeout on receive.\n"
+" (default: 120)\n"
+"\n"),
+(" -unrestartable-receive-timeout <sec>\n"
+" Timeout on non restartable connections.\n"
+" (default: 600)\n"
+"\n"
+" -bind-address <ip address>\n"
+" Use a specific local IP address.\n"
+"\n"
+" -async-dns <0>/<1>\n"
+" Asynchronous DNS resolver on(1)/off(0).\n"
+"\n"
+" -download-utime <0>/<1>\n"
+" Set time of downloaded files to last modification time reported by server.\n"
+"\n"
+" -format-cache-size <num>\n"
+" Number of formatted document pages cached.\n"
+" (default: 5)\n"
+"\n"
+" -memory-cache-size <bytes>\n"
+" Cache memory in bytes.\n"
+" (default: 1048576)\n"
+"\n"
+" -image-cache-size <bytes>\n"
+" Cache memory in bytes.\n"
+" (default: 1048576)\n"
+"\n"),
+(" -http-proxy <host:port>\n"
+" Host and port number of the HTTP proxy, or blank.\n"
+" (default: blank)\n"
+"\n"
+" -ftp-proxy <host:port>\n"
+" Host and port number of the FTP proxy, or blank.\n"
+" (default: blank)\n"
+"\n"
+" -socks-proxy <user@host:port>\n"
+" Userid, host and port of Socks4a, or blank.\n"
+" (default: blank)\n"
+"\n"
+" -append-text-to-dns-lookups <text>\n"
+" Append text to dns lookups. It is useful for specifying fixed\n"
+" tor exit node.\n"
+" (default: blank)\n"
+"\n"
+" -only-proxies <0>/<1>\n"
+" (default 0)\n"
+" \"1\" causes that Links won't initiate any non-proxy connection.\n"
+" It is useful for anonymization with tor or similar networks.\n"
+"\n"
+" -download-dir <path>\n"
+" Default download directory.\n"
+" (default: actual dir)\n"
+"\n"
+" -aggressive-cache <0>/<1>\n"
+" (default 1)\n"
+" Always cache everything regardless of server's caching recomendations.\n"
+" Many servers deny caching even if their content is not changing\n"
+" just to get more hits and more money from ads.\n"
+"\n"),
+(" -language <language>\n"
+" Set user interface language.\n"
+"\n"
+" -http-bugs.http10 <0>/<1>\n"
+" (default 0)\n"
+" \"1\" forces using only HTTP/1.0 protocol. (useful for buggy servers\n"
+" that claim to be HTTP/1.1 compliant but are not)\n"
+" \"0\" use both HTTP/1.0 and HTTP/1.1.\n"
+"\n"
+" -http-bugs.allow-blacklist <0>/<1>\n"
+" (default 1)\n"
+" \"1\" defaults to using list of servers that have broken HTTP/1.1 support.\n"
+" When links finds such server, it will retry the request with HTTP/1.0.\n"
+"\n"
+" -http-bugs.bug-302-redirect <0>/<1>\n"
+" (default 1)\n"
+" Process 302 redirect in a way that is incompatible with RFC1945 and RFC2068,\n"
+" but the same as Netscape and MSIE. Many pages depend on it.\n"
+"\n"
+" -http-bugs.bug-post-no-keepalive <0>/<1>\n"
+" (default 0)\n"
+" No keepalive connection after post requests. For some buggy servers.\n"
+"\n"
+" -http-bugs.bug-no-accept-charset <0>/<1>\n"
+" (default 0)\n"
+" Do not send Accept-Charset field of HTTP header. Because it is too long\n"
+" some servers will deny the request. Other servers will convert content\n"
+" to plain ascii when Accept-Charset is missing.\n"
+"\n"
+" -http-bugs.no-compression <0>/<1>\n"
+" (default 0)\n"
+" \"1\" causes that links won't advertise HTTP compression support (but it\n"
+" will still accept compressed data). Use it when you communicate with\n"
+" server that has broken compression support.\n"
+"\n"
+" -http-bugs.retry-internal-errors <0>/<1>\n"
+" (default 0)\n"
+" Retry on internal server errors (50x).\n"
+"\n"
+" -http.referer <0>/<1>/<2>/<3>/<4>\n"
+" (default 0)\n"
+" 0 - do not send referer\n"
+" 1 - send the requested URL as referer\n"
+" 2 - send fake referer\n"
+" 3 - send real referer\n"
+" 4 - send real referer only to the same server\n"
+"\n"
+" -http.fake-referer <string>\n"
+" Fake referer value.\n"
+"\n"
+" -http.fake-user-agent <string>\n"
+" Fake user agent value.\n"
+"\n"
+" -http.extra-header <string>\n"
+" Extra string added to HTTP header.\n"
+"\n"
+" -ftp.anonymous-password <string>\n"
+" Password for anonymous ftp access.\n"
+"\n"
+" -ftp.use-passive <0>/<1>\n"
+" Use ftp PASV command to bypass firewalls.\n"
+"\n"
+" -ftp.fast <0>/<1>\n"
+" Send more ftp commands simultaneously. Faster response when\n"
+" browsing ftp directories, but it is incompatible with RFC\n"
+" and some servers don't like it.\n"
+"\n"
+" -ftp.set-iptos <0>/<1>\n"
+" Set IP Type-of-service to high throughput on ftp connections.\n"
+"\n"
+" -menu-font-size <size>\n"
+" Size of font in menu.\n"
+"\n"
+" -menu-background-color 0xRRGGBB\n"
+" Set menu background color in graphics mode, RRGGBB are hex.\n"
+"\n"
+" -menu-foreground-color 0xRRGGBB\n"
+" Set menu foreground color in graphics mode.\n"
+"\n"
+" -scroll-bar-area-color 0xRRGGBB\n"
+" Set color of scroll bar area.\n"
+"\n"
+" -scroll-bar-bar-color 0xRRGGBB\n"
+" Set color of scroll bar.\n"
+"\n"
+" -scroll-bar-frame-color 0xRRGGBB\n"
+" Set color of scroll bar frame.\n"
+"\n"
+" -display-red-gamma <fp-value>\n"
+" Red gamma of display.\n"
+" (default 2.2)\n"
+"\n"
+" -display-green-gamma <fp-value>\n"
+" Green gamma of display.\n"
+" (default 2.2)\n"
+"\n"
+" -display-blue-gamma <fp-value>\n"
+" Blue gamma of display.\n"
+" (default 2.2)\n"
+"\n"
+" -user-gamma <fp-value>\n"
+" Additional gamma.\n"
+" (default 1)\n"
+"\n"
+" -bfu-aspect <fp-value>\n"
+" Display aspect ration.\n"
+"\n"
+" -aspect-on <0>/<1>\n"
+" Enable aspect ratio correction.\n"
+"\n"
+" -dither-letters <0>/<1>\n"
+" Do letter dithering.\n"
+"\n"
+" -dither-images <0>/<1>\n"
+" Do image dithering.\n"
+"\n"
+" -display-optimize <0>/<1>/<2>\n"
+" Optimize for CRT (0), LCD RGB (1), LCD BGR (2).\n"
+"\n"
+" -gamma correction <0>/<1>/<2>\n"
+" Type of gamma correction:\n"
+" (default 2)\n"
+" 0 - 8-bit (fast).\n"
+" 1 - 16-bit (slow).\n"
+" 2 - automatically detect according to speed of FPU.\n"
+"\n"
+#ifdef JS
+" -enable-javascript <0>/<1>\n"
+" Enable javascript.\n"
+"\n"
+" -js.verbose-errors <0>/<1>\n"
+" Display javascript errors.\n"
+"\n"
+" -js.verbose-warnings <0>/<1>\n"
+" Display javascript warnings.\n"
+"\n"
+" -js.enable-all-conversions <0>/<1>\n"
+" Enable conversions between all types in javascript.\n"
+"\n"
+" -js.enable-global-resolution <0>/<1>\n"
+" Resolve global names.\n"
+"\n"
+" -js.manual-confirmation <0>/<1>\n"
+" Ask user to confirm potentially dangerous operations.\n"
+" (opening windows, going to url etc.) Default 1.\n"
+"\n"
+" -js.recursion-depth <integer>\n"
+" Depth of javascript call stack.\n"
+"\n"
+" -js.memory-limit <memory amount>\n"
+" Amount of kilobytes the javascript may allocate.\n"
+"\n"
+#endif
+" -bookmarks-codepage <codepage>\n"
+" Character set of bookmarks file.\n"
+"\n"
+" -bookmarks-file <file>\n"
+" File to store bookmarks.\n"
+"\n"
+" -html-assume-codepage <codepage>\n"
+" If server didn't specify document character set, assume this.\n"
+"\n"
+" -html-hard-assume <0>/<1>\n"
+" Use always character set from \"-html-assume-codepage\" no matter\n"
+" what server sent.\n"
+"\n"
+" -html-tables <0>/<1>\n"
+" Render tables. (0) causes tables being rendered like in lynx.\n"
+"\n"
+" -html-frames <0>/<1>\n"
+" Render frames. (0) causes frames rendered like in lynx.\n"
+"\n"
+" -html-images <0>/<1>\n"
+" Display links to unnamed images as [IMG].\n"
+"\n"
+" -html-image-names <0>/<1>\n"
+" Display filename of an image instead of [IMG].\n"
+"\n"
+" -html-display-images <0>/<1>\n"
+" Display images in graphics mode.\n"
+"\n"
+" -html-image-scale <percent>\n"
+" Scale images in graphics mode.\n"
+"\n"
+" -html-bare-image-autoscale <0>/<1>\n"
+" Autoscale images displayed on full screen.\n"
+"\n"
+" -html-numbered-links <0>/<1>\n"
+" Number links in text mode. Allow quick link selection by typing\n"
+" link number and enter.\n"
+"\n"
+" -html-table-order <0>/<1>\n"
+" In text mode, walk through table by rows (0) or columns (1).\n"
+"\n"
+" -html-auto-refresh <0>/<1>\n"
+" Process refresh to other page (1), or display link to that page (0).\n"
+"\n"
+" -html-target-in-new-window <0>/<1>\n"
+" Allow opening new windows from html.\n"
+"\n"
+" -html-margin <number of spaces>\n"
+" Margin in text mode.\n"
+"\n"
+" -html-user-font-size <size>\n"
+" Size of font on pages in graphics mode.\n"
+"\n"
+" -html-t-text-color <0>-<15>\n"
+" Text color in text mode.\n"
+"\n"
+" -html-t-link-color <0>-<15>\n"
+" Link color in text mode.\n"
+"\n"
+" -html-t-background-color <0>-<7>\n"
+" Background color in text mode.\n"
+"\n"
+" -html-t-ignore-document-color <0>/<1>\n"
+" Ignore colors specified in html document in text mode.\n"
+"\n"
+" -html-g-text-color 0xRRGGBB\n"
+" Text color in graphics mode.\n"
+"\n"
+" -html-g-link-color 0xRRGGBB\n"
+" Link color in graphics mode.\n"
+"\n"
+" -html-g-background-color 0xRRGGBB\n"
+" Background color in graphics mode.\n"
+"\n"
+" -html-g-ignore-document-color <0>/<1>\n"
+" Ignore colors specified in html document in graphics mode.\n"
+"\n"
+" -lookup <hostname>\n"
+" Does name lookup, like command \"host\".\n"
+"\n"
+" -version\n"
+" Prints the links version number and exit.\n"
+"\n"
+" -help\n"
+" Prints this help screen\n"
+"\n"
+"\n"),
+("Keys:\n"
+" ESC display menu\n"
+" ^C quit\n"
+" ^P scroll up\n"
+" ^N scroll down\n"
+" [, ] scroll left, right\n"
+" up, down select link\n"
+" ->, enter follow link\n"
+" <-, z go back\n"
+" g go to url\n"
+" G go to url based on current url\n"
+" ^G go to url based on current link\n"
+" ^R reload\n"
+" / search\n"
+" ? search back\n"
+" n find next\n"
+" N find previous\n"
+" = document info\n"
+" \\ document source\n"
+" | HTTP header\n"
+" * toggle displaying of image links (text mode)\n"
+" d download\n"
+" s bookmarks\n"
+" q quit or close current window\n"
+" ^X cut to clipboard\n"
+" ^V paste from clipboard\n"
+" ^K cut line (in textarea) or text to the end (in field)\n"
+" ^U cut all text before cursor\n"
+" ^W autocomplete url\n"
+" Alt-1 .. Alt-9\n"
+" switch virtual screens (svgalib and framebuffer)\n"
+"\n"
+"Keys for braille terminal:\n"
+" arrows move the cursor\n"
+" enter follow link\n"
+" a cursor to status line\n"
+" w cursor to title\n"
+" ^Y next link\n"
+" ^T previous link\n"
+" y next word\n"
+" t previous word\n"
+" ^O next form field entry\n"
+));
+
+ fflush(stdout);
+ return "";
+}
+
+void end_config(void)
+{
+ struct driver_param *dp;
+ foreach(dp,driver_params)
+ {
+ if (dp->param)mem_free(dp->param);
+ if (dp->shell)mem_free(dp->shell);
+ }
+ free_list(driver_params);
+ if (links_home) mem_free(links_home);
+}
+
+int ggr = 0;
+unsigned char ggr_drv[MAX_STR_LEN] = "";
+unsigned char ggr_mode[MAX_STR_LEN] = "";
+unsigned char ggr_display[MAX_STR_LEN] = "";
+
+int anonymous = 0;
+
+unsigned char default_target[MAX_STR_LEN] ="";
+
+unsigned char *links_home = NULL;
+int first_use = 0;
+
+int no_connect = 0;
+int base_session = 0;
+int dmp = 0;
+int force_html = 0;
+
+int max_connections = 10;
+int max_connections_to_host = 8;
+int max_tries = 3;
+int receive_timeout = 120;
+int unrestartable_receive_timeout = 600;
+unsigned char bind_ip_address[16] = "";
+int async_lookup = 1;
+int download_utime = 0;
+
+int screen_width = 80;
+int dump_codepage = -1;
+
+int max_format_cache_entries = 5;
+int memory_cache_size = 1048576;
+int image_cache_size = 1048576;
+int font_cache_size = 2097152;
+
+struct document_setup dds = {
+ 0, /* assumed codepage */
+ 0, /* ignore codepage from server */
+ 1, /* tables */
+ 1, /* frames */
+ 0, /* images */
+ 0, /* image_names */
+ 3, /* margin */
+ 0, /* num_links */
+ 0, /* table_order */
+ 0, /* auto_refresh */
+ 18, /* font_size */
+ 1, /* display images */
+ 100, /* image scale */
+ 0, /* porn enable */
+ 0, /* target in new window */
+ 7, /* t text color */
+ 15, /* t link color */
+ 0, /* t background color */
+ 0, /* t ignore document color */
+ 0x000000, /* g text color */
+ 0x0000ff, /* g link color */
+ 0xc0c0c0, /* g background color */
+ 0, /* g ignore document color */
+};
+
+struct proxies proxies = { "", "", "", "", 0 };
+int js_enable=1; /* 0=disable javascript */
+int js_verbose_errors=0; /* 1=create dialog on every javascript error, 0=be quiet and continue */
+int js_verbose_warnings=0; /* 1=create dialog on every javascript warning, 0=be quiet and continue */
+int js_all_conversions=1;
+int js_global_resolve=1; /* resolvovani v globalnim adresnim prostoru, kdyz BFU vomitne document */
+int js_manual_confirmation=1; /* !0==annoying dialog on every goto url etc. */
+int js_fun_depth=100;
+int js_memory_limit=5*1024; /* in kilobytes, should be in range 1M-20M (1MB=1024*1024B) */
+
+int display_optimize=0; /*0=CRT, 1=LCD RGB, 2=LCD BGR */
+int gamma_bits=2; /*0 --- 8, 1 --- 16, 2 --- auto */
+double bfu_aspect=1; /* 0.1 to 10.0, 1.0 default. >1 makes circle wider */
+int aspect_on=1;
+
+unsigned char download_dir[MAX_STR_LEN] = "";
+
+int aggressive_cache = 1;
+
+struct ftp_options ftp_options = { "somebody@host.domain", 0, 0, 1 };
+
+/* These are workarounds for some CGI script bugs */
+struct http_options http_options = { 0, 1, 1, 0, 0, 0, 0, { REFERER_NONE, "", "", "" } };
+/*int bug_302_redirect = 0;*/
+ /* When got 301 or 302 from POST request, change it to GET
+ - this violates RFC2068, but some buggy message board scripts rely on it */
+/*int bug_post_no_keepalive = 0;*/
+ /* No keepalive connection after POST request. Some buggy PHP databases report bad
+ results if GET wants to retreive data POSTed in the same connection */
+
+static struct option links_options[] = {
+ {1, printhelp_cmd, NULL, NULL, 0, 0, NULL, NULL, "?"},
+ {1, printhelp_cmd, NULL, NULL, 0, 0, NULL, NULL, "h"},
+ {1, printhelp_cmd, NULL, NULL, 0, 0, NULL, NULL, "help"},
+ {1, printhelp_cmd, NULL, NULL, 0, 0, NULL, NULL, "-help"},
+ {1, lookup_cmd, NULL, NULL, 0, 0, NULL, NULL, "lookup"},
+ {1, version_cmd, NULL, NULL, 0, 0, NULL, NULL, "version"},
+ {1, set_cmd, NULL, NULL, 0, 0, &no_connect, NULL, "no-connect"},
+ {1, set_cmd, NULL, NULL, 0, 0, &anonymous, NULL, "anonymous"},
+ {1, set_cmd, NULL, NULL, 0, 0, &ggr, NULL, "g"},
+ {1, unset_cmd, NULL, NULL, 0, 0, &ggr, NULL, "no-g"},
+ {1, setstr_cmd, NULL, NULL, 0, MAX_STR_LEN, &ggr_drv, NULL, "driver"},
+ {1, setstr_cmd, NULL, NULL, 0, MAX_STR_LEN, &default_target, NULL, "target"},
+ {1, setstr_cmd, NULL, NULL, 0, MAX_STR_LEN, &ggr_mode, NULL, "mode"},
+ {1, setstr_cmd, NULL, NULL, 0, MAX_STR_LEN, &ggr_display, NULL, "display"},
+ {1, gen_cmd, num_rd, NULL, 0, MAXINT, &base_session, NULL, "base-session"},
+ {1, set_cmd, NULL, NULL, 0, 0, &force_html, NULL, "force-html"},
+ {1, dump_cmd, NULL, NULL, D_SOURCE, 0, NULL, NULL, "source"},
+ {1, dump_cmd, NULL, NULL, D_DUMP, 0, NULL, NULL, "dump"},
+ {1, gen_cmd, num_rd, NULL, 10, 512, &screen_width, "dump_width", "width" },
+ {1, gen_cmd, cp_rd, NULL, 1, 0, &dump_codepage, "dump_codepage", "codepage" },
+ {1, gen_cmd, num_rd, num_wr, 1, 99, &max_connections, "max_connections", "max-connections"},
+ {1, gen_cmd, num_rd, num_wr, 1, 99, &max_connections_to_host, "max_connections_to_host", "max-connections-to-host"},
+ {1, gen_cmd, num_rd, num_wr, 0, 16, &max_tries, "retries", "retries"},
+ {1, gen_cmd, num_rd, num_wr, 1, 9999, &receive_timeout, "receive_timeout", "receive-timeout"},
+ {1, gen_cmd, num_rd, num_wr, 1, 9999, &unrestartable_receive_timeout, "unrestartable_receive_timeout", "unrestartable-receive-timeout"},
+ {1, gen_cmd, ip_rd, str_wr, 0, 16, bind_ip_address, "bind_address", "bind-address"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &async_lookup, "async_dns", "async-dns"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &download_utime, "download_utime", "download-utime"},
+ {1, gen_cmd, num_rd, num_wr, 0, 999, &max_format_cache_entries, "format_cache_size", "format-cache-size"},
+ {1, gen_cmd, num_rd, num_wr, 0, MAXINT, &memory_cache_size, "memory_cache_size", "memory-cache-size"},
+ {1, gen_cmd, num_rd, num_wr, 0, MAXINT, &image_cache_size, "image_cache_size", "image-cache-size"},
+ {1, gen_cmd, num_rd, num_wr, 0, MAXINT, &font_cache_size, "font_cache_size", "font-cache-size"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, proxies.http_proxy, "http_proxy", "http-proxy"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, proxies.ftp_proxy, "ftp_proxy", "ftp-proxy"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, proxies.socks_proxy, "socks_proxy", "socks-proxy"},
+ {1, gen_cmd, str_rd, NULL, 0, MAX_STR_LEN, proxies.dns_append, "-append_text_to_dns_lookups", NULL}, /* old version incorrectly saved it with '-' */
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, proxies.dns_append, "append_text_to_dns_lookups", "append-text-to-dns-lookups"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &proxies.only_proxies, "only_proxies", "only-proxies"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, download_dir, "download_dir", "download-dir"},
+ {1, gen_cmd, lang_rd, lang_wr, 0, 0, &current_language, "language", "language"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.http10, "http_bugs.http10", "http-bugs.http10"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.allow_blacklist, "http_bugs.allow_blacklist", "http-bugs.allow-blacklist"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.bug_302_redirect, "http_bugs.bug_302_redirect", "http-bugs.bug-302-redirect"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.bug_post_no_keepalive, "http_bugs.bug_post_no_keepalive", "http-bugs.bug-post-no-keepalive"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.no_accept_charset, "http_bugs.no_accept_charset", "http-bugs.bug-no-accept-charset"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.no_compression, "http_bugs.no_compression", "http-bugs.no-compression"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &http_options.retry_internal_errors, "http_bugs.retry_internal_errors", "http-bugs.retry-internal-errors"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &aggressive_cache, "http_bugs.aggressive_cache", "aggressive-cache"},
+ {1, gen_cmd, num_rd, num_wr, 0, 4, &http_options.header.referer, "http_referer", "http.referer"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, &http_options.header.fake_referer, "fake_referer", "http.fake-referer"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, &http_options.header.fake_useragent, "fake_useragent", "http.fake-user-agent"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, &http_options.header.extra_header, "http.extra_header", "http.extra-header"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, ftp_options.anon_pass, "ftp.anonymous_password", "ftp.anonymous-password"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &ftp_options.passive_ftp, "ftp.use_passive", "ftp.use-passive"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &ftp_options.fast_ftp, "ftp.fast", "ftp.fast"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &ftp_options.set_tos, "ftp.set_iptos", "ftp.set-iptos"},
+ {1, gen_cmd, num_rd, num_wr, 1, MAX_FONT_SIZE, &menu_font_size, "menu_font_size", "menu-font-size"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &G_BFU_BG_COLOR, "background_color", "menu-background-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &G_BFU_FG_COLOR, "foreground_color", "menu-foreground-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &G_SCROLL_BAR_AREA_COLOR, "scroll_bar_area_color", "scroll-bar-area-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &G_SCROLL_BAR_BAR_COLOR, "scroll_bar_bar_color", "scroll-bar-bar-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &G_SCROLL_BAR_FRAME_COLOR, "scroll_bar_frame_color", "scroll-bar-frame-color"},
+ {1, gen_cmd, dbl_rd, dbl_wr, 1, 10000, &display_red_gamma, "display_red_gamma", "display-red-gamma"},
+ {1, gen_cmd, dbl_rd, dbl_wr, 1, 10000, &display_green_gamma, "display_green_gamma", "display-green-gamma"},
+ {1, gen_cmd, dbl_rd, dbl_wr, 1, 10000, &display_blue_gamma, "display_blue_gamma", "display-blue-gamma"},
+ {1, gen_cmd, dbl_rd, dbl_wr, 1, 10000, &user_gamma, "user_gamma", "user-gamma"},
+ {1, gen_cmd, dbl_rd, dbl_wr, 25, 400, &bfu_aspect, "bfu_aspect", "bfu-aspect"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &aspect_on, "aspect_on", "aspect-on"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dither_letters, "dither_letters", "dither-letters"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dither_images, "dither_images", "dither-images"},
+ {1, gen_cmd, num_rd, num_wr, 0, 2, &display_optimize, "display_optimize", "display-optimize"},
+ {1, gen_cmd, num_rd, num_wr, 0, 2, &gamma_bits, "gamma_correction", "gamma-correction"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &js_enable, "enable_javascript", "enable-javascript"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &js_verbose_errors, "verbose_javascript_errors", "js.verbose-errors"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &js_verbose_warnings, "verbose_javascript_warnings", "js.verbose-warnings"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &js_all_conversions, "enable_all_conversions", "js.enable-all-conversions"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &js_global_resolve, "enable_global_resolution", "js.enable-global-resolution"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &js_manual_confirmation, "javascript_manual_confirmation", "js.manual-confirmation"},
+ {1, gen_cmd, num_rd, num_wr, 0, 999999, &js_fun_depth, "js_recursion_depth", "js.recursion-depth"},
+ {1, gen_cmd, num_rd, num_wr, 1024, 30*1024, &js_memory_limit, "js_memory_limit", "js.memory-limit"},
+ {1, gen_cmd, cp_rd, cp_wr, 0, 0, &bookmarks_codepage, "bookmarks_codepage", "bookmarks-codepage"},
+ {1, gen_cmd, str_rd, str_wr, 0, MAX_STR_LEN, bookmarks_file, "bookmarks_file", "bookmarks-file"},
+ {1, gen_cmd, cp_rd, NULL, 0, 0, &dds.assume_cp, "assume_codepage", "assume-codepage"},
+ {1, NULL, term_rd, term_wr, 0, 0, NULL, "terminal", NULL},
+ {1, NULL, term2_rd, NULL, 0, 0, NULL, "terminal2", NULL},
+ {1, NULL, type_rd, type_wr, 0, 0, NULL, "association", NULL},
+ {1, NULL, ext_rd, ext_wr, 0, 0, NULL, "extension", NULL},
+ {1, NULL, prog_rd, prog_wr, 0, 0, &mailto_prog, "mailto", NULL},
+ {1, NULL, prog_rd, prog_wr, 0, 0, &telnet_prog, "telnet", NULL},
+ {1, NULL, prog_rd, prog_wr, 0, 0, &tn3270_prog, "tn3270", NULL},
+ {1, NULL, prog_rd, prog_wr, 0, 0, &mms_prog, "mms", NULL},
+ {1, NULL, prog_rd, prog_wr, 0, 0, &magnet_prog, "magnet", NULL},
+ {1, NULL, block_rd, block_wr, 0, 0, NULL, "imageblock", NULL},
+ {1, NULL, dp_rd, dp_wr, 0, 0, NULL, "video_driver", NULL},
+ {0, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL},
+};
+
+static struct option html_options[] = {
+ {1, gen_cmd, cp_rd, cp_wr, 0, 0, &dds.assume_cp, "html_assume_codepage", "html-assume-codepage"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.hard_assume, "html_hard_assume", "html-hard-assume"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.tables, "html_tables", "html-tables"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.frames, "html_frames", "html-frames"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.images, "html_images", "html-images"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.image_names, "html_image_names", "html-image-names"},
+ {1, gen_cmd, num_rd, num_wr, 0, 9, &dds.margin, "html_margin", "html-margin"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.num_links, "html_numbered_links", "html-numbered-links"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.table_order, "html_table_order", "html-table-order"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.auto_refresh, "html_auto_refresh", "html-auto-refresh"},
+ {1, gen_cmd, num_rd, num_wr, 1, MAX_FONT_SIZE, &dds.font_size, "html_font_size", "html-user-font-size"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.display_images, "html_display_images", "html-display-images"},
+ {1, gen_cmd, num_rd, num_wr, 1, 500, &dds.image_scale, "html_image_scale", "html-image-scale"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.porn_enable, "html_bare_image_autoscale", "html-bare-image-autoscale"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.target_in_new_window, "html_target_in_new_window", "html-target-in-new-window"},
+ {1, gen_cmd, num_rd, num_wr, 0, 15, &dds.t_text_color, "html_text_color", "html-text-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 15, &dds.t_link_color, "html_link_color", "html-link-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 7, &dds.t_background_color, "html_background_color", "html-background-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.t_ignore_document_color, "html_ignore_document_color", "html-ignore-document-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &dds.g_text_color, "html_g_text_color", "html-g-text-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &dds.g_link_color, "html_g_link_color", "html-g-link-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 0xffffff, &dds.g_background_color, "html_g_background_color", "html-g-background-color"},
+ {1, gen_cmd, num_rd, num_wr, 0, 1, &dds.g_ignore_document_color, "html_g_ignore_document_color", "html-g-ignore-document-color"},
+ {0, NULL, NULL, NULL, 0, 0, NULL, NULL, NULL},
+};
+
+static struct option *all_options[] = { links_options, html_options, NULL, };
+
+unsigned char *parse_options(int argc, unsigned char *argv[])
+{
+ return p_arse_options(argc, argv, all_options);
+}
+
+static void load_config_file(unsigned char *prefix, unsigned char *name)
+{
+ unsigned char *c, *config_file;
+ config_file = stracpy(prefix);
+ if (!config_file) return;
+ add_to_strn(&config_file, name);
+ if ((c = read_config_file(config_file))) goto ok;
+ mem_free(config_file);
+ config_file = stracpy(prefix);
+ if (!config_file) return;
+ add_to_strn(&config_file, ".");
+ add_to_strn(&config_file, name);
+ if ((c = read_config_file(config_file))) goto ok;
+ mem_free(config_file);
+ return;
+ ok:
+ parse_config_file(config_file, c, all_options);
+ mem_free(c);
+ mem_free(config_file);
+}
+
+void load_config(void)
+{
+#ifdef SHARED_CONFIG_DIR
+ load_config_file(SHARED_CONFIG_DIR, "links.cfg");
+#endif
+ load_config_file(links_home, "links.cfg");
+ load_config_file(links_home, "html.cfg");
+ load_config_file(links_home, "user.cfg");
+}
+
+void write_config(struct terminal *term)
+{
+#ifdef G
+ if (F) update_driver_param();
+#endif
+ write_config_data(links_home, "links.cfg", links_options, term);
+}
+
+void write_html_config(struct terminal *term)
+{
+ write_config_data(links_home, "html.cfg", html_options, term);
+}
+
+void load_url_history(void)
+{
+ unsigned char *history_file, *hs;
+ unsigned char *hsp;
+
+ if (anonymous) return;
+ /* Must have been called after init_home */
+ if (!links_home) return;
+ history_file = stracpy(links_home);
+ add_to_strn(&history_file, "links.his");
+ hs = read_config_file(history_file);
+ mem_free(history_file);
+ if (!hs) return;
+ for (hsp = hs; *hsp; ) {
+ unsigned char *hsl, *hsc;
+ for (hsl = hsp; *hsl && *hsl != 10 && *hsl != 13; hsl++)
+ ;
+ hsc = memacpy(hsp, hsl - hsp);
+ add_to_history(&goto_url_history, hsc, 0);
+ mem_free(hsc);
+ hsp = hsl;
+ while (*hsp == 10 || *hsp == 13) hsp++;
+ }
+ mem_free(hs);
+}
+
+void save_url_history(void)
+{
+ struct history_item *hi;
+ unsigned char *history_file;
+ unsigned char *hs;
+ int hsl = 0;
+ int i = 0;
+ if (anonymous) return;
+
+ /* Must have been called after init_home */
+ if (!links_home) return;
+ history_file = stracpy(links_home);
+ add_to_strn(&history_file, "links.his");
+ hs = init_str();
+ hsl = 0;
+ foreachback(hi, goto_url_history.items) {
+ if (!*hi->d || strchr(hi->d, 10) || strchr(hi->d, 13)) continue;
+ if (i++ > MAX_HISTORY_ITEMS)
+ break;
+ else {
+ add_to_str(&hs, &hsl, hi->d);
+ add_to_str(&hs, &hsl, NEWLINE);
+ }
+ }
+ write_to_config_file(history_file, hs);
+ mem_free(history_file);
+ mem_free(hs);
+ return;
+}
+