352 lines
9.0 KiB
C
352 lines
9.0 KiB
C
/* This file is part of the Project Athena Zephyr Notification System.
|
|
* It is one of the source files comprising zwgc, the Zephyr WindowGram
|
|
* client.
|
|
*
|
|
* Created by: Marc Horowitz <marc@athena.mit.edu>
|
|
*
|
|
* $Id$
|
|
*
|
|
* Copyright (c) 1989 by the Massachusetts Institute of Technology.
|
|
* For copying and distribution information, see the file
|
|
* "mit-copyright.h".
|
|
*/
|
|
|
|
#include <sysdep.h>
|
|
|
|
#if (!defined(lint) && !defined(SABER))
|
|
static const char rcsid_notice_c[] = "$Id$";
|
|
#endif
|
|
|
|
#include <zephyr/mit-copyright.h>
|
|
|
|
/****************************************************************************/
|
|
/* */
|
|
/* Module containing code to extract a notice's fields: */
|
|
/* */
|
|
/****************************************************************************/
|
|
|
|
#include <zephyr/zephyr.h>
|
|
#include <arpa/inet.h>
|
|
#include "new_memory.h"
|
|
#include "error.h"
|
|
#include "variables.h"
|
|
#include "notice.h"
|
|
#ifdef CMU_ZWGCPLUS
|
|
#include <pwd.h>
|
|
#include "plus.h"
|
|
#endif
|
|
|
|
/*
|
|
* int count_nulls(char *data, int length)
|
|
* Requires: length>=0
|
|
* Effects: Returns the # of nulls in data[0]..data[length-1]
|
|
*/
|
|
|
|
int
|
|
count_nulls(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(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(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(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(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(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(ZNotice_t *notice,
|
|
char *hostname)
|
|
{
|
|
char *temp;
|
|
string when, notyear, year, date_string, time_string;
|
|
|
|
/*
|
|
* 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("notice_charset", (char *)ZCharsetToString(notice->z_charset)); /*XXX const*/
|
|
var_set_variable("recipient",
|
|
(notice->z_recipient[0] ? notice->z_recipient : "*"));
|
|
var_set_variable("fullsender", notice->z_sender);
|
|
var_set_variable_to_number("port", (int)ntohs(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));
|
|
|
|
#ifdef CMU_ZWGCPLUS
|
|
if ((temp=getSelectedText()) != 0)
|
|
var_set_variable("selection", temp);
|
|
|
|
var_set_variable("delete_window", "none");
|
|
var_set_variable("event_time", "none");
|
|
var_set_variable("event_name", "event");
|
|
#endif
|
|
/*
|
|
* Set $sender to the name of the notice sender except first strip off the
|
|
* realm name if it is the local realm:
|
|
*/
|
|
if ( (temp=strchr(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);
|
|
#ifdef CMU_ZWGCPLUS
|
|
if (get_full_names) {
|
|
struct passwd *pwnam = getpwnam(var_get_variable("sender"));
|
|
if (pwnam) {
|
|
temp = string_Copy(pwnam->pw_gecos);
|
|
var_set_variable_then_free_value("sendername", temp);
|
|
} else {
|
|
var_set_variable("sendername", "unknown");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* 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".
|
|
*/
|
|
{
|
|
/* the fields of struct timeval might not be the right type to pass
|
|
to ctime, so use a temporary */
|
|
time_t sec = notice->z_time.tv_sec;
|
|
when = ctime(&sec);
|
|
}
|
|
time_string = string_CreateFromData(when+11,8);
|
|
var_set_variable_then_free_value("time", time_string);
|
|
date_string = string_Concat(notyear=string_CreateFromData(when,11),
|
|
year=string_CreateFromData(when+20,4));
|
|
var_set_variable_then_free_value("date", date_string);
|
|
free(notyear);
|
|
free(year);
|
|
|
|
/*
|
|
* Convert host notice sent from to ascii:
|
|
*/
|
|
var_set_variable("fromhost", hostname ? hostname :
|
|
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);
|
|
}
|