// Class implementation for scritplink object. #include #include #include #include #include #include "scriptlink.hxx" #define LINK_LOGICAL "NET_LINK:" const static int IO_SIZE=1000; scriptlink ScriptLink; $DESCRIPTOR(sysnet,"NET_LINK:"); extern "C" int SYS$OPEN(...), SYS$CONNECT(...), SYS$CLOSE(...); extern "C" int SYS$GET(...), SYS$PUT(...); ////////////////////////////////////////////////////////////////////////////// // Constructor, assign channel to network link. scriptlink::scriptlink() { this->rundown_tag = (char *) 0; this->bin_mode = 0; this->buf_used = 0; // Accept logical link this->fab = cc$rms_fab; // Get default values. this->fab.fab$l_fna = LINK_LOGICAL; this->fab.fab$b_fns = strlen(this->fab.fab$l_fna); this->fab.fab$b_fac = FAB$M_GET|FAB$M_PUT; // read/write operation this->fab.fab$b_rfm = FAB$C_VAR; // Variable length records. this->status = SYS$OPEN ( &this->fab ); // Create record stream if ( (this->status&1) == 0 ) return; this->rab = cc$rms_rab; this->rab.rab$l_fab = &this->fab; this->rab.rab$b_rac = RAB$C_SEQ; // Sequential record access this->status = SYS$CONNECT ( &this->rab ); } ////////////////////////////////////////////////////////////////////////////// // Destructor scriptlink::~scriptlink() { // write out rundown tag and close link cout << "scriptlink destructor called\n"; if ( this->buf_used > 0 ) { status = this->write ( this->buffer, this->buf_used ); this->buf_used = 0; } else status = 1; if ( this->rundown_tag ) { this->write ( this->rundown_tag, strlen(this->rundown_tag) ); delete this->rundown_tag; } this->status = SYS$CLOSE ( &this->fab ); } ////////////////////////////////////////////////////////////////////////////// // Copy rundown tag. int scriptlink::set_rundown ( char *tag ) { if ( this->rundown_tag ) delete this->rundown_tag; this->rundown_tag = new char[strlen(tag)+1]; strcpy ( this->rundown_tag, tag ); return 0; } int scriptlink::read(void *buffer, int bufsize, int &read) { int status; if ( this->buf_used > 0 ) status = this->flush(); this->rab.rab$l_ubf = (char *) buffer; this->rab.rab$w_usz = bufsize; status = SYS$GET ( &this->rab ); read = this->rab.rab$w_rsz; return status; } int scriptlink::write(const void *outbuf, int bufsize, int frag ) { int status; char *buffer = (char *) outbuf; if ( frag <= 0 ) frag = IO_SIZE; do { // Write no more than frag bytes at a time. if ( bufsize > frag ) this->rab.rab$w_rsz = IO_SIZE; else this->rab.rab$w_rsz = bufsize; this->rab.rab$l_rbf = buffer; status = SYS$PUT ( &this->rab ); if ( (status&1) == 0 ) break; buffer = &buffer[this->rab.rab$w_rsz]; bufsize = bufsize - this->rab.rab$w_rsz; } while ( bufsize > 0 ); return status; } int scriptlink::query(const char *tag, void *buffer, int bufsize, int &transferred) { int status; status = this->write ( tag, strlen ( tag ) ); if ( (status&1) == 1 ) status = this->read ( buffer, bufsize, transferred ); return status; } //////////////////////////////////////////////////////////////////////////// // Flush pending data in buffer. // int scriptlink::flush() { int status; if ( this->buf_used > 0 ) { status = this->write ( this->buffer, this->buf_used ); this->buf_used = 0; } else status = 1; this->buf_used = 0; return status; } //////////////////////////////////////////////////////////////////////////// int scriptlink::set_mode ( int mode ) { int prev_mode; prev_mode = this->bin_mode; this->bin_mode = mode; return prev_mode; } scriptlink &scriptlink::operator<<(const int value) { char numstr[24]; int i, radix, t; radix = (value < 0) ? -10 : 10; i = 24; numstr[--i] = '\0'; for ( t = value; t != 0; ) { int d; d = t%radix; numstr[--i] = '0' + d; t = t/radix; } if ( i == (sizeof(numstr)-1) ) numstr[--i] = '0'; else if ( radix < 0 ) numstr[--i] = '-'; *this << &numstr[i]; return *this; } scriptlink &scriptlink::operator<<(const char *text) { int j, i, status; j = this->buf_used; for ( i = 0; text[i]; i++ ) { if ( j >= sizeof(this->buffer) ) { this->buf_used = 0; j = 0; status = this->flush(); if ( (status&1) == 0 ) break; j = this->buf_used; } this->buffer[j++] = text[i]; } this->buf_used = j; return *this; } /**************************************************************************/ /* Convert escaped characters in string to actual values. * (originally C code). * * Arguments: * string Character string. Modified. * length Int. On input, original length of string. * On output, final length of unescaped string. */ char * net_unescape_string ( char *string, int *length ) { int i, j, reslen, modified; /* * Scan string. */ for ( modified = reslen = i = 0; i < *length; i++ ) { if ( string[i] == '%' ) { /* * Escape seen, decode next 2 characters as hex and replace * all three with single byte. */ char value[4]; int val; value[0] = string[i+1]; value[1] = string[i+2]; value[2] = '\0'; i += 2; sscanf ( value, "%2x", &val ); if ( val > 127 ) val |= (-1 ^ 255); /* Sign extend */ string[reslen] = val; modified = 1; } else { /* Only copy bytes if escape edit took place. */ if ( modified ) string[reslen] = string[i]; } reslen++; } /* Return value is point to string editted. */ *length = reslen; return string; }