mirror of
https://https.git.savannah.gnu.org/git/bash.git
synced 2026-08-06 18:22:25 +02:00
commit bash-20040107 snapshot
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
cmp
|
||||
wc
|
||||
mkfifo
|
||||
paste
|
||||
@@ -0,0 +1,191 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
#include "common.h"
|
||||
#include "bashgetopt.h"
|
||||
|
||||
char *this_command_name = (char *)NULL;
|
||||
|
||||
void
|
||||
builtin_error (const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
char *name;
|
||||
|
||||
name = get_name_for_error ();
|
||||
fprintf (stderr, "%s: ", name);
|
||||
|
||||
if (this_command_name && *this_command_name)
|
||||
fprintf (stderr, "%s: ", this_command_name);
|
||||
|
||||
va_start (args, format);
|
||||
|
||||
vfprintf (stderr, format, args);
|
||||
va_end (args);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
int
|
||||
no_options(list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
reset_internal_getopt ();
|
||||
if (internal_getopt (list, "") != -1)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
legal_number (string, result)
|
||||
char *string;
|
||||
long *result;
|
||||
{
|
||||
long value;
|
||||
char *ep;
|
||||
|
||||
if (result)
|
||||
*result = 0;
|
||||
|
||||
value = strtol (string, &ep, 10);
|
||||
|
||||
/* If *string is not '\0' but *ep is '\0' on return, the entire string
|
||||
is valid. */
|
||||
if (string && *string && *ep == '\0')
|
||||
{
|
||||
if (result)
|
||||
*result = value;
|
||||
/* The SunOS4 implementation of strtol() will happily ignore
|
||||
overflow conditions, so this cannot do overflow correctly
|
||||
on those systems. */
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Return the number of elements in LIST, a generic list. */
|
||||
int
|
||||
list_length (list)
|
||||
GENERIC_LIST *list;
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; list; list = list->next, i++);
|
||||
return (i);
|
||||
}
|
||||
|
||||
GENERIC_LIST *
|
||||
reverse_list (list)
|
||||
GENERIC_LIST *list;
|
||||
{
|
||||
register GENERIC_LIST *next, *prev;
|
||||
|
||||
for (prev = (GENERIC_LIST *)NULL; list; )
|
||||
{
|
||||
next = list->next;
|
||||
list->next = prev;
|
||||
prev = list;
|
||||
list = next;
|
||||
}
|
||||
return (prev);
|
||||
}
|
||||
|
||||
WORD_DESC *
|
||||
make_bare_word (string)
|
||||
char *string;
|
||||
{
|
||||
WORD_DESC *temp;
|
||||
|
||||
temp = (WORD_DESC *)xmalloc (sizeof (WORD_DESC));
|
||||
if (*string)
|
||||
temp->word = savestring (string);
|
||||
else
|
||||
{
|
||||
temp->word = xmalloc (1);
|
||||
temp->word[0] = '\0';
|
||||
}
|
||||
|
||||
temp->flags = 0;
|
||||
return (temp);
|
||||
}
|
||||
WORD_LIST *
|
||||
make_word_list (word, link)
|
||||
WORD_DESC *word;
|
||||
WORD_LIST *link;
|
||||
{
|
||||
WORD_LIST *temp;
|
||||
|
||||
temp = (WORD_LIST *)xmalloc (sizeof (WORD_LIST));
|
||||
temp->word = word;
|
||||
temp->next = link;
|
||||
return (temp);
|
||||
}
|
||||
|
||||
void
|
||||
builtin_usage()
|
||||
{
|
||||
if (this_command_name && *this_command_name)
|
||||
fprintf (stderr, "%s: usage: %s args\n", this_command_name, this_command_name);
|
||||
fflush (stderr);
|
||||
}
|
||||
|
||||
char *
|
||||
xmalloc(s)
|
||||
size_t s;
|
||||
{
|
||||
return (malloc (s));
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
argv_to_word_list (array, copy, starting_index)
|
||||
char **array;
|
||||
int copy, starting_index;
|
||||
{
|
||||
WORD_LIST *list;
|
||||
WORD_DESC *w;
|
||||
int i, count;
|
||||
|
||||
if (array == 0 || array[0] == 0)
|
||||
return (WORD_LIST *)NULL;
|
||||
|
||||
for (count = 0; array[count]; count++)
|
||||
;
|
||||
|
||||
for (i = starting_index, list = (WORD_LIST *)NULL; i < count; i++)
|
||||
{
|
||||
w = make_bare_word (copy ? "" : array[i]);
|
||||
if (copy)
|
||||
{
|
||||
free (w->word);
|
||||
w->word = array[i];
|
||||
}
|
||||
list = make_word_list (w, list);
|
||||
}
|
||||
return (REVERSE_LIST(list, WORD_LIST *));
|
||||
}
|
||||
|
||||
/* Convert a WORD_LIST into a C-style argv. Return the number of elements
|
||||
in the list in *IP, if IP is non-null. A convenience function for
|
||||
loadable builtins; also used by `test'. */
|
||||
char **
|
||||
make_builtin_argv (list, ip)
|
||||
WORD_LIST *list;
|
||||
int *ip;
|
||||
{
|
||||
char **argv;
|
||||
|
||||
argv = strvec_from_word_list (list, 0, 1, ip);
|
||||
argv[0] = this_command_name;
|
||||
return argv;
|
||||
}
|
||||
|
||||
@@ -247,10 +247,17 @@ struct stat *st;
|
||||
struct passwd *pw;
|
||||
struct group *gr;
|
||||
char *owner;
|
||||
int ma, mi, d;
|
||||
|
||||
ma = major (st->st_rdev);
|
||||
mi = minor (st->st_rdev);
|
||||
#if defined (makedev)
|
||||
d = makedev (ma, mi);
|
||||
#else
|
||||
d = st->st_rdev & 0xFF;
|
||||
#endif
|
||||
printf("Device (major/minor): %d (%d/%d)\n", d, ma, mi);
|
||||
|
||||
printf("Device (major/minor): %d (%d/%d)\n", (int) (st->st_dev & 0xFF),
|
||||
(int) major (st->st_dev),
|
||||
(int) minor (st->st_dev));
|
||||
printf("Inode: %d\n", (int) st->st_ino);
|
||||
printf("Mode: (%o) ", (int) st->st_mode);
|
||||
printmode((int) st->st_mode);
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
/usr/local/build/chet/bash/bash-current/examples/loadables/perl/Makefile
|
||||
@@ -0,0 +1,611 @@
|
||||
This file is pushd.def, from which is created pushd.c. It implements the
|
||||
builtins "pushd", "popd", and "dirs" in Bash.
|
||||
|
||||
Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Bash, the Bourne Again SHell.
|
||||
|
||||
Bash 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 1, or (at your option) any later
|
||||
version.
|
||||
|
||||
Bash 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 Bash; see the file COPYING. If not, write to the Free Software
|
||||
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
$PRODUCES pushd.c
|
||||
|
||||
$BUILTIN pushd
|
||||
$FUNCTION pushd_builtin
|
||||
$DEPENDS_ON PUSHD_AND_POPD
|
||||
$SHORT_DOC pushd [dir | +N | -N] [-n]
|
||||
Adds a directory to the top of the directory stack, or rotates
|
||||
the stack, making the new top of the stack the current working
|
||||
directory. With no arguments, exchanges the top two directories.
|
||||
|
||||
+N Rotates the stack so that the Nth directory (counting
|
||||
from the left of the list shown by `dirs', starting with
|
||||
zero) is at the top.
|
||||
|
||||
-N Rotates the stack so that the Nth directory (counting
|
||||
from the right of the list shown by `dirs', starting with
|
||||
zero) is at the top.
|
||||
|
||||
-n suppress the normal change of directory when adding directories
|
||||
to the stack, so only the stack is manipulated.
|
||||
|
||||
dir adds DIR to the directory stack at the top, making it the
|
||||
new current working directory.
|
||||
|
||||
You can see the directory stack with the `dirs' command.
|
||||
$END
|
||||
|
||||
$BUILTIN popd
|
||||
$FUNCTION popd_builtin
|
||||
$DEPENDS_ON PUSHD_AND_POPD
|
||||
$SHORT_DOC popd [+N | -N] [-n]
|
||||
Removes entries from the directory stack. With no arguments,
|
||||
removes the top directory from the stack, and cd's to the new
|
||||
top directory.
|
||||
|
||||
+N removes the Nth entry counting from the left of the list
|
||||
shown by `dirs', starting with zero. For example: `popd +0'
|
||||
removes the first directory, `popd +1' the second.
|
||||
|
||||
-N removes the Nth entry counting from the right of the list
|
||||
shown by `dirs', starting with zero. For example: `popd -0'
|
||||
removes the last directory, `popd -1' the next to last.
|
||||
|
||||
-n suppress the normal change of directory when removing directories
|
||||
from the stack, so only the stack is manipulated.
|
||||
|
||||
You can see the directory stack with the `dirs' command.
|
||||
$END
|
||||
|
||||
$BUILTIN dirs
|
||||
$FUNCTION dirs_builtin
|
||||
$DEPENDS_ON PUSHD_AND_POPD
|
||||
$SHORT_DOC dirs [-clpv] [+N] [-N]
|
||||
Display the list of currently remembered directories. Directories
|
||||
find their way onto the list with the `pushd' command; you can get
|
||||
back up through the list with the `popd' command.
|
||||
|
||||
The -l flag specifies that `dirs' should not print shorthand versions
|
||||
of directories which are relative to your home directory. This means
|
||||
that `~/bin' might be displayed as `/homes/bfox/bin'. The -v flag
|
||||
causes `dirs' to print the directory stack with one entry per line,
|
||||
prepending the directory name with its position in the stack. The -p
|
||||
flag does the same thing, but the stack position is not prepended.
|
||||
The -c flag clears the directory stack by deleting all of the elements.
|
||||
|
||||
+N displays the Nth entry counting from the left of the list shown by
|
||||
dirs when invoked without options, starting with zero.
|
||||
|
||||
-N displays the Nth entry counting from the right of the list shown by
|
||||
dirs when invoked without options, starting with zero.
|
||||
$END
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#if defined (PUSHD_AND_POPD)
|
||||
#include <stdio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#if defined (HAVE_UNISTD_H)
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "../bashansi.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <tilde/tilde.h>
|
||||
|
||||
#include "../shell.h"
|
||||
#include "../maxpath.h"
|
||||
#include "common.h"
|
||||
#include "builtext.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif /* !errno */
|
||||
|
||||
static char *m_badarg = "%s: bad argument";
|
||||
|
||||
/* The list of remembered directories. */
|
||||
static char **pushd_directory_list = (char **)NULL;
|
||||
|
||||
/* Number of existing slots in this list. */
|
||||
static int directory_list_size;
|
||||
|
||||
/* Offset to the end of the list. */
|
||||
static int directory_list_offset;
|
||||
|
||||
static void pushd_error ();
|
||||
static void clear_directory_stack ();
|
||||
static int cd_to_string ();
|
||||
static int change_to_temp ();
|
||||
static int get_dirstack_index ();
|
||||
static void add_dirstack_element ();
|
||||
|
||||
#define NOCD 0x01
|
||||
#define ROTATE 0x02
|
||||
#define LONGFORM 0x04
|
||||
#define CLEARSTAK 0x08
|
||||
|
||||
int
|
||||
pushd_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
char *temp, *current_directory, *top;
|
||||
int j, flags;
|
||||
long num;
|
||||
char direction;
|
||||
|
||||
/* If there is no argument list then switch current and
|
||||
top of list. */
|
||||
if (list == 0)
|
||||
{
|
||||
if (directory_list_offset == 0)
|
||||
{
|
||||
builtin_error ("no other directory");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
current_directory = get_working_directory ("pushd");
|
||||
if (current_directory == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
j = directory_list_offset - 1;
|
||||
temp = pushd_directory_list[j];
|
||||
pushd_directory_list[j] = current_directory;
|
||||
j = change_to_temp (temp);
|
||||
free (temp);
|
||||
return j;
|
||||
}
|
||||
|
||||
for (flags = 0; list; list = list->next)
|
||||
{
|
||||
if (ISOPTION (list->word->word, 'n'))
|
||||
{
|
||||
flags |= NOCD;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (list->word->word[0] == '-' && list->word->word[1] == '\0')
|
||||
/* Let `pushd -' work like it used to. */
|
||||
break;
|
||||
else if (((direction = list->word->word[0]) == '+') || direction == '-')
|
||||
{
|
||||
if (legal_number (list->word->word + 1, &num) == 0)
|
||||
{
|
||||
builtin_error (m_badarg, list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
if (direction == '-')
|
||||
num = directory_list_offset - num;
|
||||
|
||||
if (num > directory_list_offset || num < 0)
|
||||
{
|
||||
pushd_error (directory_list_offset, list->word->word);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
flags |= ROTATE;
|
||||
}
|
||||
else if (*list->word->word == '-')
|
||||
{
|
||||
bad_option (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (flags & ROTATE)
|
||||
{
|
||||
/* Rotate the stack num times. Remember, the current
|
||||
directory acts like it is part of the stack. */
|
||||
temp = get_working_directory ("pushd");
|
||||
|
||||
if (num == 0)
|
||||
{
|
||||
j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
|
||||
free (temp);
|
||||
return j;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
top = pushd_directory_list[directory_list_offset - 1];
|
||||
|
||||
for (j = directory_list_offset - 2; j > -1; j--)
|
||||
pushd_directory_list[j + 1] = pushd_directory_list[j];
|
||||
|
||||
pushd_directory_list[j + 1] = temp;
|
||||
|
||||
temp = top;
|
||||
num--;
|
||||
}
|
||||
while (num);
|
||||
|
||||
j = ((flags & NOCD) == 0) ? change_to_temp (temp) : EXECUTION_SUCCESS;
|
||||
free (temp);
|
||||
return j;
|
||||
}
|
||||
|
||||
if (list == 0)
|
||||
return (EXECUTION_SUCCESS);
|
||||
|
||||
/* Change to the directory in list->word->word. Save the current
|
||||
directory on the top of the stack. */
|
||||
current_directory = get_working_directory ("pushd");
|
||||
if (current_directory == 0)
|
||||
return (EXECUTION_FAILURE);
|
||||
|
||||
j = ((flags & NOCD) == 0) ? cd_builtin (list) : EXECUTION_SUCCESS;
|
||||
if (j == EXECUTION_SUCCESS)
|
||||
{
|
||||
add_dirstack_element ((flags & NOCD) ? savestring (list->word->word) : current_directory);
|
||||
dirs_builtin ((WORD_LIST *)NULL);
|
||||
if (flags & NOCD)
|
||||
free (current_directory);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
free (current_directory);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Pop the directory stack, and then change to the new top of the stack.
|
||||
If LIST is non-null it should consist of a word +N or -N, which says
|
||||
what element to delete from the stack. The default is the top one. */
|
||||
int
|
||||
popd_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
register int i;
|
||||
long which;
|
||||
int flags;
|
||||
char direction;
|
||||
char *which_word;
|
||||
|
||||
which_word = (char *)NULL;
|
||||
for (flags = 0, which = 0L, direction = '+'; list; list = list->next)
|
||||
{
|
||||
if (ISOPTION (list->word->word, 'n'))
|
||||
{
|
||||
flags |= NOCD;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (((direction = list->word->word[0]) == '+') || direction == '-')
|
||||
{
|
||||
if (legal_number (list->word->word + 1, &which) == 0)
|
||||
{
|
||||
builtin_error (m_badarg, list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
which_word = list->word->word;
|
||||
}
|
||||
else if (*list->word->word == '-')
|
||||
{
|
||||
bad_option (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (which > directory_list_offset || (directory_list_offset == 0 && which == 0))
|
||||
{
|
||||
pushd_error (directory_list_offset, which_word ? which_word : "");
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
/* Handle case of no specification, or top of stack specification. */
|
||||
if ((direction == '+' && which == 0) ||
|
||||
(direction == '-' && which == directory_list_offset))
|
||||
{
|
||||
i = ((flags & NOCD) == 0) ? cd_to_string (pushd_directory_list[directory_list_offset - 1])
|
||||
: EXECUTION_SUCCESS;
|
||||
if (i != EXECUTION_SUCCESS)
|
||||
return (i);
|
||||
free (pushd_directory_list[--directory_list_offset]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Since an offset other than the top directory was specified,
|
||||
remove that directory from the list and shift the remainder
|
||||
of the list into place. */
|
||||
i = (direction == '+') ? directory_list_offset - which : which;
|
||||
free (pushd_directory_list[i]);
|
||||
directory_list_offset--;
|
||||
|
||||
/* Shift the remainder of the list into place. */
|
||||
for (; i < directory_list_offset; i++)
|
||||
pushd_directory_list[i] = pushd_directory_list[i + 1];
|
||||
}
|
||||
|
||||
dirs_builtin ((WORD_LIST *)NULL);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
/* Print the current list of directories on the directory stack. */
|
||||
int
|
||||
dirs_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int flags, desired_index, index_flag, vflag;
|
||||
long i;
|
||||
char *temp, *w;
|
||||
|
||||
for (flags = vflag = index_flag = 0, desired_index = -1, w = ""; list; list = list->next)
|
||||
{
|
||||
if (ISOPTION (list->word->word, 'l'))
|
||||
{
|
||||
flags |= LONGFORM;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, 'c'))
|
||||
{
|
||||
flags |= CLEARSTAK;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, 'v'))
|
||||
{
|
||||
vflag |= 2;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, 'p'))
|
||||
{
|
||||
vflag |= 1;
|
||||
}
|
||||
else if (ISOPTION (list->word->word, '-'))
|
||||
{
|
||||
list = list->next;
|
||||
break;
|
||||
}
|
||||
else if (*list->word->word == '+' || *list->word->word == '-')
|
||||
{
|
||||
int sign;
|
||||
if (legal_number (w = list->word->word + 1, &i) == 0)
|
||||
{
|
||||
builtin_error (m_badarg, list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
sign = (*list->word->word == '+') ? 1 : -1;
|
||||
desired_index = get_dirstack_index (i, sign, &index_flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
bad_option (list->word->word);
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & CLEARSTAK)
|
||||
{
|
||||
clear_directory_stack ();
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
if (index_flag && (desired_index < 0 || desired_index > directory_list_offset))
|
||||
{
|
||||
pushd_error (directory_list_offset, w);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
#define DIRSTACK_FORMAT(temp) \
|
||||
(flags & LONGFORM) ? temp : polite_directory_format (temp)
|
||||
|
||||
/* The first directory printed is always the current working directory. */
|
||||
if (index_flag == 0 || (index_flag == 1 && desired_index == 0))
|
||||
{
|
||||
temp = get_working_directory ("dirs");
|
||||
if (temp == 0)
|
||||
temp = savestring ("<no current directory>");
|
||||
if (vflag & 2)
|
||||
printf ("%2d %s", 0, DIRSTACK_FORMAT (temp));
|
||||
else
|
||||
printf ("%s", DIRSTACK_FORMAT (temp));
|
||||
free (temp);
|
||||
if (index_flag)
|
||||
{
|
||||
putchar ('\n');
|
||||
return EXECUTION_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
#define DIRSTACK_ENTRY(i) \
|
||||
(flags & LONGFORM) ? pushd_directory_list[i] \
|
||||
: polite_directory_format (pushd_directory_list[i])
|
||||
|
||||
/* Now print the requested directory stack entries. */
|
||||
if (index_flag)
|
||||
{
|
||||
if (vflag & 2)
|
||||
printf ("%2d %s", directory_list_offset - desired_index,
|
||||
DIRSTACK_ENTRY (desired_index));
|
||||
else
|
||||
printf ("%s", DIRSTACK_ENTRY (desired_index));
|
||||
}
|
||||
else
|
||||
for (i = directory_list_offset - 1; i >= 0; i--)
|
||||
if (vflag >= 2)
|
||||
printf ("\n%2d %s", directory_list_offset - (int)i, DIRSTACK_ENTRY (i));
|
||||
else
|
||||
printf ("%s%s", (vflag & 1) ? "\n" : " ", DIRSTACK_ENTRY (i));
|
||||
|
||||
putchar ('\n');
|
||||
fflush (stdout);
|
||||
return (EXECUTION_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
pushd_error (offset, arg)
|
||||
int offset;
|
||||
char *arg;
|
||||
{
|
||||
if (offset == 0)
|
||||
builtin_error ("directory stack empty");
|
||||
else if (arg)
|
||||
builtin_error ("%s: bad directory stack index", arg);
|
||||
else
|
||||
builtin_error ("bad directory stack index");
|
||||
}
|
||||
|
||||
static void
|
||||
clear_directory_stack ()
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 0; i < directory_list_offset; i++)
|
||||
free (pushd_directory_list[i]);
|
||||
directory_list_offset = 0;
|
||||
}
|
||||
|
||||
/* Switch to the directory in NAME. This uses the cd_builtin to do the work,
|
||||
so if the result is EXECUTION_FAILURE then an error message has already
|
||||
been printed. */
|
||||
static int
|
||||
cd_to_string (name)
|
||||
char *name;
|
||||
{
|
||||
WORD_LIST *tlist;
|
||||
int result;
|
||||
|
||||
tlist = make_word_list (make_word (name), NULL);
|
||||
result = cd_builtin (tlist);
|
||||
dispose_words (tlist);
|
||||
return (result);
|
||||
}
|
||||
|
||||
static int
|
||||
change_to_temp (temp)
|
||||
char *temp;
|
||||
{
|
||||
int tt;
|
||||
|
||||
tt = temp ? cd_to_string (temp) : EXECUTION_FAILURE;
|
||||
|
||||
if (tt == EXECUTION_SUCCESS)
|
||||
dirs_builtin ((WORD_LIST *)NULL);
|
||||
|
||||
return (tt);
|
||||
}
|
||||
|
||||
static void
|
||||
add_dirstack_element (dir)
|
||||
char *dir;
|
||||
{
|
||||
int j;
|
||||
|
||||
if (directory_list_offset == directory_list_size)
|
||||
{
|
||||
j = (directory_list_size += 10) * sizeof (char *);
|
||||
pushd_directory_list = (char **)xrealloc (pushd_directory_list, j);
|
||||
}
|
||||
pushd_directory_list[directory_list_offset++] = dir;
|
||||
}
|
||||
|
||||
static int
|
||||
get_dirstack_index (ind, sign, indexp)
|
||||
int ind, sign, *indexp;
|
||||
{
|
||||
if (indexp)
|
||||
*indexp = sign > 0 ? 1 : 2;
|
||||
|
||||
/* dirs +0 prints the current working directory. */
|
||||
/* dirs -0 prints last element in directory stack */
|
||||
if (ind == 0 && sign > 0)
|
||||
return 0;
|
||||
else if (ind == directory_list_offset)
|
||||
{
|
||||
if (indexp)
|
||||
*indexp = sign > 0 ? 2 : 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return (sign > 0 ? directory_list_offset - ind : ind);
|
||||
}
|
||||
|
||||
char *
|
||||
get_dirstack_element (ind, sign)
|
||||
int ind, sign;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = get_dirstack_index (ind, sign, (int *)NULL);
|
||||
return (i < 0 || i > directory_list_offset) ? (char *)NULL
|
||||
: pushd_directory_list[i];
|
||||
}
|
||||
|
||||
void
|
||||
set_dirstack_element (ind, sign, value)
|
||||
int ind, sign;
|
||||
char *value;
|
||||
{
|
||||
int i;
|
||||
|
||||
i = get_dirstack_index (ind, sign, (int *)NULL);
|
||||
if (ind == 0 || i < 0 || i > directory_list_offset)
|
||||
return;
|
||||
free (pushd_directory_list[i]);
|
||||
pushd_directory_list[i] = savestring (value);
|
||||
}
|
||||
|
||||
WORD_LIST *
|
||||
get_directory_stack ()
|
||||
{
|
||||
register int i;
|
||||
WORD_LIST *ret;
|
||||
char *d, *t;
|
||||
|
||||
for (ret = (WORD_LIST *)NULL, i = 0; i < directory_list_offset; i++)
|
||||
{
|
||||
d = polite_directory_format (pushd_directory_list[i]);
|
||||
ret = make_word_list (make_word (d), ret);
|
||||
}
|
||||
/* Now the current directory. */
|
||||
d = get_working_directory ("dirstack");
|
||||
i = 0; /* sentinel to decide whether or not to free d */
|
||||
if (d == 0)
|
||||
d = ".";
|
||||
else
|
||||
{
|
||||
t = polite_directory_format (d);
|
||||
/* polite_directory_format sometimes returns its argument unchanged.
|
||||
If it does not, we can free d right away. If it does, we need to
|
||||
mark d to be deleted later. */
|
||||
if (t != d)
|
||||
{
|
||||
free (d);
|
||||
d = t;
|
||||
}
|
||||
else /* t == d, so d is what we want */
|
||||
i = 1;
|
||||
}
|
||||
ret = make_word_list (make_word (d), ret);
|
||||
if (i)
|
||||
free (d);
|
||||
return ret; /* was (REVERSE_LIST (ret, (WORD_LIST *)); */
|
||||
}
|
||||
#endif /* PUSHD_AND_POPD */
|
||||
@@ -0,0 +1,90 @@
|
||||
static char *dirs_doc[] = {
|
||||
"Display the list of currently remembered directories. Directories",
|
||||
"find their way onto the list with the `pushd' command; you can get",
|
||||
"back up through the list with the `popd' command.",
|
||||
"",
|
||||
"The -l flag specifies that `dirs' should not print shorthand versions",
|
||||
"of directories which are relative to your home directory. This means",
|
||||
"that `~/bin' might be displayed as `/homes/bfox/bin'. The -v flag",
|
||||
"causes `dirs' to print the directory stack with one entry per line,",
|
||||
"prepending the directory name with its position in the stack. The -p",
|
||||
"flag does the same thing, but the stack position is not prepended.",
|
||||
"The -c flag clears the directory stack by deleting all of the elements.",
|
||||
"",
|
||||
"+N displays the Nth entry counting from the left of the list shown by",
|
||||
" dirs when invoked without options, starting with zero.",
|
||||
"",
|
||||
"-N displays the Nth entry counting from the right of the list shown by",
|
||||
" dirs when invoked without options, starting with zero.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
static char *pushd_doc[] = {
|
||||
"Adds a directory to the top of the directory stack, or rotates",
|
||||
"the stack, making the new top of the stack the current working",
|
||||
"directory. With no arguments, exchanges the top two directories.",
|
||||
"",
|
||||
"+N Rotates the stack so that the Nth directory (counting",
|
||||
" from the left of the list shown by `dirs', starting with"
|
||||
" zero) is at the top.",
|
||||
"",
|
||||
"-N Rotates the stack so that the Nth directory (counting",
|
||||
" from the right of the list shown by `dirs', starting with"
|
||||
" zero) is at the top.",
|
||||
"",
|
||||
"-n suppress the normal change of directory when adding directories",
|
||||
" to the stack, so only the stack is manipulated.",
|
||||
"",
|
||||
"dir adds DIR to the directory stack at the top, making it the",
|
||||
" new current working directory.",
|
||||
"",
|
||||
"You can see the directory stack with the `dirs' command.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
static char *popd_doc[] = {
|
||||
"Removes entries from the directory stack. With no arguments,",
|
||||
"removes the top directory from the stack, and cd's to the new",
|
||||
"top directory.",
|
||||
"",
|
||||
"+N removes the Nth entry counting from the left of the list",
|
||||
" shown by `dirs', starting with zero. For example: `popd +0'",
|
||||
" removes the first directory, `popd +1' the second.",
|
||||
"",
|
||||
"-N removes the Nth entry counting from the right of the list",
|
||||
" shown by `dirs', starting with zero. For example: `popd -0'",
|
||||
" removes the last directory, `popd -1' the next to last.",
|
||||
"",
|
||||
"-n suppress the normal change of directory when removing directories",
|
||||
" from the stack, so only the stack is manipulated.",
|
||||
"",
|
||||
"You can see the directory stack with the `dirs' command.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin pushd_struct = {
|
||||
"pushd",
|
||||
pushd_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
pushd_doc,
|
||||
"pushd [+N | -N] [-n] [dir]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin popd_struct = {
|
||||
"popd",
|
||||
popd_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
popd_doc,
|
||||
"popd [+N | -N] [-n]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin dirs_struct = {
|
||||
"dirs",
|
||||
dirs_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
dirs_doc,
|
||||
"dirs [-clpv] [+N] [-N]",
|
||||
0
|
||||
};
|
||||
@@ -0,0 +1,514 @@
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if !defined(BUILTIN) && !defined(SHELL)
|
||||
#ifndef lint
|
||||
static char copyright[] =
|
||||
"@(#) Copyright (c) 1989, 1993\n\
|
||||
The Regents of the University of California. All rights reserved.\n";
|
||||
#endif /* not lint */
|
||||
#endif
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 7/20/93";
|
||||
#endif /* not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bashansi.h"
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "stdc.h"
|
||||
|
||||
#if !defined (errno)
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
static char sbuf[1024];
|
||||
static int sblen;
|
||||
|
||||
/* Gee, I wish sprintf could be reliably counted upon to return the
|
||||
number of characters written :-( */
|
||||
#define PF(f, func) \
|
||||
do { \
|
||||
if (fieldwidth) \
|
||||
if (precision) \
|
||||
sprintf(sbuf, f, fieldwidth, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, fieldwidth, func); \
|
||||
else if (precision) \
|
||||
sprintf(sbuf, f, precision, func); \
|
||||
else \
|
||||
sprintf(sbuf, f, func); \
|
||||
spaddstr (sbuf, strlen (sbuf)); \
|
||||
} while (0)
|
||||
|
||||
static int asciicode __P((void));
|
||||
static void escape __P((char *));
|
||||
static int getchr __P((void));
|
||||
static double getdouble __P((void));
|
||||
static int getint __P((int *));
|
||||
static int getlong __P((long *));
|
||||
static char *getstr __P((void));
|
||||
static char *mklong __P((char *, int));
|
||||
static void usage __P((void));
|
||||
|
||||
static char **gargv;
|
||||
|
||||
static char *outstr;
|
||||
static int outsize;
|
||||
static int outind;
|
||||
|
||||
int sprintf_builtin ();
|
||||
static int sprintf_main ();
|
||||
static void spaddstr ();
|
||||
|
||||
extern char *this_command_name;
|
||||
extern char *single_quote ();
|
||||
extern char **make_builtin_argv ();
|
||||
|
||||
static char *sprintf_doc[] = {
|
||||
"sprintf formats and outputs its arguments, after the second, under control",
|
||||
"of the format and assigns the result to the variable named by its first",
|
||||
"argument. The format is a character string which contains three types",
|
||||
"of objects: plain characters, which are simply copied to the output string,",
|
||||
"character escape sequences which are converted and copied to the output",
|
||||
"string, and format specifications, each of which causes printing of the",
|
||||
"next successive argument. In addition to the standard sprintf(3) formats,",
|
||||
"%b means to expand escapes in the corresponding argument, and %q means",
|
||||
"to quote the argument in a way that can be reused as shell input. Each",
|
||||
"one of the format specifications must not expand to more than 1024",
|
||||
"characters, though there is no limit on the total size of the output",
|
||||
"string.",
|
||||
(char *)NULL
|
||||
};
|
||||
|
||||
struct builtin sprintf_struct = {
|
||||
"sprintf",
|
||||
sprintf_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
sprintf_doc,
|
||||
"sprintf var format [arguments]",
|
||||
(char *)0
|
||||
};
|
||||
|
||||
int
|
||||
sprintf_builtin (list)
|
||||
WORD_LIST *list;
|
||||
{
|
||||
int c, r;
|
||||
char **v, *varname;
|
||||
WORD_LIST *l;
|
||||
SHELL_VAR *var;
|
||||
|
||||
if (list == 0)
|
||||
{
|
||||
builtin_usage ();
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
varname = list->word->word;
|
||||
list = list->next;
|
||||
|
||||
if (legal_identifier (varname) == 0)
|
||||
{
|
||||
builtin_error ("%s: not a legal variable name", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
outind = 0;
|
||||
if (outstr == 0)
|
||||
outstr = xmalloc (outsize = 64);
|
||||
outstr[0] = '\0';
|
||||
|
||||
v = make_builtin_argv (list, &c);
|
||||
r = sprintf_main (c, v);
|
||||
free (v);
|
||||
|
||||
var = bind_variable (varname, outstr);
|
||||
if (readonly_p (var))
|
||||
{
|
||||
builtin_error ("%s: readonly variable", varname);
|
||||
return (EXECUTION_FAILURE);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
spaddstr(str, len)
|
||||
char *str;
|
||||
int len;
|
||||
{
|
||||
RESIZE_MALLOCED_BUFFER (outstr, outind, len, outsize, 64);
|
||||
strcpy (outstr + outind, str);
|
||||
outind += len;
|
||||
}
|
||||
|
||||
static int
|
||||
sprintf_main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
extern int optind;
|
||||
static char *skip1, *skip2;
|
||||
int ch, end, fieldwidth, precision;
|
||||
char convch, nextch, *format, *fmt, *start;
|
||||
|
||||
while ((ch = getopt(argc, argv, "")) != EOF)
|
||||
switch (ch) {
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (argc < 1) {
|
||||
usage();
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Basic algorithm is to scan the format string for conversion
|
||||
* specifications -- once one is found, find out if the field
|
||||
* width or precision is a '*'; if it is, gather up value. Note,
|
||||
* format strings are reused as necessary to use up the provided
|
||||
* arguments, arguments of zero/null string are provided to use
|
||||
* up the format string.
|
||||
*/
|
||||
skip1 = "#-+ 0";
|
||||
skip2 = "*0123456789";
|
||||
|
||||
escape(fmt = format = *argv); /* backslash interpretation */
|
||||
gargv = ++argv;
|
||||
for (;;) {
|
||||
end = 0;
|
||||
/* find next format specification */
|
||||
next: for (start = fmt;; ++fmt) {
|
||||
if (!*fmt) {
|
||||
/* avoid infinite loop */
|
||||
if (end == 1) {
|
||||
warnx("missing format character",
|
||||
NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
end = 1;
|
||||
if (fmt > start)
|
||||
(void)printf("%s", start);
|
||||
if (!*gargv)
|
||||
return (0);
|
||||
fmt = format;
|
||||
goto next;
|
||||
}
|
||||
/* %% prints a % */
|
||||
if (*fmt == '%') {
|
||||
if (*++fmt != '%')
|
||||
break;
|
||||
*fmt++ = '\0';
|
||||
(void)printf("%s", start);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip to field width */
|
||||
for (; strchr(skip1, *fmt); ++fmt);
|
||||
if (*fmt == '*') {
|
||||
if (getint(&fieldwidth))
|
||||
return (1);
|
||||
} else
|
||||
fieldwidth = 0;
|
||||
|
||||
/* skip to possible '.', get following precision */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (*fmt == '.')
|
||||
++fmt;
|
||||
if (*fmt == '*') {
|
||||
if (getint(&precision))
|
||||
return (1);
|
||||
} else
|
||||
precision = 0;
|
||||
|
||||
/* skip to conversion char */
|
||||
for (; strchr(skip2, *fmt); ++fmt);
|
||||
if (!*fmt) {
|
||||
warnx("missing format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
|
||||
convch = *fmt;
|
||||
nextch = *++fmt;
|
||||
*fmt = '\0';
|
||||
switch(convch) {
|
||||
case 'c': {
|
||||
char p;
|
||||
|
||||
p = getchr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 's': {
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
case 'b': { /* expand escapes in argument */
|
||||
char *p;
|
||||
|
||||
p = getstr();
|
||||
escape(p);
|
||||
PF("%s", p);
|
||||
break;
|
||||
}
|
||||
case 'q': { /* print with shell single quoting */
|
||||
char *p, *p2;
|
||||
|
||||
p = getstr();
|
||||
p2 = single_quote(p);
|
||||
PF("%s", p2);
|
||||
free(p2);
|
||||
break;
|
||||
}
|
||||
case 'd': case 'i': case 'o': case 'u': case 'x': case 'X': {
|
||||
long p;
|
||||
char *f;
|
||||
|
||||
if ((f = mklong(start, convch)) == NULL)
|
||||
return (1);
|
||||
if (getlong(&p))
|
||||
return (1);
|
||||
PF(f, p);
|
||||
break;
|
||||
}
|
||||
case 'e': case 'E': case 'f': case 'g': case 'G': {
|
||||
double p;
|
||||
|
||||
p = getdouble();
|
||||
PF(start, p);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
warnx("illegal format character", NULL, NULL);
|
||||
return (1);
|
||||
}
|
||||
*fmt = nextch;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
static char *
|
||||
mklong(str, ch)
|
||||
char *str;
|
||||
int ch;
|
||||
{
|
||||
static char copy[64];
|
||||
int len;
|
||||
|
||||
len = strlen(str) + 2;
|
||||
memmove(copy, str, len - 3);
|
||||
copy[len - 3] = 'l';
|
||||
copy[len - 2] = ch;
|
||||
copy[len - 1] = '\0';
|
||||
return (copy);
|
||||
}
|
||||
|
||||
static void
|
||||
escape(fmt)
|
||||
register char *fmt;
|
||||
{
|
||||
register char *store;
|
||||
register int value, c;
|
||||
|
||||
for (store = fmt; c = *fmt; ++fmt, ++store) {
|
||||
if (c != '\\') {
|
||||
*store = c;
|
||||
continue;
|
||||
}
|
||||
switch (*++fmt) {
|
||||
case '\0': /* EOS, user error */
|
||||
*store = '\\';
|
||||
*++store = '\0';
|
||||
return;
|
||||
case '\\': /* backslash */
|
||||
case '\'': /* single quote */
|
||||
*store = *fmt;
|
||||
break;
|
||||
case 'a': /* bell/alert */
|
||||
*store = '\7';
|
||||
break;
|
||||
case 'b': /* backspace */
|
||||
*store = '\b';
|
||||
break;
|
||||
case 'c':
|
||||
return;
|
||||
case 'e':
|
||||
case 'E':
|
||||
*store = '\033';
|
||||
break;
|
||||
case 'f': /* form-feed */
|
||||
*store = '\f';
|
||||
break;
|
||||
case 'n': /* newline */
|
||||
*store = '\n';
|
||||
break;
|
||||
case 'r': /* carriage-return */
|
||||
*store = '\r';
|
||||
break;
|
||||
case 't': /* horizontal tab */
|
||||
*store = '\t';
|
||||
break;
|
||||
case 'v': /* vertical tab */
|
||||
*store = '\13';
|
||||
break;
|
||||
/* octal constant */
|
||||
case '0': case '1': case '2': case '3':
|
||||
case '4': case '5': case '6': case '7':
|
||||
for (c = 3, value = 0;
|
||||
c-- && *fmt >= '0' && *fmt <= '7'; ++fmt) {
|
||||
value <<= 3;
|
||||
value += *fmt - '0';
|
||||
}
|
||||
--fmt;
|
||||
*store = value;
|
||||
break;
|
||||
default:
|
||||
*store = *fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*store = '\0';
|
||||
}
|
||||
|
||||
static int
|
||||
getchr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ('\0');
|
||||
return ((int)**gargv++);
|
||||
}
|
||||
|
||||
static char *
|
||||
getstr()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ("");
|
||||
return (*gargv++);
|
||||
}
|
||||
|
||||
static char *Number = "+-.0123456789";
|
||||
static int
|
||||
getint(ip)
|
||||
int *ip;
|
||||
{
|
||||
long val;
|
||||
|
||||
if (getlong(&val))
|
||||
return (1);
|
||||
if (val > INT_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
*ip = val;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
getlong(lp)
|
||||
long *lp;
|
||||
{
|
||||
long val;
|
||||
char *ep;
|
||||
|
||||
if (!*gargv) {
|
||||
*lp = 0;
|
||||
return (0);
|
||||
}
|
||||
if (strchr(Number, **gargv)) {
|
||||
errno = 0;
|
||||
val = strtol(*gargv, &ep, 0);
|
||||
if (*ep != '\0') {
|
||||
warnx("%s: illegal number", *gargv, NULL);
|
||||
return (1);
|
||||
}
|
||||
if (errno == ERANGE)
|
||||
if (val == LONG_MAX) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
if (val == LONG_MIN) {
|
||||
warnx("%s: %s", *gargv, strerror(ERANGE));
|
||||
return (1);
|
||||
}
|
||||
|
||||
*lp = val;
|
||||
++gargv;
|
||||
return (0);
|
||||
}
|
||||
*lp = (long)asciicode();
|
||||
return (0);
|
||||
}
|
||||
|
||||
static double
|
||||
getdouble()
|
||||
{
|
||||
if (!*gargv)
|
||||
return ((double)0);
|
||||
if (strchr(Number, **gargv))
|
||||
return (atof(*gargv++));
|
||||
return ((double)asciicode());
|
||||
}
|
||||
|
||||
static int
|
||||
asciicode()
|
||||
{
|
||||
register int ch;
|
||||
|
||||
ch = **gargv;
|
||||
if (ch == '\'' || ch == '"')
|
||||
ch = (*gargv)[1];
|
||||
++gargv;
|
||||
return (ch);
|
||||
}
|
||||
|
||||
static void
|
||||
usage()
|
||||
{
|
||||
(void)fprintf(stderr, "usage: printf format [arg ...]\n");
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Originally from
|
||||
* http://www.excessus.demon.co.uk/misc-hacks/index.html#xtitle
|
||||
*/
|
||||
|
||||
/*
|
||||
* Made into a loadable builtin by chet@po.cwru.edu.
|
||||
*/
|
||||
|
||||
#if defined (HAVE_CONFIG_H)
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <termios.h>
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
#include "shell.h"
|
||||
#include "builtins.h"
|
||||
#include "bashgetopt.h"
|
||||
#endif
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
int xtitle_builtin(WORD_LIST *list)
|
||||
#else
|
||||
int main(int argc, char *argv[])
|
||||
#endif
|
||||
{
|
||||
int query = 0;
|
||||
int fd;
|
||||
int openned = 0;
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
reset_internal_getopt();
|
||||
#endif
|
||||
for (;;) {
|
||||
#ifdef BASH_BUILTIN
|
||||
int i;
|
||||
i = internal_getopt(list, "q");
|
||||
#else
|
||||
int i = getopt(argc, argv, "q");
|
||||
#endif
|
||||
if (i < 0)
|
||||
break;
|
||||
switch (i) {
|
||||
case 'q':
|
||||
query = 1;
|
||||
break;
|
||||
default:
|
||||
#ifdef BASH_BUILTIN
|
||||
builtin_usage();
|
||||
#else
|
||||
fprintf(stderr, "usage: xtitle [-q] [string]\n");
|
||||
#endif
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
if (!query && loptend == 0) {
|
||||
#else
|
||||
if (!query && optind == argc) {
|
||||
#endif
|
||||
fprintf(stderr, "xtitle: no string to set\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
{
|
||||
char *t = getenv("TERM");
|
||||
if (!t || strncmp(t, "xterm", 5))
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (isatty(0))
|
||||
fd = 0;
|
||||
else {
|
||||
fd = open("/dev/tty", O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "xtitle: couldn't open terminal: %s", strerror(errno));
|
||||
return (1);
|
||||
}
|
||||
openned = 1;
|
||||
}
|
||||
|
||||
if (!query) {
|
||||
#ifdef BASH_BUILTIN
|
||||
WORD_LIST *l = loptend;
|
||||
char sp = ' ';
|
||||
write(fd, "\33]0;", 4);
|
||||
while (l) {
|
||||
write(fd, l->word->word, strlen(l->word->word));
|
||||
if (l->next)
|
||||
write(fd, &sp, 1);
|
||||
l = l->next;
|
||||
}
|
||||
write(fd, "\33\\", 2);
|
||||
#else
|
||||
int i;
|
||||
char sp = ' ';
|
||||
write(fd, "\33]0;", 4);
|
||||
for (i = optind; i < argc; i++) {
|
||||
write(fd, argv[i], strlen(argv[i]));
|
||||
if (i < argc - 1)
|
||||
write(fd, &sp, 1);
|
||||
}
|
||||
write(fd, "\33\\", 2);
|
||||
#endif
|
||||
} else {
|
||||
struct termios o, n;
|
||||
char hack;
|
||||
int state = 0;
|
||||
|
||||
tcgetattr(fd, &o);
|
||||
n = o;
|
||||
n.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|
||||
|INLCR|IGNCR|ICRNL|IXON);
|
||||
n.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
|
||||
n.c_cflag &= ~(CSIZE|PARENB);
|
||||
n.c_cflag |= CS8;
|
||||
tcsetattr(fd, TCSAFLUSH, &n);
|
||||
write(fd, "\33[21t", 5);
|
||||
|
||||
while (state != -1) {
|
||||
if (read(fd, &hack, 1) < 1)
|
||||
break;
|
||||
switch (state) {
|
||||
case 0:
|
||||
if (hack == '\33') state = 1;
|
||||
break;
|
||||
case 1:
|
||||
if (hack == ']') state = 2; else state = 0;
|
||||
break;
|
||||
case 2:
|
||||
if (hack == 'l') state = 3; else state = 0;
|
||||
break;
|
||||
case 3:
|
||||
if (hack == '\33') state = 4; else putchar(hack);
|
||||
break;
|
||||
case 4:
|
||||
if (hack == '\\') { state = -1; putchar('\n'); }
|
||||
else { putchar('\33'); putchar(hack); state = 3; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tcsetattr(fd, TCSAFLUSH, &o);
|
||||
}
|
||||
|
||||
if (openned)
|
||||
close(fd);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef BASH_BUILTIN
|
||||
|
||||
static char *xtitle_doc[] = {
|
||||
"Either set or read the title of the current xterm window. With the",
|
||||
"-q option, writes the current xterm title to standard output. Without",
|
||||
"the -q option, sets the xterm title to be the arguments given,",
|
||||
"separated by space characters. [By Mark Wooding, mdw@nsict.org]",
|
||||
0
|
||||
};
|
||||
|
||||
struct builtin xtitle_struct = {
|
||||
"xtitle",
|
||||
xtitle_builtin,
|
||||
BUILTIN_ENABLED,
|
||||
xtitle_doc,
|
||||
"xtitle [-q] [arguments]",
|
||||
0
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user