rllib  1
rlmailbox.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                           rlmailbox.cpp  -  description
00003                              -------------------
00004     begin                : Tue Jan 02 2001
00005     copyright            : (C) 2001 by Rainer Lehrig
00006     email                : lehrig@t-online.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This library is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as        *
00013  *   published by the Free Software Foundation                             *
00014  *                                                                         *
00015  ***************************************************************************/
00016 #include "rldefine.h"
00017 #include <stdio.h>
00018 #include <stdarg.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #ifndef RLWIN32
00022 #include <unistd.h>
00023 #endif
00024 #include "rlmailbox.h"
00025 #include "rlcutil.h"
00026 
00027 #ifdef RLUNIX
00028 #include <fcntl.h>
00029 #include <sys/stat.h>
00030 #include <sys/types.h>
00031 #include <sys/ipc.h>
00032 #include <sys/msg.h>
00033 #endif
00034 
00035 #ifdef __VMS
00036 #include <lib$routines.h>
00037 #include <libdef.h>
00038 #include <dvidef.h>
00039 #include <ssdef.h>
00040 #include <iodef.h>
00041 #include <descrip.h>
00042 #include <starlet.h>
00043 typedef struct
00044 {
00045   short    iostat;
00046   unsigned short msg_len;
00047   int      reader_pid;
00048 }IOSB;
00049 #endif
00050 
00051 #ifdef RLWIN32
00052 #include <windows.h>
00053 #endif
00054 
00055 rlMailbox::rlMailbox(const char *mbxname)
00056 {
00057 #ifdef RLUNIX
00058 FILE  *fp;
00059 key_t key;
00060 
00061   status = OK;
00062   name = new char[strlen(mbxname)+1];
00063   strcpy(name,mbxname);
00064   // create file
00065   fp = fopen(name,"r");
00066   if(fp == NULL)
00067   {
00068     fp = fopen(name,"w");
00069     if(fp == NULL)
00070     {
00071       int ret;
00072       char buf[1024];
00073       sprintf(buf,"could not write mailbox=%s\n",mbxname);
00074       ret = ::write(1,buf,strlen(buf));
00075       if(ret < 0) exit(-1);
00076       sprintf(buf,"you have to run this program as root !!!\n");
00077       ret = ::write(1,buf,strlen(buf));
00078       if(ret < 0) exit(-1);
00079       exit(-1);
00080     }
00081     fchmod(fileno(fp),0x0fff);
00082     if(fp == NULL) { status=COULD_NOT_CREATE_MAILBOX; return; }
00083   }
00084   fclose(fp);
00085   // getkey
00086 
00087   // old stuff, without suggestions from Stefan Lievens 
00088   // key = ftok(name, 'R');
00089 
00090   key = ftok(name, 'b');
00091   if(key == ((key_t) (-1))) { status=COULD_NOT_GET_KEY; return; }
00092   // get chanid
00093 
00094   // old stuff, without suggestions from Stefan Lievens 
00095   // chanid = msgget(key,IPC_CREAT);
00096   chanid = msgget(key, 0600 | IPC_CREAT);
00097   if(chanid == -1) { status=COULD_NOT_GET_CHAN_ID; return; }
00098 #endif
00099 
00100 #ifdef __VMS
00101   long   ret;
00102   short  chan_id;
00103   struct dsc$descriptor_s dmbxname;
00104 
00105   chanid = -1;
00106   status = OK;
00107   name = new char[strlen(mbxname)+1];
00108   strcpy(name,mbxname);
00109   dmbxname.dsc$w_length  = strlen(name);
00110   dmbxname.dsc$a_pointer = name;
00111   dmbxname.dsc$b_dtype   = DSC$K_DTYPE_T;
00112   dmbxname.dsc$b_class   = DSC$K_CLASS_S;
00113   ret = sys$crembx((char)1,                     // 0 temp 1 permanence flag
00114                    &chan_id,                    // i/o channel
00115                    MAX_MAILBOX,                 // max msg length
00116                    MAX_MAILBOX*4,               // max buffer size
00117                    (long)0,
00118                    (long)0,
00119                    &dmbxname);                   // mailbox name
00120   if(ret == SS$_NORMAL) { chanid = chan_id; return; }
00121   else                  { status = COULD_NOT_CREATE_MAILBOX; return; }
00122 #endif
00123 
00124 #ifdef RLWIN32
00125   chanid = -1;
00126   status = OK;
00127   name = new char[strlen(mbxname)+1];
00128   strcpy(name,mbxname);
00129 #endif
00130 }
00131 
00132 rlMailbox::~rlMailbox()
00133 {
00134   delete [] name;
00135   if(chanid < 0) return;
00136 
00137 #ifdef __VMS
00138   sys$dassgn((short)chanid);
00139 #endif
00140 
00141 #ifdef RLWIN32
00142   CloseHandle((HANDLE) chanid);
00143 #endif
00144 }
00145 
00146 int rlMailbox::write(const void *buf, int len)
00147 {
00148   status = OK;
00149 
00150 #ifdef RLUNIX
00151   int retlen;
00152   unsigned char *message = new unsigned char [sizeof(long) + len];
00153   long *lptr = (long *) message;
00154   *lptr = 1; // mtype
00155   memcpy(&message[sizeof(long)],buf,len);
00156   retlen = msgsnd(chanid,(struct msgbuf *) message, len, 0);
00157   delete [] message;
00158   return retlen;
00159 #endif
00160 
00161 #ifdef __VMS
00162   int  ret;
00163   IOSB iosb;
00164   ret = sys$qiow (0,
00165                   (short) chanid,
00166                   IO$_WRITEVBLK | IO$M_NOW | IO$M_NORSWAIT,
00167                   &iosb,
00168                   0,0,
00169                   buf,
00170                   len,0,0,0,0);
00171   len = iosb.msg_len;
00172   if     (ret == SS$_MBFULL) return MAILBOX_FULL;
00173   else if(ret != SS$_NORMAL) return MAILBOX_ERROR;
00174   else                       return len; // Success
00175 #endif
00176 
00177 #ifdef RLWIN32
00178   BOOL bret;
00179   unsigned long numWritten;
00180 
00181   if(chanid == -1)
00182   {
00183     HANDLE h;
00184     char   mbxname[1024];
00185     strcpy(mbxname,"\\\\.\\mailslot\\"); strcat(mbxname,name);
00186     h = CreateFile(
00187               mbxname,                             // pointer to name of the file
00188               GENERIC_READ | GENERIC_WRITE,        // access (read-write) mode
00189               FILE_SHARE_READ | FILE_SHARE_WRITE,  // share mode
00190               NULL,                                // pointer to security attributes
00191               OPEN_EXISTING,                       // how to create
00192               FILE_ATTRIBUTE_NORMAL,               // file attributes
00193               NULL                                 // handle to file with attributes to copy
00194                   );
00195     if(h == INVALID_HANDLE_VALUE)
00196     {
00197       status = GetLastError();
00198       return MAILBOX_ERROR;
00199     }
00200     chanid = (int) h;
00201   }
00202 
00203   bret = WriteFile(
00204             (HANDLE) chanid,      // handle to file to write to
00205             buf,                  // pointer to data to write to file
00206             len,                  // number of bytes to write
00207             &numWritten,          // pointer to number of bytes written
00208             NULL                  // pointer to structure for overlapped I/O
00209                   );
00210   if(bret==0)
00211   {
00212     status = GetLastError();
00213     CloseHandle((HANDLE) chanid);
00214     chanid = -1;
00215     return MAILBOX_ERROR;
00216   }
00217   return numWritten;
00218 #endif
00219 }
00220 
00221 int rlMailbox::read(void *buf, int maxlen, int wait)
00222 {
00223   char *cbuf;
00224   status = OK;
00225   cbuf = (char *) buf;
00226 
00227 #ifdef RLUNIX
00228   int len;
00229   unsigned char *message = new unsigned char [sizeof(long) + maxlen];
00230   if(wait == WAIT ) len = msgrcv(chanid,(struct msgbuf *) message, maxlen,0,0);
00231   else              len = msgrcv(chanid,(struct msgbuf *) message, maxlen,0,IPC_NOWAIT);
00232   if(len < maxlen && len >= 0) 
00233   {
00234     memcpy(buf,&message[sizeof(long)],len);
00235     cbuf[len] = '\0';
00236   }
00237   else
00238   {
00239     cbuf[0] = '\0';
00240   }
00241   delete [] message;
00242   return len;
00243 #endif
00244 
00245 #ifdef __VMS
00246   int  ret,len;
00247   IOSB iosb;
00248   if(wait == NOWAIT)
00249   {
00250     ret = sys$qiow(0,
00251                    (short) chanid,
00252                    IO$_READVBLK | IO$M_NOW,       // I/O CODE
00253                    &iosb,
00254                    0,0,
00255                    buf,
00256                    maxlen,0,0,0,0);
00257   }
00258   else
00259   {
00260     ret = sys$qiow(0,
00261                    (short) chanid,
00262                    IO$_READVBLK,                  // I/O CODE
00263                    &iosb,
00264                    0,0,
00265                    buf,
00266                    maxlen,0,0,0,0);
00267   }
00268   len = (int) iosb.msg_len;
00269   if(len < maxlen && len >= 0) cbuf[len] = '\0';
00270   if     (ret == SS$_NORMAL && iosb.iostat == SS$_NORMAL)   return len;
00271   else if(iosb.iostat == SS$_NORMAL)                        { status = -1; return MAILBOX_ERROR; }
00272   else if(ret         == SS$_NORMAL)
00273   {
00274     if(wait == NOWAIT && iosb.iostat == SS$_ENDOFFILE)      { status = -2; return MAILBOX_ERROR; }
00275     else                                                    { status = -3; return MAILBOX_ERROR; }
00276   }
00277                                                               status = -4; return MAILBOX_ERROR;
00278 #endif
00279 
00280 #ifdef RLWIN32
00281   HANDLE h;
00282   char   mbxname[1024];
00283   unsigned long lenRead;
00284   BOOL   bret,bret2;
00285 
00286   if(chanid == -1)
00287   {
00288     strcpy(mbxname,"\\\\.\\mailslot\\"); strcat(mbxname,name);
00289     h = CreateMailslot(
00290                  mbxname,                // pointer to string for mailslot name
00291                  MAX_MAILBOX,            // maximum message size
00292                  MAILSLOT_WAIT_FOREVER,  // milliseconds before read time-out
00293                  NULL);                  // pointer to security structure
00294     if(h == INVALID_HANDLE_VALUE) { status = GetLastError(); return MAILBOX_ERROR; }
00295     chanid = (int) h;
00296 
00297     bret2 = SetMailslotInfo((HANDLE) chanid, MAILSLOT_WAIT_FOREVER);
00298     if(bret2 == 0) { status = GetLastError();  return MAILBOX_ERROR; }
00299   }
00300 
00301   if(wait == NOWAIT) // begin wait
00302   {
00303     lenRead = 0;
00304     bret2 = SetMailslotInfo((HANDLE) chanid, 0);
00305     if(bret2 == 0) { status = GetLastError(); return MAILBOX_ERROR; }
00306     bret = ReadFile(
00307              (HANDLE) chanid,                        // handle of file to read
00308              buf,                                    // pointer to buffer
00309              maxlen,                                 // number of bytes to read
00310              &lenRead,                               // pointer to number of bytes read
00311              NULL                                    // pointer to structure for data
00312                    );
00313     bret2 = SetMailslotInfo((HANDLE) chanid, MAILSLOT_WAIT_FOREVER);
00314     if(bret2 == 0) { status = GetLastError(); return MAILBOX_ERROR; }
00315     if(bret == 0)  { status = GetLastError(); return MAILBOX_ERROR; }
00316     if((int) lenRead < maxlen && (int) lenRead >= 0) cbuf[lenRead] = '\0';
00317     return lenRead;
00318   } // end wait
00319 
00320   lenRead = 0;
00321   bret = ReadFile(
00322            (HANDLE) chanid,                        // handle of file to read
00323            buf,                                    // pointer to buffer
00324            maxlen,                                 // number of bytes to read
00325            &lenRead,                               // pointer to number of bytes read
00326            NULL                                    // pointer to structure for data
00327                  );
00328   if(bret == 0) { status = GetLastError(); return MAILBOX_ERROR; }
00329   if((int) lenRead < maxlen && (int) lenRead >= 0) cbuf[lenRead] = '\0';
00330   return lenRead;
00331 #endif
00332 }
00333 
00334 void rlMailbox::clear()
00335 {
00336   char *buf = new char[MAX_MAILBOX];
00337   while(read(buf,MAX_MAILBOX,NOWAIT) > 0);
00338   delete [] buf;
00339 }
00340 
00341 int rlMailbox::printf(const char *format, ...)
00342 {
00343   int ret;
00344   char message[rl_PRINTF_LENGTH]; // should be big enough
00345 
00346   va_list ap;
00347   va_start(ap,format);
00348   ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap);
00349   va_end(ap);
00350   if(ret < 0) return ret;
00351   return write(message,strlen(message));
00352 }