The Assimilation Project  based on Assimilation version 1.1.7.1474836767
gmainfd.c
Go to the documentation of this file.
1 
25 #include <projectcommon.h>
26 #include <memory.h>
27 #include <gmainfd.h>
28 #include <errno.h>
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 # ifdef HAVE_FCNTL_H
32 # include <fcntl.h>
33 # endif
34 #endif
35 
36 #define READBUFSIZE 1024
37 
42 
43 
44 FSTATIC gboolean gmainfd_gsource_prepare(GSource* source, gint* timeout);
45 FSTATIC gboolean gmainfd_gsource_check(GSource* source);
46 FSTATIC gboolean gmainfd_gsource_dispatch(GSource* source, GSourceFunc callback, gpointer user_data);
48 FSTATIC void gmainfd_gsource_finalize(GSource* source);
49 
50 static GSourceFuncs gmainfd_source_funcs = {
55  NULL,
56  NULL
57 };
58 
59 FSTATIC void gmainfd_newtext(GMainFd*, const char *, int len);
61 
63 GMainFd*
64 gmainfd_new(gsize cpsize, int fd, int priority, GMainContext* context)
65 {
66  GSource* source;
67  GMainFd* self;
68 
69  if (cpsize < sizeof(GMainFd)) {
70  cpsize = sizeof(GMainFd);
71  }
72  source = g_source_new(&gmainfd_source_funcs, cpsize);
73  g_return_val_if_fail(source != NULL, NULL);
74  proj_class_register_object(source, "GSource");
75  self = NEWSUBCLASS(GMainFd, source);
76 
77  self->textread = NULL;
78  self->finalize = NULL;
79  self->newtext = gmainfd_newtext;
80  self->readmore = gmainfd_gsource_readmore;
81  memset(&self->gfd, 0, sizeof(self->gfd));
82 
83 
84  /* Now initialize all the gmainloop stuff */
85  self->gfd.fd = fd;
86  self->gfd.events = G_IO_IN|G_IO_ERR|G_IO_HUP;
87  self->gfd.revents = 0;
88 #ifdef HAVE_FCNTL
89  {
90  int fdflags;
91  fdflags = fcntl(fd, F_GETFL);
92  if (-1 == fdflags) {
93  g_warning("%s.%d: fcntl(%d, F_GETFL) failed errno=%d [%s]"
94  , __FUNCTION__, __LINE__, fd, errno, g_strerror(errno));
95  }else{
96  fdflags |= O_NONBLOCK;
97  if (fcntl(fd, F_SETFL, fdflags) < 0) {
98  g_warning("%s.%d: fcntl(%d, F_SETFL, 0x%x) failed) errno=%d [%s]"
99  , __FUNCTION__, __LINE__, fd, fdflags
100  , errno, g_strerror(errno));
101  }
102  }
103  }
104 #endif
105  g_source_add_poll(source, &self->gfd);
106  g_source_set_priority(source, priority);
107  self->gsourceid = g_source_attach(source, context);
108  if (self->gsourceid == 0) {
109  g_source_remove_poll(source, &self->gfd);
110  memset(self, 0, sizeof(*self));
111  g_source_unref(source); // Should cause proj_class_dissociate(source) to be called
112  source = NULL;
113  self = NULL;
114  }
115  return self;
116 }
117 
119 FSTATIC void
120 gmainfd_newtext(GMainFd* self, const char * string, int len)
121 {
122  if (self->textread) {
123  self->textread = g_string_append_len(self->textread, string, len);
124  }else{
125  self->textread = g_string_new_len(string, len);
126  }
127 }
128 
129 
131 FSTATIC gboolean
132 gmainfd_gsource_prepare(GSource* dummysource, gint* dummytimeout)
133 {
134  // Don't need to do anything prior to a poll(2) call...
135  (void)dummysource;
136  (void)dummytimeout;
137  return FALSE;
138 }
139 
141 FSTATIC gboolean
142 gmainfd_gsource_check(GSource* source)
143 {
144  GMainFd* self = CASTTOCLASS(GMainFd, source);
145  // revents: received events...
146  if (self->gfd.revents & G_IO_HUP) {
147  g_source_remove_poll(source, &self->gfd);
148  // The other end of the pipe was closed
149  self->gfd.events = 0;
150  self->atEOF = TRUE; // is this right?
151  }
152  if (self->gfd.revents & G_IO_ERR) {
153  g_warning("%s.%d: received I/O error on file descriptor %d"
154  , __FUNCTION__, __LINE__, self->gfd.fd);
155  g_source_remove_poll(source, &self->gfd);
156  self->gfd.events = 0;
157  self->atEOF = TRUE; // is this right?
158  }
159  return 0 != self->gfd.revents;
160 }
161 
163 FSTATIC gboolean
164 gmainfd_gsource_dispatch(GSource* source, GSourceFunc unusedcallback, gpointer unused_user_data)
165 {
166  GMainFd* self = CASTTOCLASS(GMainFd, source);
167 
168  (void)unusedcallback;
169  (void)unused_user_data;
170  return gmainfd_gsource_readmore(self);
171 }
172 
173 FSTATIC gboolean
175 {
176  char readbuf[READBUFSIZE];
177  int readrc;
178 
179  while ((readrc = read(self->gfd.fd, &readbuf, sizeof(readbuf))) > 0) {
180  self->newtext(self, readbuf, readrc);
181  }
182  // End of File?
183  if (0 == readrc) {
184  self->atEOF = TRUE;
185  self->gfd.events = 0;
186  }
187  return !self->atEOF && self->gfd.events != 0;
188 }
189 
191 FSTATIC void
192 gmainfd_gsource_finalize(GSource* source)
193 {
194  GMainFd* self = CASTTOCLASS(GMainFd, source);
195 
196  if (self->finalize) {
197  self->finalize(self);
198  }
199  if (self->textread) {
200  g_string_free(self->textread, TRUE);
201  self->textread = NULL;
202  }
203  if (self->gfd.fd >= 0) {
204  close(self->gfd.fd);
205  self->gfd.fd = -1;
206  }
207  proj_class_dissociate(source);
208  source = NULL;
209  self = NULL;
210 }
FSTATIC gboolean gmainfd_gsource_readmore(GMainFd *self)
Definition: gmainfd.c:174
#define READBUFSIZE
Definition: gmainfd.c:36
#define FSTATIC
Definition: projectcommon.h:31
FSTATIC gboolean gmainfd_gsource_prepare(GSource *source, gint *timeout)
GmainFd class. version of a gmainloop prepare function - get ready to go into the poll function ...
Definition: gmainfd.c:132
#define __FUNCTION__
void proj_class_register_object(gpointer object, const char *static_classname)
Log the creation of a new object, and its association with a given type.
Definition: proj_classes.c:100
FSTATIC gboolean gmainfd_gsource_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
GmainFd class. version of a gmainloop dispatch function - we read the data from the file descriptor ...
Definition: gmainfd.c:164
Project common header file.
FSTATIC gboolean gmainfd_gsource_check(GSource *source)
GmainFd class. version of a gmainloop check function - check for input after the poll function ...
Definition: gmainfd.c:142
void proj_class_dissociate(gpointer object)
Dissociate an object from the C class system (typically coupled with freeing it). ...
Definition: proj_classes.c:228
FSTATIC void gmainfd_finalize(GMainFd *)
GMainFd * gmainfd_new(gsize cpsize, int fd, int priority, GMainContext *context)
Construct a new GMainFd object and return it.
Definition: gmainfd.c:64
FSTATIC void gmainfd_newtext(GMainFd *, const char *, int len)
Just stash away our new string - appending to what&#39;s already there.
Definition: gmainfd.c:120
#define CASTTOCLASS(Cclass, obj)
Safely cast &#39;obj&#39; to C-class &#39;class&#39; - verifying that it was registerd as being of type class ...
Definition: proj_classes.h:66
Implements a gmainloop source for reading file descriptor pipes.
#define NEWSUBCLASS(Cclass, obj)
Definition: proj_classes.h:67
FSTATIC void gmainfd_gsource_finalize(GSource *source)
GmainFd class. version of a gmainloop finalize function
Definition: gmainfd.c:192
struct _GMainFd GMainFd
Definition: gmainfd.h:32