rllib  1
rlmailbox.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rlmailbox.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 #endif
24 #include "rlmailbox.h"
25 #include "rlcutil.h"
26 
27 #ifdef RLUNIX
28 #include <fcntl.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/ipc.h>
32 #include <sys/msg.h>
33 #endif
34 
35 #ifdef __VMS
36 #include <lib$routines.h>
37 #include <libdef.h>
38 #include <dvidef.h>
39 #include <ssdef.h>
40 #include <iodef.h>
41 #include <descrip.h>
42 #include <starlet.h>
43 typedef struct
44 {
45  short iostat;
46  unsigned short msg_len;
48 }IOSB;
49 #endif
50 
51 #ifdef RLWIN32
52 #include <windows.h>
53 #endif
54 
55 rlMailbox::rlMailbox(const char *mbxname)
56 {
57 #ifdef RLUNIX
58 FILE *fp;
59 key_t key;
60 
61  status = OK;
62  buffer = NULL;
63  buffer_size = 0;
64  name = new char[strlen(mbxname)+1];
65  strcpy(name,mbxname);
66  // create file
67  fp = fopen(name,"r");
68  if(fp == NULL)
69  {
70  fp = fopen(name,"w");
71  if(fp == NULL)
72  {
73  int ret;
74  char buf[1024];
75  sprintf(buf,"could not write mailbox=%s\n",mbxname);
76  ret = ::write(1,buf,strlen(buf));
77  if(ret < 0) exit(-1);
78  sprintf(buf,"you have to run this program as root !!!\n");
79  ret = ::write(1,buf,strlen(buf));
80  if(ret < 0) exit(-1);
81  exit(-1);
82  }
83  fchmod(fileno(fp),0x0fff);
84  if(fp == NULL) { status=COULD_NOT_CREATE_MAILBOX; return; }
85  }
86  fclose(fp);
87  // getkey
88 
89  // old stuff, without suggestions from Stefan Lievens
90  // key = ftok(name, 'R');
91 
92  key = ftok(name, 'b');
93  if(key == ((key_t) (-1))) { status=COULD_NOT_GET_KEY; return; }
94  // get chanid
95 
96  // old stuff, without suggestions from Stefan Lievens
97  // chanid = msgget(key,IPC_CREAT);
98  chanid = msgget(key, 0600 | IPC_CREAT);
99  if(chanid == -1) { status=COULD_NOT_GET_CHAN_ID; return; }
100 #endif
101 
102 #ifdef __VMS
103  long ret;
104  short chan_id;
105  struct dsc$descriptor_s dmbxname;
106 
107  chanid = -1;
108  status = OK;
109  name = new char[strlen(mbxname)+1];
110  strcpy(name,mbxname);
111  dmbxname.dsc$w_length = strlen(name);
112  dmbxname.dsc$a_pointer = name;
113  dmbxname.dsc$b_dtype = DSC$K_DTYPE_T;
114  dmbxname.dsc$b_class = DSC$K_CLASS_S;
115  ret = sys$crembx((char)1, // 0 temp 1 permanence flag
116  &chan_id, // i/o channel
117  MAX_MAILBOX, // max msg length
118  MAX_MAILBOX*4, // max buffer size
119  (long)0,
120  (long)0,
121  &dmbxname); // mailbox name
122  if(ret == SS$_NORMAL) { chanid = chan_id; return; }
123  else { status = COULD_NOT_CREATE_MAILBOX; return; }
124 #endif
125 
126 #ifdef RLWIN32
127  chanid = -1;
128  status = OK;
129  name = new char[strlen(mbxname)+1];
130  strcpy(name,mbxname);
131 #endif
132 }
133 
135 {
136  delete [] name;
137  if(buffer != NULL) delete [] buffer;
138  if(chanid < 0) return;
139 
140 #ifdef __VMS
141  sys$dassgn((short)chanid);
142 #endif
143 
144 #ifdef RLWIN32
145  CloseHandle((HANDLE) chanid);
146 #endif
147 }
148 
149 int rlMailbox::write(const void *buf, int len)
150 {
151  status = OK;
152 
153 #ifdef RLUNIX
154  int retlen;
155  unsigned char *message = new unsigned char [sizeof(long) + len];
156  long *lptr = (long *) message;
157  *lptr = 1; // mtype
158  memcpy(&message[sizeof(long)],buf,len);
159  retlen = msgsnd(chanid,(struct msgbuf *) message, len, 0);
160  delete [] message;
161  return retlen;
162 #endif
163 
164 #ifdef __VMS
165  int ret;
166  IOSB iosb;
167  ret = sys$qiow (0,
168  (short) chanid,
169  IO$_WRITEVBLK | IO$M_NOW | IO$M_NORSWAIT,
170  &iosb,
171  0,0,
172  buf,
173  len,0,0,0,0);
174  len = iosb.msg_len;
175  if (ret == SS$_MBFULL) return MAILBOX_FULL;
176  else if(ret != SS$_NORMAL) return MAILBOX_ERROR;
177  else return len; // Success
178 #endif
179 
180 #ifdef RLWIN32
181  BOOL bret;
182  unsigned long numWritten;
183 
184  if(chanid == -1)
185  {
186  HANDLE h;
187  char mbxname[1024];
188  strcpy(mbxname,"\\\\.\\mailslot\\"); strcat(mbxname,name);
189  h = CreateFile(
190  mbxname, // pointer to name of the file
191  GENERIC_READ | GENERIC_WRITE, // access (read-write) mode
192  FILE_SHARE_READ | FILE_SHARE_WRITE, // share mode
193  NULL, // pointer to security attributes
194  OPEN_EXISTING, // how to create
195  FILE_ATTRIBUTE_NORMAL, // file attributes
196  NULL // handle to file with attributes to copy
197  );
198  if(h == INVALID_HANDLE_VALUE)
199  {
200  status = GetLastError();
201  return MAILBOX_ERROR;
202  }
203  chanid = (int) h;
204  }
205 
206  bret = WriteFile(
207  (HANDLE) chanid, // handle to file to write to
208  buf, // pointer to data to write to file
209  len, // number of bytes to write
210  &numWritten, // pointer to number of bytes written
211  NULL // pointer to structure for overlapped I/O
212  );
213  if(bret==0)
214  {
215  status = GetLastError();
216  CloseHandle((HANDLE) chanid);
217  chanid = -1;
218  return MAILBOX_ERROR;
219  }
220  return numWritten;
221 #endif
222 }
223 
224 int rlMailbox::read(void *buf, int maxlen, int wait)
225 {
226  char *cbuf;
227  status = OK;
228  cbuf = (char *) buf;
229 
230 #ifdef RLUNIX
231  int len;
232  unsigned char *message = new unsigned char [sizeof(long) + maxlen];
233  if(wait == WAIT ) len = msgrcv(chanid,(struct msgbuf *) message, maxlen,0,0);
234  else len = msgrcv(chanid,(struct msgbuf *) message, maxlen,0,IPC_NOWAIT);
235  if(len < maxlen && len >= 0)
236  {
237  memcpy(buf,&message[sizeof(long)],len);
238  cbuf[len] = '\0';
239  }
240  else
241  {
242  cbuf[0] = '\0';
243  }
244  delete [] message;
245  return len;
246 #endif
247 
248 #ifdef __VMS
249  int ret,len;
250  IOSB iosb;
251  if(wait == NOWAIT)
252  {
253  ret = sys$qiow(0,
254  (short) chanid,
255  IO$_READVBLK | IO$M_NOW, // I/O CODE
256  &iosb,
257  0,0,
258  buf,
259  maxlen,0,0,0,0);
260  }
261  else
262  {
263  ret = sys$qiow(0,
264  (short) chanid,
265  IO$_READVBLK, // I/O CODE
266  &iosb,
267  0,0,
268  buf,
269  maxlen,0,0,0,0);
270  }
271  len = (int) iosb.msg_len;
272  if(len < maxlen && len >= 0) cbuf[len] = '\0';
273  if (ret == SS$_NORMAL && iosb.iostat == SS$_NORMAL) return len;
274  else if(iosb.iostat == SS$_NORMAL) { status = -1; return MAILBOX_ERROR; }
275  else if(ret == SS$_NORMAL)
276  {
277  if(wait == NOWAIT && iosb.iostat == SS$_ENDOFFILE) { status = -2; return MAILBOX_ERROR; }
278  else { status = -3; return MAILBOX_ERROR; }
279  }
280  status = -4; return MAILBOX_ERROR;
281 #endif
282 
283 #ifdef RLWIN32
284  HANDLE h;
285  char mbxname[1024];
286  unsigned long lenRead;
287  BOOL bret,bret2;
288 
289  if(chanid == -1)
290  {
291  strcpy(mbxname,"\\\\.\\mailslot\\"); strcat(mbxname,name);
292  h = CreateMailslot(
293  mbxname, // pointer to string for mailslot name
294  MAX_MAILBOX, // maximum message size
295  MAILSLOT_WAIT_FOREVER, // milliseconds before read time-out
296  NULL); // pointer to security structure
297  if(h == INVALID_HANDLE_VALUE) { status = GetLastError(); return MAILBOX_ERROR; }
298  chanid = (int) h;
299 
300  bret2 = SetMailslotInfo((HANDLE) chanid, MAILSLOT_WAIT_FOREVER);
301  if(bret2 == 0) { status = GetLastError(); return MAILBOX_ERROR; }
302  }
303 
304  if(wait == NOWAIT) // begin wait
305  {
306  lenRead = 0;
307  bret2 = SetMailslotInfo((HANDLE) chanid, 0);
308  if(bret2 == 0) { status = GetLastError(); return MAILBOX_ERROR; }
309  bret = ReadFile(
310  (HANDLE) chanid, // handle of file to read
311  buf, // pointer to buffer
312  maxlen, // number of bytes to read
313  &lenRead, // pointer to number of bytes read
314  NULL // pointer to structure for data
315  );
316  bret2 = SetMailslotInfo((HANDLE) chanid, MAILSLOT_WAIT_FOREVER);
317  if(bret2 == 0) { status = GetLastError(); return MAILBOX_ERROR; }
318  if(bret == 0) { status = GetLastError(); return MAILBOX_ERROR; }
319  if((int) lenRead < maxlen && (int) lenRead >= 0) cbuf[lenRead] = '\0';
320  return lenRead;
321  } // end wait
322 
323  lenRead = 0;
324  bret = ReadFile(
325  (HANDLE) chanid, // handle of file to read
326  buf, // pointer to buffer
327  maxlen, // number of bytes to read
328  &lenRead, // pointer to number of bytes read
329  NULL // pointer to structure for data
330  );
331  if(bret == 0) { status = GetLastError(); return MAILBOX_ERROR; }
332  if((int) lenRead < maxlen && (int) lenRead >= 0) cbuf[lenRead] = '\0';
333  return lenRead;
334 #endif
335 }
336 
338 {
339  char *buf = new char[MAX_MAILBOX];
340  while(read(buf,MAX_MAILBOX,NOWAIT) > 0);
341  delete [] buf;
342 }
343 
344 int rlMailbox::printf(const char *format, ...)
345 {
346  int ret;
347  char message[rl_PRINTF_LENGTH]; // should be big enough
348 
349  va_list ap;
350  va_start(ap,format);
351  ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap);
352  va_end(ap);
353  if(ret < 0) return ret;
354  return write(message,strlen(message));
355 }
356 
358 {
359  if(buffer != NULL) delete [] buffer;
360  buffer_size = size;
361  buffer = new char[size];
362  return size;
363 }
364 
365 const char *rlMailbox::read(int wait)
366 {
367  if(buffer == NULL)
368  {
369  buffer_size = 4096;
370  buffer = new char[buffer_size];
371  }
372  int ret = read(buffer,buffer_size,wait);
373  if(ret < 0) buffer[0] = '\0';
374  return buffer;
375 }
376 
377 int rlMailbox::write(const char *message)
378 {
379  return write(message,strlen(message)+1);
380 }
381 
382 
short iostat
Definition: rlmailbox.cpp:45
char * buffer
Definition: rlmailbox.h:124
void clear()
Definition: rlmailbox.cpp:337
int reader_pid
Definition: rlmailbox.cpp:47
#define rl_PRINTF_LENGTH
Definition: rldefine.h:71
int setReadBufferSize(int size)
Definition: rlmailbox.cpp:357
int printf(const char *format,...)
Definition: rlmailbox.cpp:344
unsigned short msg_len
Definition: rlmailbox.cpp:46
int status
Definition: rlmailbox.h:114
int rlvsnprintf(char *text, int len, const char *format, va_list ap)
Definition: rlcutil.cpp:197
rlMailbox(const char *name)
Definition: rlmailbox.cpp:55
virtual ~rlMailbox()
Definition: rlmailbox.cpp:134
int read(void *buf, int maxlen, int wait=WAIT)
Definition: rlmailbox.cpp:224
char * name
Definition: rlmailbox.h:119
int buffer_size
Definition: rlmailbox.h:123
int write(const void *buf, int len)
Definition: rlmailbox.cpp:149
return codes for write()
Definition: rlmailbox.h:35
int chanid
Definition: rlmailbox.h:122
wait parameter for read()
Definition: rlmailbox.h:38
status:
Definition: rlmailbox.h:43
maximum mailbox length
Definition: rlmailbox.h:41