139beb93cSSam Leffler /* 239beb93cSSam Leffler * wpa_supplicant/hostapd / OS specific functions for UNIX/POSIX systems 339beb93cSSam Leffler * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> 439beb93cSSam Leffler * 539beb93cSSam Leffler * This program is free software; you can redistribute it and/or modify 639beb93cSSam Leffler * it under the terms of the GNU General Public License version 2 as 739beb93cSSam Leffler * published by the Free Software Foundation. 839beb93cSSam Leffler * 939beb93cSSam Leffler * Alternatively, this software may be distributed under the terms of BSD 1039beb93cSSam Leffler * license. 1139beb93cSSam Leffler * 1239beb93cSSam Leffler * See README and COPYING for more details. 1339beb93cSSam Leffler */ 1439beb93cSSam Leffler 1539beb93cSSam Leffler #include "includes.h" 1639beb93cSSam Leffler 1739beb93cSSam Leffler #include "os.h" 1839beb93cSSam Leffler 1939beb93cSSam Leffler void os_sleep(os_time_t sec, os_time_t usec) 2039beb93cSSam Leffler { 2139beb93cSSam Leffler if (sec) 2239beb93cSSam Leffler sleep(sec); 2339beb93cSSam Leffler if (usec) 2439beb93cSSam Leffler usleep(usec); 2539beb93cSSam Leffler } 2639beb93cSSam Leffler 2739beb93cSSam Leffler 2839beb93cSSam Leffler int os_get_time(struct os_time *t) 2939beb93cSSam Leffler { 3039beb93cSSam Leffler int res; 3139beb93cSSam Leffler struct timeval tv; 3239beb93cSSam Leffler res = gettimeofday(&tv, NULL); 3339beb93cSSam Leffler t->sec = tv.tv_sec; 3439beb93cSSam Leffler t->usec = tv.tv_usec; 3539beb93cSSam Leffler return res; 3639beb93cSSam Leffler } 3739beb93cSSam Leffler 3839beb93cSSam Leffler 3939beb93cSSam Leffler int os_mktime(int year, int month, int day, int hour, int min, int sec, 4039beb93cSSam Leffler os_time_t *t) 4139beb93cSSam Leffler { 4239beb93cSSam Leffler struct tm tm, *tm1; 4339beb93cSSam Leffler time_t t_local, t1, t2; 4439beb93cSSam Leffler os_time_t tz_offset; 4539beb93cSSam Leffler 4639beb93cSSam Leffler if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 4739beb93cSSam Leffler hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 4839beb93cSSam Leffler sec > 60) 4939beb93cSSam Leffler return -1; 5039beb93cSSam Leffler 5139beb93cSSam Leffler memset(&tm, 0, sizeof(tm)); 5239beb93cSSam Leffler tm.tm_year = year - 1900; 5339beb93cSSam Leffler tm.tm_mon = month - 1; 5439beb93cSSam Leffler tm.tm_mday = day; 5539beb93cSSam Leffler tm.tm_hour = hour; 5639beb93cSSam Leffler tm.tm_min = min; 5739beb93cSSam Leffler tm.tm_sec = sec; 5839beb93cSSam Leffler 5939beb93cSSam Leffler t_local = mktime(&tm); 6039beb93cSSam Leffler 6139beb93cSSam Leffler /* figure out offset to UTC */ 6239beb93cSSam Leffler tm1 = localtime(&t_local); 6339beb93cSSam Leffler if (tm1) { 6439beb93cSSam Leffler t1 = mktime(tm1); 6539beb93cSSam Leffler tm1 = gmtime(&t_local); 6639beb93cSSam Leffler if (tm1) { 6739beb93cSSam Leffler t2 = mktime(tm1); 6839beb93cSSam Leffler tz_offset = t2 - t1; 6939beb93cSSam Leffler } else 7039beb93cSSam Leffler tz_offset = 0; 7139beb93cSSam Leffler } else 7239beb93cSSam Leffler tz_offset = 0; 7339beb93cSSam Leffler 7439beb93cSSam Leffler *t = (os_time_t) t_local - tz_offset; 7539beb93cSSam Leffler return 0; 7639beb93cSSam Leffler } 7739beb93cSSam Leffler 7839beb93cSSam Leffler 7939beb93cSSam Leffler #ifdef __APPLE__ 8039beb93cSSam Leffler #include <fcntl.h> 8139beb93cSSam Leffler static int os_daemon(int nochdir, int noclose) 8239beb93cSSam Leffler { 8339beb93cSSam Leffler int devnull; 8439beb93cSSam Leffler 8539beb93cSSam Leffler if (chdir("/") < 0) 8639beb93cSSam Leffler return -1; 8739beb93cSSam Leffler 8839beb93cSSam Leffler devnull = open("/dev/null", O_RDWR); 8939beb93cSSam Leffler if (devnull < 0) 9039beb93cSSam Leffler return -1; 9139beb93cSSam Leffler 9239beb93cSSam Leffler if (dup2(devnull, STDIN_FILENO) < 0) { 9339beb93cSSam Leffler close(devnull); 9439beb93cSSam Leffler return -1; 9539beb93cSSam Leffler } 9639beb93cSSam Leffler 9739beb93cSSam Leffler if (dup2(devnull, STDOUT_FILENO) < 0) { 9839beb93cSSam Leffler close(devnull); 9939beb93cSSam Leffler return -1; 10039beb93cSSam Leffler } 10139beb93cSSam Leffler 10239beb93cSSam Leffler if (dup2(devnull, STDERR_FILENO) < 0) { 10339beb93cSSam Leffler close(devnull); 10439beb93cSSam Leffler return -1; 10539beb93cSSam Leffler } 10639beb93cSSam Leffler 10739beb93cSSam Leffler return 0; 10839beb93cSSam Leffler } 10939beb93cSSam Leffler #else /* __APPLE__ */ 11039beb93cSSam Leffler #define os_daemon daemon 11139beb93cSSam Leffler #endif /* __APPLE__ */ 11239beb93cSSam Leffler 11339beb93cSSam Leffler 11439beb93cSSam Leffler int os_daemonize(const char *pid_file) 11539beb93cSSam Leffler { 11639beb93cSSam Leffler #ifdef __uClinux__ 11739beb93cSSam Leffler return -1; 11839beb93cSSam Leffler #else /* __uClinux__ */ 11939beb93cSSam Leffler if (os_daemon(0, 0)) { 12039beb93cSSam Leffler perror("daemon"); 12139beb93cSSam Leffler return -1; 12239beb93cSSam Leffler } 12339beb93cSSam Leffler 12439beb93cSSam Leffler if (pid_file) { 12539beb93cSSam Leffler FILE *f = fopen(pid_file, "w"); 12639beb93cSSam Leffler if (f) { 12739beb93cSSam Leffler fprintf(f, "%u\n", getpid()); 12839beb93cSSam Leffler fclose(f); 12939beb93cSSam Leffler } 13039beb93cSSam Leffler } 13139beb93cSSam Leffler 13239beb93cSSam Leffler return -0; 13339beb93cSSam Leffler #endif /* __uClinux__ */ 13439beb93cSSam Leffler } 13539beb93cSSam Leffler 13639beb93cSSam Leffler 13739beb93cSSam Leffler void os_daemonize_terminate(const char *pid_file) 13839beb93cSSam Leffler { 13939beb93cSSam Leffler if (pid_file) 14039beb93cSSam Leffler unlink(pid_file); 14139beb93cSSam Leffler } 14239beb93cSSam Leffler 14339beb93cSSam Leffler 14439beb93cSSam Leffler int os_get_random(unsigned char *buf, size_t len) 14539beb93cSSam Leffler { 14639beb93cSSam Leffler FILE *f; 14739beb93cSSam Leffler size_t rc; 14839beb93cSSam Leffler 14939beb93cSSam Leffler f = fopen("/dev/urandom", "rb"); 15039beb93cSSam Leffler if (f == NULL) { 15139beb93cSSam Leffler printf("Could not open /dev/urandom.\n"); 15239beb93cSSam Leffler return -1; 15339beb93cSSam Leffler } 15439beb93cSSam Leffler 15539beb93cSSam Leffler rc = fread(buf, 1, len, f); 15639beb93cSSam Leffler fclose(f); 15739beb93cSSam Leffler 15839beb93cSSam Leffler return rc != len ? -1 : 0; 15939beb93cSSam Leffler } 16039beb93cSSam Leffler 16139beb93cSSam Leffler 16239beb93cSSam Leffler unsigned long os_random(void) 16339beb93cSSam Leffler { 16439beb93cSSam Leffler return random(); 16539beb93cSSam Leffler } 16639beb93cSSam Leffler 16739beb93cSSam Leffler 16839beb93cSSam Leffler char * os_rel2abs_path(const char *rel_path) 16939beb93cSSam Leffler { 17039beb93cSSam Leffler char *buf = NULL, *cwd, *ret; 17139beb93cSSam Leffler size_t len = 128, cwd_len, rel_len, ret_len; 17239beb93cSSam Leffler int last_errno; 17339beb93cSSam Leffler 17439beb93cSSam Leffler if (rel_path[0] == '/') 17539beb93cSSam Leffler return strdup(rel_path); 17639beb93cSSam Leffler 17739beb93cSSam Leffler for (;;) { 17839beb93cSSam Leffler buf = malloc(len); 17939beb93cSSam Leffler if (buf == NULL) 18039beb93cSSam Leffler return NULL; 18139beb93cSSam Leffler cwd = getcwd(buf, len); 18239beb93cSSam Leffler if (cwd == NULL) { 18339beb93cSSam Leffler last_errno = errno; 18439beb93cSSam Leffler free(buf); 18539beb93cSSam Leffler if (last_errno != ERANGE) 18639beb93cSSam Leffler return NULL; 18739beb93cSSam Leffler len *= 2; 18839beb93cSSam Leffler if (len > 2000) 18939beb93cSSam Leffler return NULL; 19039beb93cSSam Leffler } else { 19139beb93cSSam Leffler buf[len - 1] = '\0'; 19239beb93cSSam Leffler break; 19339beb93cSSam Leffler } 19439beb93cSSam Leffler } 19539beb93cSSam Leffler 19639beb93cSSam Leffler cwd_len = strlen(cwd); 19739beb93cSSam Leffler rel_len = strlen(rel_path); 19839beb93cSSam Leffler ret_len = cwd_len + 1 + rel_len + 1; 19939beb93cSSam Leffler ret = malloc(ret_len); 20039beb93cSSam Leffler if (ret) { 20139beb93cSSam Leffler memcpy(ret, cwd, cwd_len); 20239beb93cSSam Leffler ret[cwd_len] = '/'; 20339beb93cSSam Leffler memcpy(ret + cwd_len + 1, rel_path, rel_len); 20439beb93cSSam Leffler ret[ret_len - 1] = '\0'; 20539beb93cSSam Leffler } 20639beb93cSSam Leffler free(buf); 20739beb93cSSam Leffler return ret; 20839beb93cSSam Leffler } 20939beb93cSSam Leffler 21039beb93cSSam Leffler 21139beb93cSSam Leffler int os_program_init(void) 21239beb93cSSam Leffler { 21339beb93cSSam Leffler return 0; 21439beb93cSSam Leffler } 21539beb93cSSam Leffler 21639beb93cSSam Leffler 21739beb93cSSam Leffler void os_program_deinit(void) 21839beb93cSSam Leffler { 21939beb93cSSam Leffler } 22039beb93cSSam Leffler 22139beb93cSSam Leffler 22239beb93cSSam Leffler int os_setenv(const char *name, const char *value, int overwrite) 22339beb93cSSam Leffler { 22439beb93cSSam Leffler return setenv(name, value, overwrite); 22539beb93cSSam Leffler } 22639beb93cSSam Leffler 22739beb93cSSam Leffler 22839beb93cSSam Leffler int os_unsetenv(const char *name) 22939beb93cSSam Leffler { 23039beb93cSSam Leffler #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) 23139beb93cSSam Leffler unsetenv(name); 23239beb93cSSam Leffler return 0; 23339beb93cSSam Leffler #else 23439beb93cSSam Leffler return unsetenv(name); 23539beb93cSSam Leffler #endif 23639beb93cSSam Leffler } 23739beb93cSSam Leffler 23839beb93cSSam Leffler 23939beb93cSSam Leffler char * os_readfile(const char *name, size_t *len) 24039beb93cSSam Leffler { 24139beb93cSSam Leffler FILE *f; 24239beb93cSSam Leffler char *buf; 24339beb93cSSam Leffler 24439beb93cSSam Leffler f = fopen(name, "rb"); 24539beb93cSSam Leffler if (f == NULL) 24639beb93cSSam Leffler return NULL; 24739beb93cSSam Leffler 24839beb93cSSam Leffler fseek(f, 0, SEEK_END); 24939beb93cSSam Leffler *len = ftell(f); 25039beb93cSSam Leffler fseek(f, 0, SEEK_SET); 25139beb93cSSam Leffler 25239beb93cSSam Leffler buf = malloc(*len); 25339beb93cSSam Leffler if (buf == NULL) { 25439beb93cSSam Leffler fclose(f); 25539beb93cSSam Leffler return NULL; 25639beb93cSSam Leffler } 25739beb93cSSam Leffler 25839beb93cSSam Leffler if (fread(buf, 1, *len, f) != *len) { 25939beb93cSSam Leffler fclose(f); 26039beb93cSSam Leffler free(buf); 26139beb93cSSam Leffler return NULL; 26239beb93cSSam Leffler } 26339beb93cSSam Leffler 26439beb93cSSam Leffler fclose(f); 26539beb93cSSam Leffler 26639beb93cSSam Leffler return buf; 26739beb93cSSam Leffler } 26839beb93cSSam Leffler 26939beb93cSSam Leffler 27039beb93cSSam Leffler void * os_zalloc(size_t size) 27139beb93cSSam Leffler { 27239beb93cSSam Leffler return calloc(1, size); 27339beb93cSSam Leffler } 27439beb93cSSam Leffler 27539beb93cSSam Leffler 27639beb93cSSam Leffler size_t os_strlcpy(char *dest, const char *src, size_t siz) 27739beb93cSSam Leffler { 27839beb93cSSam Leffler const char *s = src; 27939beb93cSSam Leffler size_t left = siz; 28039beb93cSSam Leffler 28139beb93cSSam Leffler if (left) { 28239beb93cSSam Leffler /* Copy string up to the maximum size of the dest buffer */ 28339beb93cSSam Leffler while (--left != 0) { 28439beb93cSSam Leffler if ((*dest++ = *s++) == '\0') 28539beb93cSSam Leffler break; 28639beb93cSSam Leffler } 28739beb93cSSam Leffler } 28839beb93cSSam Leffler 28939beb93cSSam Leffler if (left == 0) { 29039beb93cSSam Leffler /* Not enough room for the string; force NUL-termination */ 29139beb93cSSam Leffler if (siz != 0) 29239beb93cSSam Leffler *dest = '\0'; 29339beb93cSSam Leffler while (*s++) 29439beb93cSSam Leffler ; /* determine total src string length */ 29539beb93cSSam Leffler } 29639beb93cSSam Leffler 29739beb93cSSam Leffler return s - src - 1; 29839beb93cSSam Leffler } 299