00001 /* 00002 SMI - System V messages 00003 AUP2, Sec. 7.05.3 00004 00005 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00006 May be copied only for purposes and under conditions described 00007 on the Web page www.basepath.com/aup/copyright.htm. 00008 00009 The Example Files are provided "as is," without any warranty; 00010 without even the implied warranty of merchantability or fitness 00011 for a particular purpose. The author and his publisher are not 00012 responsible for any damages, direct or incidental, resulting 00013 from the use or non-use of these Example Files. 00014 00015 The Example Files may contain defects, and some contain deliberate 00016 coding mistakes that were included for educational reasons. 00017 You are responsible for determining if and how the Example Files 00018 are to be used. 00019 00020 */ 00021 #include "defs.h" 00022 #include "smi_msg.h" 00023 #ifdef HAVE_SYSVMSG 00024 #include <sys/msg.h> 00025 /*[top]*/ 00026 typedef struct { 00027 SMIENTITY sq_entity; /* entity */ 00028 int sq_qid_server; /* server identifier */ 00029 int sq_qid_client; /* client identifier (not used by server) */ 00030 char sq_name[SERVER_NAME_MAX]; /* server name */ 00031 struct client_id sq_client; /* client ID */ 00032 size_t sq_msgsize; /* msg size */ 00033 struct smi_msg *sq_msg; /* msg buffer */ 00034 } SMIQ_MSG; 00035 /*[mkmsg_name_server]*/ 00036 static void mkmsg_name_server(const SMIQ_MSG *p, char *msgname, 00037 size_t msgname_max) 00038 { 00039 snprintf(msgname, msgname_max, "/tmp/smimsg-%s", p->sq_name); 00040 } 00041 /*[smi_open_msg]*/ 00042 SMIQ *smi_open_msg(const char *name, SMIENTITY entity, size_t msgsize) 00043 { 00044 SMIQ_MSG *p = NULL; 00045 char msgname[SERVER_NAME_MAX + 100]; 00046 key_t key; 00047 00048 ec_null( p = calloc(1, sizeof(SMIQ_MSG)) ) 00049 p->sq_msgsize = msgsize + offsetof(struct smi_msg, smi_data); 00050 ec_null( p->sq_msg = calloc(1, p->sq_msgsize) ) 00051 p->sq_qid_server = p->sq_qid_client = -1; 00052 p->sq_entity = entity; 00053 if (strlen(name) >= SERVER_NAME_MAX) { 00054 errno = ENAMETOOLONG; 00055 EC_FAIL 00056 } 00057 strcpy(p->sq_name, name); 00058 mkmsg_name_server(p, msgname, sizeof(msgname)); 00059 (void)close(open(msgname, O_WRONLY | O_CREAT, 0)); 00060 ec_neg1( key = ftok(msgname, 1) ) 00061 if (p->sq_entity == SMI_SERVER) { 00062 if ((p->sq_qid_server = msgget(key, PERM_FILE)) != -1) 00063 (void)msgctl(p->sq_qid_server, IPC_RMID, NULL); 00064 ec_neg1( p->sq_qid_server = msgget(key, IPC_CREAT | PERM_FILE) ) 00065 } 00066 else { 00067 ec_neg1( p->sq_qid_server = msgget(key, 0) ) 00068 ec_neg1( p->sq_qid_client = msgget(IPC_PRIVATE, PERM_FILE) ); 00069 } 00070 return (SMIQ *)p; 00071 00072 EC_CLEANUP_BGN 00073 if (p != NULL) 00074 (void)smi_close_msg((SMIQ *)p); 00075 return NULL; 00076 EC_CLEANUP_END 00077 } 00078 /*[smi_close_msg]*/ 00079 bool smi_close_msg(SMIQ *sqp) 00080 { 00081 SMIQ_MSG *p = (SMIQ_MSG *)sqp; 00082 00083 if (p->sq_entity == SMI_SERVER) { 00084 char msgname[FILENAME_MAX]; // wrong symbol... need max pathname 00085 00086 (void)msgctl(p->sq_qid_server, IPC_RMID, NULL); 00087 mkmsg_name_server(p, msgname, sizeof(msgname)); 00088 (void)unlink(msgname); 00089 } 00090 else 00091 (void)msgctl(p->sq_qid_client, IPC_RMID, NULL); 00092 free(p->sq_msg); 00093 free(p); 00094 return true; 00095 } 00096 /*[smi_send_getaddr_msg]*/ 00097 bool smi_send_getaddr_msg(SMIQ *sqp, struct client_id *client, 00098 void **addr) 00099 { 00100 SMIQ_MSG *p = (SMIQ_MSG *)sqp; 00101 00102 if (p->sq_entity == SMI_SERVER) 00103 p->sq_client = *client; 00104 *addr = p->sq_msg; 00105 return true; 00106 } 00107 00108 bool smi_send_release_msg(SMIQ *sqp) 00109 { 00110 SMIQ_MSG *p = (SMIQ_MSG *)sqp; 00111 int qid_receiver; 00112 00113 p->sq_msg->smi_mtype = 1; 00114 if (p->sq_entity == SMI_SERVER) 00115 qid_receiver = p->sq_client.c_id1; 00116 else { 00117 qid_receiver = p->sq_qid_server; 00118 p->sq_msg->smi_client.c_id1 = p->sq_qid_client; 00119 } 00120 ec_neg1( msgsnd(qid_receiver, p->sq_msg, 00121 p->sq_msgsize - sizeof(p->sq_msg->smi_mtype), 0) ) 00122 return true; 00123 00124 EC_CLEANUP_BGN 00125 return false; 00126 EC_CLEANUP_END 00127 } 00128 /*[smi_receive_getaddr_msg]*/ 00129 bool smi_receive_getaddr_msg(SMIQ *sqp, void **addr) 00130 { 00131 SMIQ_MSG *p = (SMIQ_MSG *)sqp; 00132 int qid_receiver; 00133 ssize_t nrcv; 00134 00135 if (p->sq_entity == SMI_SERVER) 00136 qid_receiver = p->sq_qid_server; 00137 else 00138 qid_receiver = p->sq_qid_client; 00139 ec_neg1( nrcv = msgrcv(qid_receiver, p->sq_msg, 00140 p->sq_msgsize - sizeof(p->sq_msg->smi_mtype), 0, 0) ) 00141 *addr = p->sq_msg; 00142 return true; 00143 00144 EC_CLEANUP_BGN 00145 return false; 00146 EC_CLEANUP_END 00147 } 00148 00149 bool smi_receive_release_msg(SMIQ *sqp) 00150 { 00151 return true; 00152 } 00153 /*[]*/ 00154 00155 #else /* HAVE_SYSVMSG */ 00156 SMIQ *smi_open_msg(const char *name, SMIENTITY entity, size_t msgsize) 00157 { 00158 errno = ENOSYS; 00159 return NULL; 00160 } 00161 00162 bool smi_close_msg(SMIQ *sqp) 00163 { 00164 errno = ENOSYS; 00165 return false; 00166 } 00167 00168 bool smi_send_getaddr_msg(SMIQ *sqp, struct client_id *client, 00169 void **addr) 00170 { 00171 errno = ENOSYS; 00172 return false; 00173 } 00174 00175 bool smi_send_release_msg(SMIQ *sqp) 00176 { 00177 errno = ENOSYS; 00178 return false; 00179 } 00180 00181 bool smi_receive_getaddr_msg(SMIQ *sqp, void **addr) 00182 { 00183 errno = ENOSYS; 00184 return false; 00185 } 00186 00187 bool smi_receive_release_msg(SMIQ *sqp) 00188 { 00189 errno = ENOSYS; 00190 return false; 00191 } 00192 00193 #endif /* HAVE_SYSVMSG */