260 lines
7.3 KiB
C
260 lines
7.3 KiB
C
/*---------------------------------------------------------------------------
|
|
|
|
One more approach for the implementation of Aliases
|
|
|
|
|
|
|
|
Markus Zolliker, September 2000
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
---------------------------------------------------------------------------*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "strlutil.h"
|
|
#include "dynstring.h"
|
|
#include "definealias.h"
|
|
|
|
typedef struct __Aitem {
|
|
struct __Aitem *pNext;
|
|
char *pName;
|
|
char *pCmd;
|
|
} AliasItem;
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
char *TranslateAlias(AliasList * pAList, char *pCmd)
|
|
{
|
|
AliasItem *pAlias;
|
|
|
|
assert(pAList != NULL && pCmd != NULL);
|
|
|
|
pAlias = pAList->pFirst;
|
|
while (pAlias != NULL) {
|
|
if (0 == strcmp(pAlias->pName, pCmd)) {
|
|
pCmd = pAlias->pCmd; /* note that there may be cascaded translations */
|
|
}
|
|
pAlias = pAlias->pNext;
|
|
}
|
|
return (pCmd);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int RemoveAlias(AliasList * pAList, char *pCmd)
|
|
{
|
|
AliasItem *pAlias = NULL, *pPrev = NULL;
|
|
|
|
assert(pAList != NULL && pCmd != NULL);
|
|
|
|
pPrev = (AliasItem *) pAList;
|
|
pAlias = pAList->pFirst;
|
|
while (pAlias != NULL && 0 != strcmp(pAlias->pName, pCmd)) {
|
|
pPrev = pAlias;
|
|
pAlias = pAlias->pNext;
|
|
}
|
|
if (pAlias == NULL) {
|
|
return 0; /* not found */
|
|
}
|
|
|
|
/* remove it */
|
|
pPrev->pNext = pAlias->pNext;
|
|
free(pAlias->pName);
|
|
free(pAlias->pCmd);
|
|
free(pAlias);
|
|
return (1);
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
void FreeAliasList(AliasList * pAList)
|
|
{
|
|
AliasItem *pAlias = NULL, *pNext = NULL;
|
|
|
|
assert(pAList != NULL);
|
|
|
|
pAlias = pAList->pFirst;
|
|
while (pAlias != NULL) {
|
|
pNext = pAlias->pNext;
|
|
free(pAlias->pName);
|
|
free(pAlias->pCmd);
|
|
free(pAlias);
|
|
pAlias = pNext;
|
|
}
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
char *CreateAlias(AliasList * pAList, char *pName, char *pTranslation)
|
|
{ /* arguments must be lower case */
|
|
AliasItem *pAlias = NULL, *pNew = NULL, *pTail = NULL;
|
|
char *pCmd;
|
|
|
|
/* translate 2nd argument */
|
|
pCmd = TranslateAlias(pAList, pTranslation);
|
|
if (0 == strcmp(pName, pCmd)) { /* translation matches */
|
|
return "recursive alias not allowed";
|
|
}
|
|
|
|
/* find last element pTail and check that alias does not yet exist */
|
|
pTail = (AliasItem *) pAList;
|
|
pAlias = pAList->pFirst;
|
|
while (pAlias != NULL) {
|
|
pTail = pAlias;
|
|
if (0 == strcmp(pAlias->pName, pName)) {
|
|
return "alias already exists";
|
|
}
|
|
pAlias = pAlias->pNext;
|
|
}
|
|
|
|
/* allocate the list entry */
|
|
pNew = malloc(sizeof(AliasItem));
|
|
if (pNew != NULL) {
|
|
pNew->pNext = NULL;
|
|
pNew->pName = strdup(pName);
|
|
if (pNew->pName != NULL) {
|
|
pNew->pCmd = strdup(pCmd);
|
|
if (pNew->pCmd != NULL) {
|
|
/* insert at tail */
|
|
pTail->pNext = pNew;
|
|
return NULL; /* o.k. */
|
|
}
|
|
}
|
|
}
|
|
return "not enough memory to create an alias";
|
|
|
|
}
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
int DefineAlias(pSConnection pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
char arg1[256];
|
|
char arg2[256];
|
|
int iRet;
|
|
CommandList *pCom = NULL;
|
|
char *pErr;
|
|
char *pCmd;
|
|
AliasItem *pAlias;
|
|
pDynString str;
|
|
|
|
if (argc == 3) {
|
|
strlcpy(arg2, argv[2], sizeof arg2);
|
|
strtolower(arg2);
|
|
} else if (argc > 3 || argc < 2) {
|
|
SCWrite(pCon, "ERROR: illegal number of arguments to DefineAlias",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
strlcpy(arg1, argv[1], sizeof arg1);
|
|
strtolower(arg1);
|
|
|
|
if (argc == 3 && strcasecmp(arg1, "-show") == 0) {
|
|
for (pAlias = pSics->AList.pFirst; pAlias!=NULL; pAlias=pAlias->pNext) {
|
|
if (0 == strcmp(pAlias->pName, arg2)) {
|
|
SCWrite(pCon, pAlias->pCmd, eValue);
|
|
return 1;
|
|
}
|
|
}
|
|
SCWrite(pCon, "NA", eValue);
|
|
return 1;
|
|
}
|
|
|
|
if (argc == 2 && strcasecmp(arg1, "-list") == 0) {
|
|
str = CreateDynString(60,63);
|
|
for (pAlias = pSics->AList.pFirst; pAlias!=NULL; pAlias=pAlias->pNext) {
|
|
DynStringConcat(str, pAlias->pName);
|
|
DynStringConcat(str, " ");
|
|
}
|
|
if (GetDynStringLength(str) > 0) {
|
|
DynStringBackspace(str);
|
|
}
|
|
SCWrite(pCon, GetCharArray(str), eValue);
|
|
DeleteDynString(str);
|
|
return 1;
|
|
}
|
|
|
|
if (argc == 3 && strcasecmp(arg1, "-translate") == 0) {
|
|
pCmd = TranslateAlias(&pSics->AList, arg2);
|
|
SCWrite(pCon, pCmd, eValue);
|
|
return 1;
|
|
}
|
|
|
|
if (!SCMatchRights(pCon, usMugger)) {
|
|
SCWrite(pCon, "ERROR: only managers may define aliases", eError);
|
|
return 0;
|
|
}
|
|
|
|
if (argc == 2) { /* remove case */
|
|
iRet = RemoveAlias(&pSics->AList, arg1);
|
|
if (iRet == 0) {
|
|
SCWrite(pCon, "ERROR: alias not found", eError);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
pCom = FindCommand(pSics, arg1);
|
|
/* do not complain when the command was a translated alias */
|
|
if (pCom != NULL && strcmp(pCom->pName, arg1) == 0) {
|
|
SCWrite(pCon, "ERROR: an alias must not overwrite a command", eError);
|
|
return 0;
|
|
}
|
|
|
|
/* remove the old alias, if any */
|
|
RemoveAlias(&pSics->AList, arg1);
|
|
|
|
pErr = CreateAlias(&pSics->AList, arg1, arg2);
|
|
if (pErr != NULL) {
|
|
SCPrintf(pCon, eError, "ERROR: %s", pErr);
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static int AliasSaver(void *object, char *name, FILE * fil)
|
|
{
|
|
AliasItem *pAlias;
|
|
|
|
for (pAlias = pServ->pSics->AList.pFirst; pAlias != NULL; pAlias = pAlias->pNext) {
|
|
fprintf(fil, "definealias %s %s\n", pAlias->pName, pAlias->pCmd);
|
|
}
|
|
return 1;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
void DefineAliasInit(void) {
|
|
Dummy *as;
|
|
as = CreateDummy("alias saver");
|
|
as->pDescriptor->SaveStatus = AliasSaver;
|
|
AddCommandWithFlag(pServ->pSics, "definealias", DefineAlias, KillDummy, as, 0);
|
|
}
|