1 /* $Id: etc.c,v 1.81 2007/05/23 15:06:05 inu Exp $ */
3 #ifndef __MINGW32_VERSION
12 #include <sys/types.h>
14 #if defined(HAVE_WAITPID) || defined(HAVE_WAIT3)
20 #define read(a,b,c) read_s(a,b,c)
21 #define close(x) close_s(x)
22 #endif /* __WATT32__ */
33 struct auth_pass *next;
36 struct auth_pass *passwords = NULL;
39 columnSkip(Buffer *buf, int offset)
42 int column = buf->currentColumn + offset;
43 int nlines = buf->LINES + 1;
47 for (i = 0, l = buf->topLine; i < nlines && l != NULL; i++, l = l->next) {
49 l->width = COLPOS(l, l->len);
50 if (l->width - 1 > maxColumn)
51 maxColumn = l->width - 1;
53 maxColumn -= buf->COLS - 1;
54 if (column < maxColumn)
59 if (buf->currentColumn == maxColumn)
61 buf->currentColumn = maxColumn;
66 columnPos(Line *line, int column)
70 for (i = 1; i < line->len; i++) {
71 if (COLPOS(line, i) > column)
75 for (i--; i > 0 && line->propBuf[i] & PC_WCHAR2; i--) ;
83 lineSkip(Buffer *buf, Line *line, int offset, int last)
88 l = currentLineSkip(buf, line, offset, last);
89 if (!nextpage_topline)
90 for (i = buf->LINES - 1 - (buf->lastLine->linenumber - l->linenumber);
91 i > 0 && l->prev != NULL; i--, l = l->prev) ;
96 currentLineSkip(Buffer *buf, Line *line, int offset, int last)
101 if (buf->pagerSource && !(buf->bufferprop & BP_CLOSE)) {
102 n = line->linenumber + offset + buf->LINES;
103 if (buf->lastLine->linenumber < n)
104 getNextPage(buf, n - buf->lastLine->linenumber);
105 while ((last || (buf->lastLine->linenumber < n)) &&
106 (getNextPage(buf, 1) != NULL)) ;
114 for (i = 0; i < offset && l->next != NULL; i++, l = l->next) ;
116 for (i = 0; i < -offset && l->prev != NULL; i++, l = l->prev) ;
120 #define MAX_CMD_LEN 128
125 extern Hash_si tagtable;
126 char cmdstr[MAX_CMD_LEN];
132 /* first character */
133 if (IS_ALNUM(**s) || **s == '_' || **s == '/') {
134 *(p++) = TOLOWER(**s);
141 while ((IS_ALNUM(**s) || **s == '_') && p - cmdstr < MAX_CMD_LEN) {
142 *(p++) = TOLOWER(**s);
145 if (p - cmdstr == MAX_CMD_LEN) {
146 /* buffer overflow: perhaps caused by bad HTML source */
153 cmd = getHash_si(&tagtable, cmdstr, HTML_UNKNOWN);
154 while (**s && **s != '>')
161 #ifdef USE_ANSI_COLOR
163 parse_ansi_color(char **str, Lineprop *effect, Linecolor *color)
166 Lineprop e = *effect;
167 Linecolor c = *color;
170 if (*p != ESC_CODE || *(p + 1) != '[')
173 for (q = p; IS_DIGIT(*q) || *q == ';'; q++) ;
185 for (p++; IS_DIGIT(*p); p++) ;
186 i = atoi(allocStr(q, p - q));
202 case 100: /* for EWS4800 kterm */
212 if (i >= 30 && i <= 37)
213 c = (c & 0xf0) | (i - 30) | 0x08;
214 else if (i >= 40 && i <= 47)
215 c = (c & 0x0f) | ((i - 40) << 4) | 0x80;
234 * Check character type
238 checkType(Str s, Lineprop **oprop, Linecolor **ocolor)
241 Lineprop effect = PE_NORMAL;
243 static Lineprop *prop_buffer = NULL;
244 static int prop_size = 0;
245 char *str = s->ptr, *endp = &s->ptr[s->length], *bs = NULL;
246 #ifdef USE_ANSI_COLOR
247 Lineprop ceffect = PE_NORMAL;
249 int check_color = FALSE;
250 Linecolor *color = NULL;
251 static Linecolor *color_buffer = NULL;
252 static int color_size = 0;
259 if (prop_size < s->length) {
260 prop_size = (s->length > LINELEN) ? s->length : LINELEN;
261 prop_buffer = New_Reuse(Lineprop, prop_buffer, prop_size);
266 bs = memchr(str, '\b', s->length);
267 #ifdef USE_ANSI_COLOR
269 es = memchr(str, ESC_CODE, s->length);
271 if (color_size < s->length) {
272 color_size = (s->length > LINELEN) ? s->length : LINELEN;
273 color_buffer = New_Reuse(Linecolor, color_buffer,
276 color = color_buffer;
281 #ifdef USE_ANSI_COLOR
286 s = Strnew_size(s->length);
288 ep = bs ? (bs - 2) : endp;
289 #ifdef USE_ANSI_COLOR
290 if (es && ep > es - 2)
293 for (; str < ep && IS_ASCII(*str); str++) {
294 *(prop++) = PE_NORMAL | (IS_CNTRL(*str) ? PC_CTRL : PC_ASCII);
295 #ifdef USE_ANSI_COLOR
300 Strcat_charp_n(s, sp, (int)(str - sp));
304 for (; str < endp && IS_ASCII(*str); str++)
305 *(prop++) = PE_NORMAL | (IS_CNTRL(*str) ? PC_CTRL : PC_ASCII);
309 if (prop - prop_buffer >= prop_size)
313 if (str == bs - 2 && !strncmp(str, "__\b\b", 4)) {
317 bs = memchr(str, '\b', endp - str);
322 if (str == bs - 1 && *str == '_') {
326 bs = memchr(str, '\b', endp - str);
329 else if (str == bs) {
330 if (*(str + 1) == '_') {
334 for (i = 1; i <= plen; i++)
335 *(prop - i) |= PE_UNDER;
337 *(prop - 1) |= PE_UNDER;
345 else if (!strncmp(str + 1, "\b__", 3)) {
347 str += (plen == 1) ? 3 : 4;
348 for (i = 1; i <= plen; i++)
349 *(prop - i) |= PE_UNDER;
355 else if (*(str + 1) == '\b') {
357 clen = get_mclen(str + 2);
359 !strncmp(str - plen, str + 2, plen)) {
360 for (i = 1; i <= plen; i++)
361 *(prop - i) |= PE_BOLD;
378 clen = get_mclen(str + 1);
380 !strncmp(str - plen, str + 1, plen)) {
381 for (i = 1; i <= plen; i++)
382 *(prop - i) |= PE_BOLD;
391 if (*(str - 1) == *(str + 1)) {
392 *(prop - 1) |= PE_BOLD;
407 bs = memchr(str, '\b', endp - str);
410 #ifdef USE_ANSI_COLOR
412 bs = memchr(str, '\b', endp - str);
415 #ifdef USE_ANSI_COLOR
418 int ok = parse_ansi_color(&str, &ceffect, &cmode);
420 es = memchr(str, ESC_CODE, endp - str);
428 es = memchr(str, ESC_CODE, endp - str);
432 plen = get_mclen(str);
433 mode = get_mctype(str) | effect;
434 #ifdef USE_ANSI_COLOR
443 mode = (mode & ~PC_WCHAR1) | PC_WCHAR2;
444 for (i = 1; i < plen; i++) {
446 #ifdef USE_ANSI_COLOR
452 Strcat_charp_n(s, (char *)str, plen);
459 Strcat_char(s, (char)*str);
464 *oprop = prop_buffer;
465 #ifdef USE_ANSI_COLOR
467 *ocolor = check_color ? color_buffer : NULL;
473 nextColumn(int n, char *p, Lineprop *pr)
477 return (n + Tabstop) / Tabstop * Tabstop;
485 if (*pr & PC_UNKNOWN)
487 return n + wtf_width((wc_uchar *) p);
494 calcPosition(char *l, Lineprop *pr, int len, int pos, int bpos, int mode)
496 static int *realColumn = NULL;
498 static char *prevl = NULL;
501 if (l == NULL || len == 0)
503 if (l == prevl && mode == CP_AUTO) {
505 return realColumn[pos];
507 if (size < len + 1) {
508 size = (len + 1 > LINELEN) ? (len + 1) : LINELEN;
509 realColumn = New_N(int, size);
515 if (pr[i] & PC_WCHAR2) {
516 for (; i < len && pr[i] & PC_WCHAR2; i++)
518 if (i > 0 && pr[i - 1] & PC_KANJI && WcOption.use_wide)
526 j = nextColumn(j, &l[i], &pr[i]);
529 for (; i < len && pr[i] & PC_WCHAR2; i++)
530 realColumn[i] = realColumn[i - 1];
535 return realColumn[pos];
539 columnLen(Line *line, int column)
543 for (i = 0, j = 0; i < line->len;) {
544 j = nextColumn(j, &line->lineBuf[i], &line->propBuf[i]);
549 while (i < line->len && line->propBuf[i] & PC_WCHAR2)
557 lastFileName(char *path)
568 return allocStr(q, -1);
571 #ifdef USE_INCLUDED_SRAND48
572 static unsigned long R1 = 0x1234abcd;
573 static unsigned long R2 = 0x330e;
581 R1 = (unsigned long)seed;
588 R1 = (A1 * R1 << 16) + A1 * R2 + A2 * R1 + ((A2 * R2 + C) >> 16);
589 R2 = (A2 * R2 + C) & 0xffff;
590 return (long)(R1 >> 1);
600 while (s <= p && *p != '/')
606 return allocStr(p, -1);
617 while (s != p && *p == '/')
619 while (s != p && *p != '/')
623 while (s != p && *p == '/')
625 return allocStr(s, strlen(s) - strlen(p) + 1);
628 #ifndef HAVE_STRERROR
632 extern char *sys_errlist[];
633 return sys_errlist[errno];
635 #endif /* not HAVE_STRERROR */
637 #ifndef HAVE_SYS_ERRLIST
640 prepare_sys_errlist()
645 while (strerror(i) != NULL)
648 sys_errlist = New_N(char *, n);
650 for (i = 1; i < n; i++)
651 sys_errlist[i] = strerror(i);
653 #endif /* not HAVE_SYS_ERRLIST */
656 next_status(char c, int *status)
673 *status = R_ST_CMNT1;
677 /* continues to next case */
680 *status = R_ST_NORMAL;
686 *status = R_ST_DQUOTE;
688 *status = R_ST_QUOTE;
689 else if (IS_SPACE(c))
692 *status = R_ST_NORMAL;
694 *status = R_ST_VALUE;
706 *status = R_ST_NORMAL;
707 else if (IS_SPACE(c))
712 *status = R_ST_NORMAL;
715 else if (c != '#' && !IS_ALNUM(c) && c != '_') {
716 /* something's wrong! */
717 *status = R_ST_NORMAL;
725 *status = R_ST_CMNT2;
728 *status = R_ST_NORMAL;
731 *status = R_ST_IRRTAG;
740 *status = R_ST_NORMAL;
743 *status = R_ST_IRRTAG;
748 *status = R_ST_NCMNT1;
752 *status = R_ST_NCMNT2;
759 *status = R_ST_NORMAL;
762 *status = R_ST_NCMNT2;
766 *status = R_ST_NCMNT3;
775 *status = R_ST_NORMAL;
778 *status = R_ST_NCMNT1;
782 *status = R_ST_NCMNT3;
790 *status = R_ST_NORMAL;
798 read_token(Str buf, char **instr, int *status, int pre, int append)
807 for (p = *instr; *p; p++) {
808 prev_status = *status;
809 next_status(*p, status);
812 if (prev_status == R_ST_AMP && *p != ';') {
816 if (prev_status == R_ST_NCMNT2 || prev_status == R_ST_NCMNT3 ||
817 prev_status == R_ST_IRRTAG || prev_status == R_ST_CMNT1) {
818 if (prev_status == R_ST_CMNT1 && !append && !pre)
821 Strcat_char(buf, *p);
825 Strcat_char(buf, (!pre && IS_SPACE(*p)) ? ' ' : *p);
826 if (ST_IS_REAL_TAG(prev_status)) {
828 if (buf->length < 2 ||
829 buf->ptr[buf->length - 2] != '<' ||
830 buf->ptr[buf->length - 1] != '>')
837 if (prev_status == R_ST_NORMAL && p != *instr) {
839 *status = prev_status;
842 if (*status == R_ST_TAG0 && !REALLY_THE_BEGINNING_OF_A_TAG(p)) {
843 /* it seems that this '<' is not a beginning of a tag */
845 * Strcat_charp(buf, "<");
847 Strcat_char(buf, '<');
848 *status = R_ST_NORMAL;
851 Strcat_char(buf, *p);
858 Strcat_char(buf, *p);
863 Strcat_char(buf, *p);
874 Strcat_char(buf, *p);
884 correct_irrtag(int status)
889 while (status != R_ST_NORMAL) {
891 case R_ST_CMNT: /* required "-->" */
892 case R_ST_NCMNT1: /* required "->" */
902 case R_ST_EQL: /* required ">" */
918 next_status(c, &status);
925 * RFC2617: 1.2 Access Authentication Framework
927 * The realm value (case-sensitive), in combination with the canonical root
928 * URL (the absoluteURI for the server whose abs_path is empty; see section
929 * 5.1.2 of RFC2616 ) of the server being accessed, defines the protection
930 * space. These realms allow the protected resources on a server to be
931 * partitioned into a set of protection spaces, each with its own
932 * authentication scheme and/or authorization database.
936 add_auth_pass_entry(const struct auth_pass *ent, int netrc, int override)
938 if ((ent->host || netrc) /* netrc accept default (host == NULL) */
939 &&(ent->is_proxy || ent->realm || netrc)
940 && ent->uname && ent->pwd) {
941 struct auth_pass *newent = New(struct auth_pass);
942 memcpy(newent, ent, sizeof(struct auth_pass));
944 newent->next = passwords;
948 if (passwords == NULL)
950 else if (passwords->next == NULL)
951 passwords->next = newent;
953 struct auth_pass *ep = passwords;
954 for (; ep->next; ep = ep->next) ;
959 /* ignore invalid entries */
962 static struct auth_pass *
963 find_auth_pass_entry(char *host, int port, char *realm, char *uname,
966 struct auth_pass *ent;
967 for (ent = passwords; ent != NULL; ent = ent->next) {
968 if (ent->is_proxy == is_proxy
969 && (ent->bad != TRUE)
970 && (!ent->host || !Strcasecmp_charp(ent->host, host))
971 && (!ent->port || ent->port == port)
972 && (!ent->uname || !uname || !Strcmp_charp(ent->uname, uname))
973 && (!ent->realm || !realm || !Strcmp_charp(ent->realm, realm))
981 find_auth_user_passwd(ParsedURL *pu, char *realm,
982 Str *uname, Str *pwd, int is_proxy)
984 struct auth_pass *ent;
986 if (pu->user && pu->pass) {
987 *uname = Strnew_charp(pu->user);
988 *pwd = Strnew_charp(pu->pass);
991 ent = find_auth_pass_entry(pu->host, pu->port, realm, pu->user, is_proxy);
1001 add_auth_user_passwd(ParsedURL *pu, char *realm, Str uname, Str pwd,
1004 struct auth_pass ent;
1005 memset(&ent, 0, sizeof(ent));
1007 ent.is_proxy = is_proxy;
1008 ent.host = Strnew_charp(pu->host);
1009 ent.port = pu->port;
1010 ent.realm = Strnew_charp(realm);
1013 add_auth_pass_entry(&ent, 0, 1);
1017 invalidate_auth_user_passwd(ParsedURL *pu, char *realm, Str uname, Str pwd,
1020 struct auth_pass *ent;
1021 ent = find_auth_pass_entry(pu->host, pu->port, realm, NULL, is_proxy);
1034 * path <file> ; not used
1046 if (arg == NULL || arg->length == 0)
1055 narg = Strnew_charp(q);
1061 parsePasswd(FILE * fp, int netrc)
1063 struct auth_pass ent;
1066 bzero(&ent, sizeof(struct auth_pass));
1071 if (line == NULL || line->length == 0)
1072 line = Strfgets(fp);
1073 if (line->length == 0)
1076 Strremovefirstspaces(line);
1078 if (*p == '#' || *p == '\0') {
1080 continue; /* comment or empty line */
1082 arg = next_token(line);
1084 if (!strcmp(p, "machine") || !strcmp(p, "host")
1085 || (netrc && !strcmp(p, "default"))) {
1086 add_auth_pass_entry(&ent, netrc, 0);
1087 bzero(&ent, sizeof(struct auth_pass));
1089 ent.port = 21; /* XXX: getservbyname("ftp"); ? */
1090 if (strcmp(p, "default") != 0) {
1091 line = next_token(arg);
1098 else if (!netrc && !strcmp(p, "port") && arg) {
1099 line = next_token(arg);
1100 ent.port = atoi(arg->ptr);
1102 else if (!netrc && !strcmp(p, "proxy")) {
1106 else if (!netrc && !strcmp(p, "path")) {
1107 line = next_token(arg);
1108 /* ent.file = arg; */
1110 else if (!netrc && !strcmp(p, "realm")) {
1111 /* XXX: rest of line becomes arg for realm */
1115 else if (!strcmp(p, "login")) {
1116 line = next_token(arg);
1119 else if (!strcmp(p, "password") || !strcmp(p, "passwd")) {
1120 line = next_token(arg);
1123 else if (netrc && !strcmp(p, "machdef")) {
1124 while ((line = Strfgets(fp))->length != 0) {
1125 if (*line->ptr == '\n')
1130 else if (netrc && !strcmp(p, "account")) {
1132 line = next_token(arg);
1135 /* ignore rest of line */
1139 add_auth_pass_entry(&ent, netrc, 0);
1142 /* FIXME: gettextize? */
1143 #define FILE_IS_READABLE_MSG "SECURITY NOTE: file %s must not be accessible by others"
1146 openSecretFile(char *fname)
1153 efname = expandPath(fname);
1154 if (stat(efname, &st) < 0)
1157 /* check permissions, if group or others readable or writable,
1158 * refuse it, because it's insecure.
1160 * XXX: disable_secret_security_check will introduce some
1161 * security issues, but on some platform such as Windows
1162 * it's not possible (or feasible) to disable group|other
1163 * readable and writable.
1164 * [w3m-dev 03368][w3m-dev 03369][w3m-dev 03370]
1166 if (disable_secret_security_check)
1168 else if ((st.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
1169 if (fmInitialized) {
1170 message(Sprintf(FILE_IS_READABLE_MSG, fname)->ptr, 0, 0);
1174 fputs(Sprintf(FILE_IS_READABLE_MSG, fname)->ptr, stderr);
1175 fputc('\n', stderr);
1181 return fopen(efname, "r");
1190 fp = openSecretFile(passwd_file);
1197 fp = openSecretFile("~/.netrc");
1205 /* get last modified time */
1207 last_modified(Buffer *buf)
1212 if (buf->document_header) {
1213 for (ti = buf->document_header->first; ti; ti = ti->next) {
1214 if (strncasecmp(ti->ptr, "Last-modified: ", 15) == 0) {
1215 return ti->ptr + 15;
1220 else if (buf->currentURL.scheme == SCM_LOCAL) {
1221 if (stat(buf->currentURL.file, &st) < 0)
1223 return ctime(&st.st_mtime);
1228 static char roman_num1[] = {
1229 'i', 'x', 'c', 'm', '*',
1231 static char roman_num5[] = {
1236 romanNum2(int l, int n)
1245 Strcat_char(s, roman_num1[l]);
1248 Strcat_char(s, roman_num1[l]);
1249 Strcat_char(s, roman_num5[l]);
1255 Strcat_char(s, roman_num5[l]);
1256 for (n -= 5; n > 0; n--)
1257 Strcat_char(s, roman_num1[l]);
1260 Strcat_char(s, roman_num1[l]);
1261 Strcat_char(s, roman_num1[l + 1]);
1275 Strcat_charp(r, "**");
1278 Strcat(r, romanNum2(3, n / 1000));
1279 Strcat(r, romanNum2(2, (n % 1000) / 100));
1280 Strcat(r, romanNum2(1, (n % 100) / 10));
1281 Strcat(r, romanNum2(0, n % 10));
1287 romanAlphabet(int n)
1298 buf[l++] = 'a' + (n - 1) % 26;
1303 Strcat_char(r, buf[l]);
1309 #define SIGIOT SIGABRT
1310 #endif /* not SIGIOT */
1316 mySignal(SIGHUP, SIG_DFL); /* terminate process */
1318 mySignal(SIGINT, SIG_DFL); /* terminate process */
1320 mySignal(SIGQUIT, SIG_DFL); /* terminate process */
1322 mySignal(SIGTERM, SIG_DFL); /* terminate process */
1323 mySignal(SIGILL, SIG_DFL); /* create core image */
1324 mySignal(SIGIOT, SIG_DFL); /* create core image */
1325 mySignal(SIGFPE, SIG_DFL); /* create core image */
1327 mySignal(SIGBUS, SIG_DFL); /* create core image */
1330 mySignal(SIGCHLD, SIG_IGN);
1333 mySignal(SIGPIPE, SIG_IGN);
1338 #define FOPEN_MAX 1024 /* XXX */
1342 close_all_fds_except(int i, int f)
1344 switch (i) { /* fall through */
1346 dup2(open(DEV_NULL_PATH, O_RDONLY), 0);
1348 dup2(open(DEV_NULL_PATH, O_WRONLY), 1);
1350 dup2(open(DEV_NULL_PATH, O_WRONLY), 2);
1352 /* close all other file descriptors (socket, ...) */
1353 for (i = 3; i < FOPEN_MAX; i++) {
1360 setup_child(int child, int i, int f)
1363 mySignal(SIGINT, SIG_IGN);
1364 #ifndef __MINGW32_VERSION
1367 #endif /* __MINGW32_VERSION */
1369 close_all_fds_except(i, f);
1370 QuietMessage = TRUE;
1371 fmInitialized = FALSE;
1375 #ifndef __MINGW32_VERSION
1377 open_pipe_rw(FILE ** fr, FILE ** fw)
1383 if (fr && pipe(fdr) < 0)
1385 if (fw && pipe(fdw) < 0)
1409 *fr = fdopen(fdr[0], "r");
1416 *fw = fdopen(fdw[1], "w");
1433 #endif /* __MINGW32_VERSION */
1436 myExec(char *command)
1438 mySignal(SIGINT, SIG_DFL);
1439 execl("/bin/sh", "sh", "-c", command, NULL);
1444 mySystem(char *command, int background)
1446 #ifndef __MINGW32_VERSION
1451 setup_child(FALSE, 0, -1);
1455 Str cmd = Strnew_charp("start /f ");
1456 Strcat_charp(cmd, command);
1461 #endif /* __MINGW32_VERSION */
1466 myExtCommand(char *cmd, char *arg, int redirect)
1470 int set_arg = FALSE;
1472 for (p = cmd; *p; p++) {
1473 if (*p == '%' && *(p + 1) == 's' && !set_arg) {
1475 tmp = Strnew_charp_n(cmd, (int)(p - cmd));
1476 Strcat_charp(tmp, arg);
1482 Strcat_char(tmp, *p);
1487 tmp = Strnew_m_charp("(", cmd, ") < ", arg, NULL);
1489 tmp = Strnew_m_charp(cmd, " ", arg, NULL);
1495 myEditor(char *cmd, char *file, int line)
1499 int set_file = FALSE, set_line = FALSE;
1501 for (p = cmd; *p; p++) {
1502 if (*p == '%' && *(p + 1) == 's' && !set_file) {
1504 tmp = Strnew_charp_n(cmd, (int)(p - cmd));
1505 Strcat_charp(tmp, file);
1509 else if (*p == '%' && *(p + 1) == 'd' && !set_line && line > 0) {
1511 tmp = Strnew_charp_n(cmd, (int)(p - cmd));
1512 Strcat(tmp, Sprintf("%d", line));
1518 Strcat_char(tmp, *p);
1523 tmp = Strnew_charp(cmd);
1524 if (!set_line && line > 1 && strcasestr(cmd, "vi"))
1525 Strcat(tmp, Sprintf(" +%d", line));
1526 Strcat_m_charp(tmp, " ", file, NULL);
1531 #ifdef __MINGW32_VERSION
1533 expandName(char *name)
1535 return getenv("HOME");
1539 expandName(char *name)
1542 struct passwd *passent, *getpwnam(const char *);
1549 if ((*(p + 1) == '~' && IS_ALPHA(*(p + 2)))
1550 && personal_document_root) {
1554 if (q) { /* /~user/dir... */
1555 passent = getpwnam(allocStr(p, q - p));
1559 passent = getpwnam(p);
1564 extpath = Strnew_m_charp(passent->pw_dir, "/",
1565 personal_document_root, NULL);
1566 if (*personal_document_root == '\0' && *p == '/')
1571 if (Strcmp_charp(extpath, "/") == 0 && *p == '/')
1573 Strcat_charp(extpath, p);
1574 return extpath->ptr;
1577 return expandPath(p);
1584 file_to_url(char *file)
1587 #ifdef SUPPORT_DOS_DRIVE_PREFIX
1590 #ifdef SUPPORT_NETBIOS_SHARE
1594 file = expandPath(file);
1595 #ifdef SUPPORT_NETBIOS_SHARE
1596 if (file[0] == '/' && file[1] == '/') {
1600 p = strchr(file, '/');
1601 if (p != NULL && p != file) {
1602 host = allocStr(file, (p - file));
1608 #ifdef SUPPORT_DOS_DRIVE_PREFIX
1609 if (IS_ALPHA(file[0]) && file[1] == ':') {
1610 drive = allocStr(file, 2);
1615 if (file[0] != '/') {
1616 tmp = Strnew_charp(CurrentDir);
1617 if (Strlastchar(tmp) != '/')
1618 Strcat_char(tmp, '/');
1619 Strcat_charp(tmp, file);
1622 tmp = Strnew_charp("file://");
1623 #ifdef SUPPORT_NETBIOS_SHARE
1625 Strcat_charp(tmp, host);
1627 #ifdef SUPPORT_DOS_DRIVE_PREFIX
1629 Strcat_charp(tmp, drive);
1631 Strcat_charp(tmp, file_quote(cleanupName(file)));
1637 url_unquote_conv(char *url, wc_ces charset)
1640 url_unquote_conv0(char *url)
1644 wc_uint8 old_auto_detect = WcOption.auto_detect;
1647 tmp = Str_url_unquote(Strnew_charp(url), FALSE, TRUE);
1649 if (!charset || charset == WC_CES_US_ASCII)
1650 charset = SystemCharset;
1651 WcOption.auto_detect = WC_OPT_DETECT_ON;
1652 tmp = convertLine(NULL, tmp, RAW_MODE, &charset, charset);
1653 WcOption.auto_detect = old_auto_detect;
1658 static char *tmpf_base[MAX_TMPF_TYPE] = {
1659 "tmp", "src", "frame", "cache", "cookie",
1661 static unsigned int tmpf_seq[MAX_TMPF_TYPE];
1664 tmpfname(int type, char *ext)
1667 tmpf = Sprintf("%s/w3m%s%d-%d%s",
1670 CurrentPid, tmpf_seq[type]++, (ext) ? ext : "");
1671 pushText(fileToDelete, tmpf->ptr);
1675 static char *monthtbl[] = {
1676 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1677 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1690 while (**s && IS_DIGIT(**s))
1691 Strcat_char(tmp, *((*s)++));
1693 day = atoi(tmp->ptr);
1695 if (day < 1 || day > 31) {
1712 while (**s && IS_DIGIT(**s))
1713 Strcat_char(tmp, *((*s)++));
1714 if (tmp->length > 0) {
1715 mon = atoi(tmp->ptr);
1718 while (**s && IS_ALPHA(**s))
1719 Strcat_char(tmp, *((*s)++));
1720 for (mon = 1; mon <= 12; mon++) {
1721 if (strncmp(tmp->ptr, monthtbl[mon - 1], 3) == 0)
1725 if (mon < 1 || mon > 12) {
1742 while (**s && IS_DIGIT(**s))
1743 Strcat_char(tmp, *((*s)++));
1744 if (tmp->length != 2 && tmp->length != 4) {
1749 year = atoi(tmp->ptr);
1750 if (tmp->length == 2) {
1760 get_time(char **s, int *hour, int *min, int *sec)
1768 while (**s && IS_DIGIT(**s))
1769 Strcat_char(tmp, *((*s)++));
1774 *hour = atoi(tmp->ptr);
1778 while (**s && IS_DIGIT(**s))
1779 Strcat_char(tmp, *((*s)++));
1784 *min = atoi(tmp->ptr);
1788 while (**s && IS_DIGIT(**s))
1789 Strcat_char(tmp, *((*s)++));
1790 *sec = atoi(tmp->ptr);
1792 if (*hour < 0 || *hour >= 24 ||
1793 *min < 0 || *min >= 60 || *sec < 0 || *sec >= 60) {
1801 get_zone(char **s, int *z_hour, int *z_min)
1810 if (**s == '+' || **s == '-')
1811 Strcat_char(tmp, *((*s)++));
1812 while (**s && IS_DIGIT(**s))
1813 Strcat_char(tmp, *((*s)++));
1814 if (!(tmp->length == 4 && IS_DIGIT(*ss)) &&
1815 !(tmp->length == 5 && (*ss == '+' || *ss == '-'))) {
1820 zone = atoi(tmp->ptr);
1821 *z_hour = zone / 100;
1822 *z_min = zone - (zone / 100) * 100;
1826 /* RFC 1123 or RFC 850 or ANSI C asctime() format string -> time_t */
1828 mymktime(char *timestr)
1831 int day, mon, year, hour, min, sec, z_hour = 0, z_min = 0;
1833 if (!(timestr && *timestr))
1838 fprintf(stderr, "mktime: %s\n", timestr);
1841 while (*s && IS_ALPHA(*s))
1843 while (*s && !IS_ALNUM(*s))
1847 /* RFC 1123 or RFC 850 format */
1848 if ((day = get_day(&s)) == -1)
1851 while (*s && !IS_ALNUM(*s))
1853 if ((mon = get_month(&s)) == -1)
1856 while (*s && !IS_DIGIT(*s))
1858 if ((year = get_year(&s)) == -1)
1861 while (*s && !IS_DIGIT(*s))
1869 if (get_time(&s, &hour, &min, &sec) == -1)
1871 while (*s && !IS_DIGIT(*s) && *s != '+' && *s != '-')
1873 get_zone(&s, &z_hour, &z_min);
1877 /* ANSI C asctime() format. */
1878 while (*s && !IS_ALNUM(*s))
1880 if ((mon = get_month(&s)) == -1)
1883 while (*s && !IS_DIGIT(*s))
1885 if ((day = get_day(&s)) == -1)
1888 while (*s && !IS_DIGIT(*s))
1890 if (get_time(&s, &hour, &min, &sec) == -1)
1893 while (*s && !IS_DIGIT(*s))
1895 if ((year = get_year(&s)) == -1)
1900 "year=%d month=%d day=%d hour:min:sec=%d:%d:%d zone=%d:%d\n", year,
1901 mon, day, hour, min, sec, z_hour, z_min);
1909 day += (year - 1968) * 1461 / 4;
1910 day += ((((mon * 153) + 2) / 5) - 672);
1913 return (time_t) ((day * 60 * 60 * 24) +
1914 (hour * 60 * 60) + (min * 60) + sec);
1919 #include <sys/socket.h>
1921 #ifndef __MINGW32_VERSION
1924 #include <winsock.h>
1931 struct hostent *entry;
1939 if (strcasecmp(host, "localhost") == 0)
1942 for (p = host; *p && *p != '.'; p++) ;
1948 if (!(entry = gethostbyname(host)))
1951 return allocStr(entry->h_name, -1);
1953 for (af = ai_family_order_table[DNS_order];; af++) {
1955 struct addrinfo hints;
1956 struct addrinfo *res, *res0;
1959 memset(&hints, 0, sizeof(hints));
1960 hints.ai_flags = AI_CANONNAME;
1961 hints.ai_family = *af;
1962 hints.ai_socktype = SOCK_STREAM;
1963 error = getaddrinfo(host, NULL, &hints, &res0);
1965 if (*af == PF_UNSPEC) {
1969 /* try next address family */
1972 for (res = res0; res != NULL; res = res->ai_next) {
1973 if (res->ai_canonname) {
1975 namebuf = strdup(res->ai_canonname);
1981 if (*af == PF_UNSPEC) {
1990 #endif /* USE_COOKIE */
1992 void (*mySignal(int signal_number, void (*action) (int))) (int) {
1994 struct sigaction new_action, old_action;
1996 sigemptyset(&new_action.sa_mask);
1997 new_action.sa_handler = action;
1998 if (signal_number == SIGALRM) {
2000 new_action.sa_flags = SA_INTERRUPT;
2002 new_action.sa_flags = 0;
2006 new_action.sa_flags = SA_RESTART;
2008 sigaction(signal_number, &new_action, &old_action);
2009 return (old_action.sa_handler);
2011 return (signal(signal_number, action));