w3mail

program to send a web page by email
git clone https://logand.com/git/w3mail.git/
Log | Files | Refs | README | LICENSE

utils.c (3640B)


      1 #include "utils.h"
      2 
      3 #include <ctype.h>
      4 #include <errno.h>
      5 #include <stdarg.h>
      6 #include <string.h>
      7 #include <stdlib.h>
      8 #include <unistd.h>
      9 #include <sys/wait.h>
     10 
     11 const int BLEN = 4 * 1024;
     12 
     13 void quit(int code, char *fmt, ...) {
     14   va_list v;
     15   va_start(v, fmt);
     16   vfprintf(stderr, fmt, v);
     17   exit(code);
     18   va_end(v);
     19 }
     20 
     21 void die(int code, char *fmt, ...) {
     22   va_list v;
     23   va_start(v, fmt);
     24   char msg[BLEN];
     25   vsnprintf(msg, BLEN, fmt, v);
     26   perror(msg);
     27   exit(code);
     28   va_end(v);
     29 }
     30 
     31 void rtrim(char *s) {
     32   if(!s) die(1, "rtrim(): nothing to trim");
     33   char *e = s + strlen(s) - 1;
     34   while(s < e && isspace(*e)) *e-- = '\0';
     35 }
     36 
     37 void in(void *udata, in_cb cb, char *cmd, ...) {
     38   va_list v;
     39   va_start(v, cmd);
     40   char buf[BLEN];
     41   vsnprintf(buf, BLEN, cmd, v);
     42   FILE *pipe = popen(buf, "r");
     43   if(!pipe) die(1, "in(): cannot open pipe to '%s'", buf);
     44   cb(udata, pipe);
     45   pclose(pipe);
     46   va_end(v);
     47 }
     48 
     49 void out(void *udata, out_cb cb, char *cmd, ...) {
     50   va_list v;
     51   va_start(v, cmd);
     52   char buf[BLEN];
     53   vsnprintf(buf, BLEN, cmd, v);
     54   FILE *pipe = popen(buf, "w");
     55   if(!pipe) die(1, "out(): cannot open pipe to '%s'", buf);
     56   cb(udata, pipe);
     57   pclose(pipe);
     58   va_end(v);
     59 }
     60 
     61 void tmpf(void *udata, tmpf_cb cb, char *fname, ...) {
     62   va_list v;
     63   va_start(v, fname);
     64   char buf[BLEN];
     65   vsnprintf(buf, BLEN, fname, v);
     66   int fd = mkstemp(buf);
     67   if(fd == -1) die(errno, "tmpf(): cannot create temporary file '%s'", buf);
     68   close(fd);
     69   cb(udata, buf);
     70   unlink(buf);
     71   va_end(v);
     72 }
     73 
     74 void dir(void *udata, dir_cb cb, char *path, ...) {
     75   va_list v;
     76   va_start(v, path);
     77   char buf[BLEN];
     78   vsnprintf(buf, BLEN, path, v);
     79   DIR *d = opendir(buf);
     80   if(!d) die(1, "dir(): cannot open dir '%s'", buf);
     81   struct dirent *e;
     82   while((e = readdir(d))) {
     83     char fname[BLEN];
     84     snprintf(fname, BLEN, "%s/%s", buf, e->d_name);
     85     struct stat s;
     86     if(lstat(fname, &s) < 0)
     87       die(1, "stat_cb(): lstat('%s') failed", fname);
     88     if(!cb(udata, buf, fname, e, &s)) break;
     89   }
     90   closedir(d);
     91   va_end(v);
     92 }
     93 
     94 int systemf(char *cmd, ...) {
     95   va_list v;
     96   va_start(v, cmd);
     97   char buf[BLEN];
     98   vsnprintf(buf, BLEN, cmd, v);
     99   va_end(v);
    100   fprintf(stderr, "sh: %s\n", buf); // TODO remove
    101   int x = system(buf);
    102   return 0 <= x && WIFEXITED(x) ? WEXITSTATUS(x) : -1;
    103 }
    104 
    105 void wget(char *url, char *fname) {
    106   // http://www.gnu.org/software/wget/manual/html_node/Exit-Status.html
    107   static char *wgetmsg[] = {
    108     "No problems occurred",
    109     "Generic error code",
    110     "Parse error, e.g. when parsing command-line options, .wgetrc or .netrc",
    111     "File I/O error",
    112     "Network failure",
    113     "SSL verification failure",
    114     "Username/password authentication failure",
    115     "Protocol errors",
    116     "Server issued an error response"
    117   };
    118   int pid = fork();
    119   if(pid < 0) die(pid, "wget(): fork failed");
    120   else if(pid == 0) execlp("wget", "wget", "-q", "-O", fname, "--", url, NULL);
    121   else {
    122     int x;
    123     do {
    124       pid_t w = waitpid(pid, &x, WUNTRACED | WCONTINUED);
    125       if(w == -1) die(1, "wget(): waitpid failed on wget '%s'", url);
    126       if(WIFEXITED(x)) {
    127         int n = WEXITSTATUS(x);
    128         if(n)
    129           fprintf(stderr, "wget '%s' failed with status %d: %s\n", url,
    130                   n, (0 <= n && n <= 8) ? wgetmsg[n] : "unexpected status");
    131       }
    132       else if(WIFSIGNALED(x))
    133         fprintf(stderr, "wget '%s' killed by signal %d\n", url,
    134                 WTERMSIG(x));
    135       else if(WIFSTOPPED(x))
    136         fprintf(stderr, "wget '%s' stopped by signal %d\n", url,
    137                 WSTOPSIG(x));
    138       else if(WIFCONTINUED(x))
    139         fprintf(stderr, "wget '%s' continued\n", url);
    140     } while(!WIFEXITED(x) && !WIFSIGNALED(x));
    141   }
    142 }