ind.c - rohrpost - A commandline mail client to change the world as we see it.
 (HTM) git clone git://r-36.net/rohrpost
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       ind.c (8246B)
       ---
            1 /*
            2  * Copy me if you can.
            3  * by 20h
            4  */
            5 
            6 #include <unistd.h>
            7 #include <stdio.h>
            8 #include <stdlib.h>
            9 #include <stdarg.h>
           10 #include <fcntl.h>
           11 #include <string.h>
           12 #include <strings.h>
           13 #include <errno.h>
           14 #include <ctype.h>
           15 #include <sys/types.h>
           16 #include <sys/stat.h>
           17 #include <time.h>
           18 #include <limits.h>
           19 
           20 #include "ind.h"
           21 
           22 void
           23 edie(char *fmt, ...)
           24 {
           25         va_list fmtargs;
           26 
           27         va_start(fmtargs, fmt);
           28         vfprintf(stderr, fmt, fmtargs);
           29         va_end(fmtargs);
           30         fprintf(stderr, ": ");
           31 
           32         perror(NULL);
           33 
           34         exit(1);
           35 }
           36 
           37 void
           38 die(char *fmt, ...)
           39 {
           40         va_list fmtargs;
           41 
           42         va_start(fmtargs, fmt);
           43         vfprintf(stderr, fmt, fmtargs);
           44         va_end(fmtargs);
           45 
           46         exit(1);
           47 }
           48 
           49 void *
           50 reallocz(void *p, int l, int z)
           51 {
           52         p = realloc(p, l);
           53         if(p == NULL)
           54                 edie("realloc");
           55         if(z)
           56                 memset(p, 0, l);
           57 
           58         return p;
           59 }
           60 
           61 void *
           62 mallocz(int l, int z)
           63 {
           64         return reallocz(NULL, l, z);
           65 }
           66 
           67 void *
           68 memdup(void *p, int l)
           69 {
           70         char *ret;
           71 
           72         ret = reallocz(NULL, l, 2);
           73         memmove(ret, p, l);
           74 
           75         return (void *)ret;
           76 }
           77 
           78 void *
           79 memdupz(void *p, int l)
           80 {
           81         char *ret;
           82 
           83         ret = reallocz(NULL, l+1, 2);
           84         memmove(ret, p, l);
           85 
           86         return (void *)ret;
           87 }
           88 
           89 void *
           90 memdups(void *p)
           91 {
           92         char *ret;
           93         int l;
           94 
           95         l = strlen(p) + 1;
           96 
           97         ret = reallocz(NULL, l, 2);
           98         memmove(ret, p, l);
           99 
          100         return (void *)ret;
          101 }
          102 
          103 /*
          104  * Append the data at c with the length of lc to
          105  * p, at position lp of p.
          106  */
          107 void *
          108 memdupcat(void *p, int lp, void *c, int lc)
          109 {
          110         p = reallocz(p, lp+lc, 0);
          111         memset(&((char *)p)[lp], 0, lc);
          112 
          113         memmove(&((char *)p)[lp], c, lc);
          114 
          115         return p;
          116 }
          117 
          118 char *
          119 vsmprintf(char *fmt, va_list fmtargs, int size)
          120 {
          121         char *ret;
          122 
          123         ret = reallocz(NULL, ++size, 2);
          124         vsnprintf(ret, size, fmt, fmtargs);
          125 
          126         return ret;
          127 }
          128 
          129 char *
          130 smprintf(char *fmt, ...)
          131 {
          132         va_list fmtargs;
          133         char *ret;
          134         int len;
          135 
          136         va_start(fmtargs, fmt);
          137         len = vsnprintf(NULL, 0, fmt, fmtargs);
          138         va_end(fmtargs);
          139 
          140         if (len == INT_MAX)
          141                 return NULL;
          142 
          143         va_start(fmtargs, fmt);
          144         ret = vsmprintf(fmt, fmtargs, len);
          145         va_end(fmtargs);
          146 
          147         return ret;
          148 }
          149 
          150 void
          151 setnonblocking(int fd)
          152 {
          153         int opts;
          154 
          155         opts = fcntl(fd, F_GETFL);
          156         if(opts < 0)
          157                 edie("setnonblocking");
          158 
          159         if(fcntl(fd, F_SETFL, opts | O_NONBLOCK) < 0)
          160                 edie("setnonblocking");
          161 }
          162 
          163 void
          164 setblocking(int fd)
          165 {
          166         int opts;
          167 
          168         opts = fcntl(fd, F_GETFL);
          169         if(opts < 0)
          170                 edie("setblocking");
          171 
          172         if(fcntl(fd, F_SETFL, opts & ~O_NONBLOCK) < 0)
          173                 edie("setblocking");
          174 }
          175 
          176 int
          177 runcmd(char *cmd, int *infd, int *outfd, int *errfd, int keepold)
          178 {
          179         int pid, nullfd, status;
          180         int pstdin[2], pstdout[2], pstderr[2];
          181 
          182         enum {
          183                 DOSTDOUT = 0x01,
          184                 DOSTDIN = 0x02,
          185                 DOSTDERR = 0x04,
          186                 HAVENULLFD = 0x08
          187         };
          188 
          189         status = 0;
          190 
          191         if (infd) {
          192                 if (pipe(pstdin))
          193                         goto runcmderror;
          194                 status |= DOSTDOUT;
          195         }
          196         if (outfd) {
          197                 if (pipe(pstdout))
          198                         goto runcmderror;
          199                 status |= DOSTDIN;
          200         }
          201         if (errfd) {
          202                 if (pipe(pstderr))
          203                         goto runcmderror;
          204                 status |= DOSTDERR;
          205         }
          206         if (!keepold && ((status & DOSTDIN) || (status & DOSTDOUT)
          207                         || (status & DOSTDERR))) {
          208                 nullfd = open("/dev/null", O_RDWR);
          209                 if (nullfd < 0)
          210                         goto runcmderror;
          211                 status |= HAVENULLFD;
          212         }
          213 
          214         pid = fork();
          215         switch(pid) {
          216         case -1:
          217                 return pid;
          218         case 0:
          219                 if (status & DOSTDIN) {
          220                         close(pstdin[1]);
          221                         dup2(pstdin[0], 0);
          222                 } else {
          223                         if (!keepold)
          224                                 dup2(nullfd, 0);
          225                 }
          226                 if (status & DOSTDOUT) {
          227                         close(pstdout[0]);
          228                         dup2(pstdout[1], 1);
          229                 } else {
          230                         if (!keepold)
          231                                 dup2(nullfd, 1);
          232                 }
          233                 if (status & DOSTDERR) {
          234                         close(pstderr[1]);
          235                         dup2(pstderr[0], 2);
          236                 } else {
          237                         if (!keepold)
          238                                 dup2(nullfd, 2);
          239                 }
          240 
          241                 execl("/bin/sh", "sh", "-c", cmd, NULL);
          242                 exit(1);
          243         default:
          244                 break;
          245         }
          246 
          247         if (status & DOSTDIN) {
          248                 close(pstdin[0]);
          249                 *infd = pstdin[1];
          250         }
          251         if (status & DOSTDOUT) {
          252                 close(pstdout[1]);
          253                 *outfd = pstdout[0];
          254         }
          255         if (status & DOSTDERR) {
          256                 close(pstderr[1]);
          257                 *errfd = pstderr[1];
          258         }
          259 
          260         return pid;
          261 runcmderror:
          262         if (status & DOSTDIN) {
          263                 close(pstdin[0]);
          264                 close(pstdin[1]);
          265         }
          266         if (status & DOSTDOUT) {
          267                 close(pstdout[0]);
          268                 close(pstdout[1]);
          269         }
          270         if (status & DOSTDERR) {
          271                 close(pstderr[0]);
          272                 close(pstderr[1]);
          273         }
          274         if (status & HAVENULLFD)
          275                 close(nullfd);
          276 
          277         return -1;
          278 }
          279 
          280 char *
          281 expandhome(char *path)
          282 {
          283         char *home, *retpath;
          284 
          285         retpath = NULL;
          286 
          287         if (path[0] == '~') {
          288                 home = getenv("HOME");
          289                 if (home != NULL)
          290                         retpath = smprintf("%s%s", home, path+1);
          291         }
          292         if (retpath == NULL)
          293                 retpath = memdups(path);
          294 
          295         return retpath;
          296 }
          297 
          298 int
          299 writeall(FILE *fd, void *data, int len)
          300 {
          301         int written;
          302 
          303         for (written = 0; len > 0; ) {
          304                 written = fwrite(data, 1, len, fd);
          305                 len -= written;
          306         }
          307 
          308         return 0;
          309 }
          310 
          311 int
          312 writeallfd(int fd, void *data, int len)
          313 {
          314         int written;
          315 
          316         for (written = 0; len > 0; ) {
          317                 written = write(fd, &((char *)data)[written], len);
          318                 len -= written;
          319         }
          320 
          321         return 0;
          322 }
          323 
          324 int
          325 writefile(char *file, void *data, int len, char *mode)
          326 {
          327         FILE *fd;
          328 
          329         fd = fopen(file, mode);
          330         if (fd == NULL)
          331                 return 1;
          332         if (writeall(fd, data, len))
          333                 return 1;
          334         fclose(fd);
          335 
          336         return 0;
          337 }
          338 
          339 int
          340 getfilesize(char *file)
          341 {
          342         struct stat fs;
          343 
          344         if (stat(file, &fs) < 0)
          345                 return -1;
          346 
          347         return fs.st_size;
          348 }
          349 
          350 char *
          351 readtoeof(FILE *fd, int *len)
          352 {
          353         char *ret, buf[4096];
          354         int olen, nlen, rl;
          355 
          356         for (nlen = 0, olen = 0, ret = NULL; !feof(fd); olen = nlen) {
          357                 rl = fread(buf, 1, sizeof(buf), fd);
          358                 if (rl > 0) {
          359                         nlen += rl;
          360                         ret = reallocz(ret, nlen+1, 0);
          361                         ret[nlen] = '\0';
          362 
          363                         memmove(&ret[olen], buf, rl);
          364                 }
          365         }
          366 
          367         *len = nlen;
          368         return ret;
          369 }
          370 
          371 char *
          372 readtoeoffd(int fd, int *len)
          373 {
          374         char *ret, buf[4096];
          375         int olen, nlen, rl;
          376 
          377         for (nlen = 0, olen = 0, ret = NULL;
          378                         (rl = read(fd, buf, sizeof(buf))); olen = nlen) {
          379                 if (rl > 0) {
          380                         nlen += rl;
          381                         ret = reallocz(ret, nlen+1, 0);
          382                         ret[nlen] = '\0';
          383 
          384                         memmove(&ret[olen], buf, rl);
          385                 }
          386         }
          387 
          388         *len = nlen;
          389         return ret;
          390 }
          391 
          392 char *
          393 readfile(char *file, int *len)
          394 {
          395         FILE *fd;
          396         char *data;
          397 
          398         fd = fopen(file, "r");
          399         if (fd == NULL)
          400                 return NULL;
          401 
          402         data = readtoeof(fd, len);
          403         fclose(fd);
          404 
          405         return data;
          406 }
          407 
          408 char *
          409 readstdin(int *len)
          410 {
          411         return readtoeof(stdin, len);
          412 }
          413 
          414 /*
          415  * Get line from string buffer.
          416  */
          417 char *
          418 sgets(char *s, int size, char **p)
          419 {
          420         char *np;
          421         int cl;
          422 
          423         if (*p == NULL)
          424                 return NULL;
          425 
          426         np = strchr(*p, '\n');
          427         if (np == NULL) {
          428                 cl = strlen(*p);
          429                 if (cl < 1) {
          430                         *p = NULL;
          431                         return NULL;
          432                 }
          433         } else {
          434                 cl = np - *p;
          435         }
          436 
          437         if (cl >= size)
          438                 cl = size - 1;
          439         memmove(s, *p, cl);
          440         s[cl] = '\0';
          441 
          442         if (np == NULL) {
          443                 *p = NULL;
          444         } else {
          445                 *p = np+1;
          446         }
          447 
          448         return s;
          449 }
          450 
          451 char *
          452 sgetuntil(char *str, char **p, char *max, int *len)
          453 {
          454         char *ret, *op;
          455         int si;
          456 
          457         ret = NULL;
          458 
          459         si = 0;
          460         for (op = *p; op < max; op++) {
          461                 if (str[si] == '\0')
          462                         break;
          463                 if (op[0] == str[si]) {
          464                         si++;
          465                 } else {
          466                         si = 0;
          467                 }
          468         }
          469         if (str[si] == '\0') {
          470                 *len = op - *p - strlen(str);
          471                 ret = memdupz(*p, *len);
          472                 *p = op;
          473         }
          474 
          475         return ret;
          476 }
          477 
          478 char *
          479 strrlnspn(char *p, char *chars, int limit)
          480 {
          481         char *np;
          482 
          483         np = &p[limit-1];
          484         for(; !strchr(chars, np[0] && p != np); np--);
          485 
          486         return np;
          487 }
          488 
          489 int
          490 strisascii(char *str)
          491 {
          492         int len, i;
          493 
          494         len = strlen(str);
          495         for (i = 0; i < len; i++) {
          496                 if (!isascii(str[i]))
          497                         return 0;
          498         }
          499 
          500         return 1;
          501 }
          502 
          503 void
          504 strnormalizespace(char *str)
          505 {
          506         int len, i;
          507 
          508         len = strlen(str);
          509         for (i = 0; i < len; i++) {
          510                 if (isspace(str[i]))
          511                         str[i] = ' ';
          512         }
          513 }
          514 
          515 /*
          516  * Find a whitespace character in a certain limit. This is used for formatting
          517  * mail to a certain width.
          518  */
          519 char *
          520 findlimitws(char *str, int limit)
          521 {
          522         int len;
          523         char *ptr;
          524 
          525         len = strlen(str);
          526         if (len < limit)
          527                 return NULL;
          528 
          529         ptr = strrlnspn(str, "\t\r\v\f ", limit);
          530         if (ptr == str)
          531                 return &str[limit-1];
          532         return ptr;
          533 }
          534 
          535 char *
          536 mktmpfile(char *prefix, char *suffix, int *fd)
          537 {
          538         char *name;
          539         time_t tm;
          540         int tfd;
          541 
          542         tm = time(NULL);
          543         srand(tm);
          544 
          545         for (tfd = -1; tfd < 0;) {
          546                 name = smprintf("/tmp/%s.%d.%d.%s", prefix, getpid(), rand(),
          547                                 suffix);
          548                 tfd = open(name, O_EXCL|O_CREAT|O_RDWR|O_TRUNC,
          549                                 S_IRUSR|S_IWUSR);
          550                 if (tfd >= 0)
          551                         break;
          552                 if (tfd < 0 && errno != EEXIST)
          553                         edie("mktmpfile");
          554                 free(name);
          555         }
          556 
          557         *fd = tfd;
          558 
          559         return name;
          560 }
          561 
          562 int
          563 intcmp(const void *p1, const void *p2)
          564 {
          565         return *((int *)p1) - *((int *)p2);
          566 }
          567 
          568 char *
          569 smftime(char *fmt, const struct tm *tm)
          570 {
          571         int len, rlen;
          572         char *ret;
          573 
          574         len = strlen(fmt);
          575         ret = NULL;
          576         for (; len < 1024;) {
          577                 len *= 2;
          578                 ret = reallocz(ret, len, 0);
          579                 rlen = strftime(ret, len, fmt, tm);
          580                 if (rlen == 0)
          581                         continue;
          582         }
          583 
          584         return ret;
          585 }
          586