builtins.cc
// $Id: builtins.cc,v 1.3 2003/04/11 03:48:16 vickery Exp $
/* Definitions of functions for jsh builtin commands.
*
* $Log: builtins.cc,v $
* Revision 1.3 2003/04/11 03:48:16 vickery
* Implemented doAlias and doUnalias completely.
*
* Revision 1.2 2003/04/04 23:32:28 vickery
* Added doChdir and doEcho builtins.
*
* Revision 1.1 2003/04/04 22:37:45 vickery
* Initial revision
*
*/
#include "jsh.h"
#include "alias_table.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// Hack to get WIFEXITED to recognize "return JSH_ERR_RETURN"
// as equivalent to "exit( 1 )".
#define JSH_ERR_RETURN 256
// doUnalias()
// ------------------------------------------------------------------
/*
* Deletes an alias.
*/
int
doUnalias( const int argc, const char *argv[] )
{
if ( argc != 2 )
{
fprintf( stderr, "Usage: unalias <name>\n" );
return JSH_ERR_RETURN;
}
if ( deleteAlias( argv[1] ) != 1 )
{
return JSH_ERR_RETURN;
}
return 0;
}
// doAlias()
// ------------------------------------------------------------------
/*
* Displays current aliases or defines a new one.
*
* With no arguments, list all aliases.
* With one argument, list the named alias
* With two or more arguments, define a new one or replace existing
* one.
*/
int
doAlias( const int argc, const char *argv[] )
{
if ( 1 == argc )
{
listAliases();
return 0;
}
// Add or replace an alias
// --------------------------------------------------------------
// Create a single value from all arguments after the name
int len = 1;
for (int i = 2; i < argc; i++ )
{
len += strlen( argv[i] );
}
if ( 1 == len )
{
// No value: list value, if there is one.
const char *value = lookupAlias( argv[1] );
if ( value != 0 )
{
printf( "alias %s = %s\n", argv[1], value );
}
else
{
printf( "alias: \"%s\" is not defined\n", argv[1] );
}
}
else
{
char *key = (char *) malloc( 1 + strlen( argv[1] ) );
err_check( "malloc alias key", __FILE__, __LINE__ );
strcpy( key, argv[1] );
char *value = (char *) malloc( len );
err_check( "malloc alias", __FILE__, __LINE__ );
strcpy( value, argv[2] );
for( int i = 3; i < argc; i++ )
{
strcat( value, argv[i] );
}
defineAlias( key, value );
}
return 0;
}
// doChdir()
// ------------------------------------------------------------------
/*
* Changes the shell's working directory.
*/
int
doChdir( const int argc, const char *argv[] )
{
switch ( argc )
{
case 1:
{
char *home = getenv( "HOME" );
if ( 0 == home )
{
fprintf( stderr, "Unable to determine home directory\n" );
return JSH_ERR_RETURN;
}
if ( -1 == chdir( home ) )
{
perror( home );
return JSH_ERR_RETURN;
}
return 0;
break;
}
case 2:
if ( -1 == chdir( argv[1] ) )
{
perror( argv[1] );
return JSH_ERR_RETURN;
}
return 0;
break;
default:
fprintf(stderr, "Usage: cd [<directory>]\n" );
return JSH_ERR_RETURN;
break;
}
}
// doEcho()
// ------------------------------------------------------------------
/*
* Echoes command line arguments.
*/
int
doEcho( const int argc, const char *argv[] )
{
for (int i = 1; i < argc; i++ )
{
printf( "%s ", argv[i] );
}
printf( "\n" );
return 0;
}
// doExit()
// ------------------------------------------------------------------
/*
* Exits the shell.
*/
int
doExit( const int argc, const char *argv[] )
{
if ( argc > 2 )
{
fprintf( stderr, "Usage: exit <number>\n" );
return JSH_ERR_RETURN;
}
if ( argc > 1 )
{
exit( strtol( argv[1], 0, 0 ) );
}
else
{
exit( 0 );
}
}