summaryrefslogtreecommitdiff
path: root/zwgc/notice.c
diff options
context:
space:
mode:
authorGravatar Marc Horowitz <marc@mit.edu>1989-11-01 20:02:01 +0000
committerGravatar Marc Horowitz <marc@mit.edu>1989-11-01 20:02:01 +0000
commitd13d8a046838ce3d0e2643bb5b49f2ff77d679ca (patch)
tree05737bc11e3461836ce817939b9129ed58545ac7 /zwgc/notice.c
parentfd994e4099ad66fb3bf26cd636ca5d5cae72da68 (diff)
Initial revision
Diffstat (limited to 'zwgc/notice.c')
-rw-r--r--zwgc/notice.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/zwgc/notice.c b/zwgc/notice.c
new file mode 100644
index 0000000..a4dfd0a
--- /dev/null
+++ b/zwgc/notice.c
@@ -0,0 +1,306 @@
+/****************************************************************************/
+/* */
+/* Module containing code to extract a notice's fields: */
+/* */
+/****************************************************************************/
+
+#include <zephyr/zephyr.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "new_memory.h"
+#include "error.h"
+#include "variables.h"
+#include "notice.h"
+
+/*
+ * int count_nulls(char *data, int length)
+ * Requires: length>=0
+ * Effects: Returns the # of nulls in data[0]..data[length-1]
+ */
+
+int count_nulls(data, length)
+ char *data;
+ int length;
+{
+ int count = 0;
+
+ for (; length; data++, length--)
+ if (!*data)
+ count++;
+
+ return(count);
+}
+
+/*
+ * string get_next_field(char **data_p, int *length_p)
+ * Requires: *length_p >= 0
+ * Modifies: *data_p, *length_p
+ * Effects: Treats (*data_p)[0], (*data_p)[1], ... (*data_p)[length-1]
+ * as a series of null-seperated fields. This function
+ * returns a copy of the first field on the heap. This
+ * string must eventually be freed. Also, *data_p is
+ * advanced and *length_p decreased so that another
+ * call to this procedure with the same arguments will
+ * return the second field. The next call will return
+ * the third field, etc. "" is returned if 0 fields
+ * remain. (this is the case when *length_p == 0)
+ */
+
+string get_next_field(data_p, length_p)
+ char **data_p;
+ int *length_p;
+{
+ char *data = *data_p;
+ int length = *length_p;
+ char *ptr;
+
+ for (ptr=data; length; ptr++, length--)
+ if (!*ptr) {
+ *data_p = ptr+1;
+ *length_p = length-1;
+ return(string_Copy(data));
+ }
+
+ length = *length_p;
+ *data_p = ptr;
+ *length_p = 0;
+ return(string_CreateFromData(data, length));
+}
+
+/*
+ * string get_field(char *data, int length, int num)
+ * Requires: length>=0, num>0
+ * Effects: Treats data[0]..data[length-1] as a series of
+ * null-seperated fields. This function returns a copy of
+ * the num'th field (numbered from 1 in this case) on the
+ * heap. This string must eventually be freed. If there
+ * is no num'th field (because num<1 or num># of fields),
+ * "" is returned.
+ */
+
+string get_field(data, length, num)
+ char *data;
+ int length;
+ int num;
+{
+ /*
+ * While num>1 and there are fields left, skip a field & decrement num:
+ */
+ while (length && num>1) {
+ if (!*data)
+ num--;
+ length--;
+ data++;
+ }
+
+ /*
+ * If any more fields left, the first field is the one we want.
+ * Otherwise, there is no such field as num -- return "".
+ */
+ if (length)
+ return(get_next_field(&data, &length));
+ else
+ return(string_Copy(""));
+}
+
+/*
+ * string convert_nulls_to_newlines(data, length)
+ * Requires: length>=0, malloc never returns NULL
+ * Effects: Takes data[0]..data[length-1], converts all nulls to
+ * newlines ('\n') and returns the result as a null-terminated
+ * string on the heap. The returned string must eventually
+ * be freed.
+ */
+
+string convert_nulls_to_newlines(data, length)
+ char *data;
+ int length;
+{
+ char *result, *ptr;
+ char c;
+
+ result = (char *) malloc(length+1);
+ result[length] = '\0';
+
+ for (ptr=result; length; data++, ptr++, length--)
+ *ptr = (c = *data) ? c : '\n';
+
+ return(result);
+}
+
+
+/*
+ * Internal Routine:
+ *
+ * string z_kind_to_ascii(ZNotice_Kind_t z_kind)
+ * Effects: Returns an ascii representation for z_kind.
+ * The string returned is on the heap and must be freed
+ * eventually.
+ */
+
+static string z_kind_to_ascii(z_kind)
+ ZNotice_Kind_t z_kind;
+{
+ string result;
+
+ switch (z_kind) {
+ case UNSAFE:
+ result = "unsafe";
+ break;
+
+ case UNACKED:
+ result = "unacked";
+ break;
+
+ case ACKED:
+ result = "acked";
+ break;
+
+ case HMACK:
+ result = "hmack";
+ break;
+
+ case HMCTL:
+ result = "hmctl";
+ break;
+
+ case SERVACK:
+ result = "servack";
+ break;
+
+ case SERVNAK:
+ result = "servnak";
+ break;
+
+ case CLIENTACK:
+ result = "clientack";
+ break;
+
+ case STAT:
+ result = "stat";
+ break;
+
+ default:
+ result = "<unknown kind>";
+ break;
+ }
+
+ return(string_Copy(result));
+}
+
+/*
+ * Internal Routine:
+ *
+ * string z_auth_to_ascii(int z_auth)
+ * Effects: Returns an ascii representation for z_auth.
+ * The string returned is on the heap and must be freed
+ * eventually.
+ */
+
+static string z_auth_to_ascii(z_auth)
+ int z_auth;
+{
+ string result;
+
+ switch (z_auth) {
+ case ZAUTH_FAILED:
+ result = "forged";
+ break;
+
+ case ZAUTH_NO:
+ result = "no";
+ break;
+
+ case ZAUTH_YES:
+ result = "yes";
+ break;
+
+ default:
+ result = "unknown";
+ break;
+ }
+
+ return(string_Copy(result));
+}
+
+/*
+ * char *decode_notice(ZNotice_t *notice)
+ * Modifies: various description language variables
+ * Effects:
+ */
+
+char *decode_notice(notice)
+ ZNotice_t *notice;
+{
+ char *temp;
+ string time, notyear, year, date_string, time_string;
+ struct hostent *fromhost;
+
+ /*
+ * Convert useful notice fields to ascii and store away in
+ * description language variables for later use by the
+ * the user's program:
+ */
+ var_set_variable("zephyr_version", notice->z_version);
+ var_set_variable("class", notice->z_class);
+ var_set_variable("instance", notice->z_class_inst);
+ var_set_variable("opcode", notice->z_opcode);
+ var_set_variable("default", notice->z_default_format);
+ var_set_variable("recipient", notice->z_recipient);
+ var_set_variable("fullsender", notice->z_sender);
+ var_set_variable_to_number("port", (int)notice->z_port);
+ var_set_variable_then_free_value("kind", z_kind_to_ascii(notice->z_kind));
+ var_set_variable_then_free_value("auth", z_auth_to_ascii(notice->z_auth));
+
+ /*
+ * Set $sender to the name of the notice sender except first strip off the
+ * realm name if it is the local realm:
+ */
+ if ( (temp=index(notice->z_sender,'@')) && string_Eq(temp+1, ZGetRealm()) )
+ var_set_variable_then_free_value("sender",
+ string_CreateFromData(notice->z_sender,
+ temp-notice->z_sender));
+ else
+ var_set_variable("sender", notice->z_sender);
+
+ /*
+ * Convert time & date notice was sent to ascii. The $time
+ * has the format "01:03:52" while $date has the format
+ * "Sun Sep 16 1973".
+ */
+ time = ctime(&(notice->z_time.tv_sec));
+ time_string = string_CreateFromData(time+11,8);
+ var_set_variable_then_free_value("time", time_string);
+ date_string = string_Concat(notyear=string_CreateFromData(time,11),
+ year=string_CreateFromData(time+20,4));
+ var_set_variable_then_free_value("date", date_string);
+ free(notyear);
+ free(year);
+
+ /*
+ * Convert host notice sent from to ascii:
+ */
+ fromhost = gethostbyaddr(&(notice->z_sender_addr), sizeof(struct in_addr),
+ AF_INET);
+ var_set_variable("fromhost", fromhost ? fromhost->h_name :
+ inet_ntoa(notice->z_sender_addr));
+
+ /*
+ * Set $message to the message field of the notice with nulls changed
+ * to newlines:
+ */
+ var_set_variable_then_free_value("message",
+ convert_nulls_to_newlines(notice->z_message,
+ notice->z_message_len));
+
+ /*
+ * Decide if its a control notice. If so, return the notice's
+ * opcode. Otherwise, return NULL:
+ */
+ if ((strcasecmp(notice->z_class, WG_CTL_CLASS)==0) && /* <<<>>> */
+ (strcasecmp(notice->z_class_inst, WG_CTL_USER)==0))
+ return(notice->z_opcode);
+ return(0);
+}