#include #include #include "net.h" #include "err.h" #include "doc.h" int net_addr(const char *url, struct addr *adr, enum protocol prot_default) { char *prot_mark; if ((prot_mark = strstr(url, "://"))) { static struct { const char *str; enum protocol prot; } prot_str_tbl[] = { { "gopher", PROT_GOPHER }, { "gemini", PROT_GEMINI }, { "file", PROT_FILE }, }; size_t n = prot_mark - url; adr->prot = PROT_UNKNOWN; for (size_t i = 0; i < sizeof prot_str_tbl / sizeof *prot_str_tbl; i++) { if (!strncmp(prot_str_tbl[i].str, url, n)) { adr->prot = prot_str_tbl[i].prot; break; } } url = prot_mark + 3; } else { adr->prot = prot_default; } if (adr->prot == PROT_FILE) { adr->host_len = 0; size_t n = strlen(url); if (n >= PATH_MAX) return -1; adr->path_len = n; memcpy(adr->path, url, n + 1); } else { adr->host_len = 0; while (*url && *url != '/' && adr->host_len < HOST_MAX) { adr->host[adr->host_len++] = *url++; } adr->host[adr->host_len] = 0; if (*url && *url != '/') { perr("hostname too long"); return -1; } if (*url) url++; adr->path_len = 0; while (*url && adr->path_len < HOST_MAX) { adr->path[adr->path_len++] = *url++; } adr->path[adr->path_len] = 0; if (*url) { perr("path too long"); return -1; } } return 0; } static int file_fetch(const struct addr *adr, struct buf *buf, enum doc_type *doct) { FILE *f = fopen(adr->path, "r/o"); if (!f) { perr("file not found"); return -1; } buf_init(buf, 1024); char b[256]; while (fgets(b, sizeof b, f)) { buf_cat(buf, b, strlen(b)); } buf_catc(buf, 0); fclose(f); *doct = DOC_PLAIN; return 0; } int net_fetch(const struct addr *adr, struct buf *buf, enum doc_type *doct) { switch (adr->prot) { case PROT_FILE: return file_fetch(adr, buf, doct); default: perr("unsupported protocol"); return -1; } }