ARPDAS_QNX6 1.0
|
00001 #include <unistd.h> 00002 #include <errno.h> 00003 #include <sys/types.h> 00004 #include <sys/stat.h> 00005 #include <fcntl.h> 00006 #include <string.h> 00007 #include <ctype.h> 00008 #include "DG_Resmgr.h" 00009 #include "DG_cmd.h" 00010 #include "nortlib.h" 00011 #include "nl_assert.h" 00012 #include "tm.h" 00013 00014 static DG_cmd *Cmd; 00015 resmgr_connect_funcs_t DG_cmd::connect_funcs; 00016 resmgr_io_funcs_t DG_cmd::io_funcs; 00017 iofunc_attr_t DG_cmd::cmd_attr; 00018 00019 /** 00020 * buf is guaranteed to be nul-terminated 00021 * We will strip any trailing newlines before forwarding to dg->execute() 00022 */ 00023 int DG_cmd::execute(char *buf) { 00024 assert(buf != 0); 00025 int len = strlen(buf); 00026 while ( len > 0 && isspace(buf[len-1]) ) 00027 buf[--len] = '\0'; 00028 return dg->execute(buf); 00029 } 00030 00031 DG_cmd::DG_cmd(data_generator *data_gen) : DG_dispatch_client() { 00032 dg = data_gen; 00033 } 00034 00035 void DG_cmd::attach() { 00036 dispatch_t *dpp = dg->dispatch->dpp; 00037 if (Cmd != NULL) 00038 nl_error(3,"Only one DG_cmd instance allowed"); 00039 00040 // This is our write-only command interface 00041 resmgr_attr_t resmgr_attr; 00042 memset(&resmgr_attr, 0, sizeof(resmgr_attr)); 00043 resmgr_attr.nparts_max = 1; 00044 resmgr_attr.msg_max_size = DG_CMD_BUFSIZE+1; 00045 00046 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &connect_funcs, 00047 _RESMGR_IO_NFUNCS, &io_funcs ); 00048 io_funcs.write = DG_cmd_io_write; 00049 00050 iofunc_attr_init( &DG_cmd::cmd_attr, S_IFNAM | 0222, 0, 0 ); // write-only 00051 const char *wr_devname = tm_dev_name( "DG/cmd" ); 00052 dev_id = resmgr_attach( dpp, &resmgr_attr, wr_devname, _FTYPE_ANY, 0, 00053 &DG_cmd::connect_funcs, &DG_cmd::io_funcs, &DG_cmd::cmd_attr ); 00054 if ( dev_id == -1 ) 00055 nl_error( 3, "Unable to attach name %s: errno %d", wr_devname, errno ); 00056 00057 Cmd = this; 00058 DG_dispatch_client::attach(dg->dispatch); // Now get in on the quit loop 00059 } 00060 00061 DG_cmd::~DG_cmd() { } 00062 00063 int DG_cmd_io_write( resmgr_context_t *ctp, 00064 io_write_t *msg, RESMGR_OCB_T *ocb ) { 00065 int status, msgsize; 00066 char buf[DG_cmd::DG_CMD_BUFSIZE+1]; 00067 00068 status = iofunc_write_verify(ctp, msg, (iofunc_ocb_t *)ocb, NULL); 00069 if ( status != EOK ) 00070 return status; 00071 00072 if ((msg->i.xtype &_IO_XTYPE_MASK) != _IO_XTYPE_NONE ) 00073 return ENOSYS; 00074 00075 msgsize = msg->i.nbytes; 00076 if ( msgsize > DG_cmd::DG_CMD_BUFSIZE ) 00077 return E2BIG; 00078 00079 00080 resmgr_msgread( ctp, buf, msgsize, sizeof(msg->i) ); 00081 buf[msgsize] = '\0'; 00082 00083 // Handle the message 00084 // Reply to sender before handling the command to 00085 // reduce possibility of deadlock. 00086 MsgReply(ctp->rcvid, msg->i.nbytes, NULL, 0); 00087 Cmd->execute(buf); 00088 return _RESMGR_NOREPLY; 00089 00090 //_IO_SET_WRITE_NBYTES( ctp, msg->i.nbytes ); 00091 // return EOK; 00092 } 00093 00094 /** DG_cmd::ready_to_quit() returns true if we are ready to terminate. For DG/cmd, that means all writers 00095 have closed their connections and we have detached the device. 00096 */ 00097 int DG_cmd::ready_to_quit() { 00098 // unlink the name 00099 if ( dev_id != -1 ) { 00100 int rc = resmgr_detach( dispatch->dpp, dev_id, _RESMGR_DETACH_PATHNAME ); 00101 if ( rc == -1 ) 00102 nl_error( 2, "Error returned from resmgr_detach: %d", errno ); 00103 dev_id = -1; 00104 } 00105 // ### Need to make sure my data_generator knows it's time to quit 00106 return cmd_attr.count == 0; 00107 }