Release of Queue for printing Task(Application is in QNX 4)

We have SCADA for steel making process ,developed in QNX 4.25 ,Watcom C & Photon MicroGUI.After each Process completion, one has to take the printout for Logsheet and every morning copy of Dailyreport has to be taken.In a day (24 hours) at most 20 prints are taken.
In our SCADA we have not installed the Printer(DOT MATRIX), just we are taking by dumping the file on port and we are maintaining the PRINT QUEUE for data SPOOLing .Sometimes printer becomes unable to print and display USER DEFINED MESSAGE, then one has to restart the computer only.Can we use function for cleaning up the PRINT QUEUE or you have any suggestion for above mentioned problem ? The details are given below:

CALLED FUNCTION :-
ret= queue_open("//0/PRNTQ",“w”,1000);

if(ret <0)
{
//Some User-Defined Message
}

CALLING FUNCTION (Program):-

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#include <sys/kernel.h>
#include <sys/name.h>
#include <sys/osinfo.h>
#include <sys/vc.h>
#include <unistd.h>

#include “queue.h”

/*
#define DEBUG
*/

struct queue_table_entry queue_table[MAX_QUEUE_OPENS];

int queue_open(char *name, char *mode, unsigned window_size)
{
char *p;
struct queue_table_entry *qp,
*qqp,
*free_qp = NULL,
*copy_qp = NULL;
nid_t nid = 0;
pid_t vid;
struct
{ struct queuehdr qhdr;
char msg_queue_mode_name[QMODE_SIZE+QNAME_SIZE+1];

} msg;
struct _osinfo				 osinfo;
char queuename[25];    /* name of queue administrator */

p = name;

if ( *p == ‘/’ && p++ == ‘/’ ) { / QNX 4 explicit node e.g. //1/hello */
strcpy(queuename,“queue”);
for ( ++p, nid = 0 ; *p && *p != ‘/’ ; ++p )
if ( *p >= ‘0’ && p <= ‘9’ )
nid = nid
10 + (*p - ‘0’);

 if ( nid == 0 ) {
	qnx_osinfo( (nid_t) 0, &osinfo );
	nid = osinfo.nodename;
	}
 if ( *p )
	++p;
 }

else {
nid = 0;
strcpy(queuename,"/queue"); /* go for the global queue admin */
}

#ifdef DEBUG
printf(“name=%s, nid=%d, p=%s\n, mode=%s, queueadmin=%s\n”,
name,nid,p, mode, queuename);
#endif

if( *p == ‘\0’ || (strlen(p) > QNAME_SIZE) )
return QSTAT_NAME;

for(qp = &queue_table[MAX_QUEUE_OPENS-1] ; qp >= &queue_table[0] ; --qp) {
if(qp->queue_vid == 0) free_qp = qp;
else if(qp->queue_nid == nid) copy_qp = qp;
}

if((qp = free_qp) == NULL) return(QSTAT_SLOT);
qp->queue_nid = nid;
if( copy_qp == NULL ) {
/* we don’t have an existing pid/vid for this queue so we need to find
the queue admin.
If node is 0, then we try the global queue only.
Otherwise we try the queue admin on the specific node.
*/

if ( (qp->queue_vid = qnx_name_locate( nid, queuename, 0, NULL ) ) == -1 ) {
	return QSTAT_FIND;
    }
}
else
	qp->queue_vid = copy_qp->queue_vid;

#ifdef DEBUG
printf(“queue_vid on name_locate=%d\n”,qp->queue_vid);
#endif

msg.qhdr.msg_type = QUEUE_OPEN;
msg.qhdr.msg_queue_size = window_size;
strcpy(msg.msg_queue_mode_name, mode ? mode : “”);
strcpy(msg.msg_queue_mode_name + strlen(msg.msg_queue_mode_name) + 1, p);

if ( Send( qp->queue_vid, &msg, &msg,
sizeof (struct queuehdr) + QNAME_SIZE+1 + QMODE_SIZE,
sizeof (struct queuehdr) ) == -1 ) {
#ifdef DEBUG
printf(“Send failed: errno=%s\n”,strerror(errno));
#endif
for(qqp = &queue_table[0] ; qqp < &queue_table[MAX_QUEUE_OPENS] ; ++qqp) {
vid = qp->queue_vid;
if(qqp->queue_vid == vid) {
qqp->queue_vid = 0;
qqp->queue_nid = 0;
}
}
qnx_vc_detach(vid);
return(QSTAT_SEND);
}

if(msg.qhdr.msg_type) {
if(copy_qp == NULL) qnx_vc_detach(qp->queue_vid);
qp->queue_vid = 0;
qp->queue_nid = 0;
return(msg.qhdr.msg_type);
}

qp->queue_id = msg.qhdr.msg_queue_id;
return(qp - &queue_table[0]); /* Return small positive int 0 → n */
}

