root/piperespawn/piperespawn.c

Revision 3f477e9d20f3fbc79e60facde22e17834e54152d, 2.7 kB (checked in by Robin Gareus <robin@…>, 2 years ago)

added piperespawn.

  • Property mode set to 100644
Line 
1#include <stdio.h>
2#include <string.h>
3#include <stdlib.h>
4#include <poll.h>
5#include <unistd.h>
6#include <sys/types.h>
7#include <sys/stat.h>
8#include <fcntl.h>
9
10#define BUFFERSIZE BUFSIZ
11//#define BLOCKINGIO 1
12
13static FILE *out = NULL;
14static char *cmd = NULL;
15
16void respawn_pclose () {
17  if (out) pclose(out);
18  out=NULL;
19}
20
21void respawn_popen () {
22//fprintf(stderr,"p(re)open\n");
23  respawn_pclose();
24  out=popen(cmd, "w");
25}
26
27int respawn_write (char *buf, int count, int retry_cnt) {
28  struct pollfd pfd;
29  size_t c;
30  int pv;
31
32wait:
33  if (retry_cnt > 5) return 0;
34  if (!out) respawn_popen();
35
36  pfd.fd=fileno(out);
37  pfd.events=POLLOUT; //|POLLERR|POLLHUP|POLLNVAL;
38  pfd.revents=0;
39
40  pv=poll(&pfd,1,5000);
41  if (pv < 1) goto retry;
42  if (pv==0) {retry_cnt++; if (retry_cnt > 5)goto retry; else goto wait;}
43  if ((pfd.revents & ~POLLOUT) != 0 ) goto retry;
44
45  c=fwrite(buf,sizeof(char),count,out);
46  if (c==0) goto retry;
47//fprintf(stderr,"out: %i/%i\n",c,count);
48  fflush(out);
49  return c;
50
51retry:
52//fprintf(stderr,"retry: %i\n",pfd.revents);
53  respawn_pclose();
54  c=respawn_write(buf, count, retry_cnt+1);
55  return c;
56}
57
58
59int main (int argc, char **argv) {
60
61  size_t r,w;
62  char buf[BUFFERSIZE];
63  if (argc<2) {
64    fprintf(stderr, "usage %s <command> [arg]*\n",argv[0]);
65    return 1;
66  }
67
68// parse argv
69  int i,len;
70  for (i=1,len=0;i<argc;i++) {
71    len+=strlen(argv[i])+1;
72    if (i>1) len+=2; // quotes
73  }
74  cmd=malloc(sizeof(char)*len);
75  for (i=1,len=0;i<argc;i++) {
76    if (i>1) cmd[len++]='"';
77    memcpy(cmd+len,argv[i],strlen(argv[i]));
78    len+=strlen(argv[i]);
79    if (i>1) cmd[len++]='"';
80    cmd[len++]=' ';
81  }
82  if (len<2) {
83    fprintf(stderr,"invalid command given.\n");
84    return 1;
85  }
86  cmd[len-1]=0; // terminate
87//fprintf(stderr,"COMMAND: '%s'\n",cmd);
88
89#ifdef BLOCKINGIO
90  FILE *in =stdin;
91  if (!in) return 2;
92#else 
93  int fin = open ("/dev/stdin", O_RDONLY|O_NONBLOCK);
94  if (fin<0) return 2;
95#endif
96
97// TODO: catch signals.
98
99
100  while (
101#ifdef BLOCKINGIO
102    !feof(in)
103#else
1041
105#endif
106        ) {
107
108#ifndef BLOCKINGIO
109    struct pollfd pfd;
110    pfd.events=POLLIN;
111    pfd.revents=0;
112    pfd.fd=fin;
113    int pv = poll(&pfd,1,1000);
114    if (pv<0) break; // error
115    if (pv==0) continue; // nothing to read
116    if ((pfd.revents & ~POLLIN) != 0 ) break; // read eof/hup/err
117#endif
118 
119#ifdef BLOCKINGIO
120    r=fread(buf,sizeof(char),BUFFERSIZE,in);
121#else
122    r=read(fin, buf,sizeof(char)*BUFFERSIZE);
123    if (r==-1) break;
124#endif
125
126    if (r==0) break;
127    w=respawn_write(buf,r,0);
128    if (w==0) {
129//    fprintf(stderr,"respawning too fast.\n");
130      break;
131    }
132    if (w!=r) {
133//    fprintf(stderr,"incomplete write. some data lost.\n");
134      // TODO: tx remaining:
135      // w+=respawn_write(buf[r-w],r-w,0);
136    }
137  }
138  respawn_pclose();
139  free(cmd);
140  return 0;
141}
Note: See TracBrowser for help on using the browser.