"Fossies" - the Fresh Open Source Software Archive

Member "mpr-2.8/mprhook.c" (18 Dec 2003, 6157 Bytes) of package /linux/misc/old/mpr-2.8.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 #include <stdlib.h>
    2 #include <string.h>
    3 #include <unistd.h>
    4 #include <signal.h>
    5 #include <stdarg.h>
    6 #include <fcntl.h>
    7 #include <unistd.h>
    8 #include <errno.h>
    9 #include <sys/types.h>
   10 #include <sys/wait.h>
   11 
   12 #undef malloc
   13 #undef free
   14 #undef calloc
   15 #undef realloc
   16 #include <malloc.h>
   17 
   18 #undef ulong
   19 #define ulong unsigned long
   20 
   21 extern void mprbt(int);
   22 extern void *(*__mpr_malloc_hook)(size_t);
   23 static void *(*old_malloc_hook)(size_t);
   24 extern void (*__mpr_free_hook)(void *);
   25 static void (*old_free_hook)(void *);
   26 extern void *(*__mpr_realloc_hook)(void *, size_t);
   27 static void *(*old_realloc_hook)(void *, size_t);
   28 static void hook(void), unhook(void);
   29 int     mprprint(int fd, char *fmt, ...);
   30 
   31 static pid_t    mprmypid;   /* current process id */
   32 static pid_t    mprpid;     /* MPRFI child process id */
   33 static int  mprfd=-1;   /* MPRFI pipe descriptor */
   34 static int  mprsync;    /* == 0 -> buffer writes to mprfd */
   35 static char mprbuf[8192];   /* buffer for mprfd */
   36 static char *mprbp=mprbuf;  /* current buffer pointer */
   37 
   38 static int
   39 xwrite(int fd, char *buf, int len)
   40 {
   41     int nleft, n;
   42 
   43     for (nleft=len; nleft>0; nleft-=n, buf+=n) {
   44         n = write(fd, buf, nleft);
   45         if (n < 0) {
   46             if (errno == EINTR) {
   47                 n=0;
   48                 continue;
   49             }
   50             if (fd != 2)
   51                 mprprint(2, "xwrite: warning: write failed errno=%d\n", errno);
   52             return len-nleft;
   53         }
   54     }
   55     return len;
   56 }
   57 
   58 static void
   59 mprflush(void)
   60 {
   61     xwrite(mprfd, mprbuf, mprbp-mprbuf);
   62     mprbp = mprbuf;
   63 }
   64 
   65 static int
   66 mprwrite(int fd, char *str, char *buf, int len)
   67 {
   68     if (str) {
   69         memmove(str, buf, len);
   70         return len;
   71     }
   72     if (fd != mprfd) {
   73         xwrite(fd, buf, len);
   74         return len;
   75     }
   76     if (mprbp+len > mprbuf+sizeof(mprbuf))  /* flush */
   77         mprflush();
   78     if (mprbp+len > mprbuf+sizeof(mprbuf))  /* can't buffer */
   79         xwrite(fd, buf, len);
   80     else {                  /* buffer */
   81         memmove(mprbp, buf, len);
   82         mprbp += len;
   83     }
   84     return len;
   85 }
   86 
   87 static int
   88 mprvprint(int fd, char *str, char *fmt, va_list ap)
   89 {
   90     ulong ul;
   91     int i, len;
   92     char *ep, *cp, buf[64];
   93 
   94     for (ep=fmt, len=0; *ep; ep++) {
   95         if (*ep == '%') {
   96             switch (*++ep) {
   97             case 'U':
   98                 ul = va_arg(ap, ulong);
   99                 cp = buf + sizeof(buf);
  100                 do
  101                     *--cp = '0' + ul%10;
  102                 while ((ul/=10) != 0);
  103                 len += mprwrite(fd, str, cp, buf+sizeof(buf)-cp);
  104                 break;
  105             case 'd':
  106                 i = va_arg(ap, int);
  107                 ul = i<0 ? -i : i;
  108                 cp = buf + sizeof(buf);
  109                 do
  110                     *--cp = '0' + ul%10;
  111                 while ((ul/=10) != 0);
  112                 if (i < 0)
  113                     *--cp = '-';
  114                 len += mprwrite(fd, str, cp, buf+sizeof(buf)-cp);
  115                 break;
  116             case 's':
  117                 cp = va_arg(ap, char *);
  118                 len += mprwrite(fd, str, cp, strlen(cp));
  119                 break;
  120             default:
  121                 abort();
  122             }
  123         }
  124         else {
  125             len += mprwrite(fd, str, ep, 1);
  126             if (mprsync && fd == mprfd && *ep == '\n')
  127                 mprflush();
  128         }
  129     }
  130     return len;
  131 }
  132 
  133 int
  134 mprprint(int fd, char *fmt, ...)
  135 {
  136     int len;
  137     va_list ap;
  138 
  139     if (fd < 0)
  140         return -1;
  141     va_start(ap, fmt);
  142     len = mprvprint(fd, 0, fmt, ap);
  143     va_end(ap);
  144     return len;
  145 }
  146 
  147 static int
  148 mprsprint(char *str, char *fmt, ...)
  149 {
  150     int len;
  151     va_list ap;
  152 
  153     va_start(ap, fmt);
  154     len = mprvprint(-1, str, fmt, ap);
  155     va_end(ap);
  156     return len;
  157 }
  158 
  159 static void
  160 mprexit(void)
  161 {
  162     pid_t pid;
  163     int status;
  164 
  165     if (mprfd < 0)
  166         return;
  167     mprflush();
  168     if (close(mprfd) < 0)
  169         mprprint(2, "mprexit: warning: close failed errno=%d\n", errno);
  170     mprfd = -1;
  171     unhook();
  172     if (mprmypid != getpid())   /* child */
  173         return;
  174     do
  175         pid = waitpid(mprpid, &status, 0);
  176     while (pid < 0 && errno == EINTR);
  177     if (pid < 0) {
  178         mprprint(2, "mprexit: warning: waitpid failed errno=%d\n", errno);
  179         return;
  180     }
  181     if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
  182         mprprint(2, "mprexit: warning: MPRFI exited %d\n", WEXITSTATUS(status));
  183     if (WIFSIGNALED(status))
  184         mprprint(2, "mprexit: warning: MPRFI caught signal %d\n", WTERMSIG(status));
  185 }
  186 
  187 static void *
  188 malloc_hook(size_t sz)
  189 {
  190     void *ptr;
  191 
  192     unhook();
  193     ptr = malloc(sz);
  194     mprprint(mprfd, "m:");
  195     mprbt(mprfd);
  196     mprprint(mprfd, "%U:%U\n", (ulong)sz, (ulong)ptr);
  197     hook();
  198     return ptr;
  199 }
  200 
  201 static void
  202 free_hook(void *ptr)
  203 {
  204     unhook();
  205     mprprint(mprfd, "f:");
  206     mprbt(mprfd);
  207     mprprint(mprfd, "%U\n", (ulong)ptr);
  208     free(ptr);
  209     hook();
  210 }
  211 
  212 static void *
  213 realloc_hook(void *ptr, size_t sz)
  214 {
  215     void *ptr2;
  216 
  217     unhook();
  218     ptr2 = realloc(ptr, sz);
  219     mprprint(mprfd, "r:");
  220     mprbt(mprfd);
  221     mprprint(mprfd, "%U:%U:%U\n", (ulong)sz, (ulong)ptr, (ulong)ptr2);
  222     hook();
  223     return ptr2;
  224 }
  225 
  226 static void
  227 hook(void)
  228 {
  229     old_malloc_hook = __mpr_malloc_hook;
  230     old_free_hook = __mpr_free_hook;
  231     old_realloc_hook = __mpr_realloc_hook;
  232     __mpr_malloc_hook = malloc_hook;
  233     __mpr_free_hook = free_hook;
  234     __mpr_realloc_hook = realloc_hook;
  235 }
  236 
  237 static void
  238 unhook(void)
  239 {
  240     __mpr_malloc_hook = old_malloc_hook;
  241     __mpr_free_hook = old_free_hook;
  242     __mpr_realloc_hook = old_realloc_hook;
  243 }
  244 
  245 static int
  246 mprpopen(char *mprfi)
  247 {
  248     char cmd[256], *cp, *mprsh;
  249     struct sigaction sa;
  250     int pfd[2];
  251 
  252     for (cp=cmd; *mprfi && cp<cmd+sizeof(cmd); ) {  /* s/%p/pid/ */
  253         if (mprfi[0] == '%' && mprfi[1] == 'p') {
  254             cp += mprsprint(cp, "%d", getpid());
  255             mprfi += 2;
  256         }
  257         else
  258             *cp++ = *mprfi++;
  259     }
  260     *cp = '\0';
  261 
  262     if (pipe(pfd) < 0)
  263         return -1;
  264     if ((mprpid = fork()) < 0) {
  265         close(pfd[0]);
  266         close(pfd[1]);
  267         return -1;
  268     }
  269     else if (mprpid == 0) {
  270         close(pfd[1]);
  271         if (pfd[0] != 0) {
  272             if (dup2(pfd[0], 0) < 0) {
  273                 mprprint(2, "mprpopen: dup2 failed: errno=%d\n", errno);
  274                 exit(1);
  275             }
  276             close(pfd[0]);
  277         }
  278         putenv("MPRFI=");
  279         if (!(mprsh = getenv("MPRSH")))
  280             mprsh = "/bin/sh";
  281         sa.sa_handler = SIG_IGN;
  282         sa.sa_flags = 0;
  283         sigemptyset(&sa.sa_mask);
  284         sigaction(SIGINT, &sa, 0);
  285         sigaction(SIGTERM, &sa, 0);
  286         execl(mprsh, "sh", "-c", cmd, 0);
  287         mprprint(2, "mprpopen: error: could not exec %s\n", mprsh);
  288         _exit(127);
  289     }
  290     close(pfd[0]);
  291     return pfd[1];
  292 }
  293 
  294 int
  295 mprhook(void)
  296 {
  297     char *mprfi;
  298     static int mprinit;
  299 
  300     if (mprinit)
  301         return 0;
  302     mprmypid = getpid();
  303     mprinit = 1;
  304     if (!(mprfi = getenv("MPRFI")) || !*mprfi)
  305         return 0;
  306     if ((mprfd = mprpopen(mprfi)) < 0) {
  307         mprprint(2, "mpr: error: mprpopen() failed\n");
  308         return -1;
  309     }
  310     if (atexit(mprexit) < 0) {
  311         mprprint(2, "mpr: error: atexit failed\n");
  312         close(mprfd);
  313         return -1;
  314     }
  315     if (getenv("MPRSYNC"))
  316         mprsync = 1;
  317     if (getenv("MPRNOCHILD"))
  318         putenv("MPRFI=");
  319     hook();
  320     return 0;
  321 }