/***********************************************************************/
/*********************************************************************
* This software is Copyright (C) 1988 by Steven Dorner and the
* University of Illinois Board of Trustees, and by CSNET. No warranties of
* any kind are expressed or implied. No support will be provided.
* This software may not be redistributed without prior consent of CSNET.
* You may direct questions to
[email protected].
**********************************************************************/
/***********************************************************************
* This is a client program for CSO's nameserver. It attempts to contact
* the nameserver running on garcon.cso.uiuc.edu, and query it about
* entries. The following entries in /etc/hosts (if you're using one) and
* /etc/services will help matters:
*
* /etc/hosts:
* 128.174.5.58 garcon.cso.uiuc.edu garcon
*
* /etc/services:
* ns 105/tcp ns # CSO nameserver
*************************************************************************/
#ifdef VMS
/*
P H for V A X / V M S
Ported to VAX/VMS Version 5.3 using VAXC 3.2 and TGV MultiNet 3.0
by Mark Sandrock, UIUC School of Chemical Sciences Computing Services
and R. Kevin Oberman, Lawrence Livermore National Laboratory.
VMS 4.4 implementation notes:
1) VAXCRTL does not supply the following routines used by PH:
a) fork -- SYS$CREPRC or LIB$SPAWN should be used instead.
b) execlp -- VAXCRTL does provide execl, but it is too limited.
c) popen/pclose -- VAXCRTL does provide "pipe" instead.
d) index/rindex -- VAXCRTL "strchr/strrchr" functions are equivalent.
e) getpass -- implemented in this file.
f) unlink -- VAXCRTL does provide "delete" function.
2) VAX/VMS does not provide the following utilities used by PH:
a) /usr/ucb/more -- VMS PH does not do paging yet.
b) /usr/ucb/vi -- EDT or TPU should be used instead.
3) The VAXCRTL "getenv" function does not recognize the following
environment names. SYS$TRNLNM could be used instead, if need be:
a) PAGER: specifies "pager" other than the default (TYPE/PAGE).
b) EDITOR: specifies editor other than the default (EDT).
4) The SOCKET INTERFACE implemented by TGV MultiNet 3.0 returns
a channel number rather than a standard file descriptor, and thus
is not compatible with the UNIX-style i/o functions such as fdopen,
read and write. Instead MultiNet provides special versions of read/
write called socket_read/socket_write for network i/o.
5) The VMS VAXC include files are used wherever possible, with several
exceptions as noted in the MultiNet Programmer's Guide. The following
include files do not exist under VMS VAXC 3.2 and were simply copied
over from uxc (4.3 bsd):
a) #include <sgtty.h>
b) #include <syslog.h>
Change log:
05-May-1988 12:09 MTS Initial port of ph.c,v 2.15 to vms_ph.c.
Initial port of cryptit.c to vms_cryptit.c.
13-Feb-1991 16:08 MTS Has it really been that long? Re-ported
ph v4.10 under VMS 5.3 and WIN/TCP 5.1.
15-Oct-1991 14:44 RKO Modified for MultiNet V3.0.
/*
***************************************************************************/
static char *rcsid = "VAX/VMS: ph.c,v 4.10 91/10/15 14:44:00 sandrock-oberman";
#include stdio
#include signal
#include "multinet_root:[multinet.include.sys]types.h"
#include "multinet_root:[multinet.include.sys]socket.h"
#include file
#include stat
#include "multinet_root:[multinet.include.netinet]in.h"
#include "multinet_root:[multinet.include]netdb.h"
#include ctype
/* #include <strings.h> */
#include descrip /* VMS descriptor structures defs */
#include iodef /* VMS I/O function definitions */
#include ssdef /* VMS System Status definitions */
#include ttdef /* VMS terminal characteristics */
#include "termdefs.h" /* VMS defs for setterm() function */
#else
static char *rcsid = "$Date: 91/02/06 07:24:53 $$Revision: 4.10 $";
static char *srcid = "$Source: /nameserv/Src/Ph/RCS/ph.c,v $";
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <ctype.h>
#include <strings.h>
#ifdef hpux
#include <memory.h>
#define bcopy(source,dest,count) memcpy(dest,source,count)
#define index(string,ch) strchr(string,ch)
#define rindex(string,ch) strrchr(string,ch)
#else
#ifndef NeXT
void bcopy();
#endif
#endif
#endif
#include "replies.h"
/***********************************************************************
* vital defines
***********************************************************************/
#define MAXSTR 2048 /* max string length */
#define MAXVAL 14000 /* max value length */
#define DELIM " \t\n"/* command delimiters */
#define MAXARGS 20 /* maximum # of arguments in PH environ var. */
/***********************************************************************
* declarations for a couple of useful functions
***********************************************************************/
char *GetValue();
char *strtok();
char *getenv();
#ifdef VMS
char *strchr(); /* VMS equivalent of "index" */
char *strrchr(); /* VMS equivalent of "rindex" */
#define index(a,b) strchr(a,b)
#define rindex(a,b) strrchr(a,b)
#define GetQValue(aLine) \
(strchr(strchr(aLine,':')+1,':')+1)
#else
FILE *popen();
#define GetQValue(aLine) \
(index(index(aLine,':')+1,':')+1)
#endif
char *malloc();
char *getpass();
void exit(), free(), perror();
char *makestr();
/************************************************************************
* declarations for the functions in this file
************************************************************************/
int main();
char *issub();
int ContactQI();
int DoId();
int PrintResponse();
int GetGood();
void EnvOptions();
void ComplainAboutService();
void ComplainAboutHost();
void Interactive();
int DoCommand();
int DoOtherWPage();
int DoOther();
#ifdef MACC
int DoFields();
#endif
int DoHelp();
int DoQuery();
int DoLogin();
int DoQuit();
int DoEdit();
int DoMake();
int EditValue();
int UpdateValue();
int DoFields();
int DoMe();
int DoPassword();
int DoLogout();
void VetPassword();
int AllDigits();
int PrintQResponse();
/* void DoAutoLogin(); */
void SkipMacdef();
/* int TryLogin(); */
void EmailLine();
void NotRegisteredLine();
FILE *OpenPager();
int DoSwitch();
/***********************************************************************
* These are external for convenience' sake
***********************************************************************/
#ifdef MACC_ECHO
int maccecho =0;
#endif
#ifdef VMS
int ToQI; /* write to this to tell the nameserver stuff */
int FromQI; /* read nameserver responses from here */
char ToQIBuf[MAXSTR];
int ToQILen;
#define qprintf \
{ \
char *ToQI=ToQIBuf; \
sprintf
#define qflush(foobar) \
ToQILen = strlen(ToQIBuf); \
} \
socket_write(ToQI,ToQIBuf,ToQILen)
#else
FILE *ToQI; /* write to this to tell the nameserver stuff */
FILE *FromQI; /* read nameserver responses from here */
#define qprintf fprintf
#define qflush fflush
#endif
char MyAlias[MAXSTR]; /* currently logged-in alias */
char *Me; /* the name of this program */
char *MyPassword=NULL; /* password read from .netrc (if any) */
/************************************************************************
* switches
************************************************************************/
int NoNetrc = 0; /* -n don't read .netrc */
char *UseHost = 0; /* -s use server on what machine */
int UsePort = 0; /* -p use port # */
int NoReformat=1; /* -i don't reformat email fields */
int NoPager=0; /* -m don't use pager */
int NoBeautify=0; /* -b don't beautify output */
int NoLabels=0; /* -l don't use labels */
int Confirm=0; /* -c confirm Edit */
char *DefType=0; /* -t prepend this type to queries */
char *ReturnFields=NULL;/* -f give list of fields */
/***********************************************************************
* and the fun begins...
***********************************************************************/
int main(argc, argv)
int argc;
char **argv;
{
int theCode=LR_ERROR;
int optionsCount;
char buffer[4096];
#ifdef MACC_ECHO
int margc=0;
#endif
#ifdef VMS
char *temps; /* temp strings */
#endif
/*
* figure out what this program is called
*/
#ifdef VMS
Me = " ph";
#else
Me = rindex(*argv,'/');
#endif
if (Me)
Me++;
else
Me = *argv;
EnvOptions(CLIENT);
if (strcmp(CLIENT,Me))
{
sprintf(buffer,"-t %s",Me);
(void) OptionLine(buffer);
EnvOptions(Me);
}
optionsCount = ProcessOptions(--argc,++argv);
argc -= optionsCount;
argv += optionsCount;
if (!ContactQI())
{
fputs("Sorry--phone book not available now.\n", stderr);
#ifdef VMS
exit(SS$_CONNECFAIL);
#else
exit(1);
#endif
}
/*
* identify ourselves
*/
if ((theCode=DoId())>=400) exit(theCode/100);
if (argc==0)
Interactive(); /* no arguments--interactive mode */
else
{
/* make a query out of the arguments */
strcpy(buffer,"query ");
for (; argc; argc--, argv++)
{
strcat(buffer,*argv);
if (argc > 1)
strcat(buffer," ");
}
strcat(buffer,"\n");
theCode = DoCommand(buffer);
qprintf(ToQI,"\nquit\n");
qflush(ToQI);
}
#ifdef VMS
exit(SS$_NORMAL);
#else
exit(theCode > 299 ? theCode/100 : 0);
#endif
}
/***********************************************************************
* contact the central nameserver
***********************************************************************/
int ContactQI()
{
int sock; /* our socket */
static struct sockaddr_in QI; /* the address of the nameserver */
struct servent *theNs; /* nameserver service entry */
static struct hostent *theHost; /* host entry for nameserver */
char host[80];
char *baseHost;
int backupNum=0;
int mightBackup;
/* create the socket */
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0)
return (0);
QI.sin_family = AF_INET;
/* find the proper port */
if (UsePort)
QI.sin_port = UsePort;
else if (theNs = getservbyname(NSSERVICE, "tcp"))
{
QI.sin_port = theNs->s_port;
}
else
{
ComplainAboutService();
QI.sin_port = htons(FALLBACKPORT);
}
/* find the proper host */
baseHost = UseHost ? UseHost : HOST;
if (mightBackup=(*baseHost=='.'))
sprintf(host,"%s%s",NSSERVICE,baseHost);
else
strcpy(host,baseHost);
for (;;)
{
/* create the socket */
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock < 0)
return (0);
QI.sin_family = AF_INET;
if (theHost = gethostbyname(host))
{
bcopy(theHost->h_addr, (char *) &QI.sin_addr.s_addr, 4);
}
else if (!backupNum)
{
ComplainAboutHost(host);
QI.sin_addr.s_addr = htonl(FALLBACKADDR);
theHost = gethostbyaddr(&QI.sin_addr.s_addr, 4, AF_INET);
}
else
{
fprintf(stderr,"No more backups to try.\n");
return(0);
}
/* connect to the nameserver */
if (connect(sock, (struct sockaddr *)&QI, sizeof(QI)) < 0)
{
perror(host);
if (mightBackup)
{
backupNum++;
sprintf(host,"%s%d%s",NSSERVICE,backupNum,baseHost);
}
else
return (0);
}
else break;
}
if (backupNum)
fprintf(stderr,"WARNING--backup host %s; information may be out of date.\n",host);
/* open path to nameserver */
#ifdef VMS
ToQI = sock; /* copy socket channel for netwrite calls */
FromQI = sock; /* ditto for netread calls */
#else
if ((ToQI = fdopen(sock, "w")) == NULL)
{
perror("to qi");
return (0);
}
/* open path from nameserver */
if ((FromQI = fdopen(sock, "r")) == NULL)
{
perror("from qi");
return (0);
}
#endif
UseHost = theHost->h_name;
UsePort = QI.sin_port;
return (1);
}
/***********************************************************************
* identify ourselves to the nameserver
***********************************************************************/
int DoId()
{
qprintf(ToQI,"id %d\n",getuid());
qflush(ToQI);
return (PrintResponse(-1));
}
/***********************************************************************
* print what the QI (Query Interpreter; nameserver) says
* read replies from nameserver until code indicates a completed
* command. This routine does not beautify the responses in any way.
* if doPaging is 1, the pager will be used.
* if doPaging is 0, no pager will be used.
* if doPaging is -1, the response will not be printed at all.
***********************************************************************/
int PrintResponse(doPaging)
int doPaging; /* use the pager? */
{
char scratch[MAXSTR]; /* some space */
int code=LR_ERROR; /* the reply code */
FILE *theOutput;
theOutput = OpenPager(doPaging);
while (GetGood(scratch, MAXSTR, FromQI)) /* read it */
{
code = atoi(scratch);
if (doPaging!= -1 || code>=400) fputs(scratch, theOutput); /* echo it */
if (code >= LR_OK)
break;
}
#ifdef VMS
#else
if (theOutput != stdout)
pclose(theOutput);
#endif
return (code); /* all done. return final code */
}
/***********************************************************************
* get a non-comment line from a stream
* a comment is a line beginning with a # sign
***********************************************************************/
int GetGood(theString, maxChars, theFile)
char *theString; /* space to put the chars */
int maxChars; /* max # of chars we want */
#ifdef VMS
int theFile; /* stream to read them from */
{
static char Qbuf [MAXSTR+4] = { '\0' } ;
static int pos = {0}, end = {0}, len = {0}, tend = {0};
char *linp;
for (;;)
{
if (pos >= len)
{
len = socket_read(theFile,Qbuf,maxChars);
if (len <= 0) return (0);
Qbuf [len] = '\0';
pos = 0;
}
linp = index(Qbuf+pos, '\n'); /* find next newline char */
if (linp == NULL)
{
strncpy(theString, Qbuf+pos, len-pos+1); /* Copy what we have */
end = len-pos; /* no newline chars left */
pos = 0; /* Start at the beginning */
len = socket_read(theFile,Qbuf,maxChars);
if (len <= 0) return (0);
Qbuf [len] = '\0';
linp = index(Qbuf, '\n');
strncpy(theString+end, Qbuf, linp-Qbuf+1);
tend = linp + end - Qbuf;
*(theString+tend-pos+1) = '\0';
end = tend - end;
}
else
{
end = linp - Qbuf; /* convert pointer to index */
strncpy(theString, Qbuf+pos, end-pos+1);
*(theString+end-pos+1) = '\0';
}
pos = end + 1; /* save new position for next time */
#else
FILE *theFile; /* stream to read them from */
{
for (;;)
{
(void) fgets(theString, maxChars, theFile);
#endif
if (*theString != '#')
return (1); /* not a comment; success! */
else
if (!*theString)
return (0); /* empty string==end of stream */
}
}
/***********************************************************************
* complain that there isn't an entry for ns in /etc/services
***********************************************************************/
void ComplainAboutService()
{
fprintf(stderr, "Warning--there is no entry for ``%s'' in /etc/services;\n",
NSSERVICE);
fputs("please have your systems administrator add one.\n", stderr);
fprintf(stderr, "I'm going to use port %d in the meantime.\n", FALLBACKPORT);
}
/***********************************************************************
* complain that there isn't an entry for garcon in /etc/hosts
***********************************************************************/
void ComplainAboutHost(name)
char *name;
{
fprintf(stderr, "Warning--unable to find address for ``%s''.\n",
name);
fprintf(stderr, "I'm going to use address 0x%x in the meantime.\n",
FALLBACKADDR);
}
/***********************************************************************
* the interactive portion of the client
***********************************************************************/
typedef struct command Command;
struct command
{
char *cName; /* the name of the command */
int cLog; /* must be logged in to use? */
int (*cFunc) (); /* function to call for command */
};
Command CommandTable[] =
{
"help", 0, DoHelp,
"?", 0, DoHelp,
"query", 0, DoQuery,
#ifndef MACC
CLIENT, 0, DoQuery,
"me", 1, DoMe,
"edit", 1, DoEdit,
"make", 1, DoMake,
"password", 1, DoPassword,
"passwd", 1, DoPassword,
"login", 0, DoLogin,
"logout", 1, DoLogout,
#endif
#ifdef MACC
"fields", 0, DoFields,
#else
"fields", 0, DoOtherWPage,
"switch", 0, DoSwitch,
#endif
#ifndef MACC
"add", 1, DoOther,
"delete", 1, DoOther,
"set", 0, DoOther,
#endif
"quit", 0, DoQuit,
"bye", 0, DoQuit,
"exit", 0, DoQuit,
0, 0, 0
};
/***********************************************************************
* the main loop
***********************************************************************/
int LastCode = 0; /* the response from the previous command */
void Interactive()
{
char inputLine[MAXSTR]; /* space for an input line */
char *spot;
*MyAlias = 0; /* nobody logged in yet... */
#ifndef MACC
puts(rcsid);
/* printf("Send mail to %s to get your password (see \"help password\").\n",PASSW); */
printf("Mail other questions or comments to %s.\n",ADMIN);
#else
printf("Lookup - ELECTRONIC MAIL DIRECTORY SERVICE\n\n");
printf("Please mail questions or comments to %s.\n",ADMIN);
#endif
/*
* print database status
*/
LastCode = DoOther("status\n",0);
/*
* autologin if possible
*/
/* #ifndef MACC
if (!NoNetrc) DoAutoLogin();
#endif */
puts(" ");
while (1)
{
(void) signal(SIGPIPE,SIG_IGN);
#ifdef MACC_ECHO
if (!maccecho)
printf("%s> ",Me);
#else
printf("%s> ",Me);
#endif
(void) fflush(stdout); /* prompt */
spot=inputLine;
do {
if (!fgets(spot, MAXSTR-(spot-inputLine), stdin))
return; /* read line */
spot = inputLine + strlen(inputLine)-2;
if (*spot=='\\') *spot++ = ' ';
else spot=inputLine-1;
}
while (spot>=inputLine);
#ifdef MACC_ECHO
if (maccecho)
printf("%s> %s",Me,inputLine);
#endif
if (!(LastCode=DoCommand(inputLine))) /* is it a command we know? */
LastCode = DoOther(inputLine); /* unrecognized command */
}
}
/***********************************************************************
* look at input line, and if we have a specific command for it, do it
***********************************************************************/
int DoCommand(inputLine)
char *inputLine; /* the input line */
{
char scratch[MAXSTR]; /* some space */
char *theToken; /* a token from the command line */
Command *theCommand; /* the command name */
Command *doMe;
int len;
/* make a safe copy of the input line, so we can play with it */
strcpy(scratch, inputLine);
if (!(theToken = strtok(scratch, DELIM)))
return (LR_ERROR); /* blank line */
/* search command table linearly */
doMe = NULL;
len = strlen(theToken);
for (theCommand = CommandTable; theCommand->cName; theCommand++)
if (!strncmp(theCommand->cName, theToken, len))
{
if (doMe) /* we found 2 commands that match (bad) */
{
printf("%s is ambiguous.\n", theToken);
return (LR_ERROR);
}
doMe = theCommand; /* we found a command that matches */
}
if (doMe) /* found one and only one command */
{
/* expand command name */
theToken = strtok((char *)0, "\n");
sprintf(inputLine, "%s %s\n", doMe->cName, theToken ? theToken : "");
/* execute command */
if (doMe->cLog && !*MyAlias)
printf("You must be logged in to use %s.\n",doMe->cName);
else
return((*doMe->cFunc) (inputLine));
return (LR_ERROR);
}
return (0); /* didn't find it */
}
/***********************************************************************
* execute a command for which we do nothing special; use the pager
***********************************************************************/
int DoOtherWPage(inputLine)
char *inputLine;
{
qprintf(ToQI,"%s",inputLine); /* send command */
qflush(ToQI);
return (PrintResponse(1)); /* get response */
}
/***********************************************************************
* execute a command for which we do nothing special; don't use pager
***********************************************************************/
int DoOther(inputLine)
char *inputLine;
{
qprintf(ToQI,"%s",inputLine); /* send command */
qflush(ToQI);
return (PrintResponse(0)); /* get response */
}
#ifdef MACC
int DoFields(inputLine)
char *inputLine;
{
printf("Field Name Description\n");
printf("------------------------------\n");
printf("name Person Name\n");
printf("email Electronic Mail Address if exists\n");
printf("phone Telephone Number One\n");
printf("phone2 Telephone Number Two\n");
printf("address Street Address of the Building\n");
printf("building Building Name\n");
printf("department Department Number One of Person\n");
printf("department2 Department number Two of Person\n");
printf("appointment Appointment Classification Code Number One \n");
printf("appointment2 Appointment Classification Code Number Two\n");
printf("title Title One\n");
printf("title2 Title Two\n");
printf("alias Unique Name built from First Letter of First Name, Last\n");
printf(" Name and a Number\n\n");
return(LR_OK);
}
#endif
/***********************************************************************
* execute a query request
***********************************************************************/
int DoQuery(inputLine)
char *inputLine;
{
char scratch[4096];
char *args;
int noReformatWas = NoReformat;
int code;
if (ReturnFields && !issub(inputLine,"return"))
{
args=inputLine+strlen(inputLine)-1;
sprintf(args," return %s\n",ReturnFields);
for (;*args;args++) if (*args==',') *args=' ';
}
if (!NoBeautify && !NoReformat)
{
char *ret = issub(inputLine,"return");
if (ret) NoReformat = !issub(ret,"email");
}
if (!DefType || issub(inputLine,"type="))
{
qprintf(ToQI,"%s",inputLine); /* send command */
qflush(ToQI);
}
else
{
strcpy(scratch,inputLine);
args = strtok(scratch," \t");
args = strtok(0,"\n");
if (args)
{
qprintf(ToQI,"query type=\"%s\" %s\n",DefType,args); /* send command */
qflush(ToQI);
}
else
{
qprintf(ToQI,"%s",inputLine);
qflush(ToQI);
}
}
code = (NoBeautify ? PrintResponse(1) : PrintQResponse(1,0));
NoReformat = noReformatWas;
return (code);
}
/***********************************************************************
* execute a login request
***********************************************************************/
int DoLogin(inputLine)
char *inputLine;
{
char encryptMe[MAXSTR]; /* string from nameserver */
char encrypted[MAXSTR]; /* string from ns, encrypted */
char *password; /* user's nameserver password */
int code;
char scratch[MAXSTR];
strcpy(scratch,inputLine);
(void) strtok(scratch,DELIM); /* the login part of the command */
if (!strtok(0,DELIM)) /* check for an alias */
{
printf("Enter nameserver alias: "); /* ask for missing alias */
fgets(scratch,sizeof(scratch),stdin);
if (!*scratch) return(LR_ERROR);
sprintf(inputLine,"login %s",scratch);
}
qprintf(ToQI,"%s",inputLine); /* send login request */
qflush(ToQI);
for (;;) /* read the response */
{
if (!GetGood(encryptMe, MAXSTR, FromQI))
{
fprintf(stderr, "Whoops--the nameserver died.\n");
exit(1);
}
code = atoi(encryptMe);
if (code != LR_LOGIN) /* intermediate or strange response */
fputs(encryptMe, stdout);
if (code >= LR_OK) /* final response */
break;
}
if (code == LR_LOGIN)
{
/* the nameserver has issued a challenge */
password = MyPassword ? MyPassword :
getpass("Enter nameserver password: ");
crypt_start(password);
/* encrypt the challenge with the password */
encryptMe[strlen(encryptMe) - 1] = '\0'; /* strip linefeed */
encrypted[encryptit(encrypted, index(encryptMe, ':') + 1)] = '\0';
/* send the encrypted text to qi */
qprintf(ToQI, "answer %s\n", encrypted);
qflush(ToQI);
/* get the final response */
for (;;)
{
if (!GetGood(encryptMe, MAXSTR, FromQI))
{
fprintf(stderr, "Whoops--the nameserver died.\n");
exit(1);
}
code = atoi(encryptMe);
fputs(encryptMe, stdout);
if (code >= LR_OK) /* final response */
break;
}
}
if (code == LR_OK) /* logged in */
{
strcpy(MyAlias, index(encryptMe, ':') + 1);
*index(MyAlias, ':') = '\0';
VetPassword(password); /* make sure password is reasonable */
}
else
*MyAlias = '\0';
return(code);
}
/***********************************************************************
* execute a quit request
***********************************************************************/
int DoQuit(inputLine)
char *inputLine;
{
DoOther("quit\n");
#ifdef VMS
exit(SS$_NORMAL);
#else
exit(LastCode<LR_OK || LastCode >=LR_MORE ? LastCode/100 : 0);
#endif
}
/***********************************************************************
* edit a field
***********************************************************************/
int DoEdit(inputLine)
char *inputLine;
{
char *theField;
char *theAlias;
char *theValue;
int theCode=LR_OK;
char confirm[10];
(void) strtok(inputLine, DELIM); /* skip ``edit'' */
if (!(theField = strtok((char *) 0, DELIM)))
{
(void) DoCommand("help edit\n");
return(LR_ERROR);
}
if (!(theAlias = strtok((char *) 0, DELIM)))
theAlias = MyAlias;
if ((theValue = GetValue(theAlias, theField)) && EditValue(theValue))
{
for (theCode=UpdateValue(theAlias,theField,theValue);
400<=theCode && theCode<=499;
theCode=UpdateValue(theAlias,theField,theValue))
{
if (!isatty(0)) break;
printf("Shall I try again [y/n]? ");
fgets(confirm,sizeof(confirm),stdin);
if (*confirm!='y' && *confirm!='Y') break;
}
if (theCode<300 && !strcmp(theField,"alias"))
strcpy(MyAlias,theValue);
}
return(theCode);
}
/***********************************************************************
* get the value of a field from the nameserver
***********************************************************************/
char *GetValue(theAlias, theField)
char *theAlias;
char *theField;
{
static char theValue[MAXVAL]; /* will hold the value */
char *vSpot;
char scratch[MAXSTR];
int code;
if (!strcmp(theField, "password"))
{
puts("Use the ``password'' command, not edit.");
return (NULL);
}
/* do the query */
qprintf(ToQI, "query alias=%s return %s\n", theAlias, theField);
qflush(ToQI);
*theValue = '\0';
/* read qi response lines, concatenating the responses into one value */
for (vSpot = theValue;; vSpot += strlen(vSpot))
{
if (!GetGood(scratch, MAXSTR, FromQI))
{
fprintf(stderr, "Ding-dong the server's dead!\n");
exit(0);
}
if ((code = atoi(scratch)) == -LR_OK)
strcpy(vSpot, index(GetQValue(scratch), ':') + 2); /* part of value */
else
if (code >= LR_OK)
break; /* final response */
else
fputs(scratch, stdout); /* ??? */
}
if (code != LR_OK) /* error */
fputs(scratch, stdout);
return (code == LR_OK ? theValue : NULL);
}
/***********************************************************************
* Edit a value
***********************************************************************/
int EditValue(theValue)
char *theValue; /* the value to edit */
{
char *theFileName; /* name of temp file to use */
char *mktemp();
#ifdef VMS
struct dsc$descriptor_s cli_input;
char template[28], f1[28], f2[28], edit_command[64];
int istat;
#else
char template[20];
#endif
int fd; /* file descriptor for temp file */
static char newValue[MAXVAL]; /* new value */
char *editor; /* editor program to use */
int bytes; /* numnber of bytes in file */
register char *from, *to;
int badChar; /* did we find a bad character? */
int junk;
char scratch[80];
/* put the value into a temp file */
#ifdef VMS
strcpy(template, "SYS$SCRATCH:PHXXXXXX.TMP");
theFileName = mktemp(template);
strcpy (f1, theFileName);
strcpy (f2, theFileName);
strcat (f1, ";1"); /* versions needed for delete function */
strcat (f2, ";2");
if ((fd = creat(theFileName, 0)) < 0)
#else
strcpy(template, "/tmp/phXXXXXX");
theFileName = mktemp(template);
if ((fd = open(theFileName, O_RDWR | O_CREAT, 0777)) < 0)
#endif
{
perror(theFileName);
return (0);
}
if (write(fd, theValue, strlen(theValue)) < 0)
{
perror(theFileName);
(void) close(fd);
return (0);
}
(void) close(fd);
/* run an editor on the temp file */
#ifdef VMS
if (!(editor = getenv("EDITOR")))
editor = "EDIT/TPU";
strcpy(edit_command, editor);
strcat(edit_command, " ");
strcat(edit_command, theFileName);
cli_input.dsc$w_length = strlen(edit_command); /* descriptor for spawn */
cli_input.dsc$a_pointer = edit_command;
cli_input.dsc$b_class = DSC$K_CLASS_S;
cli_input.dsc$b_dtype = DSC$K_DTYPE_T;
if( (istat = LIB$SPAWN(&cli_input)) != SS$_NORMAL )
{
(void) delete (f1);
exit(istat);
}
#else
if (!(editor = getenv("EDITOR")))
#ifdef hpux
editor = "/usr/bin/vi";
#else
editor = "/usr/ucb/vi";
#endif
if (fork())
(void) wait((union wait *)&junk);
else
{
(void) execlp(editor, editor, theFileName, NULL);
fprintf(stderr,"Whoops! Failed to exec %s\n",editor);
exit(1);
}
#endif
/* does the user want the value? */
if (Confirm)
{
do
{
printf("Change the value [y]? ");
gets(scratch);
}
while (*scratch && !index("yYnN",*scratch));
}
/* read the value back out */
if ((fd = open(theFileName, 0)) < 0)
{
perror(theFileName);
#ifdef VMS
#else
(void) unlink(theFileName);
#endif
return (0);
}
#ifdef VMS
#else
(void) unlink(theFileName);
#endif
if ((bytes = read(fd, newValue, MAXSTR - 1)) < 0)
{
perror(theFileName);
(void) close(fd);
#ifdef VMS
(void) delete (f1); /* delete 1st temp file */
(void) delete (f2); /* delete 2nd temp file */
#endif
return (0);
}
(void) close(fd);
#ifdef VMS
(void) delete (f1); /* delete 1st temp file */
(void) delete (f2); /* delete 2nd temp file */
#endif
newValue[bytes] = 0;
/* did the value change? */
if (Confirm && *scratch && *scratch!='y' && *scratch!='Y' ||
!strcmp(newValue, theValue))
return (0);
/* copy new value into old, stripping bad characters */
badChar = 0;
for (to = theValue, from = newValue; *from; from++)
if (*from == '"')
{
*to++ = '\\';
*to++ = '"';
}
else
if (*from >= ' ' && *from <= '~')
*to++ = *from;
else
if (*from == '\t')
{
*to++ = '\\';
*to++ = 't';
}
else
if (*from == '\n')
{
if (*(from + 1)) /* skip terminating newline from vi */
{
*to++ = '\\';
*to++ = 'n';
}
}
else
badChar = 1;
*to = 0;
if (badChar) /* complain if we found bad characters */
{
fputs("Illegal characters were found in your value.\n", stderr);
fputs("Please use only printable characters, newlines, and tabs.\n", stderr);
fputs("The offending characters were removed.\n", stderr);
}
return (1);
}
/***********************************************************************
* update a nameserver field with a new value
***********************************************************************/
int UpdateValue(theAlias, theField, theValue)
char *theAlias;
char *theField;
char *theValue;
{
qprintf(ToQI, "change alias=%s make %s=\"%s\"\n", theAlias, theField, theValue);
qflush(ToQI);
return(PrintResponse(0));
}
/***********************************************************************
* print info on current user
***********************************************************************/
/*ARGSUSED*/
int DoMe(inputLine)
char *inputLine;
{
if (!*MyAlias)
{
return(DoHelp("help me"));
}
qprintf(ToQI, "query alias=%s return all\n", MyAlias);
qflush(ToQI);
return(NoBeautify ? PrintResponse(0) : PrintQResponse(0,0));
}
/***********************************************************************
* set command-line switches
***********************************************************************/
int DoSwitch(inputLine)
char *inputLine;
{
inputLine = strtok(inputLine,DELIM);
if (!OptionLine(strtok(0,"\n")))
{
printf("The following things can be changed with \"switch\":\n\n");
printf(" Paging is %s; use \"switch -%c\" to turn it %s.\n",
NoPager ? "OFF" : "ON",
NoPager ? 'M' : 'm',
NoPager ? "on" : "off");
printf(" Email reformatting is %s; use \"switch -%c\" to turn it %s.\n",
NoReformat ? "OFF" : "ON",
NoReformat ? 'R' : 'r',
NoReformat ? "on" : "off");
printf(" Query beautification is %s; use \"switch -%c\" to turn it %s.\n",
NoBeautify ? "OFF" : "ON",
NoBeautify ? 'B' : 'b',
NoBeautify ? "on" : "off");
printf(" Label printing is %s; use \"switch -%c\" to turn it %s.\n",
NoLabels ? "OFF" : "ON",
NoLabels ? 'L' : 'l',
NoLabels ? "on" : "off");
printf(" Edit confirmation is %s; use \"switch -%c\" to turn it %s.\n",
Confirm ? "ON" : "OFF",
Confirm ? 'c' : 'C',
Confirm ? "off" : "on");
printf(" Default entry type is %s; use \"switch -%c%s\" to %s %s.\n",
DefType ? DefType : "OFF",
DefType ? 'T' : 't',
DefType ? "" : " name-of-type",
DefType ? "turn it" : "set it to",
DefType ? "off" : "\"name-of-type\"");
printf(" Default field list is %s; use \"switch -%c%s\" to %s to %s.\n",
ReturnFields ? ReturnFields : "default",
ReturnFields ? 'F' : 'f',
ReturnFields ? "" : " field1,field2,... ",
ReturnFields ? "revert" : "set it",
ReturnFields ? "default" : "\"field1,field2,...\"");
printf("\nThe following things cannot be changed with \"switch\":\n\n");
printf(" Connected to server %s at port %d\n", UseHost,UsePort);
printf(" The .netrc file was %sread.\n", NoNetrc ? "not " : "");
}
return(LR_OK);
}
/***********************************************************************
* change a field value from the command line
***********************************************************************/
int DoMake(inputLine)
char *inputLine;
{
int theCode=LR_ERROR;
if (!*MyAlias)
DoHelp("help make");
else
{
qprintf(ToQI,"change alias=%s %s",MyAlias,inputLine);
qflush(ToQI);
theCode = PrintResponse(0);
}
return(theCode);
}
/***********************************************************************
* change password
***********************************************************************/
int DoPassword(inputLine)
char *inputLine;
{
char password[80];
char *confirm;
char *theAlias;
int theCode=LR_ERROR;
if (!*MyAlias)
{
return(DoHelp("help password"));
}
/* which alias to use? */
(void) strtok(inputLine, DELIM);
if (!(theAlias = strtok((char *) 0, DELIM)))
theAlias = MyAlias;
/* get the password */
strcpy(password, getpass("Enter new password: "));
if (!*password) return(LR_ERROR);
confirm = getpass("Type it again: ");
if (strcmp(confirm, password))
{
fprintf(stderr, "Sorry--passwords didn't match.\n");
return(theCode);
}
VetPassword(confirm); /* complain if we don't like the password */
/* encrypt and send the password */
password[encryptit(password, confirm)] = '\0';
qprintf(ToQI, "change alias=%s make password=%s\n", theAlias, password);
qflush(ToQI);
/* see what the nameserver says */
if ((theCode=PrintResponse(0)) == LR_OK && !strcmp(theAlias,MyAlias))
crypt_start(confirm);
return(theCode);
}
/***********************************************************************
* log out the current user
***********************************************************************/
int DoLogout(inputLine)
char *inputLine;
{
*MyAlias = '\0';
return(DoOther(inputLine));
}
/***********************************************************************
* complain about passwords we don't like
***********************************************************************/
void VetPassword(thePassword)
char *thePassword;
{
if (strlen(thePassword) < 5 || /* too short */
AllDigits(thePassword)) /* digits only */
fputs("That is an insecure password; please change it.\n", stderr);
}
/***********************************************************************
* is a string all digits
***********************************************************************/
int AllDigits(theString)
register char *theString;
{
for (; *theString; theString++)
if (!isdigit(*theString))
return (0);
return (1);
}
/***********************************************************************
* print the response to a query
* this strips out all the nameserver reply codes.
***********************************************************************/
int PrintQResponse(reformatEmail,amHelping)
int reformatEmail;
int amHelping;
{
char theLine[MAXSTR];
int theCode=LR_ERROR;
int currentPerson = 0;
int thePerson;
register char *cp;
FILE *theOutput;
char nickname[MAXSTR];
char alias[MAXSTR];
char email[MAXSTR];
int copiedEmail=0;
theOutput = OpenPager(1);
*alias = *email = *nickname = 0; /* haven't found an alias or nickname yet */
if (NoReformat) reformatEmail=0;
/* get the response */
while (GetGood(theLine, MAXSTR, FromQI))
{
theCode = atoi(theLine);
if (theCode == LR_NUMRET)
{
#ifdef MACC
cp = strchr(theLine,':');
if ( cp != 0)
fprintf(theOutput,"\n%s\n",cp+1); /* strchr returns pointer to : then add one */
#endif MACC
}
else
if (theCode == -LR_OK || theCode == -LR_AINFO || theCode == -LR_ABSENT
|| theCode == -LR_ISCRYPT)
{
thePerson = atoi(index(theLine, ':') + 1);
/* output a delimiter */
if (thePerson != currentPerson)
{
if (*alias && !*email)
NotRegisteredLine(alias,theOutput);
else if (*email)
{
EmailLine(email,alias,nickname);
fputs(GetQValue(email),theOutput);
*email = 0;
}
fputs("----------------------------------------\n", theOutput);
currentPerson = thePerson;
copiedEmail=0;
}
if (reformatEmail)
{
cp = GetQValue(theLine);
while (*cp && *cp==' ') cp++;
if (!strncmp("alias",cp,5))
{
copiedEmail = 0;
strcpy(alias,theLine);
continue;
}
else if (!strncmp("email",cp,5))
{
strcpy(email,theLine);
copiedEmail = 1;
continue;
}
else if (!strncmp("nickname",cp,8))
{
copiedEmail = 0;
strcpy(nickname,theLine);
continue;
}
else if (*cp==':' && copiedEmail)
continue;
else
copiedEmail = 0;
}
/* output the line */
if (NoLabels && !amHelping)
fputs(index(GetQValue(theLine),':')+2, theOutput);
else
fputs(GetQValue(theLine), theOutput);
}
else if (theCode != LR_OK)
fputs(theLine, theOutput); /* error */
if (theCode >= LR_OK)
{
if (*alias && !*email)
NotRegisteredLine(alias,theOutput);
else if (*email)
{
EmailLine(email,alias,nickname);
/* output the line */
if (NoLabels && !amHelping)
fputs(index(GetQValue(email),':')+2, theOutput);
else
fputs(GetQValue(email), theOutput);
}
break;
}
}
/* final "delimiter" */
if (currentPerson)
fputs("----------------------------------------\n", theOutput);
#ifdef VMS
#else
if (theOutput != stdout)
(void) pclose(theOutput);
#endif
return(theCode);
}
#ifndef NeXT
/***********************************************************************
* break a string into tokens. this code is NOT lifted from sysV, but
* was written from scratch.
***********************************************************************/
/*
* function: strtok purpose: to break a string into tokens parameters:
* s1 string to be tokenized or 0 (which will use last string) s2 delimiters
* returns: pointer to first token. Puts a null after the token. returns
* NULL if no tokens remain.
*/
char *
strtok(s1, s2)
char *s1, *s2;
{
static char *old = 0;
char *p1, *p2;
if (!(s1 || old))
return (NULL);
p1 = (s1 ? s1 : old);
while (*p1 && (index(s2, *p1) != NULL))
p1++;
if (*p1)
{
p2 = p1;
while (*p2 && (index(s2, *p2) == NULL))
p2++;
if (*p2)
{
*p2 = '\0';
old = ++p2;
}
else
old = 0;
return (p1);
}
else
return (NULL);
}
#endif
#ifdef VMS
/* setterm.c
*
* module in termlib
*
* contains routines to set terminal mode
*
* V1.0 19-jul-84 P. Schleifer Initial draft
*/
setterm(characteristic, state)
long *characteristic, *state;
{
int status;
long efn;
long new_state;
short term_chan;
struct char_buff mode;
struct mode_iosb term_iosb;
$DESCRIPTOR(term_desc, "TT:");
/* get event flag */
status = lib$get_ef(&efn);
if ( status != SS$_NORMAL ) return (status);
/* get channel to terminal */
status = sys$assign(&term_desc, &term_chan, 0, 0);
if (status != SS$_NORMAL) return (status);
/* if characteristic is BROADCAST, ECHO, or TYPEAHEAD, state must be toggled */
if (*characteristic == BROADCAST || *characteristic == ECHO || *characteristic == TYPEAHEAD)
new_state = !(*state);
else
new_state = *state;
/* get current mode */
status = sys$qiow(efn, term_chan, IO$_SENSEMODE, &term_iosb, 0, 0, &mode, 12, 0, 0, 0, 0);
if (status != SS$_NORMAL || term_iosb.stat != SS$_NORMAL) { sys$dassgn(term_chan); return (status); }
/* change characteristics buffer */
if (new_state == ON)
mode.basic_char |= *characteristic;
else
mode.basic_char &= ~(*characteristic);
/* $ SET TERM/... and then deassign channel */
status = sys$qiow(efn, term_chan, IO$_SETMODE, &term_iosb, 0, 0, &mode, 12, 0, 0, 0, 0);
sys$dassgn(term_chan);
lib$free_ef(&efn);
if (status != SS$_NORMAL) return (status);
else return (term_iosb.stat);
}
/***********************************************************************
* get password from stdin
*
* implement for VMS, since VAXCRTL lacks getpass() function.
***********************************************************************/
char *getpass(prompt)
char *prompt;
{
static char line [12];
static int echo = {ECHO}, off = {OFF}, on = {ON};
printf(prompt); (void) fflush(stdout); /* prompt */
setterm(&echo, &off);
gets(line);
setterm(&echo, &on);
puts("");
return(line);
}
#endif
/***********************************************************************
* use .netrc to login to nameserver, if possible
***********************************************************************/
void DoAutoLogin()
{
FILE *netrc; /* the .netrc file */
char pathName[1024];/* pathname of .netrc file */
struct stat theStat;/* permissions, etc. of .netrc file */
char key[80], val[80]; /* line from the .netrc file */
char *token; /* token (word) from the line from the .netrc file */
char *alias=NULL; /* the user's alias */
char *pw=NULL; /* the user's password */
/*
* manufacture the pathname of the user's .netrc file
*/
sprintf(pathName,"%s/.netrc",getenv("HOME"));
/*
* make sure its permissions are ok
*/
if (stat(pathName,&theStat)<0)
return;
if (theStat.st_mode & 077)
return; /* refuse insecure files */
/*
* try to open it
*/
if (!(netrc=fopen(pathName,"r")))
return;
/*
* look for a ``machine'' named ``ph''
*/
while (2==fscanf(netrc,"%s %s",key,val))
{
if (!strcmp(key,"machine") && !strcmp(val,CLIENT))
{
/*
* found an entry for ph. look now for other items
*/
while (2==fscanf(netrc,"%s %s",key,val))
{
if (!strcmp(key,"machine")) /* new machine */
{
if (alias) {free(alias);alias=NULL;}
if (pw) {free(pw);pw=NULL;}
break;
}
else if (!strcmp(key,"login"))
alias=strcpy(malloc((unsigned)strlen(val)+1),val);
else if (!strcmp(key,"password"))
pw=strcpy(malloc((unsigned)strlen(val)+1),val);
else if (!strcmp(key,"macdef")) SkipMacdef(netrc);
if (alias && pw && TryLogin(alias,pw))
goto done;
}
}
else if (!strcmp(key,"macdef")) SkipMacdef(netrc);
}
done:
if (alias) free(alias);
if (pw) free(pw);
return;
}
/***********************************************************************
* skip a macdef in the .netrc file
***********************************************************************/
void SkipMacdef(netrc)
FILE *netrc;
{
int c, wasNl;
for (wasNl=0;(c=getc(netrc))!=EOF;wasNl=(c=='\n'))
if (wasNl && c=='\n') break;
}
/***********************************************************************
* try a login alias and password
***********************************************************************/
int TryLogin(alias,password)
char *alias;
char *password;
{
char loginLine[80];
int success;
/*
* construct a login line
*/
sprintf(loginLine,"login %s\n",alias);
/*
* set our password
*/
MyPassword=password;
/*
* try the login
*/
success = DoLogin(loginLine,0);
/*
* reset our password
*/
MyPassword = NULL;
while (*password) *password++ = 'x';
/*
* return our success (or failure)
*/
return(success);
}
/***********************************************************************
* execute a help request
***********************************************************************/
int DoHelp(inputLine)
char *inputLine;
{
char scratch[256];
char *token;
strcpy(scratch,inputLine);
token = strtok(scratch+4,DELIM); /* the word after help */
if (token && !strcmp(token,"native")) /* looking for native help */
strcpy(scratch,inputLine); /* leave the command alone */
else
sprintf(scratch,"help %s %s",CLIENT,inputLine+4); /* insert identifier */
qprintf(ToQI,"%s",scratch); /* send command */
qflush(ToQI);
return (NoBeautify ? PrintResponse(0) : PrintQResponse(0,1));
}
/************************************************************************
* reformat an email line to include an alias address
* this is kind of a hack since we're working on an already-formatted line
************************************************************************/
void EmailLine(email,alias,nickname)
char *email;
char *alias;
char *nickname;
{
char scratch[MAXSTR];
char *emSpot; /* beginning of email account */
char *alSpot; /* beginning of nameserver alias */
char *niSpot; /* beginning of nickname field */
if (*nickname)
{
emSpot = index(GetQValue(email), ':') + 2;
niSpot = index(GetQValue(nickname), ':') + 2;
*index(niSpot,'\n') = 0;
*index(emSpot,'\n') = 0;
/*
* overwrite the email label
*/
strcpy(niSpot-2-strlen("email to"),"email to");
niSpot[-2] = ':'; /* strcpy clobbered the colon; repair */
sprintf(scratch,"@%s\n",MAILDOMAIN);
strcat(nickname,scratch);
strcpy(email,nickname); /* leave it in the "email" line */
*nickname = 0; /* we're done with the alias */
}
else if (*alias)
{
emSpot = index(GetQValue(email), ':') + 2;
alSpot = index(GetQValue(alias), ':') + 2;
*index(alSpot,'\n') = 0;
*index(emSpot,'\n') = 0;
/*
* overwrite the email label
*/
strcpy(alSpot-2-strlen("email to"),"email to");
alSpot[-2] = ':'; /* strcpy clobbered the colon; repair */
sprintf(scratch,"@%s\n",MAILDOMAIN);
strcat(alias,scratch);
strcpy(email,alias); /* leave it in the "email" line */
*alias = 0; /* we're done with the alias */
}
}
/************************************************************************
* put out a ``not registered'' line with alias
************************************************************************/
void NotRegisteredLine(alias,theOutput)
char *alias;
FILE *theOutput;
{
char scratch[MAXSTR];
register char *cp;
strcpy(scratch,alias);
cp = index(GetQValue(scratch),':');
strcpy(cp-8,"email to:");
strcpy(cp+1," (no address registered)\n");
/* output the line */
if (NoLabels)
fputs(index(GetQValue(scratch),':')+2, theOutput);
else
fputs(GetQValue(scratch), theOutput);
*alias = 0; /* done with alias */
}
/************************************************************************
* process a set of options
************************************************************************/
int ProcessOptions(argc,argv)
int argc;
char **argv;
{
int count = 0;
/*
* options processing
*/
for (;argc && **argv=='-'; argc--,argv++,count++)
{
for ((*argv)++; **argv; (*argv)++)
{
switch(**argv)
{
case 'r': NoReformat = 1; break;
case 'R': NoReformat = 0; break;
case 'n': NoNetrc = 1; break;
case 'N': NoNetrc = 0; break;
case 'm': NoPager = 1; break;
case 'M': NoPager = 0; break;
case 'b': NoBeautify = 1; break;
case 'B': NoBeautify = 0; break;
case 'l': NoLabels = 1; break;
case 'L': NoLabels = 0; break;
case 'C': Confirm = 1; break;
case 'c': Confirm = 0; break;
case 's':
if (argv[0][1])
{
if (UseHost) free(UseHost);
UseHost = makestr(*argv + 1);
goto whilebottom;
}
else if (argc>1)
{
if (UseHost) free(UseHost);
UseHost = makestr(argv[1]);
argc--,argv++,count++;
goto whilebottom;
}
else
fprintf(stderr,"-%c option given without server hostname.\n", **argv);
break;
case 't':
if (argv[0][1])
{
if (DefType) free(DefType);
DefType = makestr(*argv + 1);
goto whilebottom;
}
else if (argc>1)
{
if (DefType) free(DefType);
DefType = makestr(argv[1]);
argc--,argv++,count++;
goto whilebottom;
}
else
fprintf(stderr,"-%t option given without entry type.\n", **argv);
break;
case 'f':
if (argv[0][1])
{
if (ReturnFields) free(ReturnFields);
ReturnFields = makestr(*argv + 1);
goto whilebottom;
}
else if (argc>1)
{
if (ReturnFields) free(ReturnFields);
ReturnFields = makestr(argv[1]);
argc--,argv++,count++;
goto whilebottom;
}
else
fprintf(stderr,"-%t option given without field list.\n", **argv);
break;
case 'F':
if (ReturnFields) free(ReturnFields);
ReturnFields = 0;
break;
case 'T':
if (DefType) free(DefType);
DefType = 0;
break;
case 'p':
if (isdigit(argv[0][1]))
{
UsePort = htons(atoi(*argv + 1));
goto whilebottom;
}
else if (argc>1 && isdigit(*argv[1]))
{
UsePort = htons(atoi(argv[1]));
argc--,argv++,count++;
goto whilebottom;
}
else
fprintf(stderr,"-%c option given without port number.\n", **argv);
break;
default:
fprintf(stderr,"Unknown option: -%c.\n",**argv);
}
}
whilebottom:;
}
return(count);
}
/************************************************************************
* Process a lineful of options
************************************************************************/
OptionLine(line)
char *line;
{
int argc;
char *argv[MAXARGS];
char *token;
if (!line || !*line) return;
for (argc=0,token=strtok(line,DELIM);token;argc++,token=strtok(0,DELIM))
argv[argc] = token;
argv[argc] = 0;
return(ProcessOptions(argc,argv));
}
/************************************************************************
* OpenPager - open the user's chosen pager
************************************************************************/
FILE *OpenPager(doPaging)
int doPaging;
{
char *thePager;
FILE *theOutput;
#ifdef VMS
return(stdout); /* simpler to skip paging for right now */
#else
if (NoPager || doPaging!=1)
return(stdout);
else
{
if ((thePager = getenv("PAGER")) == NULL)
#ifdef hpux
thePager = "/usr/bin/more";
#else
thePager = "/usr/ucb/more";
#endif
if ((theOutput = popen(thePager, "w")) == NULL)
theOutput = stdout;
return(theOutput);
}
#endif
}
/************************************************************************
* makestr - make a copy of a string in malloc-space
************************************************************************/
char *makestr(str)
char *str;
{
char *copy;
int len;
len = strlen(str);
if (copy=malloc(len+1))
strcpy(copy,str);
return(copy);
}
/************************************************************************
* issub - is one string a substring of another?
************************************************************************/
char *issub(string, sub)
char *string;
char *sub;
{
int len;
len = strlen(sub);
for (; *string; string++)
if (!strncmp(string, sub, len))
return (string);
return (0);
}
/***********************************************************************
* EnvOptions - grab some options from the environment
***********************************************************************/
void EnvOptions(name)
char *name;
{
char buffer[80];
register char *np,*bp;
for (np=name,bp=buffer; *np; np++,bp++)
*bp = islower(*np) ? toupper(*np) : *np;
*bp = 0;
OptionLine(getenv(buffer));
}