LCOV - code coverage report
Current view: top level - src - system.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 57 97 58.8 %
Date: 2016-12-01 18:29:29 Functions: 13 19 68.4 %

          Line data    Source code
       1             : /* system.c - System support functions.
       2             :    Copyright (C) 2009 Free Software Foundation, Inc.
       3             : 
       4             :    This file is part of Assuan.
       5             : 
       6             :    Assuan is free software; you can redistribute it and/or modify it
       7             :    under the terms of the GNU Lesser General Public License as
       8             :    published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    Assuan is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : 
      25             : #include <stdlib.h>
      26             : #include <errno.h>
      27             : #ifdef HAVE_SYS_TYPES_H
      28             :   /* Solaris 8 needs sys/types.h before time.h.  */
      29             : # include <sys/types.h>
      30             : #endif
      31             : #include <time.h>
      32             : #ifdef HAVE_FCNTL_H
      33             : #include <fcntl.h>
      34             : #endif
      35             : 
      36             : #include "assuan-defs.h"
      37             : #include "debug.h"
      38             : 
      39             : #define DEBUG_SYSIO 0
      40             : 
      41             : 
      42             : 
      43             : 
      44             : /* Manage memory specific to a context.  */
      45             : 
      46             : void *
      47           7 : _assuan_malloc (assuan_context_t ctx, size_t cnt)
      48             : {
      49           7 :   return ctx->malloc_hooks.malloc (cnt);
      50             : }
      51             : 
      52             : void *
      53           0 : _assuan_realloc (assuan_context_t ctx, void *ptr, size_t cnt)
      54             : {
      55           0 :   return ctx->malloc_hooks.realloc (ptr, cnt);
      56             : }
      57             : 
      58             : void *
      59           2 : _assuan_calloc (assuan_context_t ctx, size_t cnt, size_t elsize)
      60             : {
      61             :   void *ptr;
      62             :   size_t nbytes;
      63             : 
      64           2 :   nbytes = cnt * elsize;
      65             : 
      66             :   /* Check for overflow.  */
      67           2 :   if (elsize && nbytes / elsize != cnt)
      68             :     {
      69           0 :       gpg_err_set_errno (ENOMEM);
      70           0 :       return NULL;
      71             :     }
      72             : 
      73           2 :   ptr = ctx->malloc_hooks.malloc (nbytes);
      74           2 :   if (ptr)
      75           2 :     memset (ptr, 0, nbytes);
      76           2 :   return ptr;
      77             : }
      78             : 
      79             : void
      80          13 : _assuan_free (assuan_context_t ctx, void *ptr)
      81             : {
      82          13 :   if (ptr)
      83           9 :     ctx->malloc_hooks.free (ptr);
      84          13 : }
      85             : 
      86             : 
      87             : /* Release the memory at PTR using the allocation handler of the
      88             :    context CTX.  This is a convenience function.  */
      89             : void
      90           0 : assuan_free (assuan_context_t ctx, void *ptr)
      91             : {
      92           0 :   _assuan_free (ctx, ptr);
      93           0 : }
      94             : 
      95             : 
      96             : 
      97             : /* Copy the system hooks struct, paying attention to version
      98             :    differences.  SRC is usually from the user, DST MUST be from the
      99             :    library.  */
     100             : void
     101           0 : _assuan_system_hooks_copy (assuan_system_hooks_t dst,
     102             :                            assuan_system_hooks_t src)
     103             : 
     104             : {
     105             :   /* Reset the defaults.  */
     106           0 :   if (dst != &_assuan_system_hooks)
     107           0 :     memcpy (dst, &_assuan_system_hooks, sizeof (*dst));
     108             : 
     109           0 :   dst->version = ASSUAN_SYSTEM_HOOKS_VERSION;
     110           0 :   if (src->version >= 1)
     111             :     {
     112           0 :       dst->usleep = src->usleep;
     113           0 :       dst->pipe = src->pipe;
     114           0 :       dst->close = src->close;
     115           0 :       dst->read = src->read;
     116           0 :       dst->write = src->write;
     117           0 :       dst->sendmsg = src->sendmsg;
     118           0 :       dst->recvmsg = src->recvmsg;
     119           0 :       dst->spawn = src->spawn;
     120           0 :       dst->waitpid = src->waitpid;
     121           0 :       dst->socketpair = src->socketpair;
     122             :     }
     123           0 :   if (src->version >= 2)
     124             :     {
     125           0 :       dst->socket = src->socket;
     126           0 :       dst->connect = src->connect;
     127             :     }
     128           0 :   if (src->version > 2)
     129             :     /* FIXME.  Application uses newer version of the library.  What to
     130             :        do?  */
     131             :     ;
     132           0 : }
     133             : 
     134             : 
     135             : 
     136             : /* Sleep for the given number of microseconds.  */
     137             : void
     138           0 : _assuan_usleep (assuan_context_t ctx, unsigned int usec)
     139             : {
     140           0 :   TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_usleep", ctx,
     141             :           "usec=%u", usec);
     142             : 
     143           0 :   (ctx->system.usleep) (ctx, usec);
     144           0 : }
     145             : 
     146             : 
     147             : 
     148             : /* Create a pipe with one inheritable end.  */
     149             : int
     150           2 : _assuan_pipe (assuan_context_t ctx, assuan_fd_t fd[2], int inherit_idx)
     151             : {
     152             :   int err;
     153           2 :   TRACE_BEG2 (ctx, ASSUAN_LOG_SYSIO, "_assuan_pipe", ctx,
     154             :               "inherit_idx=%i (Assuan uses it for %s)",
     155             :               inherit_idx, inherit_idx ? "reading" : "writing");
     156             : 
     157           2 :   err = (ctx->system.pipe) (ctx, fd, inherit_idx);
     158           2 :   if (err)
     159           0 :     return TRACE_SYSRES (err);
     160             : 
     161           2 :   return TRACE_SUC2 ("read=0x%x, write=0x%x", fd[0], fd[1]);
     162             : }
     163             : 
     164             : 
     165             : 
     166             : /* Close the given file descriptor, created with _assuan_pipe or one
     167             :    of the socket functions.  */
     168             : int
     169           9 : _assuan_close (assuan_context_t ctx, assuan_fd_t fd)
     170             : {
     171           9 :   TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_close", ctx,
     172             :           "fd=0x%x", fd);
     173             : 
     174           9 :   return (ctx->system.close) (ctx, fd);
     175             : }
     176             : 
     177             : 
     178             : /* Same as assuan_close but used for the inheritable end of a
     179             :    pipe.  */
     180             : int
     181           2 : _assuan_close_inheritable (assuan_context_t ctx, assuan_fd_t fd)
     182             : {
     183           2 :   TRACE1 (ctx, ASSUAN_LOG_SYSIO, "_assuan_close_inheritable", ctx,
     184             :           "fd=0x%x", fd);
     185             : 
     186             : #ifdef HAVE_W32CE_SYSTEM
     187             :   return 0; /* Nothing to do because it is a rendezvous id.  */
     188             : #else
     189           2 :   return (ctx->system.close) (ctx, fd);
     190             : #endif
     191             : }
     192             : 
     193             : 
     194             : 
     195             : ssize_t
     196           5 : _assuan_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
     197             : {
     198             : #if DEBUG_SYSIO
     199             :   ssize_t res;
     200             :   TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "_assuan_read", ctx,
     201             :               "fd=0x%x, buffer=%p, size=%i", fd, buffer, size);
     202             :   res = (ctx->system.read) (ctx, fd, buffer, size);
     203             :   return TRACE_SYSRES (res);
     204             : #else
     205           5 :   return (ctx->system.read) (ctx, fd, buffer, size);
     206             : #endif
     207             : }
     208             : 
     209             : 
     210             : 
     211             : ssize_t
     212          13 : _assuan_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer,
     213             :                size_t size)
     214             : {
     215             : #if DEBUG_SYSIO
     216             :   ssize_t res;
     217             :   TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "_assuan_write", ctx,
     218             :               "fd=0x%x, buffer=%p, size=%i", fd, buffer, size);
     219             :   res = (ctx->system.write) (ctx, fd, buffer, size);
     220             :   return TRACE_SYSRES (res);
     221             : #else
     222          13 :   return (ctx->system.write) (ctx, fd, buffer, size);
     223             : #endif
     224             : }
     225             : 
     226             : 
     227             : 
     228             : int
     229          32 : _assuan_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
     230             :                  int flags)
     231             : {
     232             : #if DEBUG_SYSIO
     233             :   ssize_t res;
     234             :   TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "_assuan_recvmsg", ctx,
     235             :               "fd=0x%x, msg=%p, flags=0x%x", fd, msg, flags);
     236             :   res = (ctx->system.recvmsg) (ctx, fd, msg, flags);
     237             :   if (res > 0)
     238             :     {
     239             :       struct cmsghdr *cmptr;
     240             : 
     241             :       TRACE_LOG2 ("msg->msg_iov[0] = { iov_base=%p, iov_len=%i }",
     242             :                   msg->msg_iov[0].iov_base, msg->msg_iov[0].iov_len);
     243             :       TRACE_LOGBUF (msg->msg_iov[0].iov_base, res);
     244             : 
     245             :       cmptr = CMSG_FIRSTHDR (msg);
     246             :       if (cmptr)
     247             :         {
     248             :           void *data = CMSG_DATA (cmptr);
     249             :           TRACE_LOG5 ("cmsg_len=0x%x (0x%x data), cmsg_level=0x%x, "
     250             :                       "cmsg_type=0x%x, first data int=0x%x", cmptr->cmsg_len,
     251             :                       cmptr->cmsg_len - (((char *)data) - ((char *)cmptr)),
     252             :                       cmptr->cmsg_level, cmptr->cmsg_type, *(int *)data);
     253             :         }
     254             :     }
     255             :   return TRACE_SYSRES (res);
     256             : #else
     257          32 :   return (ctx->system.recvmsg) (ctx, fd, msg, flags);
     258             : #endif
     259             : }
     260             : 
     261             : 
     262             : 
     263             : int
     264          59 : _assuan_sendmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
     265             :                  int flags)
     266             : {
     267             : #if DEBUG_SYSIO
     268             :   ssize_t res;
     269             :   TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "_assuan_sendmsg", ctx,
     270             :               "fd=0x%x, msg=%p, flags=0x%x", fd, msg, flags);
     271             :   {
     272             :     struct cmsghdr *cmptr;
     273             : 
     274             :     TRACE_LOG2 ("msg->iov[0] = { iov_base=%p, iov_len=%i }",
     275             :                 msg->msg_iov[0].iov_base, msg->msg_iov[0].iov_len);
     276             :     TRACE_LOGBUF (msg->msg_iov[0].iov_base, msg->msg_iov[0].iov_len);
     277             : 
     278             :     cmptr = CMSG_FIRSTHDR (msg);
     279             :     if (cmptr)
     280             :       {
     281             :         void *data = CMSG_DATA (cmptr);
     282             :         TRACE_LOG5 ("cmsg_len=0x%x (0x%x data), cmsg_level=0x%x, "
     283             :                     "cmsg_type=0x%x, first data int=0x%x", cmptr->cmsg_len,
     284             :                     cmptr->cmsg_len - (((char *)data) - ((char *)cmptr)),
     285             :                     cmptr->cmsg_level, cmptr->cmsg_type, *(int *)data);
     286             :       }
     287             :   }
     288             :   res = (ctx->system.sendmsg) (ctx, fd, msg, flags);
     289             :   return TRACE_SYSRES (res);
     290             : #else
     291          59 :   return (ctx->system.sendmsg) (ctx, fd, msg, flags);
     292             : #endif
     293             : }
     294             : 
     295             : 
     296             : 
     297             : /* Create a new process from NAME and ARGV.  Provide FD_IN and FD_OUT
     298             :    as stdin and stdout.  Inherit the ASSUAN_INVALID_FD-terminated
     299             :    FD_CHILD_LIST as given (no remapping), which must be inheritable.
     300             :    On Unix, call ATFORK with ATFORKVALUE after fork and before exec.  */
     301             : int
     302           2 : _assuan_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
     303             :                const char **argv,
     304             :                assuan_fd_t fd_in, assuan_fd_t fd_out,
     305             :                assuan_fd_t *fd_child_list,
     306             :                void (*atfork) (void *opaque, int reserved),
     307             :                void *atforkvalue, unsigned int flags)
     308             : {
     309             :   int res;
     310             :   int i;
     311           2 :   TRACE_BEG6 (ctx, ASSUAN_LOG_CTX, "_assuan_spawn", ctx,
     312             :               "name=%s,fd_in=0x%x,fd_out=0x%x,"
     313             :               "atfork=%p,atforkvalue=%p,flags=%i",
     314             :               name ? name : "(null)", fd_in, fd_out,
     315             :               atfork, atforkvalue, flags);
     316             : 
     317           2 :   if (name)
     318             :     {
     319           1 :       i = 0;
     320           4 :       while (argv[i])
     321             :         {
     322           2 :           TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
     323           2 :           i++;
     324             :         }
     325             :     }
     326           2 :   i = 0;
     327           2 :   if (fd_child_list)
     328             :     {
     329           7 :       while (fd_child_list[i] != ASSUAN_INVALID_FD)
     330             :         {
     331           3 :           TRACE_LOG2 ("fd_child_list[%2i] = 0x%x", i, fd_child_list[i]);
     332           3 :           i++;
     333             :         }
     334             :     }
     335             : 
     336           2 :   res = (ctx->system.spawn) (ctx, r_pid, name, argv, fd_in, fd_out,
     337             :                               fd_child_list, atfork, atforkvalue, flags);
     338             : 
     339           3 :   if (name)
     340             :     {
     341           1 :       TRACE_LOG1 ("pid = 0x%x", *r_pid);
     342             :     }
     343             :   else
     344             :     {
     345           2 :       TRACE_LOG2 ("pid = 0x%x (%s)", *r_pid, *argv);
     346             :     }
     347             : 
     348           3 :   return TRACE_SYSERR (res);
     349             : }
     350             : 
     351             : 
     352             : 
     353             : /* FIXME: Add some sort of waitpid function that covers GPGME and
     354             :    gpg-agent's use of assuan.  */
     355             : pid_t
     356           3 : _assuan_waitpid (assuan_context_t ctx, pid_t pid, int action,
     357             :                  int *status, int options)
     358             : {
     359             : #if DEBUG_SYSIO
     360             :   ssize_t res;
     361             :   TRACE_BEG4 (ctx, ASSUAN_LOG_SYSIO, "_assuan_waitpid", ctx,
     362             :               "pid=%i, action=%i, status=%p, options=%i",
     363             :               pid, action, status, options);
     364             :   res = (ctx->system.waitpid) (ctx, pid, action, status, options);
     365             :   return TRACE_SYSRES (res);
     366             : #else
     367           3 :   return (ctx->system.waitpid) (ctx, pid, action, status, options);
     368             : #endif
     369             : }
     370             : 
     371             : 
     372             : 
     373             : int
     374           1 : _assuan_socketpair (assuan_context_t ctx, int namespace, int style,
     375             :                     int protocol, assuan_fd_t filedes[2])
     376             : {
     377             :   int res;
     378           1 :   TRACE_BEG4 (ctx, ASSUAN_LOG_SYSIO, "_assuan_socketpair", ctx,
     379             :               "namespace=%i,style=%i,protocol=%i,filedes=%p",
     380             :               namespace, style, protocol, filedes);
     381             : 
     382           1 :   res = (ctx->system.socketpair) (ctx, namespace, style, protocol, filedes);
     383           1 :   if (res == 0)
     384           1 :     TRACE_LOG2 ("filedes = { 0x%x, 0x%x }", filedes[0], filedes[1]);
     385             : 
     386           1 :   return TRACE_SYSERR (res);
     387             : }
     388             : 
     389             : 
     390             : 
     391             : int
     392           0 : _assuan_socket (assuan_context_t ctx, int namespace, int style, int protocol)
     393             : {
     394             :   int res;
     395           0 :   TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "_assuan_socket", ctx,
     396             :               "namespace=%i,style=%i,protocol=%i",
     397             :               namespace, style, protocol);
     398             : 
     399           0 :   res = (ctx->system.socket) (ctx, namespace, style, protocol);
     400           0 :   return TRACE_SYSRES (res);
     401             : }
     402             : 
     403             : 
     404             : int
     405           0 : _assuan_connect (assuan_context_t ctx, int sock, struct sockaddr *addr, socklen_t length)
     406             : {
     407             :   int res;
     408           0 :   TRACE_BEG3 (ctx, ASSUAN_LOG_SYSIO, "_assuan_connect", ctx,
     409             :               "socket=%i,addr=%p,length=%i", sock, addr, length);
     410             : 
     411           0 :   res = (ctx->system.connect) (ctx, sock, addr, length);
     412           0 :   return TRACE_SYSRES (res);
     413             : }
     414             : 

Generated by: LCOV version 1.11