int queue_write(int id, void *msg, int msg_size, int priority)
{
struct queuehdr *mp = msg;

mp->msg_type = QUEUE_WRITE;
mp->msg_queue_id = queue_table[id].queue_id;
mp->msg_queue_size = msg_size;
mp->msg_queue_priority = priority;
Send( queue_table[id].queue_vid, mp, mp,sizeof (*mp) + msg_size, sizeof(mp->msg_type) );
// if ( Send( queue_table[id].queue_vid, mp, mp,sizeof (*mp) + msg_size, sizeof(mp->msg_type) ) == -1 )
// return QSTAT_SEND;
return(mp->msg_type);
}

int queue_read(int id, int wait, void *msg, int msg_size)
{
struct queuehdr *mp = msg;

mp->msg_type=QUEUE_READ;
mp->msg_queue_wait=wait;
mp->msg_queue_id=queue_table[id].queue_id;
mp->msg_queue_size=msg_size;
Send( queue_table[id].queue_vid, mp, mp,sizeof (*mp), sizeof (*mp) + msg_size );
// if ( Send( queue_table[id].queue_vid, mp, mp,sizeof (*mp), sizeof (*mp) + msg_size ) == -1 )
// return QSTAT_SEND;
return(mp->msg_type ? mp->msg_type : mp->msg_queue_size);
}

int queue_wait(int id, int wait)
{
struct queuehdr msg;

msg.msg_type = QUEUE_WAIT;
msg.msg_queue_id = queue_table[id].queue_id;
msg.msg_queue_wait = wait;
if ( Send( queue_table[id].queue_vid, &msg, &msg,
sizeof (struct queuehdr), sizeof (msg.msg_type) ) == -1 )
return QSTAT_SEND;
return(msg.msg_type);
}

int queue_wait_sig(int id, int wait, pid_t proxy)
{
struct queuehdr msg;

msg.msg_type = QUEUE_WAIT_SIG;
msg.msg_queue_id = queue_table[id].queue_id;
msg.msg_queue_wait = wait;
msg.msg_queue_proxy = proxy;
if ( Send( queue_table[id].queue_vid, &msg, &msg,
sizeof(struct queuehdr), sizeof(msg.msg_type) ) == -1 )
return QSTAT_SEND;
return(msg.msg_type);
}

int queue_last_status(int id)
{
struct queuehdr msg;

msg.msg_type = QUEUE_LAST_STATUS;
msg.msg_queue_id = queue_table[id].queue_id;
if ( Send( queue_table[id].queue_vid, &msg, &msg,
sizeof(struct queuehdr), sizeof(msg.msg_type) ) == -1 )
return QSTAT_SEND;
return(msg.msg_type);
}

static int queue_release(int id,char type)
{
struct queue_table_entry *qp;
int count = 0;
pid_t vid;
struct queuehdr msg;

msg.msg_type = type;
msg.msg_queue_id = queue_table[id].queue_id;
if ( Send( queue_table[id].queue_vid, &msg, &msg,
sizeof (struct queuehdr), sizeof (msg.msg_type) ) == -1 ) {
vid = queue_table[id].queue_vid;
for(qp = &queue_table[0] ; qp < &queue_table[MAX_QUEUE_OPENS] ; ++qp)
if(qp->queue_vid == vid)
{
qp->queue_vid = 0;
qp->queue_nid = 0;
}

qnx_vc_detach(vid);
return(QSTAT_SEND);
}

for(qp = &queue_table[0] ; qp < &queue_table[MAX_QUEUE_OPENS] ; ++qp)
if(qp->queue_vid == queue_table[id].queue_vid) ++count;

if(count == 1)
qnx_vc_detach(queue_table[id].queue_vid);
queue_table[id].queue_vid = 0;
queue_table[id].queue_nid = 0;

return(msg.msg_type);
}

