home *** CD-ROM | disk | FTP | other *** search
- /*
- 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
-