This is Hosts.m in view mode; [Download] [Up]
/*
SambaManger. A graphical frontend to configure the NetInfo enhanced samba.
Copyright (C) 1998 Robert Frank
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Robert Frank, frank@ifi.unibas.ch
*/
#import "Hosts.h"
#import "Controller.h"
#import "NIDirectory.h"
#import "NIProperty.h"
#import "NetInfoKeys.h"
// The property names of a host's directory:
#define H_NAME "name"
#define H_NETBIOSNAME "netbios name"
#define H_IPADDRESS "ip_address"
#define H_ETHERNET "en_address"
#define H_NETGROUPS "netgroups"
#define H_SYSTEM "system_type"
#define H_OWNER "owner"
#define H_BOOTFILE "bootfile"
#define H_BOOTPARAMS "bootparams"
// Class variable with the string for the open/save panel's title.
static const char *title;
static unsigned char hexOk[128] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
@implementation Hosts
// ************************************************************************
// ************************************************************************
// Class methods:
+ initialize
// Called once by the run time system
{
title = [Service stringFor:"Title:Hosts"];
return self;
}
+ new:sender at:(NXCoord *)offset
{
NIDirectory *NIDir;
Hosts *host = [Hosts alloc];
if ((NIDir = [NIDirectory new:sender root:SMNI_HOSTS directory:NULL])) {
[NIDir setDelegate:host];
if ([host init:sender dirObj:NIDir delta:offset service:NULL]) {
[NIDir setSaveTitle:title];
return host;
}
[NIDir close];
}
return [host free];
}
+ open:sender at:(NXCoord *)offset
{
NIDirectory *NIDir;
Hosts *host = [Hosts alloc];
if ((NIDir = [NIDirectory open:sender root:SMNI_HOSTS withTitle:title])) {
[NIDir setDelegate:host];
if ([host init:sender dirObj:NIDir delta:offset service:[NIDir baseName]])
return host;
[NIDir close];
}
return [host free];
}
- getBootParms:parameter
{
int i;
NIProperty *prop;
const ni_namelist *values;
if (!(prop = [ni_dirObj property:H_BOOTPARAMS]))
return self;
values = [prop valueList];
[textRootDirectory setStringValue:""];
[textPrivateDirectory setStringValue:""];
for (i = 0; i < values->ni_namelist_len; i++)
if (!strncasecmp(values->ni_namelist_val[i], "root", 4))
[textRootDirectory setStringValue:values->ni_namelist_val[i]+5];
else if (!strncasecmp(values->ni_namelist_val[i], "private", 7))
[textPrivateDirectory setStringValue:values->ni_namelist_val[i]+8];
return self;
}
- setBootParms
{
char *root = NULL, *private = NULL;
const char *s = NULL;
NIProperty *prop;
if (!(prop = [ni_dirObj property:H_BOOTPARAMS]))
return nil;
s = [textRootDirectory stringValue];
if (s && *s) {
root = (char *)NXZoneMalloc([self zone], strlen(s) + 6);
strcpy(root, "root=");
strcat(root, s);
}
s = [textPrivateDirectory stringValue];
if (s && *s) {
private = (char *)NXZoneMalloc([self zone], strlen(s) + 9);
strcpy(private, "private=");
strcat(private, s);
}
// Search. If inexistant, create! If exists and root/private non-null,
// update, otherwise delete
[prop updateValue:root at:[prop findValue:"^root.*" how:NI_FIND_REGEX]];
[prop updateValue:private at:[prop findValue:"^private.*" how:NI_FIND_REGEX]];
if (root)
NXZoneFree([self zone], root);
if (private)
NXZoneFree([self zone], private);
return self;
}
- selectAlias:sender
{
[textAliases setStringValue:[[sender selectedCell] stringValue]];
[textAliases selectText:self];
return self;
}
- (BOOL)minimumOK
{
char value[32], *c = value;
int l, ival;
if (!*[textHostname stringValue] || !*[textInternetAddress stringValue]) {
NXRunAlertPanel(getString("Alert:Alert"),
getString("Message:Must have a name and address"),
getString("Button:OK"),NULL,NULL);
return NO;
}
// Let's check a few values for correctnes:
// The Netbios name may be atmost 15 characters
if (strlen([textNetbiosname stringValue]) > 15 ) {
NXRunAlertPanel(getString("Alert:Alert"),
getString("Message:Netbios Name may have atmost 15 characters."),
getString("Button:OK"),NULL,NULL);
return NO;
}
// The IP address must be four values with three dots:
// nnn.nnn.nnn.nnn
bzero(value, 32);
if (*strncpy(value, [textInternetAddress stringValue], 30)) {
value[strlen(value)] = '.';
for (l = 4; l && c; l--) {
ival = atoi(c);
if ((ival > 0) && (ival < 256)) {
if (c = strchr(c, '.'))
c++;
} else
c = NULL;
}
if (!c) {
NXRunAlertPanel(getString("Alert:Alert"),
getString("Message:Invalid IP address.\nMust be of the form: `nnn.nnn.nnn.nnn'."),
getString("Button:OK"),NULL,NULL);
return NO;
}
}
// The Ethernet address must be six hex values with five colons,
// no leading zeros: 0:0:f:0:81:f9
bzero(value, 32);
c = value;
if (*strncpy(value, [textEthernetAddress stringValue], 30)) {
value[strlen(value)] = ':';
for (l = 6; l && c; l--) {
if (!hexOk[*c++&0x7f]) {
c = NULL;
break;
}
if (*c != ':')
if (!((*(c-1) != '0') && hexOk[*c++&0x7f])) {
c = NULL;
break;
}
if (*c != ':')
c = NULL;
else
c++;
}
if (!c) {
NXRunAlertPanel(getString("Alert:Alert"),
getString("Message:Invalid Ethernet address.\nMust be: `hh:hh:hh:hh:hh:hh' with no leading zeros."),
getString("Button:OK"),NULL,NULL);
return NO;
}
}
return YES;
}
// ************************************************************************
// Methods:
- revert:sender
{
[super revert:sender];
[browserAliases loadColumnZero];
return self;
}
- delete:sender
{
if (!strcmp([ni_dirObj baseName], "localhost") ||
!strcmp([ni_dirObj baseName], "broadcasthost")) {
NXRunAlertPanel(getString("Alert:Alert"),
getString("Message:Cannot delete localhost or broadcasthost!"),
getString("Button:OK"), NULL, NULL);
return self;
}
return [super delete:self];
}
- setupAndLoad
{
NIProperty *nbname, *name;
char *NBName, *p;
// Initialize the parameter list
name = [ni_dirObj addString:H_NAME outlet:textHostname];
nbname = [ni_dirObj addString:H_NETBIOSNAME outlet:textNetbiosname];
[ni_dirObj addString:H_IPADDRESS outlet:textInternetAddress];
[ni_dirObj addString:H_ETHERNET outlet:textEthernetAddress];
[ni_dirObj addString:H_OWNER outlet:textSystemOwner];
[ni_dirObj addPopup:H_SYSTEM outlet:popupSystemType default:"Unknown"];
[ni_dirObj addBrowser:H_NETGROUPS browser:browserNetGroups text:textNetgroups
add:buttonAddNetGroup remove:buttonDelNetGroup];
[ni_dirObj addString:H_BOOTFILE outlet:textKernel];
[ni_dirObj addCall:H_BOOTPARAMS displayAction:@selector(getBootParms:)];
// Scan the loaded NetInfo values and update the GUI.
[ni_dirObj scan];
// Check for a netbios name. If none exists, uppercase the hostname.
if (([nbname index] == NI_VALUE_NOT_FOUND) && (*[name valueAt:0])) {
NBName = NXCopyStringBufferFromZone([name valueAt:0],[self zone]);
for (p = NBName; *p; p++)
*p = NXToUpper(*p);
[nbname insertValue:NBName];
[textNetbiosname setStringValue:NBName];
NXZoneFree([self zone], NBName);
}
// Set up the alias browser and text.
[browserAliases setDelegate:self];
[browserAliases setAction:@selector(selectAlias:)];
[browserAliases loadColumnZero];
[textAliases setTextDelegate:self];
[textRootDirectory setTextDelegate:self];
[textPrivateDirectory setTextDelegate:self];
// Select the top field.
[textHostname selectText:self];
return self;
}
// ************************************************************************
// Actions:
- addAlias:sender
{
const char *v;
int i;
NIProperty *prop;
const ni_namelist *values;
if (!(prop = [ni_dirObj property:H_NAME]))
return 0;
values = [prop valueList];
v = [textAliases stringValue];
if (values->ni_namelist_len) {
for (i = 1; i < values->ni_namelist_len; i++)
if (!strcasecmp(values->ni_namelist_val[i], v)) {
[[browserAliases matrixInColumn:0] selectCellAt:i-1 :0];
return self;
} else if (strcasecmp(values->ni_namelist_val[i], v) > 0)
break;
[prop insertValue:v at:i--];
[window setDocEdited:YES];
[browserAliases reloadColumn:0];
[[browserAliases matrixInColumn:0] selectCellAt:i :0];
[textAliases selectText:self];
}
return self;
}
- removeAlias:sender
{
int i;
NIProperty *prop;
const ni_namelist *values;
id cell = [browserAliases selectedCell];
if (!cell || !(prop = [ni_dirObj property:H_NAME]))
return self;
values = [prop valueList];
i = ni_namelist_match(*values, [[browserAliases selectedCell] stringValue]);
if ((i != NI_INDEX_NULL) && (i > 0)) { // Must not delete the name!
[prop deleteValue:i];
[window setDocEdited:YES];
[browserAliases reloadColumn:0];
i-= 2; // The browser starts with value index 1!
if (i > 0)
[[browserAliases matrixInColumn:0] selectCellAt:i :0];
else if (values->ni_namelist_len)
[[browserAliases matrixInColumn:0] selectCellAt:0 :0];
}
return self;
}
- setNetBoot:sender
{
BOOL edited = [window isDocEdited];
int signal;
char *bootFile = NXCopyStringBufferFromZone([textKernel stringValue],[self zone]),
*bootParms1 = NXCopyStringBufferFromZone([textRootDirectory stringValue],[self zone]),
*bootParms2 = NXCopyStringBufferFromZone([textPrivateDirectory stringValue],[self zone]);
[textKernel selectText:self];
// Run a modal for the panel.
signal = [NXApp runModalFor:panel];
[panel close];
switch (signal) {
case NX_RUNABORTED:
// Restore to previos values
[[ni_dirObj property:H_BOOTFILE] updateProperty:bootFile default:(!bootFile || !*bootFile)];
[textKernel setStringValue:bootFile];
[textRootDirectory setStringValue:bootParms1];
[textPrivateDirectory setStringValue:bootParms2];
[window setDocEdited:edited];
break;
case NX_RUNSTOPPED:
default: ;
}
NXZoneFree([self zone], bootFile);
NXZoneFree([self zone], bootParms1);
NXZoneFree([self zone], bootParms2);
return self;
}
// Actions from the Net Boot configuration panel
- configOK:sender
{
[NXApp stopModal];
[self setBootParms];
return self;
}
- configCancel:sender
{
[NXApp abortModal];
return self;
}
// ************************************************************************
// Delegates:
- (BOOL)textWillEnd:textObject
{
const char *alert = NULL,
*path = [[textObject superview] stringValue],
*p = strchr(path,':');
if ([textObject superview] == textRootDirectory)
alert = getString("Alert:Invalid root directory.");
else if ([textObject superview] == textPrivateDirectory)
alert = getString("Alert:Invalid private directory.");
// Accept the empty input and check for ':/'.
if (alert && path && *path && ((p && (*(p+1) != '/')) || !p)) {
NXRunAlertPanel(getString("Alert:Alert"), alert, getString("Button:OK"), NULL, NULL);
return YES;
}
return NO;
}
- textDidEnd:textObject endChar:(unsigned short)whyEnd
{
if (([textObject superview] == textAliases) && (whyEnd == NX_RETURN))
[self addAlias:self];
return self;
}
- (int) browser:sender fillMatrix:matrix inColumn:(int) column
{
NIProperty *prop;
const ni_namelist *values;
int rows = 0, i = 0;
id cell;
if (!(prop = [ni_dirObj property:H_NAME])) // Can be called before ni_dirObj is set.
return 0;
if ([prop index] == NI_INDEX_NULL)
return 0;
values = [prop valueList];
for (i = 1; i < values->ni_namelist_len; i++) {
[matrix addRow];
cell = [matrix cellAt:rows :0];
[cell setStringValue:values->ni_namelist_val[i]];
[cell setLoaded:YES];
[cell setLeaf:YES];
rows++;
}
return rows;
}
@end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.