/* Misc. routines */ #include "httpd.h" #include /*************/ /* Allocate memory, quit if failed. */ void *salloc(size_t size) { void *ptr; if (!(ptr = malloc(size))) { outerr("Out of memory"); exit(40); } return ptr; } void *srealloc(void *ptr, size_t size) { if (!(ptr = realloc(ptr, size))) { outerr("Out of memory"); exit(40); } return ptr; } /*************/ /* Return the number of a month. 'month' does not have to be * null-terminated. */ static int find_month(char *month) { static char months[12][4] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; int n = 0; while (n < 12 && strncmp(months[n], month, 3)) ++n; if (n > 11) n = -1; return n; } /* Return the number of a weekday (0-6, Sun=0). 'day' does not have to be * null-terminated. */ static int find_day(char *day) { static char days[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; int n = 0; while (n < 7 && strncmp(days[n], day, 3)) ++n; if (n > 6) n = -1; return n; } /* Convert a date in either RFC 822, RFC 850, or asctime() format into a * struct tm. Uses malloc(). */ struct tm *parse_date(char *date) { struct tm *tm = malloc(sizeof(struct tm)); if (!tm) return NULL; switch (date[3]) { case ',': /* RFC 822, updated by RFC 1123 */ tm->tm_wday = find_day(date); tm->tm_mday = atoi(date+5); tm->tm_mon = find_month(date+8); tm->tm_year = atoi(date+12) - 1900; tm->tm_hour = atoi(date+17); tm->tm_min = atoi(date+20); tm->tm_sec = atoi(date+23); break; default: /* RFC 850, obsoleted by RFC 1036 */ tm->tm_wday = find_day(date); date = strchr(date, ',')+2; tm->tm_mday = atoi(date); tm->tm_mon = find_month(date+3); tm->tm_year = atoi(date+7); tm->tm_hour = atoi(date+10); tm->tm_min = atoi(date+13); tm->tm_sec = atoi(date+16); break; case ' ': /* asctime() */ tm->tm_wday = find_day(date); tm->tm_mon = find_month(date+4); tm->tm_mday = atoi(date+8); tm->tm_hour = atoi(date+11); tm->tm_min = atoi(date+14); tm->tm_sec = atoi(date+17); tm->tm_year = atoi(date+20) - 1900; } return tm; } /* Returns like strcmp(): -1 -> a a==b 1 -> a>b */ int timecmp(const struct tm *a, const struct tm *b) { if (a->tm_year < b->tm_year) return -1; else if (a->tm_year > b->tm_year) return 1; if (a->tm_yday < b->tm_yday) return -1; else if (a->tm_yday > b->tm_yday) return 1; if (a->tm_hour < b->tm_hour) return -1; else if (a->tm_hour > b->tm_hour) return 1; if (a->tm_min < b->tm_min) return -1; else if (a->tm_min > b->tm_min) return 1; if (a->tm_sec < b->tm_sec) return -1; else if (a->tm_sec > b->tm_sec) return 1; return 0; } /*************/ char *fgets2(char *buf, size_t maxlen, FILE *f) { if (buf = fgets(buf, maxlen, f)) if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; return buf; } char *Fgets2(char *buf, size_t maxlen, mFILE *f) { if (buf = Fgets(buf, maxlen, f)) if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; return buf; } /*************/ int sgetc(int s) { unsigned char c; fd_set fds, zero_fds; struct timeval tv; chkabort(); FD_ZERO(&zero_fds); FD_ZERO(&fds); FD_SET(s, &fds); tv.tv_sec = 15; tv.tv_usec = 0; // if (select(s+1, &fds, &zero_fds, &zero_fds, &tv) <= 0) // return -1; if (recv(s, &c, 1, 0) <= 0) return -1; return c; } /* if connection was broken, return NULL */ char *sgets(char *buf, unsigned int len, int s) { int c; char *ptr = buf; chkabort(); if (len == 0) return NULL; c = 0; while (--len && c != '\n' && (c = sgetc(s)) >= 0) { /* If we happen to read any backspaces or deletes, act on them */ if (c == 8 || c == 127) { if (ptr > buf) --ptr; } else { *ptr++ = c; } } if (c < 0) return NULL; *ptr = 0; return buf; } char *sgets2(char *buf, size_t maxlen, int s) { if (buf = sgets(buf, maxlen, s)) { if (buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = 0; if (buf[strlen(buf)-1] == '\r') buf[strlen(buf)-1] = 0; } return buf; } int sputs(char *str, int s) { chkabort(); return send(s, str, strlen(str), 0); } int sockprintf(int s, char *fmt,...) { va_list args; char buf[8192]; chkabort(); va_start(args, fmt); vsprintf(buf, fmt, args); sputs(buf, s); return strlen(buf); } /*************/ // Stack: 4k void outerr(char *fmt,...) { va_list args; char *buf; time_t t; char s[4096]; va_start(args, fmt); time(&t); buf = ctime(&t); buf[strlen(buf)-1] = 0; sprintf(s, "[%s] httpd: ", buf); Fputs(s, errlog); vsprintf(s, fmt, args); Fputs(s, errlog); Fputs("\n", errlog); Fflush(errlog); } /*************/ /* Open bsdsocket.library and put the library base in mytask->tc_UserData. */ int OpenSocketLibrary() { struct Library *SocketBase = OpenLibrary("bsdsocket.library", 3); struct Task *me = FindTask(NULL); ((taskData *)me->tc_UserData)->socketBase = SocketBase; return SocketBase != NULL; } /* Close bsdsocket.library from mytask->tc_UserData. */ void CloseSocketLibrary() { struct Task *me = FindTask(NULL); CloseLibrary(((taskData *)me->tc_UserData)->socketBase); } /*************/ /* Replacements for popen()/pclose(), using file routines from multi.c */ // Stack: .5k + 32 mFILE *Popen(const char *cmd, const char *mode) { char buf[32], cmdbuf[512]; static int uniq_id = 0; if (*mode != 'r' && *mode != 'w') return 0; if (*mode == 'w') { fprintf(stderr, "popen: write pipes not supported\n"); return 0; } sprintf(buf, "T:popen.%08x.%d", FindTask(NULL), uniq_id++); sprintf(cmdbuf, "%s >%s", cmd, buf); system(cmdbuf); return Fopen(buf, "r"); } // Stack: 128 int Pclose(mFILE *f) { char buf[128]; char *s; s = Fname(buf, sizeof(buf), f); Fclose(f); if (!s) return -1; remove(s); }