rllib  1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
rlspawn.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlspawn.cpp - description
3  -------------------
4  begin : Tue Jan 02 2001
5  copyright : (C) 2001 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include "rldefine.h"
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #ifndef RLWIN32
22 #include <unistd.h>
23 #include <sys/time.h>
24 #include <sys/types.h>
25 #endif
26 #include "rlspawn.h"
27 #include "rlcutil.h"
28 #ifdef RLUNIX
29 #include <sys/wait.h>
30 #include <signal.h>
31 #endif
32 
34 {
35  toChild = fromChild = NULL;
36  pid = 0;
37 }
38 
40 {
41  if(toChild != NULL) ::fclose((FILE*) toChild);
42  if(fromChild != NULL) ::fclose((FILE*) fromChild);
43 }
44 
45 int rlSpawn::spawn(const char *command)
46 {
47 #ifdef RLWIN32
48  return -1;
49 #else
50  int to_child[2],from_child[2],ret;
51 
52  if(toChild != NULL) ::fclose((FILE*) toChild);
53  if(fromChild != NULL) ::fclose((FILE*) fromChild);
54  toChild = fromChild = NULL;
55 
56  ret = ::pipe(to_child);
57  if(ret == -1) return -1;
58  ret = ::pipe(from_child);
59  if(ret == -1) return -1;
60 
61  if((pid = ::fork()) == 0)
62  {
63  if(to_child[0] != 0) // stdin
64  {
65  ::dup2(to_child[0],0);
66  ::close(to_child[0]);
67  }
68  if(from_child[1] != 2) // stderr
69  {
70  ::dup2(from_child[1] ,2);
71  }
72  if(from_child[1] != 1) // stdout
73  {
74  ::dup2(from_child[1],1);
75  ::close(from_child[1]);
76  }
77  ::close(to_child[1]);
78  ::close(from_child[0]);
79  ::rlexec(command);
80  ::exit(0);
81  }
82 
83  ::close(to_child[0]);
84  ::close(from_child[1]);
85  toChild = (void*) ::fdopen(to_child[1],"w");
86  if(toChild == NULL) { return -1; }
87  fromChild = (void*) ::fdopen(from_child[0],"r");
88  if(fromChild == NULL) { ::fclose((FILE*) toChild); return -1; }
89  return pid;
90 #endif
91 }
92 
93 const char *rlSpawn::readLine()
94 {
95  if(fromChild == NULL) return NULL;
96  if(::fgets(line,sizeof(line)-1,(FILE*) fromChild) == NULL)
97  {
98 #ifdef RLUNIX
99  if(pid != 0)
100  {
101  int status;
102  waitpid(pid, &status, 0);
103  kill(pid,SIGHUP);
104  }
105 #endif
106  return NULL;
107  }
108  return line;
109 }
110 
112 {
113  if(fromChild == NULL) return EOF;
114  return ::fgetc((FILE*) fromChild);
115 }
116 
117 int rlSpawn::write(const char *buf, int len)
118 {
119 #ifdef RLWIN32
120  return -1;
121 #else
122  if(toChild == NULL) return -1;
123  return ::write(fileno((FILE*)toChild),buf,len);
124 #endif
125 }
126 
127 int rlSpawn::printf(const char *format, ...)
128 {
129  int ret;
130  char message[rl_PRINTF_LENGTH]; // should be big enough
131 
132  va_list ap;
133  va_start(ap,format);
134  ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap);
135  va_end(ap);
136  if(ret < 0) return ret;
137  return write(message,strlen(message));
138 }
139 
140 int rlSpawn::writeString(const char *buf)
141 {
142  if(toChild == NULL) return -1;
143  return fprintf((FILE*)toChild,"%s",buf);
144 }
145 
147 {
148  const char *cptr;
149  while((cptr=readLine()) != NULL) ::printf("%s",cptr);
150 }
151 
152 int rlSpawn::select(int timeout)
153 {
154 #ifdef RLWIN32
155  return -1;
156 #else
157  struct timeval timout;
158  fd_set wset,rset,eset;
159  int ret,maxfdp1,s;
160 
161  if(fromChild == NULL) return -1;
162  s = fileno((FILE *) fromChild);
163  /* setup sockets to read */
164  maxfdp1 = s+1;
165  FD_ZERO(&rset);
166  FD_SET (s,&rset);
167  FD_ZERO(&wset);
168  FD_ZERO(&eset);
169  timout.tv_sec = timeout / 1000;
170  timout.tv_usec = (timeout % 1000) * 1000;
171 
172  ret = ::select(maxfdp1,&rset,&wset,&eset,&timout);
173  if(ret == 0) return 0; /* timeout */
174  return 1;
175 #endif
176 }
177 
178