src/platform_unix.c
author Roker <roker@pep-project.org>
Tue, 20 Sep 2016 15:54:57 +0200
branchroker-linux
changeset 1168 4d4e3ecbaf8b
parent 1095 fe699b711ae6
child 1118 df6c0c9aa76a
child 1126 129b561095a6
permissions -rw-r--r--
merge "default" into my branch
     1 #define _POSIX_C_SOURCE 200809L
     2 
     3 #include <string.h>
     4 #include <stdlib.h>
     5 #include <assert.h>
     6 #include <sys/stat.h>
     7 #include <sys/types.h>
     8 #include <fcntl.h>
     9 #include <regex.h>
    10 
    11 #include "platform_unix.h"
    12 
    13 #define MAX_PATH 1024
    14 #define LOCAL_DB_FILENAME ".pEp_management.db"
    15 #define SYSTEM_DB_FILENAME "system.db"
    16 
    17 #ifndef bool
    18 #define bool int
    19 #define true 1
    20 #define false 0
    21 #endif
    22 
    23 #ifdef ANDROID
    24 char *stpncpy(char *dst, const char *src, size_t n)
    25 {
    26     if (n != 0) {
    27         char *d = dst;
    28         const char *s = src;
    29 
    30         dst = &dst[n];
    31         do {
    32             if ((*d++ = *s++) == 0) {
    33                 dst = d - 1;
    34                 /* NUL pad the remaining n-1 bytes */
    35                 while (--n != 0)
    36                     *d++ = 0;
    37                 break;
    38             }
    39         } while (--n != 0);
    40     }
    41     return (dst);
    42 }
    43 
    44 char *stpcpy(char *dst, const char *src)
    45 {
    46     for (;; ++dst, ++src) {
    47         *dst = *src;
    48         if (*dst == 0)
    49             break;
    50     }
    51     return dst;
    52 }
    53 
    54 long int random(void)
    55 {
    56     static bool seeded = false;
    57     static unsigned short xsubi[3];
    58     if(!seeded)
    59     {
    60         const long long t = (long long)time(NULL);
    61         xsubi[0] = (unsigned short)t;
    62         xsubi[1] = (unsigned short)(t>>16);
    63         xsubi[2] = (unsigned short)(t>>32);
    64         seeded = true;
    65     }
    66 
    67     return nrand48(xsubi);
    68 }
    69 
    70 const char *android_system_db(void)
    71 {
    72     static char buffer[MAX_PATH];
    73     static bool done = false;
    74 
    75     if (!done) {
    76         char *tw_env;
    77         if(tw_env = getenv("TRUSTWORDS")){
    78             char *p = stpncpy(buffer, tw_env, MAX_PATH);
    79             ssize_t len = MAX_PATH - (p - buffer) - 2;
    80 
    81             if (len < strlen(SYSTEM_DB_FILENAME)) {
    82                 assert(0);
    83                 return NULL;
    84             }
    85 
    86             *p++ = '/';
    87             strncpy(p, SYSTEM_DB_FILENAME, len);
    88             done = true;
    89         }else{
    90             return NULL;
    91         }
    92 
    93     }
    94     return buffer;
    95 }
    96 #endif
    97 
    98 #if !defined(BSD) && !defined(__APPLE__)
    99 
   100 size_t strlcpy(char* dst, const	char* src, size_t size) {
   101     size_t retval = strlen(src);
   102     size_t size_to_copy = (retval < size ? retval : size - 1);
   103     
   104     // strlcpy doc says src and dst not allowed to overlap, as
   105     // it's undefined. So this is acceptable:
   106     memcpy((void*)dst, (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
   107     dst[size_to_copy] = '\0';
   108     return retval;
   109 }
   110 
   111 size_t strlcat(char* dst, const	char* src, size_t size) {
   112     size_t start_len = strnlen(dst, size);
   113     if (start_len == size)
   114         return size; // no copy, no null termination in size bytes, according to spec
   115     
   116     size_t add_len = strlen(src);
   117     size_t retval = start_len + add_len;
   118     size_t size_to_copy = (retval < size ? add_len : (size - start_len) - 1);
   119     
   120     // strlcat doc says src and dst not allowed to overlap, as
   121     // it's undefined. So this is acceptable:
   122     memcpy((void*)(dst + start_len), (void*)src, size_to_copy); // no defined error return, but strcpy doesn't either
   123     dst[start_len + size_to_copy] = '\0';
   124     return retval;
   125 }
   126 
   127 #ifdef USE_NETPGP
   128 // FIXME: This may cause problems - this is a quick compatibility fix for netpgp code
   129 int regnexec(const regex_t* preg, const char* string,
   130              size_t len, size_t nmatch, regmatch_t pmatch[], int eflags) {
   131     return regexec(preg, string, nmatch, pmatch, eflags);
   132 }
   133 #endif
   134 
   135 #endif
   136 
   137 const char *unix_local_db(void)
   138 {
   139     static char buffer[MAX_PATH];
   140     static bool done = false;
   141 
   142     if (!done) {
   143         char *home_env;
   144         if((home_env = getenv("HOME"))){
   145             char *p = stpncpy(buffer, home_env, MAX_PATH);
   146             ssize_t len = MAX_PATH - (p - buffer) - 2;
   147 
   148             if (len < strlen(LOCAL_DB_FILENAME)) {
   149                 assert(0);
   150                 return NULL;
   151             }
   152 
   153             *p++ = '/';
   154             strncpy(p, LOCAL_DB_FILENAME, len);
   155             done = true;
   156         }else{
   157             return NULL;
   158         }
   159 
   160     }
   161     return buffer;
   162 }
   163 
   164 static const char *gpg_conf_path = ".gnupg";
   165 static const char *gpg_conf_name = "gpg.conf";
   166 static const char *gpg_agent_conf_name = "gpg-agent.conf";
   167 static const char *gpg_conf_empty = "# Created by pEpEngine\n";
   168 
   169 static bool ensure_gpg_home(const char **conf, const char **home){
   170     static char path[MAX_PATH];
   171     static char dirname[MAX_PATH];
   172     static bool done = false;
   173 
   174     if (!done) {
   175         char *p;
   176         ssize_t len;
   177         char *gpg_home_env = getenv("GNUPGHOME");
   178         char *home_env = getenv("HOME");
   179 
   180         if(gpg_home_env){
   181 
   182             p = stpncpy(path, gpg_home_env, MAX_PATH);
   183             len = MAX_PATH - (p - path) - 2;
   184 
   185             if (len < strlen(gpg_conf_name))
   186             {
   187                 assert(0);
   188                 return false;
   189             }
   190 
   191         }else if(home_env){
   192 
   193             p = stpncpy(path, home_env, MAX_PATH);
   194             len = MAX_PATH - (p - path) - 3;
   195 
   196             if (len < strlen(gpg_conf_path) + strlen(gpg_conf_name))
   197             {
   198                 assert(0);
   199                 return false;
   200             }
   201 
   202             *p++ = '/';
   203             strncpy(p, gpg_conf_path, len);
   204             p += strlen(gpg_conf_path);
   205             len -= strlen(gpg_conf_path) - 1;
   206 
   207         }else{
   208 
   209             assert(0);
   210             return false;
   211         }
   212 
   213         strncpy(dirname, path, MAX_PATH);
   214         *p++ = '/';
   215         strncpy(p, gpg_conf_name, len);
   216 
   217         if(access(path, F_OK)){ 
   218             int fd;
   219             if(access(dirname, F_OK )) { 
   220                 mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
   221             }
   222 
   223             fd = open(path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
   224 
   225             if(fd>0) {
   226                 write(fd, gpg_conf_empty, strlen(gpg_conf_empty));
   227                 close(fd);
   228             }
   229         }
   230 
   231         done = true;
   232     }
   233 
   234     if(conf) *conf=path;
   235     if(home) *home=dirname;
   236 
   237     return true;
   238 }
   239 
   240 static bool ensure_gpg_agent_conf(const char **agent_conf){
   241     static char agent_path[MAX_PATH];
   242     static bool done = false;
   243 
   244     if (!done) {
   245         const char *dirname;
   246 
   247         if (!ensure_gpg_home(NULL, &dirname)) /* Then dirname won't be set. */
   248             return false;
   249 
   250         char *p;
   251         p = stpncpy(agent_path, dirname, MAX_PATH);
   252         
   253         ssize_t len = MAX_PATH - (p - agent_path) - 2;
   254 
   255         if (len < strlen(gpg_agent_conf_name))
   256         {
   257             assert(0);
   258             return false;
   259         }
   260 
   261         *p++ = '/';
   262      
   263         strncpy(p, gpg_agent_conf_name, len);
   264 
   265         if(access(agent_path, F_OK)){ 
   266             int fd;
   267             if(access(dirname, F_OK )) { 
   268                 mkdir(dirname, S_IRUSR | S_IWUSR | S_IXUSR);
   269             }
   270 
   271             fd = open(agent_path, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
   272 
   273             if(fd>0) {
   274                 write(fd, gpg_conf_empty, strlen(gpg_conf_empty));
   275                 close(fd);
   276             }
   277         }
   278         done = true;
   279     }
   280     if(agent_conf) *agent_conf=agent_path;
   281 
   282     return true;
   283 }
   284 
   285 const char *gpg_conf(void)
   286 {
   287     const char *conf;
   288     if(ensure_gpg_home(&conf, NULL))
   289         return conf;
   290     return NULL;
   291 }
   292 
   293 const char *gpg_home(void)
   294 {
   295     const char *home;
   296     if(ensure_gpg_home(NULL, &home))
   297         return home;
   298     return NULL;
   299 }
   300 
   301 const char *gpg_agent_conf(void)
   302 {
   303     const char *agent_conf;
   304     if(ensure_gpg_agent_conf(&agent_conf))
   305         return agent_conf;
   306     return NULL;
   307 }