int queue_close(int id)
{
return( queue_release(id,QUEUE_CLOSE) );
}

int queue_kill(int id)
{
return( queue_release(id,QUEUE_KILL) );
}

int queue_purge(int id)
{
struct queuehdr msg;

msg.msg_type = QUEUE_PURGE;
msg.msg_queue_id = queue_table[id].queue_id;
if ( Send( queue_table[id].queue_vid, &msg, &msg,
sizeof (struct queuehdr), sizeof (msg.msg_type) ) == -1 )
return QSTAT_SEND;
return(msg.msg_type);
}

int queue_info(nid_t nid, int id, void *ptr)
{
pid_t vid;
struct queuehdr *mp=ptr;
char queuename[25];

if ( nid == 0 )  /* find global queue admin */
   strcpy(queuename,"/queue");
else
   strcpy(queuename,"queue");

if ( (vid = qnx_name_locate( nid, queuename, 0, NULL )) == 0 )
	return QSTAT_FIND;

mp->msg_type		= QUEUE_INFO;
mp->msg_queue_id	= id;
if ( Send( vid, mp, mp, sizeof (*mp), 
           sizeof (*mp) + sizeof (struct queue_info ) ) == -1 ) {
   qnx_vc_detach( vid );
   return QSTAT_FIND;
   }
return mp->msg_type ? mp->msg_type : mp->msg_queue_id;

}

int queue_return_code_string(int code, char s)
{
/
this function will fill char pointer (s) with a description of the
return code. The code is a return of the queue_* routines.
e.g.
pass in code=-5, this function will fill area pointed to by s with
‘Queue has room for a message’.
This function can be useful for diagnostics.
*/

/* Here are the manifests from queue.h :
#define OK 0 Status OK
#define QSTAT_WAITM -1 Queue has a msg
#define QSTAT_WAITW -2 Queue has no writers
#define QSTAT_WAITE -3 Queue is empty
#define QSTAT_WAITR -4 Queue has no readers
#define QSTAT_WAITS -5 Queue has room for msg
#define QSTAT_WAITT -6 Queue timeout

#define QSTAT_BADMSG            -9  Invalid message
#define QSTAT_OPEN_MODE         -10 Invalid open mode
#define QSTAT_OPEN_PERMS        -11 Open for r or w denied
#define QSTAT_CREATE            -12 Unable to create
#define QSTAT_MEM               -13 No memory for request
#define QSTAT_EXIST             -14 Queue does not exist
#define QSTAT_WINDOW            -15 Queue window is full
#define QSTAT_REPLY             -16 Network error
#define QSTAT_NAME              -17 Invalid queue name
#define QSTAT_FIND              -18 Can't locate Queue administrator
#define QSTAT_SLOT              -19 Too many open queues
#define QSTAT_SEND              -20 Send failed
#define QSTAT_MSGSIZE           -21 Message to big for read.
#define QSTAT_INTERNAL          -22 Internal error.

*/

switch ( code ) {
case 0: strcpy(s, “No error. Status OK.”); break;
case -1: strcpy(s, “Queue has a message available.”); break;
case -2: strcpy(s, “Queue has no writers.”); break;
case -3: strcpy(s, “Queue is empty.”); break;
case -4: strcpy(s, “Queue has no readers.”); break;
case -5: strcpy(s, “Queue has room for a message.”); break;
case -6: strcpy(s, “Queue request timed out.”); break;
case -9: strcpy(s, “Invalid message.”); break;
case -10: strcpy(s, “Invalid open mode.”); break;
case -11: strcpy(s, “Open for read or write denied.”); break;
case -12: strcpy(s, “Unable to create queue.”); break;
case -13: strcpy(s, “No memory for request.”); break;
case -14: strcpy(s, “Queue does not exist.”); break;
case -15: strcpy(s, “Queue window is full.”); break;
case -16: strcpy(s, “Network error.”); break;
case -17: strcpy(s, “Invalid queue name.”); break;
case -18: strcpy(s, “Cannot locate queue administrator.”); break;
case -19: strcpy(s, “Too many open queues.”); break;
case -20: strcpy(s, “Send failed.”); break;
case -21: strcpy(s, “Message too big for read.”); break;
case -22: strcpy(s, “Internal error.”); break;
}
return(0);
}

                                                                                Warm Regards
                                                                                Pramod Nakhale