summaryrefslogtreecommitdiff
path: root/libtecla-1.6.1/direader.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2011-04-08 17:36:40 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2011-04-08 17:36:40 +0000
commit124da02af7a348eed58d7e3580d5176421171070 (patch)
tree8f2b8978157de21be5434e9ec5b4b5f87c46ef21 /libtecla-1.6.1/direader.c
parentf6bb837f7810457e0399a12610705143909f7040 (diff)
2011-04-08 Joel Sherrill <joel.sherrill@oarcorp.com>
* bit: Update to libtecl-1.6.1 * libtecla-1.6.1/CHANGES, libtecla-1.6.1/INSTALL, libtecla-1.6.1/LICENSE.TERMS, libtecla-1.6.1/Makefile, libtecla-1.6.1/Makefile.in, libtecla-1.6.1/Makefile.rules, libtecla-1.6.1/Makefile.stub, libtecla-1.6.1/PORTING, libtecla-1.6.1/README, libtecla-1.6.1/RELEASE.NOTES, libtecla-1.6.1/chrqueue.c, libtecla-1.6.1/chrqueue.h, libtecla-1.6.1/config.guess, libtecla-1.6.1/config.sub, libtecla-1.6.1/configure, libtecla-1.6.1/configure.in, libtecla-1.6.1/cplfile.c, libtecla-1.6.1/cplfile.h, libtecla-1.6.1/cplmatch.c, libtecla-1.6.1/cplmatch.h, libtecla-1.6.1/demo.c, libtecla-1.6.1/demo2.c, libtecla-1.6.1/demo3.c, libtecla-1.6.1/direader.c, libtecla-1.6.1/direader.h, libtecla-1.6.1/enhance.c, libtecla-1.6.1/errmsg.c, libtecla-1.6.1/errmsg.h, libtecla-1.6.1/expand.c, libtecla-1.6.1/expand.h, libtecla-1.6.1/freelist.c, libtecla-1.6.1/freelist.h, libtecla-1.6.1/getline.c, libtecla-1.6.1/getline.h, libtecla-1.6.1/hash.c, libtecla-1.6.1/hash.h, libtecla-1.6.1/history.c, libtecla-1.6.1/history.h, libtecla-1.6.1/homedir.c, libtecla-1.6.1/homedir.h, libtecla-1.6.1/install-sh, libtecla-1.6.1/ioutil.c, libtecla-1.6.1/ioutil.h, libtecla-1.6.1/keytab.c, libtecla-1.6.1/keytab.h, libtecla-1.6.1/libtecla.h, libtecla-1.6.1/libtecla.map, libtecla-1.6.1/pathutil.c, libtecla-1.6.1/pathutil.h, libtecla-1.6.1/pcache.c, libtecla-1.6.1/stringrp.c, libtecla-1.6.1/stringrp.h, libtecla-1.6.1/strngmem.c, libtecla-1.6.1/strngmem.h, libtecla-1.6.1/update_html, libtecla-1.6.1/update_version, libtecla-1.6.1/version.c, libtecla-1.6.1/html/changes.html, libtecla-1.6.1/html/cpl_complete_word.html, libtecla-1.6.1/html/ef_expand_file.html, libtecla-1.6.1/html/enhance.html, libtecla-1.6.1/html/gl_get_line.html, libtecla-1.6.1/html/gl_io_mode.html, libtecla-1.6.1/html/index.html, libtecla-1.6.1/html/libtecla.html, libtecla-1.6.1/html/pca_lookup_file.html, libtecla-1.6.1/html/release.html, libtecla-1.6.1/html/tecla.html, libtecla-1.6.1/man/file/teclarc.in, libtecla-1.6.1/man/func/cfc_file_start.in, libtecla-1.6.1/man/func/cfc_literal_escapes.in, libtecla-1.6.1/man/func/cfc_set_check_fn.in, libtecla-1.6.1/man/func/cpl_add_completion.in, libtecla-1.6.1/man/func/cpl_complete_word.in, libtecla-1.6.1/man/func/cpl_file_completions.in, libtecla-1.6.1/man/func/cpl_last_error.in, libtecla-1.6.1/man/func/cpl_list_completions.in, libtecla-1.6.1/man/func/cpl_recall_matches.in, libtecla-1.6.1/man/func/cpl_record_error.in, libtecla-1.6.1/man/func/del_CplFileConf.in, libtecla-1.6.1/man/func/del_ExpandFile.in, libtecla-1.6.1/man/func/del_GetLine.in, libtecla-1.6.1/man/func/del_PathCache.in, libtecla-1.6.1/man/func/del_PcaPathConf.in, libtecla-1.6.1/man/func/del_WordCompletion.in, libtecla-1.6.1/man/func/ef_expand_file.in, libtecla-1.6.1/man/func/ef_last_error.in, libtecla-1.6.1/man/func/ef_list_expansions.in, libtecla-1.6.1/man/func/gl_abandon_line.in, libtecla-1.6.1/man/func/gl_bind_keyseq.in, libtecla-1.6.1/man/func/gl_catch_blocked.in, libtecla-1.6.1/man/func/gl_change_terminal.in, libtecla-1.6.1/man/func/gl_clear_history.in, libtecla-1.6.1/man/func/gl_completion_action.in, libtecla-1.6.1/man/func/gl_configure_getline.in, libtecla-1.6.1/man/func/gl_customize_completion.in, libtecla-1.6.1/man/func/gl_display_text.in, libtecla-1.6.1/man/func/gl_echo_mode.in, libtecla-1.6.1/man/func/gl_erase_terminal.in, libtecla-1.6.1/man/func/gl_error_message.in, libtecla-1.6.1/man/func/gl_get_line.in, libtecla-1.6.1/man/func/gl_group_history.in, libtecla-1.6.1/man/func/gl_handle_signal.in, libtecla-1.6.1/man/func/gl_ignore_signal.in, libtecla-1.6.1/man/func/gl_inactivity_timeout.in, libtecla-1.6.1/man/func/gl_io_mode.in, libtecla-1.6.1/man/func/gl_last_signal.in, libtecla-1.6.1/man/func/gl_limit_history.in, libtecla-1.6.1/man/func/gl_list_signals.in, libtecla-1.6.1/man/func/gl_load_history.in, libtecla-1.6.1/man/func/gl_lookup_history.in, libtecla-1.6.1/man/func/gl_normal_io.in, libtecla-1.6.1/man/func/gl_pending_io.in, libtecla-1.6.1/man/func/gl_prompt_style.in, libtecla-1.6.1/man/func/gl_query_char.in, libtecla-1.6.1/man/func/gl_range_of_history.in, libtecla-1.6.1/man/func/gl_raw_io.in, libtecla-1.6.1/man/func/gl_read_char.in, libtecla-1.6.1/man/func/gl_register_action.in, libtecla-1.6.1/man/func/gl_resize_history.in, libtecla-1.6.1/man/func/gl_return_status.in, libtecla-1.6.1/man/func/gl_save_history.in, libtecla-1.6.1/man/func/gl_set_term_size.in, libtecla-1.6.1/man/func/gl_show_history.in, libtecla-1.6.1/man/func/gl_size_of_history.in, libtecla-1.6.1/man/func/gl_state_of_history.in, libtecla-1.6.1/man/func/gl_terminal_size.in, libtecla-1.6.1/man/func/gl_toggle_history.in, libtecla-1.6.1/man/func/gl_trap_signal.in, libtecla-1.6.1/man/func/gl_tty_signals.in, libtecla-1.6.1/man/func/gl_watch_fd.in, libtecla-1.6.1/man/func/libtecla_version.in, libtecla-1.6.1/man/func/new_CplFileConf.in, libtecla-1.6.1/man/func/new_ExpandFile.in, libtecla-1.6.1/man/func/new_GetLine.in, libtecla-1.6.1/man/func/new_PathCache.in, libtecla-1.6.1/man/func/new_PcaPathConf.in, libtecla-1.6.1/man/func/new_WordCompletion.in, libtecla-1.6.1/man/func/pca_last_error.in, libtecla-1.6.1/man/func/pca_lookup_file.in, libtecla-1.6.1/man/func/pca_path_completions.in, libtecla-1.6.1/man/func/pca_scan_path.in, libtecla-1.6.1/man/func/pca_set_check_fn.in, libtecla-1.6.1/man/func/ppc_file_start.in, libtecla-1.6.1/man/func/ppc_literal_escapes.in, libtecla-1.6.1/man/libr/libtecla.in, libtecla-1.6.1/man/misc/tecla.in, libtecla-1.6.1/man/prog/enhance.in: New files. * libtecla-1.4.1/CHANGES, libtecla-1.4.1/INSTALL, libtecla-1.4.1/LICENSE.TERMS, libtecla-1.4.1/Makefile, libtecla-1.4.1/Makefile.in, libtecla-1.4.1/Makefile.rules, libtecla-1.4.1/Makefile.stub, libtecla-1.4.1/PORTING, libtecla-1.4.1/README, libtecla-1.4.1/RELEASE.NOTES, libtecla-1.4.1/config.guess, libtecla-1.4.1/config.sub, libtecla-1.4.1/configure, libtecla-1.4.1/configure.in, libtecla-1.4.1/cplfile.c, libtecla-1.4.1/cplfile.h, libtecla-1.4.1/cplmatch.c, libtecla-1.4.1/demo.c, libtecla-1.4.1/demo2.c, libtecla-1.4.1/direader.c, libtecla-1.4.1/direader.h, libtecla-1.4.1/enhance.c, libtecla-1.4.1/expand.c, libtecla-1.4.1/freelist.c, libtecla-1.4.1/freelist.h, libtecla-1.4.1/getline.c, libtecla-1.4.1/getline.h, libtecla-1.4.1/hash.c, libtecla-1.4.1/hash.h, libtecla-1.4.1/history.c, libtecla-1.4.1/history.h, libtecla-1.4.1/homedir.c, libtecla-1.4.1/homedir.h, libtecla-1.4.1/install-sh, libtecla-1.4.1/keytab.c, libtecla-1.4.1/keytab.h, libtecla-1.4.1/libtecla.h, libtecla-1.4.1/libtecla.map, libtecla-1.4.1/pathutil.c, libtecla-1.4.1/pathutil.h, libtecla-1.4.1/pcache.c, libtecla-1.4.1/stringrp.c, libtecla-1.4.1/stringrp.h, libtecla-1.4.1/strngmem.c, libtecla-1.4.1/strngmem.h, libtecla-1.4.1/update_html, libtecla-1.4.1/update_version, libtecla-1.4.1/version.c, libtecla-1.4.1/html/changes.html, libtecla-1.4.1/html/cpl_complete_word.html, libtecla-1.4.1/html/ef_expand_file.html, libtecla-1.4.1/html/enhance.html, libtecla-1.4.1/html/gl_get_line.html, libtecla-1.4.1/html/index.html, libtecla-1.4.1/html/libtecla.html, libtecla-1.4.1/html/pca_lookup_file.html, libtecla-1.4.1/html/release.html, libtecla-1.4.1/man3/cfc_file_start.3, libtecla-1.4.1/man3/cfc_literal_escapes.3, libtecla-1.4.1/man3/cfc_set_check_fn.3, libtecla-1.4.1/man3/cpl_add_completion.3, libtecla-1.4.1/man3/cpl_complete_word.3, libtecla-1.4.1/man3/cpl_file_completions.3, libtecla-1.4.1/man3/cpl_last_error.3, libtecla-1.4.1/man3/cpl_list_completions.3, libtecla-1.4.1/man3/cpl_record_error.3, libtecla-1.4.1/man3/del_CplFileConf.3, libtecla-1.4.1/man3/del_ExpandFile.3, libtecla-1.4.1/man3/del_GetLine.3, libtecla-1.4.1/man3/del_PathCache.3, libtecla-1.4.1/man3/del_PcaPathConf.3, libtecla-1.4.1/man3/del_WordCompletion.3, libtecla-1.4.1/man3/ef_expand_file.3, libtecla-1.4.1/man3/ef_last_error.3, libtecla-1.4.1/man3/ef_list_expansions.3, libtecla-1.4.1/man3/enhance.3, libtecla-1.4.1/man3/gl_change_terminal.3, libtecla-1.4.1/man3/gl_clear_history.3, libtecla-1.4.1/man3/gl_configure_getline.3, libtecla-1.4.1/man3/gl_customize_completion.3, libtecla-1.4.1/man3/gl_echo_mode.3, libtecla-1.4.1/man3/gl_get_line.3, libtecla-1.4.1/man3/gl_group_history.3, libtecla-1.4.1/man3/gl_ignore_signal.3, libtecla-1.4.1/man3/gl_last_signal.3, libtecla-1.4.1/man3/gl_limit_history.3, libtecla-1.4.1/man3/gl_load_history.3, libtecla-1.4.1/man3/gl_lookup_history.3, libtecla-1.4.1/man3/gl_prompt_style.3, libtecla-1.4.1/man3/gl_range_of_history.3, libtecla-1.4.1/man3/gl_resize_history.3, libtecla-1.4.1/man3/gl_save_history.3, libtecla-1.4.1/man3/gl_show_history.3, libtecla-1.4.1/man3/gl_size_of_history.3, libtecla-1.4.1/man3/gl_state_of_history.3, libtecla-1.4.1/man3/gl_terminal_size.3, libtecla-1.4.1/man3/gl_toggle_history.3, libtecla-1.4.1/man3/gl_trap_signal.3, libtecla-1.4.1/man3/gl_watch_fd.3, libtecla-1.4.1/man3/libtecla.3, libtecla-1.4.1/man3/libtecla_version.3, libtecla-1.4.1/man3/new_CplFileConf.3, libtecla-1.4.1/man3/new_ExpandFile.3, libtecla-1.4.1/man3/new_GetLine.3, libtecla-1.4.1/man3/new_PathCache.3, libtecla-1.4.1/man3/new_PcaPathConf.3, libtecla-1.4.1/man3/new_WordCompletion.3, libtecla-1.4.1/man3/pca_last_error.3, libtecla-1.4.1/man3/pca_lookup_file.3, libtecla-1.4.1/man3/pca_path_completions.3, libtecla-1.4.1/man3/pca_scan_path.3, libtecla-1.4.1/man3/pca_set_check_fn.3, libtecla-1.4.1/man3/ppc_file_start.3, libtecla-1.4.1/man3/ppc_literal_escapes.3: Removed.
Diffstat (limited to 'libtecla-1.6.1/direader.c')
-rw-r--r--libtecla-1.6.1/direader.c309
1 files changed, 309 insertions, 0 deletions
diff --git a/libtecla-1.6.1/direader.c b/libtecla-1.6.1/direader.c
new file mode 100644
index 0000000..68db93f
--- /dev/null
+++ b/libtecla-1.6.1/direader.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2000, 2001, 2002, 2003, 2004 by Martin C. Shepherd.
+ *
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
+ * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ */
+
+/*
+ * If file-system access is to be excluded, this module has no function,
+ * so all of its code should be excluded.
+ */
+#ifndef WITHOUT_FILE_SYSTEM
+
+/*
+ * Standard includes.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * Operating system includes.
+ */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include "direader.h"
+#include "errmsg.h"
+
+/*
+ * Use the reentrant POSIX threads version of readdir()?
+ */
+#if defined(PREFER_REENTRANT) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L
+#define USE_READDIR_R 1
+#endif
+
+/*
+ * Objects of the following type are used to maintain the resources
+ * needed to read directories.
+ */
+struct DirReader {
+ ErrMsg *err; /* The error reporting buffer */
+ DIR *dir; /* The directory stream (if open, NULL otherwise) */
+ struct dirent *file; /* The latest directory entry */
+#ifdef USE_READDIR_R
+ struct dirent *buffer; /* A buffer used by the threaded version of */
+ /* readdir() */
+ int buffer_dim; /* The allocated size of buffer[] */
+#endif
+};
+
+static int _dr_path_is_dir(const char *pathname);
+
+/*.......................................................................
+ * Create a new DirReader object.
+ *
+ * Output:
+ * return DirReader * The new object, or NULL on error.
+ */
+DirReader *_new_DirReader(void)
+{
+ DirReader *dr; /* The object to be returned */
+/*
+ * Allocate the container.
+ */
+ dr = (DirReader *) malloc(sizeof(DirReader));
+ if(!dr) {
+ errno = ENOMEM;
+ return NULL;
+ };
+/*
+ * Before attempting any operation that might fail, initialize the
+ * container at least up to the point at which it can safely be passed
+ * to _del_DirReader().
+ */
+ dr->err = NULL;
+ dr->dir = NULL;
+ dr->file = NULL;
+#ifdef USE_READDIR_R
+ dr->buffer = NULL;
+ dr->buffer_dim = 0;
+#endif
+/*
+ * Allocate a place to record error messages.
+ */
+ dr->err = _new_ErrMsg();
+ if(!dr->err)
+ return _del_DirReader(dr);
+ return dr;
+}
+
+/*.......................................................................
+ * Delete a DirReader object.
+ *
+ * Input:
+ * dr DirReader * The object to be deleted.
+ * Output:
+ * return DirReader * The deleted object (always NULL).
+ */
+DirReader *_del_DirReader(DirReader *dr)
+{
+ if(dr) {
+ _dr_close_dir(dr);
+#ifdef USE_READDIR_R
+ free(dr->buffer);
+#endif
+ dr->err = _del_ErrMsg(dr->err);
+ free(dr);
+ };
+ return NULL;
+}
+
+/*.......................................................................
+ * Open a new directory.
+ *
+ * Input:
+ * dr DirReader * The directory reader resource object.
+ * path const char * The directory to be opened.
+ * Input/Output:
+ * errmsg char ** If an error occurs and errmsg isn't NULL, a
+ * pointer to an error description will be assigned
+ * to *errmsg.
+ * Output:
+ * return int 0 - OK.
+ * 1 - Error (see *errmsg for a description).
+ */
+int _dr_open_dir(DirReader *dr, const char *path, char **errmsg)
+{
+ DIR *dir = NULL; /* The directory stream */
+/*
+ * If a directory is already open, close it first.
+ */
+ (void) _dr_close_dir(dr);
+/*
+ * Is the path a directory?
+ */
+ if(!_dr_path_is_dir(path)) {
+ if(errmsg) {
+ _err_record_msg(dr->err, "Can't open directory: ", path, END_ERR_MSG);
+ *errmsg = _err_get_msg(dr->err);
+ };
+ return 1;
+ };
+/*
+ * Attempt to open the directory.
+ */
+ dir = opendir(path);
+ if(!dir) {
+ if(errmsg) {
+ _err_record_msg(dr->err, "Can't open directory: ", path, END_ERR_MSG);
+ *errmsg = _err_get_msg(dr->err);
+ };
+ return 1;
+ };
+/*
+ * If using POSIX threads, allocate a buffer for readdir_r().
+ */
+#ifdef USE_READDIR_R
+ {
+ size_t size;
+ int name_max = pathconf(path, _PC_NAME_MAX);
+#ifdef NAME_MAX
+ if(name_max < 0)
+ name_max = NAME_MAX;
+#endif
+ if(name_max < 0) {
+ if(errmsg) {
+ _err_record_msg(dr->err, "Unable to deduce readdir() buffer size.",
+ END_ERR_MSG);
+ *errmsg = _err_get_msg(dr->err);
+ };
+ closedir(dir);
+ return 1;
+ };
+/*
+ * How big a buffer do we need to allocate?
+ */
+ size = sizeof(struct dirent) + name_max;
+/*
+ * Extend the buffer?
+ */
+ if(size > dr->buffer_dim || !dr->buffer) {
+ struct dirent *buffer = (struct dirent *) (dr->buffer ?
+ realloc(dr->buffer, size) :
+ malloc(size));
+ if(!buffer) {
+ if(errmsg) {
+ _err_record_msg(dr->err, "Insufficient memory for readdir() buffer.",
+ END_ERR_MSG);
+ *errmsg = _err_get_msg(dr->err);
+ };
+ closedir(dir);
+ errno = ENOMEM;
+ return 1;
+ };
+ dr->buffer = buffer;
+ dr->buffer_dim = size;
+ };
+ };
+#endif
+/*
+ * Record the successfully opened directory.
+ */
+ dr->dir = dir;
+ return 0;
+}
+
+/*.......................................................................
+ * If the DirReader object is currently contains an open directory,
+ * close it.
+ *
+ * Input:
+ * dr DirReader * The directory reader resource object.
+ */
+void _dr_close_dir(DirReader *dr)
+{
+ if(dr && dr->dir) {
+ closedir(dr->dir);
+ dr->dir = NULL;
+ dr->file = NULL;
+ _err_clear_msg(dr->err);
+ };
+}
+
+/*.......................................................................
+ * Read the next file from the directory opened with _dr_open_dir().
+ *
+ * Input:
+ * dr DirReader * The directory reader resource object.
+ * Output:
+ * return char * The name of the new file, or NULL if we reached
+ * the end of the directory.
+ */
+char *_dr_next_file(DirReader *dr)
+{
+/*
+ * Are we currently reading a directory?
+ */
+ if(dr->dir) {
+/*
+ * Read the next directory entry.
+ */
+#ifdef USE_READDIR_R
+ if(readdir_r(dr->dir, dr->buffer, &dr->file) == 0 && dr->file)
+ return dr->file->d_name;
+#else
+ dr->file = readdir(dr->dir);
+ if(dr->file)
+ return dr->file->d_name;
+#endif
+ };
+/*
+ * When the end of a directory is reached, close it.
+ */
+ _dr_close_dir(dr);
+ return NULL;
+}
+
+/*.......................................................................
+ * Return 1 if the specified pathname refers to a directory.
+ *
+ * Input:
+ * pathname const char * The path to test.
+ * Output:
+ * return int 0 - Not a directory.
+ * 1 - pathname[] refers to a directory.
+ */
+static int _dr_path_is_dir(const char *pathname)
+{
+ struct stat statbuf; /* The file-statistics return buffer */
+/*
+ * Look up the file attributes.
+ */
+ if(stat(pathname, &statbuf) < 0)
+ return 0;
+/*
+ * Is the file a directory?
+ */
+ return S_ISDIR(statbuf.st_mode) != 0;
+}
+
+#endif /* ifndef WITHOUT_FILE_SYSTEM */