File indexing completed on 2024-12-01 06:51:48
0001 /** 0002 * KMuddy scripting - variable support 0003 * 0004 * #include this file in a C/C++ script, if you want to use variables 0005 * in that script. 0006 * 0007 * */ 0008 0009 /* PUBLIC INTERFACE: */ 0010 0011 /** call this at the beginning of your script */ 0012 void initVariableSocket (); 0013 0014 /** call this at the end of your script */ 0015 void closeVariableSocket (); 0016 0017 /** call this to set your script up to listen on an IP port */ 0018 void initIPPort(const int ip_port); 0019 0020 /** wait for and retrieve event notification from IP port */ 0021 void getEvent (char *buffer, int buflen); 0022 0023 /** reads variable value and store it in the buffer (of size buflen+1) */ 0024 void getVariable (const char *name, char *buffer, int buflen); 0025 0026 /** sets a variable value */ 0027 char setVariable (const char *name, const char *value); 0028 0029 /** unsets a variable */ 0030 char unsetVariable (const char *name); 0031 0032 /** increases a variable value */ 0033 char incVariable (const char *name, int delta); 0034 0035 /** decreases a variable value */ 0036 char decVariable (const char *name, int delta); 0037 0038 /** provide a resource */ 0039 char provideResource (const char *name); 0040 0041 /** request a resource */ 0042 char requestResource (const char *name); 0043 0044 /** request variable lock */ 0045 char lockVariable (const char *name); 0046 0047 /** unlock a variable */ 0048 void unlockVariable (const char *name); 0049 0050 /** sends a command to the MUD */ 0051 char sendCommand (const char *command); 0052 0053 0054 0055 0056 /* INTERNAL VARIABLES AND FUNCTIONS -- DO NOT USE IN THE SCRIPT */ 0057 #define MAX_PENDING_CONNECTIONS 5 0058 char internalBuffer[51]; 0059 int variableSocket = -1; 0060 int serverSocket = -1; 0061 int clientSocket = -1; 0062 char simpleCommand (const char *command, const char *name); 0063 0064 void sendAndReceive (const char *sendthis, char *buffer, int buflen); 0065 0066 /* IMPLEMENTATION */ 0067 0068 #include <errno.h> 0069 0070 #include <stdio.h> 0071 #include <stdlib.h> 0072 #include <string.h> 0073 #include <unistd.h> 0074 #include <sys/socket.h> 0075 #include <sys/types.h> 0076 #include <sys/un.h> 0077 #include <netinet/in.h> 0078 #include <arpa/inet.h> 0079 #include <kvbox.h> 0080 0081 0082 void initVariableSocket () 0083 { 0084 struct sockaddr_un sa; 0085 char *path; 0086 path = getenv ("KMUDDY_SOCKET"); 0087 if (!path) 0088 { 0089 puts ("Variable KMUDDY_SOCKET is not set - variable support won't work!\n"); 0090 fflush (stdout); 0091 return; /* bah! */ 0092 } 0093 variableSocket = socket (PF_UNIX, SOCK_STREAM, 0); 0094 sa.sun_family = AF_UNIX; 0095 strcpy (sa.sun_path, path); 0096 if (connect (variableSocket, (struct sockaddr *) &sa, sizeof (sa)) == -1) 0097 { 0098 close (variableSocket); 0099 variableSocket = -1; /* :( */ 0100 puts ("Could not connect to KMuddy!\n"); 0101 printf ("Error = %s\n", strerror (errno)); 0102 fflush (stdout); 0103 } 0104 /* okay, we should be connected now... */ 0105 } 0106 0107 void closeVariableSocket () 0108 { 0109 if (variableSocket != -1) 0110 close (variableSocket); 0111 0112 if (serverSocket != -1) 0113 close (serverSocket); 0114 0115 if (clientSocket != -1) 0116 close(clientSocket); 0117 0118 } 0119 0120 0121 /** call this to set your script up to listen on an IP port */ 0122 void initIPPort(const int ip_port) 0123 { 0124 struct sockaddr_in server_address; 0125 int val = 1; 0126 int result; 0127 0128 serverSocket = socket(AF_INET, 0129 SOCK_STREAM, 0130 0); 0131 0132 if (serverSocket < 0) 0133 { 0134 puts ("Unable to create a socket - server support won't work!\n"); 0135 fflush (stdout); 0136 return; /* bah! */ 0137 } /* endif unable to obtain a socket */ 0138 0139 result = setsockopt(serverSocket, 0140 SOL_SOCKET, 0141 SO_REUSEADDR, 0142 (char *)&val, 0143 sizeof(val)); 0144 0145 if (result != 0) 0146 { 0147 close(serverSocket); 0148 puts ("Unable to modify socket options - server support won't work!\n"); 0149 fflush (stdout); 0150 return; /* bah! */ 0151 } /* endif unable to modify socket options */ 0152 0153 server_address.sin_family = AF_INET; 0154 server_address.sin_addr.s_addr = htonl(INADDR_ANY); 0155 server_address.sin_port = htons(ip_port); 0156 0157 result = bind(serverSocket, 0158 (struct sockaddr *)&server_address, 0159 sizeof(server_address)); 0160 0161 if (result != 0) 0162 { 0163 close(serverSocket); 0164 puts ("Unable to bind socket to specified IP port - server support won't work!\n"); 0165 fflush (stdout); 0166 return; /* bah! */ 0167 } /* endif unable to modify socket options */ 0168 0169 result = listen(serverSocket, 0170 MAX_PENDING_CONNECTIONS); 0171 0172 if (result != 0) 0173 { 0174 close(serverSocket); 0175 puts ("Unable to listen on specified IP port - server support won't work!\n"); 0176 fflush (stdout); 0177 return; /* bah! */ 0178 } /* endif unable to modify socket options */ 0179 0180 } /* initIPPort */ 0181 0182 0183 /** wait for and retrieve event notification from IP port */ 0184 void getEvent (char *buffer, int buflen) 0185 { 0186 struct sockaddr_in client_address; 0187 0188 int client_name_size; 0189 char *dest; 0190 int finished = 0; 0191 int remaining; 0192 int received; 0193 int total; 0194 0195 /* Buffer to store incoming TCP/IP data */ 0196 static char recv_buffer[1024]; 0197 const int recv_buffer_maxsize = 1024; 0198 static int recv_amount = 0; /* Amount actually received from the network */ 0199 static int recv_offset = 0; /* Amount processed so far */ 0200 static int need_skip = 0; /* Set if we need to ignore everything until next \n */ 0201 0202 int buffer_offset = 0; 0203 0204 buffer[0] = '\0'; 0205 0206 if (serverSocket == -1) 0207 { 0208 return; 0209 } /* endif not listening on IP port */ 0210 0211 if (clientSocket == -1) 0212 { 0213 /* Debug message */ 0214 /* 0215 puts ("No previous connection from KMuddy - waiting for connection\n"); 0216 fflush (stdout); 0217 */ 0218 0219 client_name_size = sizeof(client_address); 0220 0221 clientSocket = accept(serverSocket, 0222 (struct sockaddr *)&client_address, 0223 (socklen_t *)&client_name_size); 0224 0225 } // endif no previous dialogue with server 0226 0227 if (clientSocket < 0) 0228 { 0229 return; 0230 } /* endif accept failed */ 0231 0232 0233 while (!finished) 0234 { 0235 if (recv_offset >= recv_amount) 0236 { 0237 recv_offset = 0; 0238 0239 recv_amount = recv(clientSocket, 0240 recv_buffer, 0241 recv_buffer_maxsize, 0242 0); 0243 0244 } /* endif need to receive more data from the network */ 0245 0246 if (need_skip) 0247 { 0248 while ((recv_offset < recv_amount)&& 0249 (recv_buffer[recv_offset] != '\n') ) 0250 { 0251 recv_offset++; 0252 } /* endwhile more characters to skip */ 0253 0254 if (recv_offset < recv_amount) 0255 { 0256 recv_offset++; 0257 need_skip = 0; 0258 } /* endif found \n */ 0259 0260 } /* endif need to ignore everything until next \n */ 0261 0262 while ((recv_offset < recv_amount)&& 0263 (buffer_offset < buflen-1) && 0264 (recv_buffer[recv_offset] != '\n') ) 0265 { 0266 buffer[buffer_offset++] = recv_buffer[recv_offset++]; 0267 0268 } /* endwhile not found complete message yet */ 0269 0270 if (buffer_offset == buflen-1) 0271 { 0272 /* Truncate message */ 0273 buffer[buflen-1] = '\0'; 0274 finished = 1; 0275 need_skip = 1; /* need to ignore everything until next \n */ 0276 } /* endif reached limits of message buffer */ 0277 else if (recv_offset < recv_amount) 0278 { 0279 /* Found \n at recv_offset */ 0280 buffer[buffer_offset] = '\0'; 0281 finished = 1; 0282 recv_offset++; 0283 } /* endif received full message */ 0284 0285 } /* endwhile more work to do to receive complete message */ 0286 0287 } /* getEvent */ 0288 0289 0290 0291 void getVariable (const char *name, char *buffer, int buflen) 0292 { 0293 int n; 0294 /* some initial tests */ 0295 if (!name) return; 0296 if (!buffer) return; 0297 if (buflen <= 0) return; 0298 //alocate memory for request-string 0299 n = strlen (name); 0300 char *request = (char *) malloc (6 + n); 0301 //build a request 0302 strcpy (request, "get "); 0303 strcat (request, name); 0304 strcat (request, "\n"); 0305 /* send it and receive the result */ 0306 sendAndReceive (request, buffer, buflen); 0307 /* free up memory used by the request-string */ 0308 free (request); 0309 } 0310 0311 char setVariable (const char *name, const char *value) 0312 { 0313 int n1, n2; 0314 /* some initial tests */ 0315 if (!name) return 0; 0316 if (!value) return 0; 0317 /* allocate memory for request-string */ 0318 n1 = strlen (name); 0319 n2 = strlen (value); 0320 char *request = (char *) malloc (7 + n1 + n2); 0321 /* build a request */ 0322 strcpy (request, "set "); 0323 strcat (request, name); 0324 strcat (request, " "); 0325 strcat (request, value); 0326 strcat (request, "\n"); 0327 /* send it and receive the result */ 0328 sendAndReceive (request, internalBuffer, 51); 0329 /* free up memory used by the request-string */ 0330 free (request); 0331 0332 if (strncmp (internalBuffer, "OK", 2) == 0) 0333 return 1; /* success */ 0334 return 0; /* failure */ 0335 } 0336 0337 char unsetVariable (const char *name) 0338 { 0339 return simpleCommand ("unset", name); 0340 } 0341 0342 char incVariable (const char *name, int delta) 0343 { 0344 int n1, n2; 0345 /* some initial tests */ 0346 if (!name) return 0; 0347 if (delta <= 0) return 0; 0348 //alocate memory for request-string 0349 n1 = strlen (name); 0350 n2 = 10; 0351 char *request = (char *) malloc (7 + n1 + n2); 0352 char *value = (char *) malloc (10); 0353 sprintf (value, "%d", delta); 0354 //build a request 0355 strcpy (request, "inc "); 0356 strcat (request, name); 0357 strcat (request, " "); 0358 strcat (request, value); 0359 strcat (request, "\n"); 0360 /* send it and receive the result */ 0361 sendAndReceive (request, internalBuffer, 51); 0362 /* free up memory used by the request-string */ 0363 free (request); 0364 0365 if (strncmp (internalBuffer, "OK", 2) == 0) 0366 return 1; /* success */ 0367 return 0; /* failure */ 0368 } 0369 0370 char decVariable (const char *name, int delta) 0371 { 0372 int n1, n2; 0373 /* some initial tests */ 0374 if (!name) return 0; 0375 if (delta <= 0) return 0; 0376 /* allocate memory for request-string */ 0377 n1 = strlen (name); 0378 n2 = 10; 0379 char *request = (char *) malloc (7 + n1 + n2); 0380 char *value = (char *) malloc (10); 0381 sprintf (value, "%d", delta); 0382 /* build a request */ 0383 strcpy (request, "dec "); 0384 strcat (request, name); 0385 strcat (request, " "); 0386 strcat (request, value); 0387 strcat (request, "\n"); 0388 /* send it and receive the result */ 0389 sendAndReceive (request, internalBuffer, 51); 0390 /* free up memory used by the request-string */ 0391 free (request); 0392 0393 if (strncmp (internalBuffer, "OK", 2) == 0) 0394 return 1; /* success */ 0395 return 0; /* failure */ 0396 } 0397 0398 char provideResource (const char *name) 0399 { 0400 return simpleCommand ("provide", name); 0401 } 0402 0403 char requestResource (const char *name) 0404 { 0405 return simpleCommand ("request", name); 0406 } 0407 0408 char lockVariable (const char *name) 0409 { 0410 return simpleCommand ("lock", name); 0411 } 0412 0413 void unlockVariable (const char *name) 0414 { 0415 simpleCommand ("unlock", name); 0416 } 0417 0418 char simpleCommand (const char *command, const char *name) 0419 { 0420 int n,k; 0421 /* some initial tests */ 0422 if (!name) return 0; 0423 /* allocate memory for request-string */ 0424 n = strlen (name); 0425 k = strlen (command); 0426 char *request = (char *) malloc (3 + k + n); 0427 /* build a request */ 0428 strcpy (request, command); 0429 strcat (request, " "); 0430 strcat (request, name); 0431 strcat (request, "\n"); 0432 /* send it and receive the result */ 0433 sendAndReceive (request, internalBuffer, 51); 0434 /* free up memory used by the request-string */ 0435 free (request); 0436 0437 if (strncmp (internalBuffer, "OK", 2) == 0) 0438 return 1; /* success */ 0439 return 0; /* failure */ 0440 } 0441 0442 void sendAndReceive (const char *sendthis, char *buffer, int buflen) 0443 { 0444 int n; 0445 int tobewritten, remaining; 0446 const char *sendme; 0447 char myBuf[101]; 0448 char gotNewLine = 0; 0449 buffer[0] = '\0'; 0450 0451 if (variableSocket == -1) 0452 return; 0453 tobewritten = strlen (sendthis); 0454 if (tobewritten == 0) 0455 return; 0456 /* pointer to data that hasn't been written yet */ 0457 sendme = sendthis; 0458 /* write it all */ 0459 while (tobewritten > 0) 0460 { 0461 n = write (variableSocket, sendme, strlen (sendme)); 0462 if (n == -1) 0463 /* TODO: some error reporting */ 0464 return; 0465 /* shift the pointer */ 0466 tobewritten -= n; // Alex change - moved from above 0467 sendme += n; 0468 } 0469 0470 /* read reply from KMuddy */ 0471 remaining = buflen; /* buffer needs to have one extra byte for \0 */ 0472 0473 while (!gotNewLine) 0474 { 0475 n = read (variableSocket, myBuf, 100); 0476 0477 if (n == -1) /* bah! */ 0478 return; 0479 myBuf[n] = '\0'; 0480 if (remaining) 0481 { 0482 strncat (buffer, myBuf, remaining); 0483 remaining -= n; 0484 if (remaining < 0) 0485 remaining = 0; 0486 n = strlen (buffer); 0487 if (n) 0488 if (buffer[n - 1] == '\n') 0489 { 0490 gotNewLine = 1; 0491 buffer[n - 1] = '\0'; /* don't return that newline */ 0492 } 0493 } 0494 } 0495 } 0496 0497 0498 0499 /* ALEX CHANGE */ 0500 char sendCommand (const char *command) 0501 { 0502 int n1; 0503 /* some initial tests */ 0504 if (!command) return 0; 0505 /* allocate memory for request-string */ 0506 n1 = strlen (command); 0507 char *request = (char *) malloc (7 + n1); 0508 /* build a request */ 0509 strcpy (request, "send "); 0510 strcat (request, command); 0511 strcat (request, "\n"); 0512 /* send it and receive the result */ 0513 sendAndReceive (request, internalBuffer, 51); 0514 /* free up memory used by the request-string */ 0515 free (request); 0516 0517 if (strncmp (internalBuffer, "OK", 2) == 0) 0518 return 1; /* success */ 0519 return 0; /* failure */ 0520 } 0521 0522 /* END ALEX CHANGE */