3942 lines
101 KiB
C++
3942 lines
101 KiB
C++
/*
|
|
* Copyright 1989,1990,1991,1992 Silicon Graphics, Inc. All rights reserved.
|
|
*
|
|
* NetGraph
|
|
*
|
|
* $Revision: 1.42 $
|
|
* $Date: 1996/02/26 01:27:47 $
|
|
*
|
|
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
|
|
* the contents of this file may not be disclosed to third parties, copied or
|
|
* duplicated in any form, in whole or in part, without the prior written
|
|
* permission of Silicon Graphics, Inc.
|
|
*
|
|
* RESTRICTED RIGHTS LEGEND:
|
|
* Use, duplication or disclosure by the Government is subject to restrictions
|
|
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
|
|
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
|
|
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
|
|
* rights reserved under the Copyright Laws of the United States.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h> // for rand()
|
|
#include <sys/types.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/stat.h>
|
|
#include <signal.h>
|
|
#include <netdb.h>
|
|
#include <netinet/in.h>
|
|
#include <net/if.h>
|
|
#include <osfcn.h>
|
|
#include <pwd.h>
|
|
#include <unistd.h>
|
|
#include <netdb.h>
|
|
#include <arpa/inet.h>
|
|
#include <ctype.h>
|
|
#include <errno.h> // for errno
|
|
#include <helpapi/HelpBroker.h>
|
|
|
|
// tinyui includes
|
|
#include <tuCallBack.h>
|
|
#include <tuFilePrompter.h>
|
|
#include <tuGadget.h>
|
|
#include <tuGC.h>
|
|
#include <tuPalette.h>
|
|
#include <tuRowColumn.h>
|
|
#include <tuScreen.h>
|
|
#include <tuTimer.h>
|
|
#include <tuTopLevel.h>
|
|
#include <tuVisual.h>
|
|
#include <tuWindow.h>
|
|
#include <tuXExec.h>
|
|
|
|
// netgraph includes
|
|
#include "arg.h"
|
|
#include "constants.h"
|
|
#include "editControl.h"
|
|
#include "messages.h"
|
|
#include "netGraph.h"
|
|
#include "paramControl.h"
|
|
#include "scrollGadget.h"
|
|
#include "timeGadget.h"
|
|
#include "viewGadget.h"
|
|
|
|
#include "dialog.h"
|
|
#include "event.h"
|
|
#include "tooloptions.h"
|
|
|
|
#include "help.h"
|
|
|
|
extern "C" {
|
|
|
|
#include <bstring.h>
|
|
#include <getopt.h>
|
|
#include <malloc.h>
|
|
|
|
// netvis/snoop includes
|
|
#include "exception.h"
|
|
#include "expr.h"
|
|
#include "license.h"
|
|
#include "protocol.h"
|
|
#include "snooper.h"
|
|
#include "snoopstream.h"
|
|
|
|
#include "netGraph_xdr.h"
|
|
|
|
int hist_init(SnoopStream*, h_info*, int interval);
|
|
int hist_read(SnoopStream*, struct histogram*);
|
|
|
|
int kill (pid_t pid, int sig);
|
|
int sethostresorder(const char *);
|
|
|
|
} // (extern C)
|
|
|
|
|
|
extern int _yp_disabled;
|
|
|
|
|
|
#define CONTROLS_FILE "~/.netgraphrc"
|
|
const float MEGABIT = (1000000.0 / 8.0); // # bytes/sec for 1M bits/sec
|
|
const float ETHER_CAPACITY = (10.0 * MEGABIT);
|
|
const float ETHER_HEAD = 24.0; // xxx is this right???
|
|
const float FDDI_CAPACITY = (100.0 * MEGABIT);
|
|
const float FDDI_HEAD = 0.0; // xxx what should this be???
|
|
const float TOKENRING_CAPACITY = (16.0 * MEGABIT);
|
|
const float TOKENRING_HEAD = 0.0; // xxx what should this be???
|
|
|
|
const char VIEW_GEOMETRY[] = "414x220+506+271";
|
|
const char EDIT_GEOMETRY[] = "445x618+8+142";
|
|
const char PARAM_GEOMETRY[] = "526x335+207+40";
|
|
|
|
|
|
// this is to convert from my "types" to event's "bases"
|
|
// static char* graphTypes[] = { "packets", "bytes", "%packets", "%bytes",
|
|
// "%ether", "%fddi", %tokenring,"%npackets", "%nbytes", 0 };
|
|
enum rateBase rateBases[] = { PACKET_BASED, BYTE_BASED, PERCENT_PKTS, PERCENT_BYTES,
|
|
PERCENT_UTIL, PERCENT_UTIL, PERCENT_UTIL, PERCENT_N_PKTS, PERCENT_N_BYTES};
|
|
|
|
void
|
|
|
|
NetGraph::doHelp(tuGadget *, void* helpCardName) {
|
|
|
|
HELPdisplay((char*)helpCardName);
|
|
|
|
}
|
|
|
|
tuDeclareCallBackClass(NetGraphCallBack, NetGraph);
|
|
tuImplementCallBackClass(NetGraphCallBack, NetGraph);
|
|
|
|
extern NetGraph *netgraph;
|
|
|
|
|
|
// Define the args that we understand. For example,
|
|
// saying "-fn foo" is the same as putting "NetGraph*font: foo" in a
|
|
// .Xdefaults file.
|
|
// HAD TO ADD -n & -s, since they were being eaten by tuResourceDB
|
|
// as -name and -sync! Also -i (-iconic)
|
|
static XrmOptionDescRec args[] = {
|
|
{"-i", "*interface", XrmoptionSepArg, NULL},
|
|
{"-u", "*controlsFile", XrmoptionSepArg, NULL},
|
|
{"-y", "*useyp", XrmoptionNoArg, "True"},
|
|
{"-h", "*help", XrmoptionNoArg, "Yes"},
|
|
{"-n", "*noTime", XrmoptionNoArg, "True"},
|
|
{"-s", "*scrollTime", XrmoptionNoArg, "True"},
|
|
};
|
|
|
|
static const int nargs = sizeof(args) / sizeof(XrmOptionDescRec);
|
|
|
|
// Define some application specific resources. Right now, they all
|
|
// need to be placed into one structure. Note that most of these
|
|
// names match up to the command line arguments above.
|
|
struct AppResources {
|
|
char* interface;
|
|
char* controlsFile;
|
|
char* hostresorder;
|
|
tuBool useyp;
|
|
tuBool help;
|
|
tuBool noTime;
|
|
tuBool scrollTime;
|
|
|
|
long editControlBackgroundColor;
|
|
long paramControlBackgroundColor;
|
|
long selectColor;
|
|
long alarmColor;
|
|
|
|
short stripBackgroundIndexColor;
|
|
short stripScaleIndexColor;
|
|
short scrollingTimeIndexColor;
|
|
};
|
|
|
|
|
|
static tuResourceItem opts[] = {
|
|
{ "interface", 0, tuResString, "", offsetof(AppResources, interface), },
|
|
{ "controlsFile", 0, tuResString, CONTROLS_FILE, offsetof(AppResources, controlsFile), },
|
|
{ "useyp", 0, tuResBool, "False", offsetof(AppResources, useyp), },
|
|
{ "hostresorder", 0, tuResString, "local", offsetof(AppResources, hostresorder), },
|
|
{ "help", 0, tuResBool, "False", offsetof(AppResources, help), },
|
|
{ "noTime", 0, tuResBool, "False", offsetof(AppResources, noTime), },
|
|
{ "scrollTime", 0, tuResBool, "False", offsetof(AppResources, scrollTime), },
|
|
|
|
{ "editControlBackgroundColor", 0, tuResColor, NULL, offsetof(AppResources, editControlBackgroundColor), },
|
|
{ "paramControlBackgroundColor", 0, tuResColor, NULL, offsetof(AppResources, paramControlBackgroundColor), },
|
|
{ "selectColor", 0, tuResColor, NULL, offsetof(AppResources, selectColor), },
|
|
{ "alarmColor", 0, tuResColor, NULL, offsetof(AppResources, alarmColor), },
|
|
|
|
{ "stripBackgroundIndexColor", 0, tuResShort, "7", offsetof(AppResources, stripBackgroundIndexColor), },
|
|
{ "stripScaleIndexColor", 0, tuResShort, "41", offsetof(AppResources, stripScaleIndexColor), },
|
|
{ "scrollingTimeIndexColor", 0, tuResShort, "0", offsetof(AppResources, scrollingTimeIndexColor), },
|
|
0,
|
|
};
|
|
|
|
|
|
NetGraph::NetGraph(int argc, char *argv[]) {
|
|
// XXXXX to see what malloc problem is.
|
|
// printf("malloc checking is enabled\n");
|
|
// mallopt(M_DEBUG, 1);
|
|
|
|
// Default and initial values
|
|
strcpy(lastFile, "");
|
|
strcpy(recordFile, "");
|
|
strcpy(logFile, "");
|
|
strcpy (windowName, "NetGraph");
|
|
|
|
viewGadgetGeom = NULL;
|
|
editControlGeom = NULL;
|
|
paramControlGeom = NULL;
|
|
freeDataList = NULL;
|
|
rfp = NULL;
|
|
afp = stderr;
|
|
|
|
// used to init localHostName, snooper stuff here, but moved
|
|
// farther down until after dialog was created, so we can
|
|
// post any error
|
|
|
|
bzero(&hist, sizeof hist);
|
|
bzero(&oldHist, sizeof oldHist);
|
|
bzero(filters, sizeof filters);
|
|
|
|
fatalError = False;
|
|
postedFatal = False;
|
|
quitNow = False;
|
|
history = False;
|
|
outputAscii = False;
|
|
lockPercentages = False;
|
|
maxValues = False;
|
|
recording = False;
|
|
sameScale = False;
|
|
snooping = False;
|
|
useLines = False;
|
|
for (int i = 0; i < 128; i++)
|
|
got[i] = False;
|
|
gotTimeType = False;
|
|
gotTimeTypeFromResource = False;
|
|
gotInterfaceFromResource = False;
|
|
editControlWasMapped = False;
|
|
paramControlWasMapped = False;
|
|
iconic = False;
|
|
|
|
errs = 0;
|
|
highestBin = -1;
|
|
highestNumber = 0;
|
|
sampleSize = 0;
|
|
historyDirection = 1;
|
|
historySamples = 0;
|
|
netfiltersPid = 0;
|
|
strips = 0;
|
|
timerSeconds = 0;
|
|
timeSinceUpdate = 0;
|
|
snpStm.ss_sock = -1; // so we can tell if it's been opened yet
|
|
|
|
interval = DEF_INTERVAL;
|
|
samples = 61;
|
|
period = 600;
|
|
avgPeriod = -1; // if user doesn't specify, we'll make it = period
|
|
updateTime = DEF_UPD_TIME;
|
|
timeType = TIME_SCROLLING; // how to display time labels
|
|
|
|
editControl = NULL;
|
|
paramControl = NULL;
|
|
selectedStrip = NULL;
|
|
specifiedFilter = NULL;
|
|
for (i = 0; i < MAX_RC_LINES; i++)
|
|
rcLines[i] = NULL;
|
|
|
|
protoInit();
|
|
|
|
// get resources
|
|
|
|
// Create a place to store the resource database, and load it
|
|
// up. This also parses the command lines, opens the X display, and
|
|
// returns to us the default screen on that display.
|
|
|
|
rdb = new tuResourceDB;
|
|
AppResources ar;
|
|
|
|
ar.editControlBackgroundColor = 0;
|
|
ar.paramControlBackgroundColor = 0;
|
|
ar.alarmColor = 0;
|
|
ar.selectColor = 0;
|
|
|
|
|
|
char* instanceName = 0;
|
|
char* className = "NetGraph";
|
|
|
|
tuScreen* screen = rdb->getAppResources(&ar, args, nargs, opts,
|
|
&instanceName, className,
|
|
&argc, argv);
|
|
|
|
cmap = screen->getDefaultColorMap();
|
|
display = rdb->getDpy();
|
|
|
|
// Initialize SGIHelp
|
|
SGIHelpInit (display, className, ".");
|
|
|
|
// Set up callbacks (must do this before create viewGadget)
|
|
(new NetGraphCallBack(this, NetGraph::quit))->
|
|
registerName("__NetGraph_quit");
|
|
(new NetGraphCallBack(this, NetGraph::save))->
|
|
registerName("__NetGraph_save");
|
|
(new NetGraphCallBack(this, NetGraph::saveAs))->
|
|
registerName("__NetGraph_saveAs");
|
|
|
|
(new NetGraphCallBack(this, NetGraph::openEditControl))->
|
|
registerName("__NetGraph_edit");
|
|
(new NetGraphCallBack(this, NetGraph::add))->
|
|
registerName("__NetGraph_add");
|
|
(new NetGraphCallBack(this, NetGraph::openParamControl))->
|
|
registerName("__NetGraph_params");
|
|
(new NetGraphCallBack(this, NetGraph::changeAll))->
|
|
registerName("__NetGraph_allBars");
|
|
(new NetGraphCallBack(this, NetGraph::changeAll))->
|
|
registerName("__NetGraph_allLines");
|
|
(new NetGraphCallBack(this, NetGraph::deleteCB))->
|
|
registerName("__NetGraph_delete");
|
|
(new NetGraphCallBack(this, NetGraph::catchUp))->
|
|
registerName("__NetGraph_catchUp");
|
|
|
|
(new tuFunctionCallBack(NetGraph::doHelp, GENERAL_HELP_CARD))->
|
|
registerName("__NetGraph_help");
|
|
|
|
|
|
// create main window (must do this before create dialog box)
|
|
toolOptions = new ToolOptions;
|
|
viewGadget = new ViewGadget(this, windowName, cmap, rdb,
|
|
instanceName, className, NULL, VIEW_GEOMETRY);
|
|
stripParent = viewGadget->getStripParent();
|
|
|
|
addItem = viewGadget->getAddItem();
|
|
editItem = viewGadget->getEditItem();
|
|
deleteItem = viewGadget->getDeleteItem();
|
|
|
|
viewGadget->setIconicCallBack(new NetGraphCallBack(this, NetGraph::iconicCB));
|
|
setSelectedStrip(NULL);
|
|
|
|
// create dialog box (must do this before have a chance of any errors)
|
|
dialog = new DialogBox("NetGraph", viewGadget, False);
|
|
setDialogBoxCallBack();
|
|
|
|
if (ar.help) {
|
|
usage();
|
|
return;
|
|
}
|
|
|
|
// whichever is last *should* win, but I can't tell order
|
|
if (ar.scrollTime) {
|
|
gotTimeTypeFromResource = True;
|
|
timeType = TIME_SCROLLING;
|
|
} else if (ar.noTime) {
|
|
gotTimeTypeFromResource = True;
|
|
timeType = TIME_NONE;
|
|
}
|
|
|
|
// Check license
|
|
char *message;
|
|
if (getLicense(className, &message) == 0) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
dialog->error(message);
|
|
openDialogBox();
|
|
return;
|
|
}
|
|
if (message != 0) {
|
|
licDialog = new DialogBox("NetGraph", viewGadget, False);
|
|
licDialog->setCallBack(new NetGraphCallBack(this, NetGraph::closeLicDialogBox));
|
|
licDialog->information(message);
|
|
licDialog->map();
|
|
XFlush(getDpy());
|
|
delete message;
|
|
}
|
|
|
|
if (gethostname(localHostName, 64) < 0) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
post(GETHOSTNAMEMSG);
|
|
return;
|
|
}
|
|
strcpy(newSnooper.node, localHostName);
|
|
strcpy(fullSnooperString, localHostName);
|
|
strcat(fullSnooperString, ":"); // so analyzer will like it
|
|
newSnooper.interface[0] = NULL;
|
|
|
|
currentSnooper.node[0] = NULL;
|
|
currentSnooper.interface[0] = NULL;
|
|
|
|
stripBackgroundIndexColor = ar.stripBackgroundIndexColor;
|
|
stripScaleIndexColor = ar.stripScaleIndexColor;
|
|
scrollingTimeIndexColor = ar.scrollingTimeIndexColor;
|
|
|
|
// process options on command line
|
|
|
|
strcpy(lastFile, ar.controlsFile);
|
|
|
|
// handle the interface; used to be fine in handleOptions,
|
|
// but now -i gets interpreted as -iconic unless we do it
|
|
// in our own resource.
|
|
if (ar.interface[0] != NULL) {
|
|
gotInterfaceFromResource = True;
|
|
fatalError = True; // since might be posted by handleIntfc()
|
|
quitNow = True;
|
|
if (handleIntfc(ar.interface, True) == -1)
|
|
return;
|
|
fatalError = False; // return this to normal value
|
|
quitNow = False;
|
|
snooperChanged();
|
|
}
|
|
|
|
int highestLine = readFile(lastFile);
|
|
if (highestLine == -1)
|
|
return;
|
|
|
|
if (handleOptions(argc, argv) == -1)
|
|
return;
|
|
|
|
|
|
// Read configuration, & process options in history file
|
|
// (that aren't already set)
|
|
if (history) {
|
|
// don't allow certain options when running from history file
|
|
undoIllegalOptions();
|
|
|
|
if (handleHistFile(fullSnooperString) == -1) {
|
|
return;
|
|
}
|
|
|
|
if (errs)
|
|
postMany(errs, errStrings);
|
|
|
|
} else {
|
|
// since we're not running from a history file,
|
|
// take care of the rest of the controlsFile.
|
|
if (doRestOfFile(highestLine) == -1)
|
|
return;
|
|
|
|
}
|
|
|
|
if (strcmp(logFile, "") && !open_plain_outfile(logFile, &afp)) {
|
|
post(LOGNOOPENMSG);
|
|
afp = stderr;
|
|
}
|
|
|
|
|
|
// add time legend to window
|
|
// first, make sure period is an integer number of Intervals
|
|
period = (samples - 1) * interval;
|
|
timeGadget = new TimeGadget(this, stripParent, "",
|
|
period, interval, timeType);
|
|
viewGadget->addTime(timeGadget);
|
|
if (timeType != TIME_NONE)
|
|
timeGadget->map();
|
|
|
|
|
|
if (history) {
|
|
addItem->setEnabled(False);
|
|
scrollGadget = new ScrollGadget(this, stripParent, "");
|
|
float percShown = ((float)samples / historySamples);
|
|
if (percShown > 1.0)
|
|
percShown = 1.0;
|
|
scrollGadget->setScrollPercShown(percShown);
|
|
scrollGadget->setScrollPerc(0.0);
|
|
scrollGadget->map();
|
|
viewGadget->addScrollBox(scrollGadget);
|
|
scrollGadget->map();
|
|
}
|
|
|
|
|
|
// open history file for writing, and write general stuff
|
|
if (recording) {
|
|
addItem->setEnabled(False);
|
|
|
|
char optStr[80];
|
|
char* optP = optStr;
|
|
|
|
optStr[0] = NULL;
|
|
|
|
buildOptLine(optP, False);
|
|
|
|
if (!open_xdr_outfile(
|
|
recordFile, &rfp, &xdr, &highestNumber, &optP)) {
|
|
post(BADXDRWROPENMSG);
|
|
recording = False;
|
|
if (rfp)
|
|
close_xdr_file(rfp, &xdr);
|
|
} else {
|
|
if (outputAscii) {
|
|
// first do stuff that open_xdr_outfile wrote to outfile
|
|
printf("Number of strip charts: %d\n", highestNumber);
|
|
printf("%s\n", optP);
|
|
}
|
|
int type, baseRate, color, avgColor, style;
|
|
int alarmSet, alarmBell;
|
|
float alarmLo, alarmHi;
|
|
char* string;
|
|
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
string = filters[sg->getBin()].expr;
|
|
type = sg->getType();
|
|
baseRate = sg->getBaseRate();
|
|
color = sg->getColor();
|
|
avgColor = sg->getAvgColor();
|
|
style = sg->getStyle();
|
|
alarmSet = (int) sg->getAlarmSet();
|
|
alarmBell = (int) sg->getAlarmBell();
|
|
alarmLo = sg->getAlarmLoVal();
|
|
alarmHi = sg->getAlarmHiVal();
|
|
|
|
// NOTE: version == 0 means use NETGRAPH_HIST_VERSION
|
|
if (!do_xdr_stripInfo(&xdr, 0,
|
|
&string, &type, &baseRate,
|
|
&color, &avgColor, &style,
|
|
&alarmSet, &alarmBell, &alarmLo, &alarmHi)) {
|
|
post(BADXDRWRITEMSG);
|
|
recording = False;
|
|
if (rfp)
|
|
close_xdr_file(rfp, &xdr);
|
|
break;
|
|
}
|
|
|
|
if (outputAscii) {
|
|
// now strip info
|
|
printf("filter: %s ", string);
|
|
if (type < TYPE_PNPACKETS)
|
|
printf("%s\n", heading[type]);
|
|
else
|
|
printf("Percent of %d %s\n",
|
|
sg->getBaseRate(), heading[type]);
|
|
|
|
} // outputAscii
|
|
} // for each strip
|
|
if (outputAscii)
|
|
printf("\n");
|
|
|
|
} // opened ok
|
|
} // recording
|
|
|
|
|
|
|
|
EV_handle evfd;
|
|
static char* appName = "NetGraph";
|
|
|
|
eh = new EV_handler(&evfd, appName);
|
|
event = new EV_event(NV_STARTUP);
|
|
alarmEvent = new EV_event();
|
|
eh->send(event);
|
|
|
|
|
|
// Create other windows
|
|
|
|
if (editControlGeom == NULL)
|
|
editControlGeom = strdup(EDIT_GEOMETRY);
|
|
if (paramControlGeom == NULL)
|
|
paramControlGeom = strdup(PARAM_GEOMETRY);
|
|
|
|
|
|
if (viewGadgetGeom == NULL)
|
|
viewGadgetGeom = strdup(VIEW_GEOMETRY);
|
|
|
|
viewGadget->parseGeometry(viewGadgetGeom, "");
|
|
|
|
editControl = new EditControl(this, "Edit Control Panel",
|
|
viewGadget, editControlGeom);
|
|
paramControl = new ParamControl(this, "Parameters Control Panel",
|
|
viewGadget, paramControlGeom);
|
|
|
|
editControlX = editControl->getXOrigin();
|
|
editControlY = editControl->getYOrigin();
|
|
paramControlX = paramControl->getXOrigin();
|
|
paramControlY = paramControl->getYOrigin();
|
|
|
|
|
|
if (ar.editControlBackgroundColor)
|
|
editControl->setBackground( (tuColor*) ar.editControlBackgroundColor);
|
|
if (ar.paramControlBackgroundColor)
|
|
paramControl->setBackground( (tuColor*) ar.paramControlBackgroundColor);
|
|
|
|
if (ar.alarmColor)
|
|
alarmColor = (tuColor*) ar.alarmColor;
|
|
else
|
|
alarmColor = tuPalette::getRed(screen);
|
|
|
|
if (ar.selectColor)
|
|
selectColor =(tuColor*) ar.selectColor;
|
|
else
|
|
selectColor = tuPalette::getSelectFillColor(screen);
|
|
|
|
|
|
|
|
toolOptions->setTopLevel(viewGadget);
|
|
|
|
// Get hints for layout and resize
|
|
tuLayoutHints hints;
|
|
viewGadget->getLayoutHints(&hints);
|
|
viewGadget->resize(hints.prefWidth, hints.prefHeight);
|
|
editControl->getLayoutHints(&hints);
|
|
editControl->resize(hints.prefWidth, hints.prefHeight);
|
|
paramControl->getLayoutHints(&hints);
|
|
paramControl->resize(hints.prefWidth, hints.prefHeight);
|
|
|
|
// Map the view window
|
|
viewGadget->map();
|
|
|
|
// Set hostresorder and _yp_disabled
|
|
if (ar.useyp)
|
|
_yp_disabled = 0;
|
|
else
|
|
_yp_disabled = 1;
|
|
sethostresorder(ar.hostresorder);
|
|
|
|
|
|
} // NetGraph
|
|
|
|
|
|
NetGraph::NetGraph(const char* instanceName, tuColorMap* cmap,
|
|
tuResourceDB* db, char* progName, char* progClass) {
|
|
// I don't think I'll need this one...
|
|
}
|
|
|
|
void
|
|
NetGraph::add(tuGadget *) {
|
|
StripGadget* sg;
|
|
if (makeNewStrip(&sg, selectedStrip) == -1)
|
|
return;
|
|
|
|
|
|
|
|
|
|
int retVal;
|
|
|
|
if (selectedStrip)
|
|
retVal = netgraph->setupStripInts((char*)selectedStrip->getFilter(),
|
|
selectedStrip->getType(), selectedStrip->getBaseRate(),
|
|
selectedStrip->getColor(), selectedStrip->getAvgColor(),
|
|
selectedStrip->getStyle(), selectedStrip->getAlarmSet(),
|
|
selectedStrip->getAlarmBell(),
|
|
selectedStrip->getAlarmLoVal(),
|
|
selectedStrip->getAlarmHiVal(), 0, sg, True);
|
|
else if (editControl && editControl->isMapped())
|
|
retVal = netgraph->setupStripInts(editControl->getFilter(),
|
|
editControl->getType(), editControl->getBaseRate(),
|
|
editControl->getColor(), editControl->getAvgColor(),
|
|
editControl->getStyle(), editControl->getAlarmSet(),
|
|
editControl->getAlarmBell(),
|
|
editControl->getAlarmLoVal(),
|
|
editControl->getAlarmHiVal(), 0, sg, True);
|
|
else
|
|
retVal = netgraph->setupStripInts("total", TYPE_PACKETS,
|
|
1000, 4, 1, STYLE_BAR, False, False,
|
|
0.0, 10.0, 0, sg, True);
|
|
|
|
|
|
if (retVal == -1) {
|
|
deleteGraph(sg);
|
|
sg->setNumber(0);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
NetGraph::openEditControl(tuGadget *) {
|
|
// give the control panel a pointer to the selected strip
|
|
editControl->setSg(selectedStrip, NULL);
|
|
|
|
if (editControl->isMapped()) {
|
|
if (editControl->getIconic())
|
|
editControl->setIconic(False);
|
|
editControl->pop();
|
|
} else
|
|
editControl->map();
|
|
|
|
} // openEditControl
|
|
|
|
void
|
|
NetGraph::closeEditControl(void) {
|
|
editControl->unmap();
|
|
}
|
|
|
|
void
|
|
NetGraph::openParamControl(tuGadget *) {
|
|
if (paramControl->isMapped()) {
|
|
if (paramControl->getIconic())
|
|
paramControl->setIconic(False);
|
|
paramControl->pop();
|
|
} else
|
|
paramControl->map();
|
|
}
|
|
|
|
void
|
|
NetGraph::closeParamControl(void) {
|
|
paramControl->unmap();
|
|
}
|
|
|
|
|
|
// this gets called AFTER we actually change state between iconic & not
|
|
void
|
|
NetGraph::iconicCB(tuGadget *) {
|
|
if (viewGadget->getIconic()) {
|
|
iconic = True;
|
|
|
|
if (editControl->isMapped()) {
|
|
editControlWasMapped = True;
|
|
editControlX = editControl->getXOrigin();
|
|
editControlY = editControl->getYOrigin();
|
|
editControl->unmap();
|
|
} else
|
|
editControlWasMapped = False;
|
|
|
|
if (paramControl->isMapped()) {
|
|
paramControlWasMapped = True;
|
|
paramControlX = paramControl->getXOrigin();
|
|
paramControlY = paramControl->getYOrigin();
|
|
paramControl->unmap();
|
|
} else
|
|
paramControlWasMapped = False;
|
|
|
|
} else {
|
|
iconic = False;
|
|
|
|
if (editControlWasMapped) {
|
|
editControl->setInitialOrigin(editControlX, editControlY);
|
|
editControl->map();
|
|
}
|
|
if (paramControlWasMapped) {
|
|
paramControl->setInitialOrigin(paramControlX, paramControlY);
|
|
paramControl->map();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
tuBool
|
|
NetGraph::isIconic(void) {
|
|
return iconic;
|
|
}
|
|
|
|
// change to all lines or all bars
|
|
void
|
|
NetGraph::changeAll(tuGadget* g) {
|
|
int newStyle;
|
|
if (strcmp(g->getInstanceName(), "allLinesItem"))
|
|
newStyle = STYLE_BAR;
|
|
else
|
|
newStyle = STYLE_LINE;
|
|
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
sg->setStyle(newStyle);
|
|
}
|
|
viewGadget->render();
|
|
|
|
// printf("NetGraph::changeAll - %s\n", graphStyles[newStyle]);
|
|
|
|
}
|
|
|
|
|
|
// delete the selected graph
|
|
void
|
|
NetGraph::deleteCB(tuGadget*) {
|
|
if (!selectedStrip) {
|
|
// printf("deleteCB - no strip selected\n");
|
|
return;
|
|
}
|
|
|
|
// printf("NetGraph::delete (%d)\n", selectedStrip->getNumber());
|
|
// xxx find selected graph and call deleteGraph()
|
|
|
|
/***** NOW, disable delete if only one strip..
|
|
// if it's the last strip, quit
|
|
if (viewGadget->getNumberOfGraphs() == 1) {
|
|
quit(NULL);
|
|
}
|
|
******/
|
|
if (selectedStrip)
|
|
deleteGraph(selectedStrip);
|
|
|
|
// if there's only one graph left now, disable delete
|
|
if (viewGadget->getNumberOfGraphs() == 1)
|
|
deleteItem->setEnabled(False);
|
|
|
|
}
|
|
|
|
|
|
void
|
|
NetGraph::catchUp(tuGadget*) {
|
|
// printf("NetGraph::catchUp\n");
|
|
if (snpStm.ss_sock != -1) {
|
|
(void) snoopStop(&snpStm);
|
|
(void) snoopStart(&snpStm);
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NetGraph::quit(tuGadget *g) {
|
|
|
|
if (recording || history)
|
|
doQuit(NULL);
|
|
else {
|
|
if (dialog->isMapped())
|
|
dialog->unmap();
|
|
|
|
// we'll make a new dialog box, because otherwise sometimes
|
|
// have trouble with it coming up iconified
|
|
dialog->markDelete();
|
|
dialog = new DialogBox("NetGraph", viewGadget, False);
|
|
|
|
if (g)
|
|
dialog->question("Save UI to %s before quitting", lastFile);
|
|
else
|
|
dialog->question("Fatal error. Save UI to %s before quitting", lastFile);
|
|
|
|
dialog->setCallBack(new NetGraphCallBack(this, NetGraph::doQuit));
|
|
dialog->map();
|
|
XFlush(getDpy());
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
NetGraph::doQuit(tuGadget *g) {
|
|
enum tuDialogHitCode hitCode;
|
|
|
|
if (g)
|
|
hitCode = dialog->getHitCode();
|
|
else
|
|
hitCode = tuNo;
|
|
|
|
|
|
// if it's a fatal error, can't cancel; take it to mean don't save
|
|
if (fatalError && hitCode == tuCancel)
|
|
hitCode = tuNo;
|
|
|
|
switch (hitCode) {
|
|
case tuYes:
|
|
if (doSave() == -1) {
|
|
openDialogBox();
|
|
return;
|
|
}
|
|
// Save was successful, fall through
|
|
case tuNo: {
|
|
// xxx actually, I think I can just unsubscribe & close
|
|
// (without bothering to stop & delete)
|
|
if (snpStm.ss_sock != -1) {
|
|
(void) snoopStop(&snpStm);
|
|
|
|
for (int bin = highestBin; bin >= 0; bin--)
|
|
(void) ss_delete(&snpStm, bin);
|
|
|
|
(void) ss_unsubscribe(&snpStm);
|
|
ss_close(&snpStm);
|
|
}
|
|
|
|
|
|
if (netfiltersPid != 0) {
|
|
kill(netfiltersPid, SIGTERM);
|
|
}
|
|
|
|
// make a new event, so it doesn't have the interface in it.
|
|
EV_event shutdown(NV_SHUTDOWN);
|
|
eh->send(&shutdown);
|
|
|
|
HELPclose();
|
|
|
|
if (fatalError)
|
|
exit(-1);
|
|
else
|
|
exit(0);
|
|
}
|
|
} // switch
|
|
|
|
}
|
|
|
|
void
|
|
NetGraph::immediateQuit(tuGadget*) {
|
|
exit(-1);
|
|
}
|
|
|
|
|
|
char *
|
|
NetGraph::expandTilde(const char *c)
|
|
{
|
|
if (c[0] != '~')
|
|
return 0;
|
|
char *p = strchr(c, '/');
|
|
if (p == c + 1 || c[1] == '\0') {
|
|
char *home = getenv("HOME");
|
|
unsigned int len = strlen(home);
|
|
if (len == 1)
|
|
len = 0;
|
|
char *nc = new char[strlen(c) + len];
|
|
strncpy(nc, home, len);
|
|
if (p != 0)
|
|
strcpy(nc + len, p);
|
|
return nc;
|
|
}
|
|
if (p != 0)
|
|
*p = '\0';
|
|
struct passwd *pw = getpwnam(c + 1);
|
|
if (pw == 0)
|
|
return 0;
|
|
unsigned int len = strlen(pw->pw_dir);
|
|
char *nc = new char[strlen(c) + len];
|
|
strncpy(nc, pw->pw_dir, len + 1);
|
|
if (p != 0) {
|
|
*(nc + len) = '/';
|
|
strcpy(nc + len + 1, p + 1);
|
|
*p = '/';
|
|
}
|
|
return nc;
|
|
} // expandTilde
|
|
|
|
|
|
/*
|
|
* Read the configuration file. If no file is specified, use CONTROLS_FILE
|
|
* from the current or home directory.
|
|
* After we get something open, set 'lastFile' to the name of the file
|
|
* we opened, so we can write back to the same place later.
|
|
*/
|
|
// copied from netgraph
|
|
// xxx return -1 == big failure; quit
|
|
// return n == highest line number we saved.
|
|
int
|
|
NetGraph::readFile(char* fileName) {
|
|
// printf("NetGraph::readFile(%s)\n", fileName);
|
|
|
|
static char white[] = " \t\n";
|
|
static char dblQuote[] = "\"";
|
|
static char sglQuote[] = "'";
|
|
static char defaultFilter[] = "total";
|
|
|
|
int err = 0;
|
|
FILE *fp = NULL;
|
|
|
|
char buf[256];
|
|
char *filtExpr;
|
|
char *tokens[9];
|
|
int lineNumber = 1;
|
|
|
|
errs = 0;
|
|
|
|
|
|
if (strcmp(fileName, "-") == 0) {
|
|
fp = stdin;
|
|
strcpy(lastFile, CONTROLS_FILE);
|
|
} else {
|
|
char* newname = expandTilde(fileName);
|
|
if (newname != 0) {
|
|
strcpy(lastFile, newname);
|
|
fileName = lastFile;
|
|
delete [] newname;
|
|
}
|
|
|
|
fp = fopen(fileName, "r");
|
|
}
|
|
|
|
// if there's no file, use the 'total' filter,
|
|
// else read options & graph specifications
|
|
if (fp == NULL) {
|
|
err = errno;
|
|
dialog->warning(errno, "Could not open %s", fileName);
|
|
openDialogBox();
|
|
strcpy(buf, defaultFilter);
|
|
} else {
|
|
fgets(buf, sizeof buf, fp);
|
|
} // (fp not null)
|
|
|
|
|
|
|
|
// go through file, get options & strip specifications
|
|
char tempStr[256];
|
|
do {
|
|
|
|
// first see if line starts with "#"; if so, it's a comment
|
|
// then see if there are any quotes in the config file line
|
|
// if yes, then first token is what's between quotes
|
|
// if not, then tokens are all separated by whitespace
|
|
// also check if it's an option or geometry line
|
|
|
|
if (buf[0] == '#')
|
|
continue;
|
|
|
|
|
|
|
|
strcpy(tempStr, buf); // copy so we can still get the whole thing
|
|
if (strchr(buf, '"')) {
|
|
filtExpr = strtok(buf, dblQuote);
|
|
} else if (strchr(buf, '\'')) {
|
|
filtExpr = strtok(buf, sglQuote);
|
|
} else {
|
|
filtExpr = strtok(buf, white);
|
|
}
|
|
|
|
if (filtExpr == NULL)
|
|
continue;
|
|
|
|
if (!strcmp(filtExpr, "option")) {
|
|
if (handleStringOfOptions(tempStr) == -1)
|
|
return -1;
|
|
|
|
} else if (!strcmp(filtExpr, "NetGraphGeometry")) {
|
|
viewGadgetGeom = strdup(strtok(NULL, white));
|
|
} else if (!strcmp(filtExpr, "EditControlGeometry")) {
|
|
editControlGeom = strdup(strtok(NULL, white));
|
|
editControlWasMapped = True;
|
|
} else if (!strcmp(filtExpr, "ParamControlGeometry")) {
|
|
paramControlGeom = strdup(strtok(NULL, white));
|
|
paramControlWasMapped = True;
|
|
|
|
} else {
|
|
// write the rest of the file (this line to the end) to
|
|
// memory. If it turns out we're running from a history file,
|
|
// we won't care about most of it.
|
|
if (lineNumber > MAX_RC_LINES) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
post(RCTOOBIGMSG);
|
|
openDialogBox();
|
|
return -1;
|
|
} else
|
|
rcLines[lineNumber] = strdup(tempStr);
|
|
}
|
|
|
|
} while (lineNumber++ && fp != NULL && fgets(buf, sizeof buf, fp) != NULL);
|
|
|
|
rcLines[lineNumber] = NULL;
|
|
|
|
if (fp != stdin)
|
|
fclose(fp);
|
|
|
|
// if we collected any errors from the config file, post them all together
|
|
|
|
if (errs) {
|
|
if (errs >= MAXERRS) {
|
|
errs = MAXERRS;
|
|
fatalError = True;
|
|
quitNow = True;
|
|
postMany(errs, errStrings);
|
|
return -1;
|
|
}
|
|
|
|
// if no legit filters, prepare to bail out.
|
|
if ((highestBin == 0) && (filters[0].used == 1)) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
postMany(errs, errStrings);
|
|
return -1;
|
|
}
|
|
|
|
postMany(errs, errStrings);
|
|
}
|
|
|
|
return lineNumber;
|
|
|
|
} // readFile
|
|
|
|
// handle the part of the controls file we just copied to memory
|
|
// when we first read the file.
|
|
int
|
|
NetGraph::doRestOfFile(int lastLine) {
|
|
|
|
// First, check time args now that we've got the options.
|
|
// Then start snooping.
|
|
if (checkTimeArgs(&samples, &period, &interval, &updateTime,
|
|
&avgPeriod, &avgSamples) == -1) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
return -1;
|
|
}
|
|
|
|
// get host, set up snoop stream
|
|
int retVal = hist_init(&snpStm, &newSnooper, interval);
|
|
if (retVal < 0) {
|
|
snpStm.ss_sock = -1;
|
|
fatalError = True;
|
|
quitNow = True;
|
|
// char ebuf[64];
|
|
// sprintf (ebuf, "%s:%s", newSnooper.node, newSnooper.interface);
|
|
post(-1 * retVal);
|
|
return -1;
|
|
} else {
|
|
snooperChanged();
|
|
}
|
|
|
|
// this filter is really only needed if user wants totals or
|
|
// percentages, but we'll always add it just to be safe and simple.
|
|
ExprError err;
|
|
int bins = ss_add(&snpStm, 0, &err);
|
|
strcpy (filters[0].expr, "total");
|
|
filters[0].used++;
|
|
if (bins < 0) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
post(NOADDPRMSCSMSG);
|
|
return -1;
|
|
}
|
|
|
|
if (specifiedFilter) {
|
|
// the user specified a filter on the command line,
|
|
// so just use it; ignore rest of the file
|
|
rcLines[1] = specifiedFilter;
|
|
lastLine = 1;
|
|
}
|
|
static char white[] = " \t\n";
|
|
static char dash[] = "-";
|
|
static char dblQuote[] = "\"";
|
|
static char sglQuote[] = "'";
|
|
|
|
|
|
char buf[256];
|
|
char *filtExpr;
|
|
char *tokens[9];
|
|
|
|
for (int lineNumber = 1; lineNumber <= lastLine; lineNumber++) {
|
|
if (rcLines[lineNumber] == NULL)
|
|
continue;
|
|
|
|
if (strchr(rcLines[lineNumber], '"')) {
|
|
filtExpr = strtok(rcLines[lineNumber], dblQuote);
|
|
} else if (strchr(rcLines[lineNumber], '\'')) {
|
|
filtExpr = strtok(rcLines[lineNumber], sglQuote);
|
|
} else {
|
|
filtExpr = strtok(rcLines[lineNumber], white);
|
|
}
|
|
if (filtExpr == NULL)
|
|
continue;
|
|
|
|
// there can be as many as 9 more tokens -
|
|
// type, N for %Nbytes/%Npackets, color, avgColor, style;
|
|
// alarmSet, alarmBell, alarmLoVal, alarmHival
|
|
for (int i = 0; i < 9; i++) {
|
|
tokens[i] = strtok(NULL, white);
|
|
}
|
|
|
|
StripGadget* sg = new StripGadget(this, stripParent, "");
|
|
if (completeNewStrip(sg, 0) == -1)
|
|
return -1;
|
|
|
|
if (setupStripTkns(filtExpr, tokens, lineNumber,
|
|
sg, False) == -1) {
|
|
// it failed, so this isn't a good strip, so delete it.
|
|
deleteGraph(sg);
|
|
}
|
|
|
|
if (errs > MAXERRS)
|
|
break;
|
|
|
|
} // for each line
|
|
|
|
if (errs) {
|
|
if (errs >= MAXERRS) {
|
|
errs = MAXERRS;
|
|
fatalError = True;
|
|
quitNow = True;
|
|
postMany(errs, errStrings);
|
|
return -1;
|
|
}
|
|
|
|
// if no legit filters, prepare to bail out.
|
|
if ((highestBin == 0) && (filters[0].used == 1)) {
|
|
fatalError = True;
|
|
quitNow = True;
|
|
postMany(errs, errStrings);
|
|
return -1;
|
|
}
|
|
|
|
postMany(errs, errStrings);
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // doRestOfFile
|
|
|
|
|
|
void
|
|
NetGraph::save(tuGadget *) {
|
|
if (doSave() == -1)
|
|
openDialogBox();
|
|
}
|
|
|
|
int
|
|
NetGraph::doSave() {
|
|
// printf("NetGraph::doSave, <%s>\n", lastFile);
|
|
|
|
FILE *fp = NULL;
|
|
fp = fopen(lastFile, "w");
|
|
|
|
if (fp == NULL) {
|
|
dialog->warning(errno, "Could not write %s", lastFile);
|
|
return - 1;
|
|
}
|
|
|
|
/***
|
|
|
|
// traffic gizmo parameters
|
|
fprintf(fp, "SnoopInterface\t%s\n", fullSnooperString);
|
|
|
|
fprintf(fp, "SnoopFilter\t\t%s\n", filter);
|
|
|
|
fprintf(fp, "MeasureTraffic\t%s\n", graphTypes[type]);
|
|
|
|
fprintf(fp, "DataUpdateTime\t%f\n",
|
|
(float)dataUpdateTime / 10.0);
|
|
|
|
if (viewGadget)
|
|
fprintf(fp, "VerticalScale\t%s\n", rescaleTypes[viewGadget->getRescaleType()]);
|
|
|
|
if (editControl)
|
|
fprintf(fp, "LockAt\t\t%d\n", editControl->getFixedScale());
|
|
****/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// vvvvvv from old netgraph.c++
|
|
|
|
// write the file.
|
|
|
|
// first, the options/args/params
|
|
char optLine[80];
|
|
optLine[0] = NULL;
|
|
buildOptLine(optLine, True);
|
|
fputs(optLine, fp);
|
|
|
|
|
|
// now the graph specifications
|
|
// note that the file has to be in the reverse order of the 'strips'
|
|
// linked list, and we don't have back-pointers on that, so do this:
|
|
// - go through 'strips'
|
|
// = get spec of each strip
|
|
// = write spec (one line) to array of spec-lines
|
|
// - go through that array backwards
|
|
// = write line to file
|
|
char* filterExpr;
|
|
char* graphType;
|
|
int baseRate;
|
|
char* graphStyle;
|
|
int colorIdx;
|
|
int avgColorIdx;
|
|
char* alarmSet;
|
|
char* alarmBell;
|
|
float alarmLo;
|
|
float alarmHi;
|
|
char specLine[20][300]; // can't fit more than 20 graphs on a screen
|
|
int line = 0;
|
|
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
filterExpr = filters[sg->getBin()].expr;
|
|
if (strchr(filterExpr, ' ')) {
|
|
char tempStr[302];
|
|
strcpy(tempStr, "\"");
|
|
strcat(tempStr, filterExpr);
|
|
strcat(tempStr, "\"");
|
|
filterExpr = tempStr;
|
|
}
|
|
graphType = graphTypes[sg->getType()];
|
|
baseRate = sg->getBaseRate();
|
|
graphStyle = graphStyles[sg->getStyle()];
|
|
colorIdx = sg->getColor();
|
|
avgColorIdx = sg->getAvgColor();
|
|
alarmSet = alarmSets[sg->getAlarmSet()];
|
|
alarmBell = alarmBells[sg->getAlarmBell()];
|
|
alarmLo = sg->getAlarmLoVal();
|
|
alarmHi = sg->getAlarmHiVal();
|
|
if (sg->getType() >= TYPE_PNPACKETS)
|
|
sprintf(specLine[line++], "%s %s %d %d %d %s %s %s %.2f %.2f\n",
|
|
filterExpr, graphType, baseRate, colorIdx, avgColorIdx, graphStyle,
|
|
alarmSet, alarmBell, alarmLo, alarmHi);
|
|
else
|
|
sprintf(specLine[line++], "%s %s %d %d %s %s %s %.2f %.2f\n",
|
|
filterExpr, graphType, colorIdx, avgColorIdx, graphStyle,
|
|
alarmSet, alarmBell, alarmLo, alarmHi);
|
|
}
|
|
|
|
line--;
|
|
|
|
do {
|
|
fputs(specLine[line--], fp);
|
|
} while (line >= 0);
|
|
|
|
// window geometry
|
|
if (viewGadget)
|
|
fprintf(fp, "NetGraphGeometry\t%dx%d%+d%+d\n",
|
|
viewGadget->getWidth(), viewGadget->getHeight(),
|
|
viewGadget->getXOrigin(), viewGadget->getYOrigin());
|
|
if (editControl && editControl->isMapped()) {
|
|
fprintf(fp, "EditControlGeometry\t%dx%d%+d%+d\n",
|
|
editControl->getWidth(), editControl->getHeight(),
|
|
editControl->getXOrigin(), editControl->getYOrigin());
|
|
}
|
|
if (paramControl && paramControl->isMapped()) {
|
|
fprintf(fp, "ParamControlGeometry\t%dx%d%+d%+d\n",
|
|
paramControl->getWidth(), paramControl->getHeight(),
|
|
paramControl->getXOrigin(), paramControl->getYOrigin());
|
|
}
|
|
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
|
|
// ^^^^^^
|
|
|
|
|
|
} // doSave
|
|
|
|
void
|
|
NetGraph::saveAs(tuGadget *) {
|
|
if (prompter == 0) {
|
|
prompter = new tuFilePrompter("prompter", viewGadget, True);
|
|
prompter->bind();
|
|
}
|
|
if (prompter->isMapped())
|
|
prompter->unmap();
|
|
char *home = getenv("HOME");
|
|
if (home == 0)
|
|
home = "/usr/tmp";
|
|
prompter->readDirectory(home);
|
|
prompter->resizeToFit();
|
|
prompter->setName("Save Controls");
|
|
prompter->setCallBack(
|
|
new NetGraphCallBack(this, NetGraph::savePrompt));
|
|
prompter->mapWithCancelUnderMouse();
|
|
|
|
}
|
|
|
|
void
|
|
NetGraph::savePrompt(tuGadget *)
|
|
{
|
|
char *file = prompter->getSelectedPath();
|
|
prompter->unmap();
|
|
if (file == 0)
|
|
return;
|
|
|
|
strcpy(lastFile, file);
|
|
if (doSave() == -1)
|
|
openDialogBox();
|
|
|
|
}
|
|
|
|
|
|
// post error or warning message
|
|
void
|
|
NetGraph::post(int msg, char* errString) {
|
|
// NetGraph::post(int msg, char* errString, int lineNumber) {
|
|
// once a fatal error is posted, don't post any more
|
|
// (this is important, because if snoop read problem, might
|
|
// continue to get more of them, and don't want lots of dialogs)
|
|
if (postedFatal)
|
|
return;
|
|
if (fatalError)
|
|
postedFatal = True;
|
|
|
|
char msgBuf[250];
|
|
|
|
switch(msg)
|
|
{
|
|
case NOSNOOPDMSG:
|
|
case SSSUBSCRIBEERRMSG:
|
|
sprintf(msgBuf, "Could not connect to %s\n\nCheck that snoopd is installed and configured correctly on the Data Station. See Appendix A of the NetVisualyzer User's Guide for detailed help", exc_message);
|
|
break;
|
|
|
|
case ILLEGALINTFCMSG:
|
|
sprintf(msgBuf, "Data Station name not recognized.\n\nCheck that %s is a valid name and is entered in the appropriate hosts data base. See Appendix A of the NetVisualyzer User's Guide for detailed help", errString);
|
|
break;
|
|
|
|
default:
|
|
if (errString == NULL && exc_message == NULL) {
|
|
strcpy(msgBuf, Message[msg]);
|
|
|
|
} else {
|
|
char buf[128];
|
|
if (exc_message != NULL) {
|
|
if (errString == NULL)
|
|
errString = exc_message;
|
|
else {
|
|
sprintf(buf, "%s: %s", errString, exc_message);
|
|
errString = buf;
|
|
}
|
|
exc_message = NULL;
|
|
}
|
|
}
|
|
|
|
if (errString == NULL)
|
|
sprintf(msgBuf, "%s\n", Message[msg]);
|
|
else
|
|
sprintf(msgBuf, "%s: %s\n", Message[msg], errString);
|
|
break;
|
|
|
|
}
|
|
|
|
if (fatalError) {
|
|
// we'll make a new dialog box, because otherwise sometimes
|
|
// have trouble with it coming up iconified
|
|
dialog->markDelete();
|
|
dialog = new DialogBox("NetGraph", viewGadget, False);
|
|
dialog->error(msgBuf);
|
|
} else
|
|
dialog->warning(msgBuf);
|
|
|
|
openDialogBox();
|
|
} // post
|
|
|
|
|
|
void
|
|
NetGraph::postMany(int count, char* msgs[]) {
|
|
// printf("NetGraph::postMany(%d)\n", count);
|
|
if (postedFatal)
|
|
return;
|
|
if (fatalError)
|
|
postedFatal = True;
|
|
|
|
dialog->setMultiMessage(True);
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
if (fatalError) {
|
|
// we'll make a new dialog box, because otherwise sometimes
|
|
// have trouble with it coming up iconified
|
|
dialog->markDelete();
|
|
dialog = new DialogBox("NetGraph", viewGadget, False);
|
|
dialog->error(msgs[i]);
|
|
} else
|
|
dialog->warning(msgs[i]);
|
|
}
|
|
|
|
openDialogBox();
|
|
|
|
dialog->setMultiMessage(False);
|
|
}
|
|
|
|
void
|
|
NetGraph::collectErrs(int msg, char *errString, int lineNumber) {
|
|
if (errs < MAXERRS) {
|
|
errStrings[errs] = (char*) malloc(200);
|
|
if (msg < 0)
|
|
strcpy(errStrings[errs], "");
|
|
else
|
|
strncpy(errStrings[errs], Message[msg], 199);
|
|
|
|
if (lineNumber) {
|
|
char tempStr[200];
|
|
sprintf(tempStr, "%s on line %d: ", errStrings[errs], lineNumber);
|
|
strncpy(errStrings[errs], tempStr, 199);
|
|
}
|
|
|
|
if (errString)
|
|
strncat(errStrings[errs], errString, 199-strlen(errStrings[errs]));
|
|
}
|
|
else if (errs == MAXERRS)
|
|
strcpy(errStrings[(MAXERRS-1)], Message[TOOMANYERRSMSG]);
|
|
errs++;
|
|
|
|
} // collectErrs
|
|
|
|
|
|
void
|
|
NetGraph::openDialogBox(void) {
|
|
if (fatalError && quitNow)
|
|
dialog->setCallBack(new NetGraphCallBack(this, NetGraph::immediateQuit));
|
|
else
|
|
dialog->setCallBack(new NetGraphCallBack(this, NetGraph::closeDialogBox));
|
|
|
|
if (dialog->isMapped())
|
|
dialog->pop();
|
|
else {
|
|
dialog->map();
|
|
XFlush(getDpy());
|
|
}
|
|
}
|
|
|
|
void
|
|
NetGraph::closeDialogBox(tuGadget *) {
|
|
dialog->unmap();
|
|
XFlush(getDpy());
|
|
if (fatalError)
|
|
quit(NULL);
|
|
}
|
|
|
|
void
|
|
NetGraph::closeLicDialogBox(tuGadget *) {
|
|
licDialog->unmap();
|
|
XFlush(getDpy());
|
|
}
|
|
|
|
void
|
|
NetGraph::setDialogBoxCallBack(void) {
|
|
dialog->setCallBack(new NetGraphCallBack(this, NetGraph::closeDialogBox));
|
|
}
|
|
|
|
int
|
|
NetGraph::openNetFilters() {
|
|
if (netfiltersPid != 0)
|
|
return 1;
|
|
|
|
int fd[2];
|
|
if (pipe(fd) != 0) {
|
|
dialog->warning(errno, "Could not start NetFilters");
|
|
return 0;
|
|
}
|
|
|
|
netfiltersPid = fork();
|
|
if (netfiltersPid < 0) {
|
|
dialog->warning(errno, "Could not start NetFilters");
|
|
return 0;
|
|
}
|
|
if (netfiltersPid == 0) {
|
|
if (dup2(fd[1], 1) < 0)
|
|
exit(-1);
|
|
execlp("netfilters", "netfilters", "-stdout", 0);
|
|
perror("netgraph: Could not start NetFilters");
|
|
exit(-1);
|
|
}
|
|
close(fd[1]);
|
|
netfilters = fdopen(fd[0], "r");
|
|
|
|
exec->addCallBack(fd[0], False,
|
|
new NetGraphCallBack(this, NetGraph::readNetFilters));
|
|
|
|
|
|
return 1;
|
|
} // openNetFilters
|
|
|
|
// read the result from NetFilters, tell editControl
|
|
void
|
|
NetGraph::readNetFilters(tuGadget*) {
|
|
char buf[256];
|
|
if (fgets(buf, 256, netfilters) == 0) {
|
|
closeNetFilters();
|
|
return;
|
|
}
|
|
char* nl = strchr(buf, '\n');
|
|
*nl = NULL;
|
|
// printf("readNetFilters: %s\n", buf);
|
|
|
|
editControl->setFilter(buf);
|
|
// make it use new filter, as if user typed it.
|
|
editControl->filterType(NULL);
|
|
|
|
} // readNetFilters
|
|
|
|
void
|
|
NetGraph::closeNetFilters(void) {
|
|
exec->removeCallBack(fileno(netfilters), False);
|
|
fclose(netfilters);
|
|
kill(netfiltersPid, SIGTERM);
|
|
netfiltersPid = 0;
|
|
}
|
|
|
|
|
|
void
|
|
NetGraph::protoInit() {
|
|
/*
|
|
* Initialize protocols
|
|
* XXX We must disable NIS temporarily, as protocol init routines
|
|
* XXX tend to call getservbyname, which is horrendously slow thanks
|
|
* XXX to Sun's quadratic-growth lookup botch.
|
|
*/
|
|
_yp_disabled = 1;
|
|
initprotocols();
|
|
_yp_disabled = 0;
|
|
}
|
|
|
|
// set up snooping services
|
|
int
|
|
NetGraph::snoopInit() {
|
|
|
|
bzero(&hist, sizeof hist);
|
|
bzero(&oldHist, sizeof oldHist);
|
|
|
|
if (!snoopStart(&snpStm)) {
|
|
fatalError = True;
|
|
post(NOSTARTSNOOPMSG);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // snoopInit
|
|
|
|
tuBool
|
|
NetGraph::isEther() {
|
|
return (!strcmp(snpStm.ss_rawproto->pr_name, "ether"));
|
|
}
|
|
|
|
tuBool
|
|
NetGraph::isFddi() {
|
|
return (!strcmp(snpStm.ss_rawproto->pr_name, "fddi"));
|
|
}
|
|
|
|
tuBool
|
|
NetGraph::isTokenRing() {
|
|
return (!strcmp(snpStm.ss_rawproto->pr_name, "tokenring"));
|
|
}
|
|
|
|
void
|
|
NetGraph::setExec(tuXExec *e) {
|
|
// printf("NetGraph::setExec\n");
|
|
exec = e;
|
|
|
|
if (fatalError)
|
|
return;
|
|
|
|
timer = new tuTimer();
|
|
timer->setCallBack(new NetGraphCallBack(this, NetGraph::reallyStart));
|
|
timer->start(1.0);
|
|
// printf("... started 1 second timer\n");
|
|
}
|
|
|
|
void
|
|
NetGraph::reallyStart(tuGadget*) {
|
|
// printf("NetGraph::reallyStart\n");
|
|
|
|
if (history) {
|
|
//timer = new tuTimer(True);
|
|
timer->setAutoReload(True);
|
|
// printf("setting timer call back\n");
|
|
timer->setCallBack(new NetGraphCallBack(this, NetGraph::historyMove));
|
|
startTimer();
|
|
} else if (snoopInit() != -1) {
|
|
if (snpStm.ss_sock != -1) {
|
|
exec->addCallBack(snpStm.ss_sock, False,
|
|
new NetGraphCallBack(this, &NetGraph::readData));
|
|
// printf("setExec - addCallBack(%d)\n", snpStm.ss_sock);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// handle a string of options, from hist file or rc file.
|
|
// If this is called to parse the command line, "fileName" will point
|
|
// to a string, and we'll return the name there.
|
|
// If it is called to parse commands in the file, "fileName" will be a
|
|
// null pointer.
|
|
int
|
|
NetGraph::handleStringOfOptions(char* str) {
|
|
|
|
// first, make like argc/argv
|
|
int argc;
|
|
char *argv[256];
|
|
static char white[] = " \t\n";
|
|
|
|
argv[0] = strtok(str, white);
|
|
if (!argv[0])
|
|
return 0;
|
|
|
|
if (strcmp(argv[0], "option")) {
|
|
argv[1] = strdup(argv[0]);
|
|
argc = 2;
|
|
} else {
|
|
argc = 1;
|
|
}
|
|
for (;; argc++) {
|
|
argv[argc] = strtok(NULL, white);
|
|
if (argv[argc] == NULL)
|
|
break;
|
|
}
|
|
|
|
// now parse the options
|
|
return handleOptions(argc, argv);
|
|
|
|
} // handleStringOfOptions
|
|
|
|
|
|
// parse "command line" options, whether from actual command line or from
|
|
// the setup file.
|
|
int
|
|
NetGraph::handleOptions(int argc, char** argv) {
|
|
// printf("NetGraph::handleOptions\n");
|
|
// for (int c = 0; c < argc; c++) printf(" %d:%s\n", c, argv[c]);
|
|
|
|
int opt;
|
|
char* options = "i:l:o:t:T:U:A:MOPSarsnh";
|
|
|
|
int optionErrs = 0;
|
|
opterr = 0; // disable error messages from getopt
|
|
optind = 1;
|
|
|
|
tuBool notHistoryYet = !(history);
|
|
while ((opt = getopt(argc, argv, options)) != -1) {
|
|
if (notHistoryYet)
|
|
got[opt] = True;
|
|
else if (got[opt])
|
|
continue;
|
|
|
|
if ((opt == 'a') || (opt == 'r') || (opt == 's') || (opt == 'n')) {
|
|
if (gotTimeTypeFromResource)
|
|
continue;
|
|
else if (notHistoryYet)
|
|
gotTimeType = True;
|
|
else if (gotTimeType)
|
|
continue;
|
|
}
|
|
|
|
switch (opt) {
|
|
case 'i':
|
|
{
|
|
if (gotInterfaceFromResource)
|
|
continue;
|
|
strcpy(fullSnooperString, optarg);
|
|
char* tempStr = strdup(optarg);
|
|
fatalError = True; // since might be posted by handleIntfc()
|
|
quitNow = True;
|
|
if (handleIntfc(tempStr, True) == -1)
|
|
return -1;
|
|
fatalError = False; // return this to normal value
|
|
quitNow = False;
|
|
snooperChanged();
|
|
}
|
|
break;
|
|
|
|
case 'o':
|
|
strcpy(recordFile, optarg);
|
|
recording = True;
|
|
break;
|
|
case 'O':
|
|
outputAscii = True;
|
|
break;
|
|
case 'l':
|
|
strcpy(logFile, optarg);
|
|
break;
|
|
case 't':
|
|
// turn into integer # of tenths and round off
|
|
interval = (int) (atof(optarg) * 10.0 + 0.5 );
|
|
break;
|
|
case 'T':
|
|
// turn into integer # of tenths and round off
|
|
period = (int) (atof(optarg) * 10.0 + 0.5 );
|
|
break;
|
|
case 'U':
|
|
// turn into integer # of tenths and round off
|
|
updateTime = (int) (atof(optarg) * 10.0 + 0.5 );
|
|
break;
|
|
case 'A':
|
|
// turn into integer # of tenths and round off
|
|
avgPeriod = (int) (atof(optarg) * 10.0 + 0.5 );
|
|
break;
|
|
case 'h':
|
|
usage();
|
|
return -1;
|
|
case 'a':
|
|
timeType = TIME_ABSOLUTE;
|
|
break;
|
|
case 'n':
|
|
timeType = TIME_NONE;
|
|
break;
|
|
case 'r':
|
|
timeType = TIME_RELATIVE;
|
|
break;
|
|
case 's':
|
|
timeType = TIME_SCROLLING;
|
|
break;
|
|
case 'M':
|
|
maxValues = True;
|
|
break;
|
|
case 'P':
|
|
lockPercentages = True;
|
|
break;
|
|
case 'S':
|
|
sameScale = True;
|
|
break;
|
|
|
|
case '?':
|
|
// If it's a valid option for us, must be a bad argument
|
|
if (strchr(options, optopt) != NULL) {
|
|
char tmpStr[80];
|
|
char *msgs[1];
|
|
msgs[0] = tmpStr;
|
|
sprintf(tmpStr,
|
|
"-%c option requires an argument", optopt);
|
|
fatalError = True;
|
|
quitNow = True;
|
|
postMany(1, msgs);
|
|
return -1;
|
|
}
|
|
optionErrs++;
|
|
break;
|
|
} // switch opt
|
|
} // while more opts
|
|
|
|
if (optionErrs) {
|
|
usage();
|
|
return -1;
|
|
}
|
|
|
|
// Parse filter expression
|
|
if (optind != argc) {
|
|
char buf[1024];
|
|
char *f = buf;
|
|
for (int i = optind; i < argc; i++) {
|
|
if (f != buf)
|
|
*f++ = ' ';
|
|
strcpy(f, argv[i]);
|
|
f += strlen(f);
|
|
}
|
|
specifiedFilter = new char[strlen(buf) + 3];
|
|
sprintf(specifiedFilter, "\"%s\"", buf);
|
|
}
|
|
|
|
return 0;
|
|
} // handleOptions (argc,argv)
|
|
|
|
|
|
// when running from history file, some options are illegal, some meaningless.
|
|
// Turn these off if they're set, and post warning (not a fatal error).
|
|
// Don't worry about -t and -U; just ignore them (automatically, since
|
|
// will read them from hist file after call this function).
|
|
// Here, just undo 'recording' if set, and post warning about that.
|
|
void
|
|
NetGraph::undoIllegalOptions() {
|
|
// doesn't make sense to read in & write out history simultaneously
|
|
if (recording) {
|
|
collectErrs(HISTNORECORDMSG);
|
|
recording = False;
|
|
if (rfp)
|
|
close_xdr_file(rfp, &xdr);
|
|
}
|
|
|
|
|
|
} // NetGraph::undoIllegalOptions
|
|
|
|
|
|
void
|
|
NetGraph::usage() {
|
|
char msgbuf[300];
|
|
|
|
strcpy(msgbuf,
|
|
"usage: netgraph [-h] [-M] [-P] [-S] [-arsn] [-u controls_file] [-i interface] ");
|
|
strcat(msgbuf,
|
|
"[-t time_interval] [-T time_period] [-U update_time] [-A average_period] ");
|
|
strcat(msgbuf,
|
|
"[-o history_output_file] [-O] [-l alarm_log_file] [-y] [filter]");
|
|
|
|
fatalError = True;
|
|
quitNow = True;
|
|
|
|
usageDialog = new DialogBox("NetGraph", viewGadget, False);
|
|
usageDialog->setCallBack(new NetGraphCallBack(this, NetGraph::immediateQuit));
|
|
usageDialog->information(msgbuf);
|
|
usageDialog->map();
|
|
XFlush(getDpy());
|
|
|
|
|
|
|
|
// dialog->information(msgbuf);
|
|
// openDialogBox();
|
|
|
|
} // usage
|
|
|
|
|
|
// if the snooper node or interface changed, this is called.
|
|
void
|
|
NetGraph::snooperChanged() {
|
|
// printf("snooperChanged; new: <%s>:<%s>; current: <%s>:<%s>\n",
|
|
// newSnooper.node, newSnooper.interface, currentSnooper.node, currentSnooper.interface);
|
|
|
|
strcpy(currentSnooper.node, newSnooper.node);
|
|
strcpy(currentSnooper.interface, newSnooper.interface);
|
|
|
|
|
|
if (fullSnooperString[0]) {
|
|
sprintf(windowName, "NetGraph -i %s", fullSnooperString);
|
|
if (!history)
|
|
toolOptions->setInterface(fullSnooperString);
|
|
} else {
|
|
char tempStr[80];
|
|
sprintf(tempStr, "%s:", localHostName); // so analyzer is happy
|
|
sprintf(windowName, "NetGraph -i %s", tempStr);
|
|
toolOptions->setInterface(tempStr);
|
|
}
|
|
|
|
viewGadget->setName(windowName);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// take an interface name, figure out what kind of snooping is required,
|
|
// fill in newSnooper struct
|
|
int
|
|
NetGraph::handleIntfc(char* name, tuBool allowTrace) {
|
|
// printf("handleIntfc: name: %s\n", name);
|
|
if (name)
|
|
strcpy(fullSnooperString, name);
|
|
else
|
|
fullSnooperString[0] = NULL;
|
|
|
|
char* newInterface;
|
|
|
|
enum snoopertype snptype = getsnoopertype(name, &newInterface);
|
|
// printf("after getsnoopertype: name: %s, newInterface: %s\n", name, newInterface);
|
|
|
|
// printf("handleIntfc: newSnooper.node (%s), newSnooper.interface (%s)\n",
|
|
// newSnooper.node, newSnooper.interface);
|
|
|
|
strcpy(newSnooper.node, name);
|
|
|
|
switch (snptype) {
|
|
case ST_LOCAL:
|
|
// strcpy(name, localHostName);
|
|
strcpy(newSnooper.node, localHostName);
|
|
|
|
break;
|
|
case ST_TRACE:
|
|
// printf("snoopertype = ST_TRACE\n");
|
|
if (allowTrace || history) {
|
|
history = True;
|
|
sprintf(windowName, "NetGraph -i %s", name);
|
|
viewGadget->setName(windowName);
|
|
} else {
|
|
post(NOHISTMSG);
|
|
return -1;
|
|
}
|
|
break;
|
|
case ST_REMOTE:
|
|
if (!newInterface)
|
|
newInterface = strdup(name);
|
|
// printf("ST_REMOTE: name(%s), hp->name(%s)\n",
|
|
// name, (*hpp)->h_name);
|
|
break;
|
|
case ST_NULL:
|
|
post(ILLEGALINTFCMSG, name);
|
|
return -1;
|
|
default:
|
|
post(BADINTFCMSG, name);
|
|
break;
|
|
}
|
|
|
|
if (newInterface)
|
|
strcpy(newSnooper.interface, newInterface);
|
|
else
|
|
newSnooper.interface[0] = NULL;
|
|
|
|
// printf("handleIntfc returned ok\n");
|
|
|
|
return 0;
|
|
} // handleIntfc
|
|
|
|
|
|
|
|
|
|
|
|
// vvvv from old netgraph.c++
|
|
|
|
/* Build the "option" line for the rc file and history file.
|
|
* The 'forConfigFile' parameter is true for the rc file - write all options
|
|
* into the line; and false for the history file, since we don't want to
|
|
* write -l & -U there.
|
|
* The -f option is never written into this option line, since by the time
|
|
* it would be read, it's always too late to matter.
|
|
* The -o option is not written into this option line, since you can't save
|
|
* to the rc file if you're running -o, and it doesn't make sense to say
|
|
* -o in the history file, since the history is already in a file.
|
|
*/
|
|
void
|
|
NetGraph::buildOptLine(char* line, tuBool forConfigFile) {
|
|
char tempStr[80];
|
|
|
|
strcat(line, "option ");
|
|
if (maxValues)
|
|
strcat(line, "-M ");
|
|
if (lockPercentages)
|
|
strcat(line, "-P ");
|
|
if (sameScale)
|
|
strcat(line, "-S ");
|
|
|
|
if (fullSnooperString[0]) {
|
|
sprintf(tempStr, "-i %s ", fullSnooperString);
|
|
strcat(line, tempStr);
|
|
}
|
|
|
|
sprintf(tempStr, "-t %.1f ", interval/10.0);
|
|
strcat(line, tempStr);
|
|
|
|
sprintf(tempStr, "-T %.1f ", period/10.0);
|
|
strcat(line, tempStr);
|
|
|
|
sprintf(tempStr, "-A %.1f ", avgPeriod/10.0);
|
|
strcat(line, tempStr);
|
|
|
|
switch (timeType) {
|
|
case TIME_ABSOLUTE:
|
|
strcat(line, "-a ");
|
|
break;
|
|
case TIME_RELATIVE:
|
|
strcat(line, "-r ");
|
|
break;
|
|
case TIME_SCROLLING:
|
|
strcat(line, "-s ");
|
|
break;
|
|
case TIME_NONE:
|
|
strcat(line, "-n ");
|
|
break;
|
|
}
|
|
|
|
if (forConfigFile && strcmp(logFile, "")) {
|
|
sprintf(tempStr, "-l %s", logFile);
|
|
strcat(line, tempStr);
|
|
sprintf(tempStr, "-U %.1f ", updateTime/10.0);
|
|
strcat(line, tempStr);
|
|
}
|
|
|
|
strcat(line, "\n");
|
|
|
|
} // NetGraph::buildOptLine
|
|
|
|
|
|
/*
|
|
* Take six tokens (filter expression, type, N, style, color, avgColor),
|
|
* convert the type,
|
|
* style & color into integers, and call another function to setup the strip
|
|
* based on those integers.
|
|
* Last param says whether to post errors immediately(True) or collect them.
|
|
* Return 0 if it worked, -1 if it failed.
|
|
*/
|
|
int
|
|
NetGraph::setupStripTkns(char* filtExpr, char* tokens[], int lineNumber,
|
|
StripGadget* sg, tuBool postNow) {
|
|
int typeInt = 0;
|
|
int baseRate = -1;
|
|
int styleInt;
|
|
int intVal;
|
|
int colorInt = -1;
|
|
int avgColorInt = 1;
|
|
tuBool alarmSet = False;
|
|
tuBool alarmBell = False;
|
|
float floatVal = 0.0;
|
|
float alarmLo = -1.0;
|
|
float alarmHi = 0.0;
|
|
int retVal = 0;
|
|
|
|
// if no style is specified in the rc file, then the -L param matters.
|
|
if (useLines)
|
|
styleInt = 1;
|
|
else
|
|
styleInt = 0;
|
|
|
|
// Just in case they're in the wrong order in the file, we'll check
|
|
// all 9 (max) tokens against all kinds of tokens.
|
|
for (int i = 0; i < 9; i++) {
|
|
if (tokens[i] &&
|
|
((retVal = matchToken(tokens[i], &typeInt,
|
|
&intVal, &styleInt,
|
|
&alarmSet, &alarmBell, &floatVal)) < 0)) {
|
|
|
|
//printf("tokens[%d]: <%s>, retVal: %d\n", i, tokens[i], retVal);
|
|
|
|
if (postNow)
|
|
post(ILLEGALTOKENMSG, tokens[i], /* lineNumber */);
|
|
else
|
|
collectErrs(ILLEGALTOKENMSG, tokens[i], lineNumber);
|
|
} else {
|
|
if (retVal == FLOAT_TKN) {
|
|
// if a float, alarmLoVal, then alarmHiVal
|
|
if (alarmLo == -1.0)
|
|
alarmLo = floatVal;
|
|
else
|
|
alarmHi = floatVal;
|
|
|
|
} else if (retVal == INT_TKN) {
|
|
// if an int, possibly baseRate, then color, then avgColor
|
|
if ((typeInt == TYPE_PNPACKETS || typeInt == TYPE_PNBYTES)
|
|
&& baseRate == -1)
|
|
baseRate = intVal;
|
|
else if (colorInt == -1)
|
|
colorInt = intVal;
|
|
else
|
|
avgColorInt = intVal;
|
|
}
|
|
}
|
|
}
|
|
|
|
// we set this to -1 to keep track of whether it had been assigned yet,
|
|
// but now make it a reasonable value if it hasn't been assigned.
|
|
if (alarmLo == -1.0)
|
|
alarmLo = 0.0;
|
|
|
|
// same with baseRate
|
|
if (typeInt == TYPE_PNPACKETS && baseRate == -1)
|
|
baseRate = 1000;
|
|
else if (typeInt== TYPE_PNBYTES && baseRate == -1)
|
|
baseRate = 10000;
|
|
|
|
// same with colorInt vs avgColorInt
|
|
if (colorInt == -1)
|
|
colorInt = 4;
|
|
|
|
retVal = setupStripInts(filtExpr, typeInt, baseRate,
|
|
colorInt, avgColorInt, styleInt,
|
|
alarmSet, alarmBell, alarmLo, alarmHi,
|
|
lineNumber, sg, postNow);
|
|
return(retVal);
|
|
} // netgraph::setupStripTkns
|
|
|
|
|
|
// take a token, and try to match it to color (int), %n base rate (int),
|
|
// graph Type, graphStyle,
|
|
// alarmSet (no or yes), alarmBell (silent or bell), or alarmVal (float).
|
|
// return value tells what it is (-1=none, 0=type, 1=style, 2=int,
|
|
// 3=alarmSet (bool), 4=alarmBell (bool), 5=float) and
|
|
// 'fooVal' is the corresponding integer value.
|
|
int
|
|
NetGraph::matchToken(char* token,
|
|
int* typeIntp, int* intp, int* styleIntp,
|
|
tuBool* alarmSetp, tuBool* alarmBellp, float* floatValp) {
|
|
|
|
if (isdigit(*token)) {
|
|
// if has a decimal point, it's a float, so alarm value (lo or hi).
|
|
// if not, then it's an int, so color.
|
|
if (strchr(token, '.')) {
|
|
*floatValp = atof(token);
|
|
return FLOAT_TKN;
|
|
} else {
|
|
*intp = atoi(token);
|
|
return INT_TKN;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < strlen(token); i++) {
|
|
if (isupper(token[i]))
|
|
token[i] = _tolower(token[i]);
|
|
}
|
|
|
|
for (i = 0; graphTypes[i] != 0; i++) {
|
|
if (strcmp(token, graphTypes[i]) == 0) {
|
|
*typeIntp = i;
|
|
return TYPE_TKN;
|
|
}
|
|
}
|
|
|
|
for (i = 0; graphStyles[i] != 0; i++) {
|
|
if (strcmp(token, graphStyles[i]) == 0) {
|
|
*styleIntp = i;
|
|
return STYLE_TKN;
|
|
}
|
|
}
|
|
|
|
for (i = 0; alarmSets[i] != 0; i++) {
|
|
if (strcmp(token, alarmSets[i]) == 0) {
|
|
*alarmSetp = i;
|
|
return ALARMSET_TKN;
|
|
}
|
|
}
|
|
|
|
for (i = 0; alarmBells[i] != 0; i++) {
|
|
if (strcmp(token, alarmBells[i]) == 0) {
|
|
*alarmBellp = i;
|
|
return ALARMBELL_TKN;
|
|
}
|
|
}
|
|
|
|
return BAD_TKN;
|
|
|
|
|
|
} // netgraph::matchToken
|
|
|
|
|
|
|
|
/*
|
|
* Take filter string, integer graph type, integer graph style and integer
|
|
* color, and set up a
|
|
* new strip. This is called when adding a strip from data at startup
|
|
* (in .netgraphrc, etc.), as well as when adding a strip on the fly.
|
|
* Last param says whether to post errors immediately(True) or collect them.
|
|
* Return 0 if it worked, -1 if it failed.
|
|
*/
|
|
int
|
|
NetGraph::setupStripInts(char* filtExpr, int typeInt, int baseRate,
|
|
int colorInt, int avgColorInt, int styleInt,
|
|
tuBool alarmSet, tuBool alarmBell, float alarmLo, float alarmHi,
|
|
int lineNumber, StripGadget* sg, tuBool postNow) {
|
|
|
|
// if sg pointer is bad, can't do anything
|
|
if (!sg) {
|
|
if (postNow)
|
|
post(BADSTRIPMSG);
|
|
else
|
|
collectErrs(BADSTRIPMSG);
|
|
return -1;
|
|
}
|
|
|
|
|
|
// if this is an existing strip, and neither the type nor the filtExpr
|
|
// changed, just change the color and/or style and get out of here.
|
|
if ((sg->getBin() >= 0) &&
|
|
(typeInt == sg->getType()) &&
|
|
(sg->getBaseRate() == baseRate) &&
|
|
!strcmp(filtExpr, filters[sg->getBin()].expr)) {
|
|
sg->setColor(colorInt);
|
|
sg->setAvgColor(avgColorInt);
|
|
sg->setStyle(styleInt);
|
|
return 0;
|
|
}
|
|
|
|
|
|
// if this filter expression matches one we already saw, don't
|
|
// bother adding it.
|
|
for (int bin = 0; bin <= highestBin; bin++) {
|
|
// check against each existing
|
|
if (!strcmp (filtExpr,filters[bin].expr)) {
|
|
// a match, so current bin is the bin the new strip will use
|
|
break;
|
|
}
|
|
} // (check existing filters)
|
|
|
|
if (bin > highestBin) {
|
|
ExprSource src;
|
|
ExprError err;
|
|
// it didn't match, so we have to add it.
|
|
if (strcmp(filtExpr, "total")) {
|
|
src.src_path = "netgraph";
|
|
src.src_line = 0;
|
|
src.src_buf = filtExpr;
|
|
// printf("adding %s\n", filtExpr);
|
|
bin = ss_compile(&snpStm, &src, &err);
|
|
// printf("bin %d: %s\n", bin, filtExpr);
|
|
} else {
|
|
bin = ss_add(&snpStm, 0, &err);
|
|
// of course, this should never happen, since we added a
|
|
// promiscuous filter up there in appInit, right after hist_init
|
|
}
|
|
|
|
if (bin < 0) {
|
|
|
|
if (postNow) {
|
|
char* msgs[2];
|
|
msgs[0] = (char*) malloc(200);
|
|
strcpy(msgs[0], "Invalid filter -- ");
|
|
if (err.err_message)
|
|
strcat(msgs[0], err.err_message);
|
|
if (lineNumber) {
|
|
char lineStr[80];
|
|
sprintf(lineStr, " on line %d", lineNumber);
|
|
strncat(msgs[0], lineStr, 199-strlen(msgs[0]));
|
|
}
|
|
if (err.err_token && (err.err_token[0] != '\0')) {
|
|
strcat(msgs[0], ": ");
|
|
strncat(msgs[0], err.err_token, 199-strlen(msgs[0]));
|
|
// msgs[1] = err.err_token;
|
|
// postMany(2, msgs);
|
|
postMany(1, msgs);
|
|
} else {
|
|
postMany(1, msgs);
|
|
}
|
|
|
|
}
|
|
else {
|
|
char tempStr[80];
|
|
strcpy(tempStr, "Invalid filter -- ");
|
|
if (err.err_message)
|
|
strcat(tempStr, err.err_message);
|
|
if (lineNumber) {
|
|
char lineStr[80];
|
|
sprintf(lineStr, " on line %d", lineNumber);
|
|
strncat(tempStr, lineStr, 199 - strlen(tempStr));
|
|
}
|
|
if (err.err_token && (err.err_token[0] != '\0')) {
|
|
strcat(tempStr, ": ");
|
|
strcat(tempStr, err.err_token);
|
|
}
|
|
collectErrs(-1, tempStr);
|
|
}
|
|
|
|
return (-1);
|
|
} // if bin < 0
|
|
highestBin = bin;
|
|
strcpy(filters[bin].expr, filtExpr);
|
|
} // (didn't match any already added filter)
|
|
|
|
filters[bin].used++;
|
|
|
|
// zero the y data
|
|
dataStruct* ptr = sg->getCurrentData();
|
|
sg->setAvgData(ptr);
|
|
sg->setSamplesSoFar(0);
|
|
for (int i = 0; i < samples; i++) {
|
|
ptr->y = 0;
|
|
ptr->avg = 0;
|
|
ptr = ptr->next;
|
|
}
|
|
|
|
|
|
// Set up this strip chart
|
|
sg->setBin(bin);
|
|
|
|
finishSetupStripInts(filtExpr, typeInt, baseRate,
|
|
colorInt, avgColorInt, styleInt,
|
|
alarmSet, alarmBell, alarmLo, alarmHi, sg);
|
|
|
|
return (0);
|
|
} // netgraph::setupStripInts
|
|
|
|
|
|
// Finish setting up the strip.
|
|
// This is broken off from setupStripInts because it is needed for
|
|
// when we're running from a history file, too.
|
|
void
|
|
NetGraph::finishSetupStripInts(char* filtExpr, int typeInt, int baseRate,
|
|
int colorInt, int avgColorInt, int styleInt,
|
|
tuBool alarmSet, tuBool alarmBell,
|
|
float alarmLo, float alarmHi, StripGadget* sg) {
|
|
|
|
// printf("finishSetupStripInts(%s, %d, %d, %d, %d, %d)\n",
|
|
// filtExpr, typeInt, baseRate, colorInt, avgColorInt, styleInt);
|
|
|
|
sg->setColor(colorInt);
|
|
sg->setAvgColor(avgColorInt);
|
|
sg->setType(typeInt);
|
|
sg->setStyle(styleInt);
|
|
sg->setAlarmSet(alarmSet);
|
|
sg->setAlarmBell(alarmBell);
|
|
sg->setAlarmLoVal(alarmLo);
|
|
sg->setAlarmHiVal(alarmHi);
|
|
if (typeInt == TYPE_PNPACKETS || typeInt == TYPE_PNBYTES)
|
|
sg->setBaseRate(baseRate);
|
|
|
|
|
|
sg->setFilter(filtExpr);
|
|
sg->setType(typeInt);
|
|
|
|
if (lockPercentages && typeInt > TYPE_BYTES) {
|
|
// Lock in percentages
|
|
sg->setScaleType(SCALE_CONSTANT);
|
|
}
|
|
|
|
// reset max, current and avg values
|
|
sg->zeroMaxVal();
|
|
sg->setCurVal(0.0);
|
|
sg->setAvgVal(0.0);
|
|
|
|
} // netGraph:finishSetupStripInts
|
|
|
|
int
|
|
NetGraph::makeNewStrip(StripGadget** sgp, StripGadget* belowSg) {
|
|
// printf("NetGraph::makeNewStrip; now has %d rows\n", stripParent->getNumRows());
|
|
|
|
stripParent->grow(stripParent->getNumRows()+1, stripParent->getNumCols());
|
|
StripGadget* newStrip = new StripGadget(this, stripParent, "");
|
|
|
|
int row, col;
|
|
|
|
if (belowSg) {
|
|
stripParent->findChild(belowSg, &row, &col);
|
|
// printf("'belowSg' is at row %d\n", row);
|
|
// move others down to make room for new one
|
|
for (int r = stripParent->getNumRows()-2; r >= row; r--) {
|
|
tuGadget* g = stripParent->getChildAt(r, col);
|
|
stripParent->place(g, r+1, col);
|
|
}
|
|
} else {
|
|
row = stripParent->getNumRows();
|
|
col = 0;
|
|
if (timeGadget)
|
|
row-=2;
|
|
else
|
|
row-=1;
|
|
stripParent->place(newStrip, row, col);
|
|
}
|
|
|
|
// printf("new strip placed at row %d of %d\n", row, stripParent->getNumRows());
|
|
// if (belowSg) {
|
|
// stripParent->findChild(belowSg, &row, &col);
|
|
// printf("'belowSg' is NOW at row %d\n", row);
|
|
// }
|
|
*sgp = newStrip;
|
|
|
|
return completeNewStrip(newStrip, belowSg);
|
|
} // NetGraph::makeNewStrip
|
|
|
|
|
|
// takes a fairly empty StripGadget, fills it in the rest of the way,
|
|
// adds it to the strip list and to the window
|
|
int
|
|
NetGraph::completeNewStrip(StripGadget* sg, StripGadget* belowSg) {
|
|
// printf("NetGraph::completeNewStrip\n");
|
|
sg->setNumber(++highestNumber);
|
|
|
|
if (maxValues)
|
|
sg->setScaleType(SCALE_MAXVALUE);
|
|
|
|
if (history) {
|
|
if (strips) {
|
|
for (StripGadget *x = strips; x->getNext() != NULL;
|
|
x = x->getNext())
|
|
;
|
|
x->setNext(sg);
|
|
} else
|
|
strips = sg;
|
|
sg->setNext(NULL);
|
|
} else {
|
|
// set up a circularly linked list for the currentData
|
|
dataStruct* ptr;
|
|
if (freeDataList) {
|
|
ptr = freeDataList->data;
|
|
freeDataList = freeDataList->next;
|
|
} else if (setupCircData(&ptr, samples) == -1) {
|
|
fatalError = True;
|
|
return -1;
|
|
}
|
|
|
|
sg->setHeadData(samples, ptr);
|
|
sg->setCurrentData(ptr);
|
|
sg->setAvgData(ptr);
|
|
|
|
|
|
if (belowSg) {
|
|
sg->setNext(belowSg->getNext());
|
|
belowSg->setNext(sg);
|
|
} else {
|
|
sg->setNext(strips);
|
|
strips = sg;
|
|
}
|
|
}
|
|
|
|
|
|
sg->setBin(-1);
|
|
|
|
// Add it to the window.
|
|
viewGadget->addAGraph(sg);
|
|
|
|
|
|
return 0;
|
|
} // NetGraph::completeNewStrip
|
|
|
|
void
|
|
NetGraph::setSameScale(tuBool newVal) {
|
|
sameScale = newVal;
|
|
}
|
|
|
|
void
|
|
NetGraph::setLockPercentages(tuBool newVal) {
|
|
lockPercentages = newVal;
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
|
|
if (lockPercentages && (sg->getType() > TYPE_BYTES)) {
|
|
// Lock in percentages
|
|
sg->setScaleType(SCALE_CONSTANT);
|
|
} else if (maxValues)
|
|
sg->setScaleType(SCALE_MAXVALUE);
|
|
else
|
|
sg->setScaleType(SCALE_VARIABLE);
|
|
|
|
}
|
|
}
|
|
|
|
void
|
|
NetGraph::setMaxVals(tuBool newVal) {
|
|
maxValues = newVal;
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
if (!(lockPercentages && (sg->getType() > TYPE_BYTES))) {
|
|
if (maxValues)
|
|
sg->setScaleType(SCALE_MAXVALUE);
|
|
else
|
|
sg->setScaleType(SCALE_VARIABLE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
NetGraph::setTimeType(int t) {
|
|
viewGadget->newTimeArgs(timeGadget, period, interval, t);
|
|
if (history) {
|
|
scrollGadget->unmap();
|
|
scrollGadget->map();
|
|
}
|
|
}
|
|
|
|
// this is called from paramControl to send all the args at once
|
|
int
|
|
NetGraph::handleNewArgs(Arg* newArgs) {
|
|
|
|
int newPeriod = newArgs->period;
|
|
int newAvgPeriod = newArgs->avgPeriod;
|
|
int newInterval = newArgs->interval;
|
|
int newUpdateTime = newArgs->updateTime;
|
|
char* newName;
|
|
if (!newArgs->interface ||
|
|
newArgs->interface && (!strcmp(newArgs->interface, ""))) {
|
|
newName = (char*) malloc (strlen(localHostName) + 1);
|
|
sprintf(newName, "%s:", localHostName);
|
|
} else
|
|
newName = strdup(newArgs->interface);
|
|
|
|
int newTimeType = newArgs->timeType;
|
|
maxValues = (tuBool)newArgs->maxValues;
|
|
lockPercentages = (tuBool)newArgs->lockPercentages;
|
|
sameScale = (tuBool)newArgs->sameScale;
|
|
updateTime = newArgs->updateTime;
|
|
|
|
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
if (lockPercentages && (sg->getType() > TYPE_BYTES))
|
|
sg->setScaleType(SCALE_CONSTANT);
|
|
else if (maxValues)
|
|
sg->setScaleType(SCALE_MAXVALUE);
|
|
else
|
|
sg->setScaleType(SCALE_VARIABLE);
|
|
|
|
}
|
|
|
|
/**
|
|
printf("handleNewArgs: newName: %s, fullSnooperString: %s\n",
|
|
newName, fullSnooperString);
|
|
printf("handleNewArgs 1; new: <%s>:<%s>; current: <%s>:<%s>\n",
|
|
newSnooper.node, newSnooper.interface, currentSnooper.node, currentSnooper.interface);
|
|
**/
|
|
|
|
// if there was a *different* interface specified, handle it.
|
|
tuBool interfaceChanged = False;
|
|
char oldFullSnooperString[100];
|
|
strcpy(oldFullSnooperString, fullSnooperString);
|
|
if (!history && strcmp(newName, fullSnooperString)) {
|
|
interfaceChanged = True;
|
|
int retVal = handleIntfc(newName, False);
|
|
delete newName;
|
|
if (retVal == -1) {
|
|
strcpy(fullSnooperString, oldFullSnooperString);
|
|
paramControl->setInterfaceField(fullSnooperString);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
printf("handleNewArgs 2; new: <%s>:<%s>; current: <%s>:<%s>\n",
|
|
newSnooper.node, newSnooper.interface, currentSnooper.node, currentSnooper.interface);
|
|
**/
|
|
// Must restart snooper if not running now,
|
|
// or if either the interval or the interface changed.
|
|
// interface changed if:
|
|
// both pointers are non-nil, and strings are different, OR
|
|
// one pointer is nil, the other isn't (& must point to a non-blank)
|
|
|
|
tuBool mustRestart = (!history) && (
|
|
(snpStm.ss_sock == -1) ||
|
|
(newInterval != interval) ||
|
|
(interfaceChanged));
|
|
|
|
if (useNewTimeArgs(newPeriod, newInterval, newUpdateTime, newAvgPeriod,
|
|
newTimeType, mustRestart) == -1)
|
|
return -1;
|
|
|
|
if (mustRestart) {
|
|
viewGadget->render();
|
|
|
|
if (restartSnooping(newInterval) == -1) {
|
|
strcpy(fullSnooperString, oldFullSnooperString);
|
|
paramControl->setInterfaceField(fullSnooperString);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // NetGraph::handleNewArgs
|
|
|
|
|
|
int
|
|
NetGraph::useNewTimeArgs(int newPeriod, int newInterval, int newUpdateTime,
|
|
int newAvgPeriod, int newTimeType, tuBool willRestart) {
|
|
|
|
int newSamples;
|
|
int newAvgSamples;
|
|
|
|
if (checkTimeArgs(&newSamples, &newPeriod, &newInterval, &newUpdateTime,
|
|
&newAvgPeriod, &newAvgSamples) == -1) {
|
|
return -1;
|
|
}
|
|
|
|
int i;
|
|
StripGadget *sg;
|
|
dataStruct *ptr;
|
|
|
|
if (history) {
|
|
if (newSamples != samples) {
|
|
// try to keep right edge fixed.
|
|
// If this puts left edge past the end (because
|
|
// we were showing more samples than in file), place left edge such
|
|
// that we see the last part of the file.
|
|
// If it puts left end before beginning, put left end *at* beginning.
|
|
long* newTimePtr = timePtr + sampleSize * (samples - newSamples);
|
|
if (newTimePtr >= historyEnd)
|
|
newTimePtr = (long*)historyEnd - sampleSize * newSamples;
|
|
|
|
if (newTimePtr < historyBeg)
|
|
timePtr = (long*) historyBeg;
|
|
else
|
|
timePtr = newTimePtr;
|
|
|
|
float* dataPtr = (float*) (timePtr + 2);
|
|
|
|
for (sg = strips; sg != 0; sg = sg->getNext(), dataPtr++) {
|
|
sg->setNumPoints(newSamples);
|
|
sg->setCurrentData((dataStruct*)dataPtr);
|
|
sg->rescale();
|
|
}
|
|
|
|
historyTicks = (timePtr - (long*)historyBeg) / sampleSize;
|
|
|
|
float percShown = ((float)newSamples / historySamples);
|
|
if (percShown > 1.0) {
|
|
percShown = 1.0;
|
|
scrollGadget->setScrollPerc(0.0);
|
|
} else {
|
|
scrollGadget->setScrollPerc(
|
|
historyTicks / (float) (historySamples - newSamples));
|
|
}
|
|
|
|
scrollGadget->setScrollPercShown(percShown);
|
|
|
|
} // numSamples != samples
|
|
|
|
if (newAvgSamples != avgSamples && newAvgSamples != 0) {
|
|
// need to recalc all averages
|
|
int samplesSoFar;
|
|
float *fPtr, *tempPtr;
|
|
|
|
for (sg = strips; sg != 0; sg = sg->getNext(), fPtr++) {
|
|
sg->setAvgVal(0.0);
|
|
sg->setAvgData(sg->getHeadData());
|
|
|
|
// step through data
|
|
for (samplesSoFar = 1, fPtr = (float*) (sg->getHeadData());
|
|
fPtr < historyEnd;
|
|
samplesSoFar++, fPtr += sampleSize) {
|
|
if (samplesSoFar > newAvgSamples) {
|
|
*(fPtr + 1) = sg->getAvgVal() +
|
|
(*fPtr - *(float*)(sg->getAvgData())) / newAvgSamples;
|
|
|
|
tempPtr = (float*) sg->getAvgData();
|
|
tempPtr += sampleSize;
|
|
sg->setAvgData((dataStruct*)tempPtr);
|
|
sg->setAvgVal(*(fPtr + 1));
|
|
|
|
} else {
|
|
*(fPtr + 1) = ((sg->getAvgVal()) * (samplesSoFar - 1) +
|
|
(*fPtr)) /
|
|
samplesSoFar;
|
|
sg->setAvgVal(*(fPtr + 1));
|
|
}
|
|
|
|
} // for each sample
|
|
|
|
} // for each strip
|
|
|
|
} // avgSamples changed
|
|
|
|
} else {
|
|
// (not history)
|
|
// If # of samples didn't change, and we're restarting, clear data.
|
|
// If # of samples changed (because of -t or -T), reallocate memory
|
|
// for each strip; if we're not restarting, copy data.
|
|
if (newSamples == samples) {
|
|
|
|
if (willRestart) {
|
|
// printf("CLEARING DATA -- samples didn't change\n");
|
|
for (sg = strips; sg != 0; sg = sg->getNext()) {
|
|
for (ptr = sg->getCurrentData(), i = 0;
|
|
i < samples; ptr = ptr->next, i++) {
|
|
ptr->y = 0;
|
|
ptr->avg = 0;
|
|
}
|
|
sg->zeroMaxVal();
|
|
sg->setCurVal(0.0);
|
|
sg->setAvgVal(0.0);
|
|
sg->setSamplesSoFar(0);
|
|
sg->setAvgData(sg->getCurrentData());
|
|
}
|
|
} // willRestart
|
|
} else {
|
|
|
|
// first free up everything that might be in freeDataList
|
|
for (dataStruct2* ptr2 = freeDataList; ptr2 != 0; ptr2 = ptr2->next) {
|
|
if (ptr2->data)
|
|
free((void*) ptr2->data);
|
|
}
|
|
freeDataList = NULL;
|
|
|
|
// temporarily stop snooping while we're moving the data
|
|
if (snpStm.ss_sock != -1)
|
|
(void) snoopStop(&snpStm);
|
|
|
|
|
|
// now go through strips, and reallocate memory
|
|
dataStruct *newPtr, *oldPtr, *ptr;
|
|
// if (willRestart)
|
|
// printf("CLEARING DATA -- number of samples changed\n");
|
|
|
|
for (sg = strips; sg != 0; sg = sg->getNext()) {
|
|
if (setupCircData(&newPtr, newSamples) == -1)
|
|
return -1;
|
|
|
|
// if we're going to restart the snooper,
|
|
// we want data area to be all zeros, and maxVal = 0;
|
|
// if we won't be restarting the snooper,
|
|
// copy data up to minimum size of old & new areas, but:
|
|
// if have fewer samples now, be sure to copy the most recent ones,
|
|
// if have more now, be sure to copy to the most recent slots.
|
|
if (willRestart) {
|
|
sg->zeroMaxVal();
|
|
sg->setCurVal(0.0);
|
|
sg->setAvgVal(0.0);
|
|
sg->setSamplesSoFar(0);
|
|
sg->setAvgData(sg->getCurrentData());
|
|
|
|
} else {
|
|
ptr = newPtr;
|
|
oldPtr = sg->getCurrentData();
|
|
if (newSamples < samples)
|
|
for (i = 0; i < (samples - newSamples); i++)
|
|
oldPtr = oldPtr->next;
|
|
else if (newSamples > samples)
|
|
for (i = 0; i < (newSamples - samples); i++)
|
|
ptr = ptr->next;
|
|
|
|
int toCopy = (samples < newSamples) ? samples : newSamples;
|
|
for (i=0; i < toCopy; i++, ptr=ptr->next, oldPtr=oldPtr->next)
|
|
ptr->y = oldPtr->y;
|
|
ptr->avg = oldPtr->avg;
|
|
}
|
|
// set avgData pointer, too, to newAvgSamples behind currentData
|
|
// which is the same as (newSamples - newAvgSamples) ahead.
|
|
ptr = newPtr;
|
|
for (i=0; i < (newSamples - newAvgSamples); i++)
|
|
ptr = ptr->next;
|
|
sg->setAvgData(ptr);
|
|
|
|
// free old data area
|
|
free(sg->getHeadData());
|
|
|
|
// set sg data area to new area
|
|
sg->setHeadData(newSamples, newPtr);
|
|
sg->setCurrentData(newPtr);
|
|
sg->rescale();
|
|
|
|
} // for each strip
|
|
|
|
if (snpStm.ss_sock != -1) {
|
|
(void) snoopStart(&snpStm);
|
|
}
|
|
|
|
} // if newSamples != samples
|
|
|
|
} // if !history
|
|
|
|
|
|
// tell timeGadget if period, interval or timeType changed
|
|
if ((newPeriod != period) || (newInterval != interval) ||
|
|
(newTimeType != timeType)) {
|
|
viewGadget->newTimeArgs(timeGadget, newPeriod, newInterval,
|
|
newTimeType);
|
|
|
|
if (history) {
|
|
samples = newSamples;
|
|
updateHistory();
|
|
}
|
|
else
|
|
viewGadget->render();
|
|
}
|
|
|
|
// if changed avgPeriod (& therefore avgSamples), have to start
|
|
// calculating averages over from scratch.
|
|
if (newAvgSamples != avgSamples && newAvgSamples != 0) {
|
|
for (sg = strips; sg != 0; sg = sg->getNext()) {
|
|
sg->setSamplesSoFar(0);
|
|
sg->setAvgVal(0.0);
|
|
sg->setAvgData(sg->getCurrentData());
|
|
}
|
|
}
|
|
|
|
timeType = newTimeType;
|
|
samples = newSamples;
|
|
avgSamples = newAvgSamples;
|
|
period = newPeriod;
|
|
avgPeriod = newAvgPeriod;
|
|
interval = newInterval;
|
|
updateTime = newUpdateTime;
|
|
|
|
drawData();
|
|
|
|
return 0;
|
|
|
|
} // NetGraph::useNewTimeArgs()
|
|
|
|
|
|
int
|
|
NetGraph::checkTimeArgs(int* newSamplesp, int* newPeriodp,
|
|
int* newIntervalp, int* newUpdateTimep,
|
|
int* newAvgPeriodp, int* newAvgSamplesp) {
|
|
|
|
int newInterval = *newIntervalp;
|
|
int newPeriod = *newPeriodp;
|
|
int newUpdateTime = *newUpdateTimep;
|
|
int newAvgPeriod = *newAvgPeriodp;
|
|
|
|
if (*newIntervalp < 0) {
|
|
// post(NEGINTVLMSG);
|
|
// return -1;
|
|
*newIntervalp = -1 * *newIntervalp;
|
|
} else if (*newIntervalp == 0)
|
|
*newIntervalp = DEF_INTERVAL;
|
|
|
|
if (*newPeriodp < 0) {
|
|
// post(NEGPERIODMSG);
|
|
// return -1;
|
|
*newPeriodp = -1 * *newPeriodp;
|
|
} else if (*newPeriodp == 0)
|
|
*newPeriodp = 600;
|
|
|
|
*newSamplesp = *newPeriodp / *newIntervalp + 1;
|
|
if (*newSamplesp <= 1) {
|
|
// post(BADPERIODMSG);
|
|
// return -1;
|
|
*newPeriodp = *newIntervalp;
|
|
*newSamplesp = 2;
|
|
}
|
|
|
|
// if update time is smaller than interval, make it same as interval
|
|
// (no longer give error message that it's too small)
|
|
if (*newUpdateTimep < *newIntervalp) {
|
|
*newUpdateTimep = *newIntervalp;
|
|
}
|
|
|
|
if (*newPeriodp < *newUpdateTimep) {
|
|
// post(BADUPDTMPERMSG);
|
|
// return -1;
|
|
*newUpdateTimep = *newPeriodp;
|
|
}
|
|
|
|
|
|
// if 0 < newAvgPeriod < *newIntervalp, make it = 0
|
|
if (*newAvgPeriodp > 0 && *newAvgPeriodp < *newIntervalp ) {
|
|
*newAvgPeriodp = 0;
|
|
}
|
|
|
|
// if newAvgPeriod > newPeriod , make it = newPeriod
|
|
if (*newAvgPeriodp > 0 && *newAvgPeriodp > *newPeriodp ) {
|
|
*newAvgPeriodp = *newPeriodp;
|
|
}
|
|
|
|
// if user didn't specify avgPeriod, make it = newPeriod
|
|
if (*newAvgPeriodp < 0) {
|
|
*newAvgPeriodp = *newPeriodp;
|
|
}
|
|
|
|
// now use that to calculate how many samples to average over
|
|
*newAvgSamplesp = *newAvgPeriodp / *newIntervalp;
|
|
|
|
// if we changed any here, correct them on paramControl (if open)
|
|
if (paramControl) {
|
|
char tempStr[20];
|
|
if (*newIntervalp != newInterval) {
|
|
sprintf(tempStr, "%.1f", *newIntervalp/10.0);
|
|
paramControl->setIntervalField(tempStr);
|
|
}
|
|
if (*newUpdateTimep != newUpdateTime) {
|
|
sprintf(tempStr, "%.1f", *newUpdateTimep/10.0);
|
|
paramControl->setUpdateField(tempStr);
|
|
}
|
|
if (*newPeriodp != newPeriod) {
|
|
sprintf(tempStr, "%.1f", *newPeriodp/10.0);
|
|
paramControl->setPeriodField(tempStr);
|
|
}
|
|
if (*newAvgPeriodp != newAvgPeriod) {
|
|
sprintf(tempStr, "%.1f", *newAvgPeriodp/10.0);
|
|
paramControl->setAvgPeriodField(tempStr);
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
} //NetGraph::checkTimeArgs
|
|
|
|
|
|
int
|
|
NetGraph::setupCircData(dataStruct** ptrp, int numSamples) {
|
|
|
|
*ptrp = (dataStruct*) malloc(numSamples * sizeof(dataStruct));
|
|
if (*ptrp == 0) {
|
|
post(MALLOCERRMSG);
|
|
return -1;
|
|
}
|
|
bzero(*ptrp, numSamples * sizeof(dataStruct));
|
|
dataStruct* ptr2 = *ptrp;
|
|
for (int i = 1; i < numSamples; i++) {
|
|
ptr2->next = ptr2 + 1;
|
|
ptr2++;
|
|
}
|
|
ptr2->next = *ptrp;
|
|
|
|
return 0;
|
|
} // NetGraph::setupCircData
|
|
|
|
int
|
|
NetGraph::snoopStart(SnoopStream* streamp) {
|
|
if (snooping)
|
|
return 0;
|
|
|
|
if (!ss_start(streamp))
|
|
return 0;
|
|
|
|
snooping = True;
|
|
|
|
event->setType(NV_START_SNOOP);
|
|
event->setInterfaceName(newSnooper.node);
|
|
eh->send(event);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
NetGraph::snoopStop(SnoopStream* streamp) {
|
|
if (!snooping)
|
|
return 0;
|
|
|
|
if (!ss_stop(streamp))
|
|
return 0;
|
|
|
|
snooping = False;
|
|
|
|
event->setType(NV_STOP_SNOOP);
|
|
event->setInterfaceName(currentSnooper.node);
|
|
eh->send(event);
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
NetGraph::restartSnooping(int intvl) {
|
|
int retVal, bin;
|
|
SnoopStream newSnpStm;
|
|
// printf("restartSnooping\n");
|
|
/**** already cleared in useNewTimeArgs
|
|
// clear out data area
|
|
printf("CLEARING DATA -- restartSnooping\n");
|
|
dataStruct *ptr;
|
|
int i;
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
for (ptr = sg->getCurrentData(), i = 0;
|
|
i < samples; ptr = ptr->next, i++) {
|
|
ptr->y = 0;
|
|
ptr->avg = 0;
|
|
}
|
|
|
|
sg->zeroMaxVal();
|
|
sg->setCurVal(0.0);
|
|
sg->setAvgVal(0.0);
|
|
sg->setSamplesSoFar(0);
|
|
sg->setAvgData(sg->getCurrentData());
|
|
}
|
|
********/
|
|
|
|
bzero(&hist, sizeof hist);
|
|
bzero(&oldHist, sizeof oldHist);
|
|
|
|
// stop (but don't close) existing snooper, try to start new one.
|
|
// if not successful, then restart existing one.
|
|
// if successful, then delete/close old one, copy new to old, etc..
|
|
|
|
// stop existing snooper
|
|
if (snpStm.ss_sock != -1) {
|
|
(void) snoopStop(&snpStm);
|
|
}
|
|
|
|
// try to start new one
|
|
newSnpStm.ss_sock = -1;
|
|
|
|
// printf("about to call hist_init; newSnooper.node: %s, newSnooper.interface:%s\n",
|
|
// newSnooper.node, newSnooper.interface);
|
|
|
|
retVal = hist_init(&newSnpStm, &newSnooper, intvl);
|
|
if (retVal < 0) {
|
|
// init of new one failed, so restart existing one and post a message
|
|
// snoopStart issues message based on newSnooper
|
|
strcpy(newSnooper.node, currentSnooper.node);
|
|
strcpy(newSnooper.interface, currentSnooper.interface);
|
|
(void) snoopStart(&snpStm);
|
|
post(-1 * retVal);
|
|
return -1;
|
|
} else {
|
|
snooperChanged();
|
|
}
|
|
|
|
// set up new snoop requests
|
|
ExprSource src;
|
|
ExprError err;
|
|
for (bin = 0; bin <= highestBin; bin++) {
|
|
if (strcmp(filters[bin].expr, "total")) {
|
|
src.src_path = "netgraph";
|
|
src.src_line = 0;
|
|
src.src_buf = filters[bin].expr;
|
|
ss_compile(&newSnpStm, &src, &err);
|
|
} else {
|
|
ss_add(&newSnpStm, 0, &err);
|
|
}
|
|
}
|
|
|
|
// start snooping again
|
|
if (!snoopStart(&newSnpStm)) {
|
|
// start of new one failed, so restart existing one and post a message
|
|
// xxx shouldn't we delete new one, too???
|
|
// snoopStart issues message based on newSnooper
|
|
strcpy(newSnooper.node, currentSnooper.node);
|
|
strcpy(newSnooper.interface, currentSnooper.interface);
|
|
(void) snoopStart(&snpStm);
|
|
post(NOSTARTSNOOPMSG);
|
|
return -1;
|
|
}
|
|
|
|
// if successful, then delete/close old one
|
|
if (snpStm.ss_sock != -1) {
|
|
for (bin = highestBin; bin >= 0; bin--)
|
|
(void) ss_delete(&snpStm, bin);
|
|
|
|
(void) ss_unsubscribe(&snpStm);
|
|
ss_close(&snpStm);
|
|
exec->removeCallBack(snpStm.ss_sock);
|
|
// printf("restartSnooping - removeCallBack(%d)\n", snpStm.ss_sock);
|
|
}
|
|
|
|
snpStm = newSnpStm;
|
|
|
|
exec->addCallBack(snpStm.ss_sock, False,
|
|
new NetGraphCallBack(this, &NetGraph::readData));
|
|
// printf("restartSnooping - addCallBack(%d)\n", snpStm.ss_sock);
|
|
|
|
// take care of the possibility that we were on an ether
|
|
// and now fddi, etc.
|
|
if (editControl)
|
|
editControl->enableIntfcButtons();
|
|
|
|
return 0;
|
|
|
|
} // NetGraph::restartSnooping
|
|
|
|
|
|
// we're going to be running from a history file, so open it, etc.
|
|
int
|
|
NetGraph::handleHistFile(char* fileName) {
|
|
// test_xdr_read(fileName, &rfp, &xdr);
|
|
|
|
// printf("NetGraph::handleHistFile(%s)\n", fileName);
|
|
int highNum, fileLength, memLength;
|
|
char optionStr[80];
|
|
char* optionStrP;
|
|
|
|
optionStrP = optionStr;
|
|
|
|
int historyVersion = open_xdr_infile(fileName, &rfp, &xdr,
|
|
&fileLength, &highNum, &optionStrP);
|
|
if (historyVersion == 0) {
|
|
fatalError = True;
|
|
post(BADXDRRDOPENMSG);
|
|
return -1;
|
|
}
|
|
|
|
handleStringOfOptions(optionStr);
|
|
|
|
if (checkTimeArgs(&samples, &period, &interval, &updateTime,
|
|
&avgPeriod, &avgSamples) == -1) {
|
|
fatalError = True;
|
|
return -1;
|
|
}
|
|
|
|
highestNumber = 0;
|
|
|
|
// setup strips
|
|
int type, baseRate, color, avgColor, style;
|
|
int alarmSet, alarmBell;
|
|
tuBool alarmSetB, alarmBellB;
|
|
float alarmLo, alarmHi;
|
|
char filterExpr[80];
|
|
char* filterExprP;
|
|
filterExprP = filterExpr;
|
|
|
|
baseRate = 99; // xxx this isn't in old history files
|
|
avgColor = 0; // xxx this isn't in old history files
|
|
|
|
StripGadget* sg;
|
|
StripGadget* lastSg = 0;
|
|
|
|
// make parent big enough for all strips
|
|
stripParent->grow(highNum + 2, 1);
|
|
|
|
for (int stripNum = 1; stripNum <= highNum; stripNum++) {
|
|
if (!do_xdr_stripInfo(&xdr, historyVersion,
|
|
&filterExprP, &type, &baseRate,
|
|
&color, &avgColor, &style,
|
|
&alarmSet, &alarmBell, &alarmLo, &alarmHi)) {
|
|
fatalError = True;
|
|
post(BADXDRREADMSG);
|
|
return -1;
|
|
}
|
|
|
|
sg = new StripGadget(this, stripParent, "");
|
|
|
|
// put this new strip in the right place
|
|
// (order in hist file is from bottom to top)
|
|
stripParent->place(sg, highNum - stripNum, 0);
|
|
// printf("strip # %d (of %d) at row %d\n", stripNum, highNum, highNum-stripNum);
|
|
if (completeNewStrip(sg, 0) == -1)
|
|
return -1; // completeNewStrips posts its own error, & sets fatal
|
|
|
|
// fake 'bin' number so can keep track of filter expressions
|
|
sg->setBin(stripNum);
|
|
strcpy(filters[stripNum].expr, filterExpr);
|
|
|
|
|
|
alarmSetB = (alarmSet != 0);
|
|
alarmBellB = (alarmBell != 0);
|
|
finishSetupStripInts(filterExpr, type, baseRate,
|
|
color, avgColor, style,
|
|
alarmSetB, alarmBellB, alarmLo, alarmHi, sg);
|
|
|
|
}
|
|
|
|
// each time sample has: 2 longs for time, 2 floats for each strip
|
|
sampleSize = 2 + 2 * highestNumber;
|
|
|
|
|
|
// calculate how much memory we need to read in all the data.
|
|
// We're already past the beginning of the file, which we don't save.
|
|
|
|
fileLength -= get_xdr_pos(&xdr);
|
|
|
|
// Now, based on (2 time + (1 data for each strip)) per sample,
|
|
// calculate how many time samples. Round up, in case got chopped.
|
|
// Also note that fileLength & memLength are in bytes; we want
|
|
// longs and floats, which are both 4 bytes long.
|
|
|
|
historySamples = (int) ((fileLength / 4.0) / (2 + highNum) + 0.5);
|
|
|
|
// for our storage, we need 2 floats per strip per sample, not 1
|
|
// (data & avg, which we'll calculate after reading the data in)
|
|
|
|
memLength = historySamples * (2 + 2 * highNum) * 4;
|
|
historyBeg = malloc(memLength);
|
|
bzero(historyBeg, memLength);
|
|
|
|
float* dataPtr;
|
|
timePtr = (long*) historyBeg;
|
|
dataPtr = (float*) (timePtr + 2); // time needs 2 longs
|
|
// printf("first timePtr: %x; file has %d samples\n", timePtr, historySamples);
|
|
|
|
// we don't really need the whole chunk -- there's the part of the file
|
|
// that we already read (setup, etc.) that doesn't get copied in.
|
|
|
|
historyEnd = (void*) ((char*)historyBeg + memLength);
|
|
|
|
// set up the pointers for each strip (where data starts for each)
|
|
for (sg = strips; sg != 0; sg = sg->getNext()) {
|
|
sg->setHeadData(samples, (dataStruct*) dataPtr);
|
|
sg->setCurrentData((dataStruct*) dataPtr);
|
|
sg->setAvgData((dataStruct*) dataPtr);
|
|
sg->setAvgVal(0.0);
|
|
|
|
dataPtr += 2; // room for sample + avg
|
|
}
|
|
|
|
|
|
// now read in the rest of the historical data
|
|
int ok;
|
|
struct timeval timestamp;
|
|
|
|
int samplesSoFar = 0; // for calculating averages
|
|
float* fPtr;
|
|
|
|
ok = do_xdr_time(&xdr, ×tamp);
|
|
while (ok) {
|
|
*timePtr++ = timestamp.tv_sec;
|
|
*timePtr++ = timestamp.tv_usec;
|
|
dataPtr = (float*) timePtr; // first data goes right after time
|
|
|
|
samplesSoFar++;
|
|
|
|
// read in data; advance dataPtr by 2, so room to put avg
|
|
for (sg = strips; sg != 0; sg = sg->getNext(), dataPtr+=2) {
|
|
if (!do_xdr_data(&xdr, dataPtr))
|
|
break;
|
|
|
|
// calc average
|
|
if (avgSamples != 0) {
|
|
if (samplesSoFar > avgSamples) {
|
|
*(dataPtr + 1) = sg->getAvgVal() +
|
|
(*dataPtr - *(float*)(sg->getAvgData()) ) / avgSamples;
|
|
|
|
fPtr = (float*) sg->getAvgData();
|
|
fPtr += sampleSize;
|
|
sg->setAvgData((dataStruct*)fPtr);
|
|
sg->setAvgVal(*(dataPtr + 1));
|
|
|
|
} else {
|
|
*(dataPtr + 1) = ((sg->getAvgVal()) * (samplesSoFar - 1) +
|
|
(*dataPtr)) /
|
|
samplesSoFar;
|
|
sg->setAvgVal(*(dataPtr + 1));
|
|
}
|
|
} // need to calc average
|
|
|
|
} // for each strip
|
|
|
|
timePtr = (long*) dataPtr; // next time goes right after last data
|
|
|
|
ok = do_xdr_time(&xdr, ×tamp);
|
|
|
|
} // while ok ( each time sample)
|
|
|
|
timePtr = (long*) historyBeg;
|
|
historyTicks = 0;
|
|
|
|
for (sg = strips; sg != 0; sg = sg->getNext()) {
|
|
// printf("%d: %s\n", sg->getNumber(), filters[sg->getBin()].expr);
|
|
sg->rescale();
|
|
}
|
|
|
|
timerSeconds = 0.5;
|
|
|
|
return 0;
|
|
|
|
} // NetGraph::handleHistFile
|
|
|
|
|
|
void
|
|
NetGraph::historyMove(tuGadget*) {
|
|
// printf("NetGraph::historyMove\n");
|
|
|
|
if (historyDirection == 0)
|
|
return;
|
|
|
|
|
|
|
|
long* timePtr1; // where timePtr would be if stepped back
|
|
long* timePtr2; // where right end would be if stepped forward
|
|
|
|
// need room for data & avgData
|
|
timePtr1 = timePtr - sampleSize;
|
|
timePtr2 = timePtr + sampleSize * samples;
|
|
|
|
if (((historyDirection == -1) && (timePtr1 < historyBeg))
|
|
|| ((historyDirection == 1) && (timePtr2 >= historyEnd))) {
|
|
historyDirection = 0;
|
|
//xxx scrollGadget->zeroThrottle();
|
|
viewGadget->render();
|
|
return;
|
|
}
|
|
|
|
timePtr = timePtr + historyDirection * sampleSize;
|
|
historyTicks += historyDirection;
|
|
scrollGadget->setScrollPerc((float)historyTicks /
|
|
(float)(historySamples - samples));
|
|
|
|
updateHistory();
|
|
} // NetGraph::historyMove
|
|
|
|
|
|
void
|
|
NetGraph::updateHistory() {
|
|
|
|
float* dataPtr = (float*) (timePtr + 2);
|
|
|
|
// For same scale option
|
|
for (int i = 0; i < NUM_GRAPH_TYPES; i++)
|
|
max[i] = 0.0;
|
|
|
|
|
|
int increment; // how far from dataPtr to "current data" (right end)
|
|
// for each time point, have 2 time vals, + data & avg for each strip
|
|
increment = sampleSize * (samples - 1);
|
|
|
|
tuBool pastEnd = (timePtr + increment >= historyEnd);
|
|
|
|
long* timePtr2; // "right" end of chart (latest time displayed)
|
|
timePtr2 = timePtr + increment;
|
|
if (pastEnd) {
|
|
hist.h_timestamp.tv_sec = 0;
|
|
hist.h_timestamp.tv_usec = 0;
|
|
} else {
|
|
hist.h_timestamp.tv_sec = *timePtr2++;
|
|
hist.h_timestamp.tv_usec = *timePtr2;
|
|
}
|
|
|
|
int newScale;
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext(), dataPtr+=2) {
|
|
sg->setCurrentData((dataStruct*) dataPtr);
|
|
// current value (for label) is at *right* end.
|
|
if (pastEnd)
|
|
sg->setCurVal(0.0);
|
|
else {
|
|
sg->setCurVal(*(dataPtr + increment));
|
|
sg->setAvgVal(*(dataPtr + increment + 1));
|
|
checkAlarms(sg, *(dataPtr + increment), hist.h_timestamp);
|
|
}
|
|
|
|
if (!lockPercentages || sg->getType() < TYPE_PPACKETS) {
|
|
if (sameScale) {
|
|
newScale = sg->findVertScale(0.0); // really could use current max
|
|
if (newScale > max[sg->getType()])
|
|
max[sg->getType()] = newScale;
|
|
} else
|
|
sg->rescale();
|
|
}
|
|
}
|
|
|
|
if (sameScale) {
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
if (!lockPercentages || sg->getType() < TYPE_PPACKETS) {
|
|
sg->setDataHeight(max[sg->getType()]);
|
|
sg->rescale(False);
|
|
}
|
|
}
|
|
}
|
|
|
|
drawData();
|
|
|
|
// timeGadget->updateTime(hist.h_timestamp);
|
|
// viewGadget->render();
|
|
|
|
} // NetGraph::updateHistory
|
|
|
|
void
|
|
NetGraph::startTimer() {
|
|
// printf("NetGraph::startTimer; timerSeconds = %f\n", timerSeconds);
|
|
if (timerSeconds > 0)
|
|
timer->start(timerSeconds);
|
|
else
|
|
timer->stop();
|
|
}
|
|
|
|
void
|
|
NetGraph::throttle(double t) {
|
|
// printf("NetGraph::throttle(%f)\n", t);
|
|
|
|
// define some different speeds at which we can run history
|
|
static float timerDelays[6] = {0.0, 1.0, 0.5, 0.2, 0.05, 0.02};
|
|
|
|
if (t == 0) {
|
|
historyDirection = 0;
|
|
} else if (t < 0) {
|
|
t = -t;
|
|
historyDirection = -1;
|
|
} else {
|
|
historyDirection = 1;
|
|
}
|
|
|
|
timerSeconds = timerDelays[(int)t];
|
|
|
|
startTimer();
|
|
} // throttle
|
|
|
|
|
|
// scroll history to the given percentage of the way through
|
|
void
|
|
NetGraph::scroll(double p) {
|
|
historyDirection = 0;
|
|
historyTicks = (int) (p * (historySamples - samples));
|
|
|
|
if (historyTicks < 0)
|
|
historyTicks = 0;
|
|
|
|
timePtr = (long*)historyBeg + historyTicks * sampleSize;
|
|
updateHistory();
|
|
|
|
}
|
|
|
|
// increment/decrement history
|
|
// -1 = dec; +1 = inc; -2/+2 = page dec/inc
|
|
void
|
|
NetGraph::scrollInc(int inc) {
|
|
throttle(0);
|
|
|
|
switch (inc) {
|
|
case -1:
|
|
historyTicks--;
|
|
break;
|
|
case 1:
|
|
historyTicks++;
|
|
break;
|
|
case -2:
|
|
historyTicks -= (samples - 1);
|
|
break;
|
|
case 2:
|
|
historyTicks += (samples - 1);
|
|
break;
|
|
}
|
|
|
|
if (historyTicks < 0)
|
|
historyTicks = 0;
|
|
if (historyTicks > historySamples)
|
|
historyTicks = historySamples;
|
|
|
|
scrollGadget->setScrollPerc(
|
|
historyTicks / (float) (historySamples - samples));
|
|
|
|
timePtr = (long*)historyBeg + historyTicks * sampleSize;
|
|
updateHistory();
|
|
}
|
|
|
|
void
|
|
NetGraph::readData(tuGadget*) {
|
|
// printf("NetGraph::readData\n");
|
|
#ifdef CHECK_TIME
|
|
struct timeval *tp1, *tp2;
|
|
tp1 = (struct timeval*)malloc(sizeof(struct timeval));
|
|
tp2 = (struct timeval*)malloc(sizeof(struct timeval));
|
|
gettimeofday(tp1, 0);
|
|
#endif
|
|
|
|
if (! hist_read(&snpStm, &hist)) {
|
|
exec->removeCallBack(snpStm.ss_sock);
|
|
fatalError = True;
|
|
post(SSREADERRMSG);
|
|
return;
|
|
}
|
|
|
|
int i;
|
|
int advanced; // how many intervals did we advance since last time?
|
|
double deltaTime = 0;
|
|
if ((oldHist.h_timestamp.tv_sec == 0) &&
|
|
(oldHist.h_timestamp.tv_usec == 0)) {
|
|
// this is the first sample, so we'll say we didn't miss anything
|
|
advanced = 1;
|
|
} else {
|
|
// did this sample come at the expected time, or was >= 1 dropped?
|
|
deltaTime = hist.h_timestamp.tv_sec - oldHist.h_timestamp.tv_sec
|
|
+ (hist.h_timestamp.tv_usec - oldHist.h_timestamp.tv_usec)/1000000.0;
|
|
|
|
if (deltaTime == 0) {
|
|
// this is screwy, but apparently happens sometimes if
|
|
// communication is lost to data station.
|
|
// If time of this sample is same as previous one, ignore it.
|
|
return;
|
|
}
|
|
advanced = (int) (deltaTime * 10.0 / interval + .5);
|
|
}
|
|
|
|
// If we're recording, make a list of timestamps (normally only one
|
|
// value, but if we skipped, calculate intermediate times).
|
|
// Then, make a list of the values for all the strips - if we skipped,
|
|
// we have to record time, data1, data2.., time, data1, data2.., etc.
|
|
typedef struct timeStr {
|
|
struct timeval tv;
|
|
struct timeStr* next;
|
|
} timeStruct;
|
|
timeStruct* timeList = NULL;
|
|
if (recording) {
|
|
if (advanced > 1) {
|
|
double secEach = deltaTime / advanced;
|
|
double timeSec = oldHist.h_timestamp.tv_sec +
|
|
oldHist.h_timestamp.tv_usec / 1000000.0;
|
|
|
|
timeStruct *t1, *t2;
|
|
t1 = NULL;
|
|
for (i = 0; i < advanced; i++) {
|
|
t2 = new timeStruct;
|
|
if (timeList)
|
|
t1->next = t2;
|
|
else
|
|
timeList = t2;
|
|
timeSec += secEach;
|
|
t2->tv.tv_sec = (long)timeSec;
|
|
t2->tv.tv_usec = (long)((timeSec - t2->tv.tv_sec) * 1000000.0);
|
|
|
|
t2->next = NULL;
|
|
t1 = t2;
|
|
} // for i
|
|
} else {
|
|
timeList = new timeStruct;
|
|
timeList->tv.tv_sec = hist.h_timestamp.tv_sec;
|
|
timeList->tv.tv_usec = hist.h_timestamp.tv_usec;
|
|
timeList->next = NULL;
|
|
}
|
|
}
|
|
|
|
oldHist.h_timestamp.tv_sec = hist.h_timestamp.tv_sec;
|
|
oldHist.h_timestamp.tv_usec = hist.h_timestamp.tv_usec;
|
|
|
|
// hist_read, via ss_read, returns cumulative numbers, so we have
|
|
// to subtract the previous values.
|
|
|
|
float temp;
|
|
|
|
for (unsigned int bin = 0; bin < hist.h_bins; bin++) {
|
|
temp = hist.h_count[bin].c_bytes;
|
|
hist.h_count[bin].c_bytes -= oldHist.h_count[bin].c_bytes;
|
|
oldHist.h_count[bin].c_bytes = temp;
|
|
|
|
temp = hist.h_count[bin].c_packets;
|
|
hist.h_count[bin].c_packets -= oldHist.h_count[bin].c_packets;
|
|
oldHist.h_count[bin].c_packets = temp;
|
|
}
|
|
|
|
// For same scale option
|
|
for (i = 0; i < NUM_GRAPH_TYPES; i++)
|
|
max[i] = 0.0;
|
|
|
|
// Update and rescale all the strips
|
|
dataStruct *ptr, *dataList, *d1, *d2;
|
|
dataList = NULL; // dataList, d1 & d2 are for recording
|
|
d1 = NULL;
|
|
int samplesSoFar;
|
|
float oldestAvgDataVal;
|
|
int trueIntvl;
|
|
int newScale;
|
|
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
// note - currentData points to 'oldest' data, which will be
|
|
// filled with brand new data.
|
|
ptr = sg->getCurrentData();
|
|
// we'll change the currentData pointer first,
|
|
// so that if changing the val (& therefore val label)
|
|
// causes a render, we'll be in the right place
|
|
sg->setCurrentData(ptr->next);
|
|
|
|
// save this in case avgPer = per, which means old data
|
|
// might be overwritten by new data before recalc average.
|
|
oldestAvgDataVal = sg->getAvgData()->y;
|
|
trueIntvl = interval * advanced;
|
|
|
|
switch (sg->getType()) {
|
|
case TYPE_PACKETS:
|
|
ptr->y = 10.0 * hist.h_count[sg->getBin()].c_packets/trueIntvl;
|
|
break;
|
|
|
|
case TYPE_BYTES:
|
|
ptr->y = 10.0 * hist.h_count[sg->getBin()].c_bytes / trueIntvl;
|
|
break;
|
|
|
|
case TYPE_PPACKETS:
|
|
if (hist.h_count[0].c_packets) {
|
|
ptr->y = 100.0 * hist.h_count[sg->getBin()].c_packets /
|
|
hist.h_count[0].c_packets;
|
|
} else {
|
|
ptr->y = 0;
|
|
}
|
|
break;
|
|
|
|
case TYPE_PBYTES:
|
|
if (hist.h_count[0].c_bytes) {
|
|
ptr->y = 100.0 * hist.h_count[sg->getBin()].c_bytes /
|
|
hist.h_count[0].c_bytes;
|
|
} else {
|
|
ptr->y = 0;
|
|
}
|
|
break;
|
|
|
|
case TYPE_PNPACKETS:
|
|
if (sg->getNPackets() <= 0)
|
|
ptr->y = 0.0;
|
|
else
|
|
ptr->y = 100.0 * hist.h_count[sg->getBin()].c_packets /
|
|
(sg->getNPackets() * trueIntvl / 10.0);
|
|
break;
|
|
|
|
case TYPE_PNBYTES:
|
|
if (sg->getNBytes() <= 0)
|
|
ptr->y = 0.0;
|
|
else
|
|
ptr->y = 100.0 * (hist.h_count[sg->getBin()].c_bytes)/
|
|
(sg->getNBytes() * trueIntvl / 10.0);
|
|
break;
|
|
case TYPE_PETHER:
|
|
ptr->y = 100.0 * (hist.h_count[sg->getBin()].c_bytes +
|
|
ETHER_HEAD * hist.h_count[sg->getBin()].c_packets)/
|
|
(ETHER_CAPACITY * trueIntvl / 10.0);
|
|
break;
|
|
case TYPE_PFDDI:
|
|
ptr->y = 100.0 * (hist.h_count[sg->getBin()].c_bytes +
|
|
FDDI_HEAD * hist.h_count[sg->getBin()].c_packets)/
|
|
(FDDI_CAPACITY * trueIntvl / 10.0);
|
|
break;
|
|
case TYPE_PTOKENRING:
|
|
ptr->y = 100.0 * (hist.h_count[sg->getBin()].c_bytes +
|
|
TOKENRING_HEAD * hist.h_count[sg->getBin()].c_packets)/
|
|
(TOKENRING_CAPACITY * trueIntvl / 10.0);
|
|
break;
|
|
} // switch
|
|
|
|
|
|
// calc average, if need to
|
|
if (avgSamples != 0) {
|
|
samplesSoFar = sg->getSamplesSoFar() + 1;
|
|
if (samplesSoFar > avgSamples) {
|
|
// we're well along, so recalc avg based on old average,
|
|
// oldest sample we used to average in, and newest sample
|
|
ptr->avg = sg->getAvgVal() +
|
|
( ptr->y - oldestAvgDataVal) / avgSamples;
|
|
|
|
sg->setAvgData(sg->getAvgData()->next);
|
|
sg->setAvgVal(ptr->avg);
|
|
|
|
} else {
|
|
// if we aren't even up to 'avgPeriod' yet, calc avg so far
|
|
ptr->avg = (sg->getAvgVal() * (samplesSoFar - advanced) +
|
|
(ptr->y)) /
|
|
samplesSoFar;
|
|
sg->setAvgVal(ptr->avg);
|
|
sg->setSamplesSoFar(samplesSoFar -1 + advanced);
|
|
}
|
|
|
|
} // calc average
|
|
|
|
|
|
if (recording) {
|
|
d2 = new dataStruct;
|
|
if (dataList)
|
|
d1->next = d2;
|
|
else
|
|
dataList = d2;
|
|
d2->y = ptr->y;
|
|
d2->avg = ptr->avg; // XXX IS THIS NECESSARY??
|
|
d2->next = NULL;
|
|
d1 = d2;
|
|
}
|
|
|
|
// copy the avg & y to any we skipped over (missed samples)
|
|
float avgY = ptr->y;
|
|
float avg = ptr->avg;
|
|
|
|
for (i = 1; i < advanced; i++) {
|
|
ptr = ptr->next;
|
|
ptr->y = avgY;
|
|
ptr->avg = avg;
|
|
sg->setAvgData(sg->getAvgData()->next);
|
|
}
|
|
|
|
|
|
sg->setCurVal(ptr->y);
|
|
|
|
checkAlarms(sg, ptr->y, hist.h_timestamp);
|
|
|
|
if (!lockPercentages || sg->getType() < TYPE_PPACKETS) {
|
|
if (sameScale) {
|
|
newScale = sg->findVertScale(0.0); // really could use current max
|
|
if (newScale > max[sg->getType()])
|
|
max[sg->getType()] = newScale;
|
|
} else
|
|
sg->rescale();
|
|
}
|
|
|
|
} // for each strip
|
|
|
|
if (recording) {
|
|
// record time, & data for each strip
|
|
// (repeat if advanced > 1)
|
|
for (timeStruct *t = timeList; t; t = t->next) {
|
|
if (!do_xdr_time(&xdr, &t->tv))
|
|
post(BADXDRWRITEMSG);
|
|
|
|
if (outputAscii) {
|
|
char timeString[20];
|
|
char usecString[10];
|
|
long clockSec;
|
|
clockSec = t->tv.tv_sec;
|
|
struct tm* tmStruct;
|
|
tmStruct = localtime(&clockSec);
|
|
ascftime(timeString, "%H:%M:%S", tmStruct);
|
|
sprintf(usecString, "%f", (float) t->tv.tv_usec/1000000.0);
|
|
printf("%s%s\n", timeString, strchr(usecString, '.'));
|
|
}
|
|
|
|
for (dataStruct* d = dataList; d; d = d->next) {
|
|
if (!do_xdr_data(&xdr, &(d->y)))
|
|
post(BADXDRWRITEMSG);
|
|
if (outputAscii)
|
|
printf("\t%6f\t%6f\n", d->y, d->avg);
|
|
}
|
|
} // for each time
|
|
} // if recording
|
|
|
|
if (sameScale) {
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
if (!lockPercentages || sg->getType() < TYPE_PPACKETS) {
|
|
sg->setDataHeight(max[sg->getType()]);
|
|
sg->rescale(False);
|
|
}
|
|
}
|
|
}
|
|
|
|
timeSinceUpdate += interval;
|
|
|
|
if (timeSinceUpdate >= updateTime) {
|
|
drawData();
|
|
timeSinceUpdate = 0;
|
|
}
|
|
|
|
#ifdef CHECK_TIME
|
|
gettimeofday(tp2, 0);
|
|
int sec, usec;
|
|
sec = tp2->tv_sec - tp1->tv_sec;
|
|
if (sec) {
|
|
sec--;
|
|
usec = 1000000 + tp2->tv_usec - tp1->tv_usec;
|
|
} else
|
|
usec = tp2->tv_usec - tp1->tv_usec;
|
|
totalSec += sec;
|
|
totalUsec += usec;
|
|
intervals++;
|
|
#endif
|
|
|
|
|
|
} // NetGraph::readData
|
|
|
|
void
|
|
NetGraph::drawData(void) {
|
|
// printf("NetGraph::drawData\n");
|
|
timeGadget->updateTime(hist.h_timestamp);
|
|
// viewGadget->render();
|
|
for (StripGadget *sg = strips; sg != 0; sg = sg->getNext()) {
|
|
sg->render();
|
|
}
|
|
} // NetGraph::drawData(void)
|
|
|
|
|
|
void
|
|
NetGraph::checkAlarms(StripGadget* sg, float value, struct timeval tval) {
|
|
tuBool alarmSet = sg->getAlarmSet();
|
|
|
|
if (!alarmSet)
|
|
return;
|
|
|
|
float loVal = sg->getAlarmLoVal();
|
|
float hiVal = sg->getAlarmHiVal();
|
|
tuBool alarmBell = sg->getAlarmBell();
|
|
tuBool alarmLoWasMet = sg->getAlarmLoMet();
|
|
tuBool alarmHiWasMet = sg->getAlarmHiMet();
|
|
int alarmType = ALM_NONE;
|
|
|
|
if (alarmLoWasMet && (value > loVal))
|
|
alarmType = NV_RATE_THRESH_LO_UN_MET;
|
|
else if (!alarmLoWasMet && (value < loVal))
|
|
alarmType = NV_RATE_THRESH_LO_MET;
|
|
|
|
if (alarmHiWasMet && (value < hiVal))
|
|
alarmType = NV_RATE_THRESH_HI_UN_MET;
|
|
else if (!alarmHiWasMet && (value > hiVal))
|
|
alarmType = NV_RATE_THRESH_HI_MET;
|
|
|
|
|
|
if (alarmType != ALM_NONE) {
|
|
long clockSec = tval.tv_sec;
|
|
struct tm* timeStruct;
|
|
char timeString[10];
|
|
timeStruct = localtime(&clockSec);
|
|
ascftime(timeString, "%H:%M:%S", timeStruct);
|
|
|
|
sendAlarmEvent(alarmType, sg, value);
|
|
|
|
switch(alarmType) {
|
|
case NV_RATE_THRESH_LO_UN_MET:
|
|
sg->setAlarmLoMet(False);
|
|
fprintf(afp,"Alarm condition no longer met at %s:\n", timeString);
|
|
fprintf(afp, " graph: %s %s\n", filters[sg->getBin()].expr, sg->getTypeText());
|
|
fprintf(afp, " value: %.2f > %.2f\n",
|
|
value, sg->getAlarmLoVal());
|
|
break;
|
|
case NV_RATE_THRESH_LO_MET:
|
|
sg->setAlarmLoMet(True);
|
|
if (alarmBell)
|
|
XBell(getDpy(), 0);
|
|
fprintf(afp, "Alarm condition met at %s:\n", timeString);
|
|
fprintf(afp, " graph: %s %s\n", filters[sg->getBin()].expr, sg->getTypeText());
|
|
fprintf(afp, " value: %.2f < %.2f\n",
|
|
value, sg->getAlarmLoVal());
|
|
break;
|
|
case NV_RATE_THRESH_HI_UN_MET:
|
|
sg->setAlarmHiMet(False);
|
|
fprintf(afp, "Alarm condition no longer met at %s:\n", timeString);
|
|
fprintf(afp, " graph: %s %s\n", filters[sg->getBin()].expr, sg->getTypeText());
|
|
fprintf(afp, " value: %.2f < %.2f\n",
|
|
value, sg->getAlarmHiVal());
|
|
break;
|
|
case NV_RATE_THRESH_HI_MET:
|
|
sg->setAlarmHiMet(True);
|
|
if (alarmBell)
|
|
XBell(getDpy(), 0);
|
|
fprintf(afp, "Alarm condition met at %s:\n", timeString);
|
|
fprintf(afp, " graph: %s %s\n", filters[sg->getBin()].expr, sg->getTypeText());
|
|
fprintf(afp, " value: %.2f > %.2f\n",
|
|
value, sg->getAlarmHiVal());
|
|
break;
|
|
} // switch
|
|
fflush(afp);
|
|
} // we have something to report
|
|
|
|
} // NetGraph::checkAlarms
|
|
|
|
void
|
|
NetGraph::sendAlarmEvent(int alarmType, StripGadget* sg, float value) {
|
|
alarmEvent->setType(alarmType);
|
|
alarmEvent->setFilter(filters[sg->getBin()].expr);
|
|
alarmEvent->setRateBase(rateBases[sg->getType()]);
|
|
alarmEvent->setRate(value);
|
|
|
|
if (sg->getType() == TYPE_PNBYTES) {
|
|
alarmEvent->setRateOfBase(sg->getNBytes());
|
|
} else if (sg->getType() == TYPE_PNPACKETS) {
|
|
alarmEvent->setRateOfBase(sg->getNPackets());
|
|
}
|
|
|
|
switch (alarmType) {
|
|
case NV_RATE_THRESH_LO_MET:
|
|
case NV_RATE_THRESH_LO_UN_MET:
|
|
alarmEvent->setThreshRate(sg->getAlarmLoVal());
|
|
break;
|
|
case NV_RATE_THRESH_HI_MET:
|
|
case NV_RATE_THRESH_HI_UN_MET:
|
|
alarmEvent->setThreshRate(sg->getAlarmHiVal());
|
|
break;
|
|
}
|
|
|
|
eh->send(alarmEvent);
|
|
|
|
} // sendAlarmEvent
|
|
|
|
|
|
void
|
|
NetGraph::deleteGraph(StripGadget *strip) {
|
|
// remove the strip from the linked list
|
|
if (strip == strips) {
|
|
strips = strip->getNext();
|
|
} else {
|
|
StripGadget *prevsg;
|
|
for (StripGadget *sg = strips; sg != 0; sg = sg->getNext()) {
|
|
if (sg == strip) {
|
|
break;
|
|
}
|
|
prevsg = sg;
|
|
}
|
|
prevsg->setNext(strip->getNext());
|
|
}
|
|
|
|
int thisBin = strip->getBin();
|
|
if (thisBin >= 0)
|
|
stopUsingBin(thisBin);
|
|
|
|
setSelectedStrip(NULL);
|
|
|
|
dataStruct2* ds = new dataStruct2;
|
|
ds->data = strip->getHeadData();
|
|
ds->next = freeDataList;
|
|
freeDataList = ds;
|
|
strip->freeData();
|
|
viewGadget->removeAGraph(strip);
|
|
|
|
|
|
} // NetGraph::deleteGraph
|
|
|
|
|
|
// When a graph is going away, call this with its bin #.
|
|
// This function decrements that filter's count, removes the filter if
|
|
// nobody else is using it, and goes through the graphs, decrementing
|
|
// the bin of each one using a higher bin. (Because snoopstream, when
|
|
// a bin is removed, shifts the higher ones down.)
|
|
// It also updates hist & oldHist, which also keep track of things per bin.
|
|
void
|
|
NetGraph::stopUsingBin(int bin) {
|
|
if (--filters[bin].used == 0) {
|
|
// filter is now unused
|
|
(void) snoopStop(&snpStm);
|
|
(void) ss_delete(&snpStm, bin);
|
|
(void) snoopStart(&snpStm);
|
|
|
|
// remove the filter, shift the others down
|
|
for (int i = bin; i < highestBin; i++) {
|
|
strcpy(filters[i].expr, filters[i+1].expr);
|
|
filters[i].used = filters[i+1].used;
|
|
|
|
hist.h_count[i].c_bytes = hist.h_count[i+1].c_bytes;
|
|
hist.h_count[i].c_packets = hist.h_count[i+1].c_packets;
|
|
oldHist.h_count[i].c_bytes = oldHist.h_count[i+1].c_bytes;
|
|
oldHist.h_count[i].c_packets = oldHist.h_count[i+1].c_packets;
|
|
}
|
|
|
|
// clear the unused bin in hist, oldHist
|
|
hist.h_count[highestBin].c_bytes = 0;
|
|
hist.h_count[highestBin].c_packets = 0;
|
|
oldHist.h_count[highestBin].c_bytes = 0;
|
|
oldHist.h_count[highestBin].c_packets = 0;
|
|
|
|
|
|
// shift the bin numbers
|
|
for (StripGadget* sg = strips; sg != 0; sg = sg->getNext()) {
|
|
sg->shiftBin(bin);
|
|
}
|
|
|
|
highestBin--;
|
|
} // filter now unused
|
|
|
|
} // NetGraph::stopUsingBin
|
|
|
|
void
|
|
NetGraph::setSelectedStrip(StripGadget *strip) {
|
|
|
|
if (editControl && editControl->isMapped())
|
|
editControl->setSg(strip, NULL);
|
|
|
|
// take care of menu items that depend on selection, etc
|
|
if (strip) {
|
|
char* filter = filters[strip->getBin()].expr;
|
|
if (strcmp(filter, "total"))
|
|
toolOptions->setFilter(filter);
|
|
else
|
|
toolOptions->setFilter(NULL);
|
|
|
|
strip->changeSelected(True);
|
|
if (!recording && !history &&
|
|
(viewGadget->getNumberOfGraphs() > 1))
|
|
deleteItem->setEnabled(True);
|
|
} else {
|
|
toolOptions->setFilter(NULL);
|
|
deleteItem->setEnabled(False);
|
|
}
|
|
|
|
|
|
if (selectedStrip)
|
|
selectedStrip->changeSelected(False);
|
|
|
|
selectedStrip = strip;
|
|
|
|
}
|
|
|
|
|
|
|
|
// simple stuff (probably should be marked "inline" in netGraph.h)
|
|
|
|
tuXExec*
|
|
NetGraph::getExec(void) { return exec; }
|
|
|
|
DialogBox*
|
|
NetGraph::getDialogBox(void) { return dialog; }
|
|
|
|
char*
|
|
NetGraph::getFullSnooperString() {
|
|
if (fullSnooperString[0])
|
|
return strdup(fullSnooperString);
|
|
else
|
|
return localHostName;
|
|
}
|
|
|
|
Display *
|
|
NetGraph::getDpy(void) { return display; }
|
|
|
|
|