1238438Sdteske/* $NetBSD: tc1.c,v 1.7 2016/02/17 19:47:49 christos Exp $ */ 2238438Sdteske 3238438Sdteske/*- 4238438Sdteske * Copyright (c) 1992, 1993 5238438Sdteske * The Regents of the University of California. All rights reserved. 6238438Sdteske * 7238438Sdteske * This code is derived from software contributed to Berkeley by 8238438Sdteske * Christos Zoulas of Cornell University. 9238438Sdteske * 10238438Sdteske * Redistribution and use in source and binary forms, with or without 11238438Sdteske * modification, are permitted provided that the following conditions 12238438Sdteske * are met: 13238438Sdteske * 1. Redistributions of source code must retain the above copyright 14238438Sdteske * notice, this list of conditions and the following disclaimer. 15238438Sdteske * 2. Redistributions in binary form must reproduce the above copyright 16238438Sdteske * notice, this list of conditions and the following disclaimer in the 17238438Sdteske * documentation and/or other materials provided with the distribution. 18238438Sdteske * 3. Neither the name of the University nor the names of its contributors 19238438Sdteske * may be used to endorse or promote products derived from this software 20238438Sdteske * without specific prior written permission. 21238438Sdteske * 22238438Sdteske * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23238438Sdteske * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24238438Sdteske * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25238438Sdteske * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26238438Sdteske * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27238438Sdteske * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28238438Sdteske * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29238438Sdteske * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30238438Sdteske * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31240684Sdteske * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32240684Sdteske * SUCH DAMAGE. 33240684Sdteske */ 34240684Sdteske 35240684Sdteske#include "config.h" 36240684Sdteske#ifndef lint 37238438Sdteske__COPYRIGHT("@(#) Copyright (c) 1992, 1993\n\ 38240684Sdteske The Regents of the University of California. All rights reserved.\n"); 39238438Sdteske#endif /* not lint */ 40238438Sdteske 41238438Sdteske#if !defined(lint) && !defined(SCCSID) 42238438Sdteske#if 0 43238438Sdteskestatic char sccsid[] = "@(#)test.c 8.1 (Berkeley) 6/4/93"; 44238438Sdteske#else 45238438Sdteske__RCSID("$NetBSD: tc1.c,v 1.7 2016/02/17 19:47:49 christos Exp $"); 46238438Sdteske#endif 47238438Sdteske#endif /* not lint && not SCCSID */ 48238438Sdteske 49238438Sdteske/* 50240783Sdteske * test.c: A little test program 51238438Sdteske */ 52238438Sdteske#include <sys/wait.h> 53238438Sdteske#include <ctype.h> 54238438Sdteske#include <dirent.h> 55238438Sdteske#include <locale.h> 56238438Sdteske#include <signal.h> 57238438Sdteske#include <stdio.h> 58238438Sdteske#include <stdlib.h> 59238438Sdteske#include <string.h> 60238438Sdteske#include <unistd.h> 61238438Sdteske 62238438Sdteske#include "histedit.h" 63243504Sdteske 64238438Sdteskestatic int continuation = 0; 65238438Sdteskevolatile sig_atomic_t gotsig = 0; 66238438Sdteske 67238438Sdteskestatic unsigned char complete(EditLine *, int); 68238438Sdteske int main(int, char **); 69238438Sdteskestatic char *prompt(EditLine *); 70238438Sdteskestatic void sig(int); 71238438Sdteske 72238438Sdteskestatic char * 73238438Sdteskeprompt(EditLine *el) 74238438Sdteske{ 75238438Sdteske static char a[] = "\1\033[7m\1Edit$\1\033[0m\1 "; 76243504Sdteske static char b[] = "Edit> "; 77238438Sdteske 78238438Sdteske return (continuation ? b : a); 79238438Sdteske} 80238438Sdteske 81238438Sdteskestatic void 82238438Sdteskesig(int i) 83238438Sdteske{ 84238438Sdteske gotsig = i; 85238438Sdteske} 86238438Sdteske 87238438Sdteskestatic unsigned char 88238438Sdteskecomplete(EditLine *el, int ch) 89238438Sdteske{ 90238438Sdteske DIR *dd = opendir("."); 91238438Sdteske struct dirent *dp; 92238438Sdteske const char* ptr; 93238438Sdteske const LineInfo *lf = el_line(el); 94238438Sdteske int len; 95238438Sdteske int res = CC_ERROR; 96238438Sdteske 97238438Sdteske /* 98238438Sdteske * Find the last word 99238438Sdteske */ 100238438Sdteske for (ptr = lf->cursor - 1; 101238438Sdteske !isspace((unsigned char)*ptr) && ptr > lf->buffer; ptr--) 102238438Sdteske continue; 103238438Sdteske len = lf->cursor - ++ptr; 104238438Sdteske 105238438Sdteske for (dp = readdir(dd); dp != NULL; dp = readdir(dd)) { 106243504Sdteske if (len > strlen(dp->d_name)) 107243504Sdteske continue; 108243504Sdteske if (strncmp(dp->d_name, ptr, len) == 0) { 109243504Sdteske if (el_insertstr(el, &dp->d_name[len]) == -1) 110243504Sdteske res = CC_ERROR; 111243504Sdteske else 112243504Sdteske res = CC_REFRESH; 113243504Sdteske break; 114243504Sdteske } 115238438Sdteske } 116243504Sdteske 117243504Sdteske closedir(dd); 118243504Sdteske return res; 119238438Sdteske} 120238438Sdteske 121238438Sdteskeint 122238438Sdteskemain(int argc, char *argv[]) 123238438Sdteske{ 124238438Sdteske EditLine *el = NULL; 125238438Sdteske int num; 126238438Sdteske const char *buf; 127238438Sdteske Tokenizer *tok; 128243504Sdteske#if 0 129238438Sdteske int lastevent = 0; 130243504Sdteske#endif 131243504Sdteske int ncontinuation; 132243504Sdteske History *hist; 133243504Sdteske HistEvent ev; 134243504Sdteske 135243504Sdteske (void) setlocale(LC_CTYPE, ""); 136243504Sdteske (void) signal(SIGINT, sig); 137243504Sdteske (void) signal(SIGQUIT, sig); 138243504Sdteske (void) signal(SIGHUP, sig); 139243504Sdteske (void) signal(SIGTERM, sig); 140243504Sdteske 141243504Sdteske hist = history_init(); /* Init the builtin history */ 142243504Sdteske /* Remember 100 events */ 143243504Sdteske history(hist, &ev, H_SETSIZE, 100); 144243504Sdteske 145243504Sdteske tok = tok_init(NULL); /* Initialize the tokenizer */ 146243504Sdteske 147238438Sdteske /* Initialize editline */ 148238438Sdteske el = el_init(*argv, stdin, stdout, stderr); 149238438Sdteske 150243504Sdteske el_set(el, EL_EDITOR, "vi"); /* Default editor is vi */ 151243475Sdteske el_set(el, EL_SIGNAL, 1); /* Handle signals gracefully */ 152243475Sdteske el_set(el, EL_PROMPT_ESC, prompt, '\1');/* Set the prompt function */ 153243475Sdteske 154243475Sdteske /* Tell editline to use this history interface */ 155243475Sdteske el_set(el, EL_HIST, history, hist); 156243475Sdteske 157243504Sdteske /* Add a user-defined function */ 158243504Sdteske el_set(el, EL_ADDFN, "ed-complete", "Complete argument", complete); 159243504Sdteske 160243504Sdteske /* Bind tab to it */ 161243504Sdteske el_set(el, EL_BIND, "^I", "ed-complete", NULL); 162243504Sdteske 163243504Sdteske /* 164243504Sdteske * Bind j, k in vi command mode to previous and next line, instead 165243504Sdteske * of previous and next history. 166243504Sdteske */ 167243504Sdteske el_set(el, EL_BIND, "-a", "k", "ed-prev-line", NULL); 168243504Sdteske el_set(el, EL_BIND, "-a", "j", "ed-next-line", NULL); 169243504Sdteske 170243504Sdteske /* 171243504Sdteske * Source the user's defaults file. 172243475Sdteske */ 173243504Sdteske el_source(el, NULL); 174243475Sdteske 175243475Sdteske while ((buf = el_gets(el, &num)) != NULL && num != 0) { 176243475Sdteske int ac, cc, co; 177243475Sdteske#ifdef DEBUG 178243475Sdteske int i; 179243475Sdteske#endif 180243475Sdteske const char **av; 181243475Sdteske const LineInfo *li; 182243475Sdteske li = el_line(el); 183243475Sdteske#ifdef DEBUG 184243475Sdteske (void) fprintf(stderr, "==> got %d %s", num, buf); 185243475Sdteske (void) fprintf(stderr, " > li `%.*s_%.*s'\n", 186243475Sdteske (li->cursor - li->buffer), li->buffer, 187243475Sdteske (li->lastchar - 1 - li->cursor), 188243475Sdteske (li->cursor >= li->lastchar) ? "" : li->cursor); 189243475Sdteske 190243475Sdteske#endif 191243475Sdteske if (gotsig) { 192243475Sdteske (void) fprintf(stderr, "Got signal %d.\n", (int)gotsig); 193243475Sdteske gotsig = 0; 194243475Sdteske el_reset(el); 195243475Sdteske } 196243475Sdteske 197243475Sdteske if (!continuation && num == 1) 198243475Sdteske continue; 199243475Sdteske 200243475Sdteske ac = cc = co = 0; 201243475Sdteske ncontinuation = tok_line(tok, li, &ac, &av, &cc, &co); 202243475Sdteske if (ncontinuation < 0) { 203243475Sdteske (void) fprintf(stderr, "Internal error\n"); 204243475Sdteske continuation = 0; 205243475Sdteske continue; 206243475Sdteske } 207243475Sdteske#ifdef DEBUG 208243475Sdteske (void) fprintf(stderr, " > nc %d ac %d cc %d co %d\n", 209243475Sdteske ncontinuation, ac, cc, co); 210243475Sdteske#endif 211243475Sdteske#if 0 212243475Sdteske if (continuation) { 213243475Sdteske /* 214243475Sdteske * Append to the right event in case the user 215243475Sdteske * moved around in history. 216243475Sdteske */ 217243475Sdteske if (history(hist, &ev, H_SET, lastevent) == -1) 218243475Sdteske err(1, "%d: %s", lastevent, ev.str); 219243475Sdteske history(hist, &ev, H_ADD , buf); 220243475Sdteske } else { 221243475Sdteske history(hist, &ev, H_ENTER, buf); 222243475Sdteske lastevent = ev.num; 223243475Sdteske } 224243475Sdteske#else 225243475Sdteske /* Simpler */ 226243475Sdteske history(hist, &ev, continuation ? H_APPEND : H_ENTER, buf); 227243475Sdteske#endif 228243475Sdteske 229243475Sdteske continuation = ncontinuation; 230243475Sdteske ncontinuation = 0; 231243475Sdteske if (continuation) 232243475Sdteske continue; 233243475Sdteske#ifdef DEBUG 234243475Sdteske for (i = 0; i < ac; i++) { 235243475Sdteske (void) fprintf(stderr, " > arg# %2d ", i); 236243475Sdteske if (i != cc) 237243475Sdteske (void) fprintf(stderr, "`%s'\n", av[i]); 238243475Sdteske else 239243475Sdteske (void) fprintf(stderr, "`%.*s_%s'\n", 240243475Sdteske co, av[i], av[i] + co); 241243475Sdteske } 242243475Sdteske#endif 243243475Sdteske 244243475Sdteske if (strcmp(av[0], "history") == 0) { 245243475Sdteske int rv; 246243504Sdteske 247243504Sdteske switch (ac) { 248243475Sdteske case 1: 249243475Sdteske for (rv = history(hist, &ev, H_LAST); rv != -1; 250243475Sdteske rv = history(hist, &ev, H_PREV)) 251243475Sdteske (void) fprintf(stdout, "%4d %s", 252243475Sdteske ev.num, ev.str); 253243475Sdteske break; 254243475Sdteske 255243475Sdteske case 2: 256243475Sdteske if (strcmp(av[1], "clear") == 0) 257243475Sdteske history(hist, &ev, H_CLEAR); 258243475Sdteske else 259243475Sdteske goto badhist; 260243475Sdteske break; 261243475Sdteske 262243475Sdteske case 3: 263243475Sdteske if (strcmp(av[1], "load") == 0) 264243475Sdteske history(hist, &ev, H_LOAD, av[2]); 265243475Sdteske else if (strcmp(av[1], "save") == 0) 266243475Sdteske history(hist, &ev, H_SAVE, av[2]); 267243475Sdteske break; 268243475Sdteske 269243475Sdteske badhist: 270243475Sdteske default: 271243475Sdteske (void) fprintf(stderr, 272243475Sdteske "Bad history arguments\n"); 273243475Sdteske break; 274243475Sdteske } 275243475Sdteske } else if (el_parse(el, ac, av) == -1) { 276243475Sdteske switch (fork()) { 277243475Sdteske case 0: 278243475Sdteske execvp(av[0], (char *const *)__UNCONST(av)); 279243475Sdteske perror(av[0]); 280243475Sdteske _exit(1); 281243475Sdteske /*NOTREACHED*/ 282243475Sdteske break; 283243504Sdteske 284243475Sdteske case -1: 285243504Sdteske perror("fork"); 286243504Sdteske break; 287243504Sdteske 288243504Sdteske default: 289243504Sdteske if (wait(&num) == -1) 290243504Sdteske perror("wait"); 291243504Sdteske (void) fprintf(stderr, "Exit %x\n", num); 292243504Sdteske break; 293243504Sdteske } 294243504Sdteske } 295243504Sdteske 296243504Sdteske tok_reset(tok); 297243475Sdteske } 298243475Sdteske 299243475Sdteske el_end(el); 300243475Sdteske tok_end(tok); 301243475Sdteske history_end(hist); 302243475Sdteske 303243475Sdteske return (0); 304243475Sdteske} 305243504Sdteske