home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
rtsi.com
/
2014.01.www.rtsi.com.tar
/
www.rtsi.com
/
OS9
/
OSK
/
CMDS
/
memacs400_src.lzh
/
MEMACS400
/
SRC
/
posix.c
< prev
next >
Wrap
Text File
|
1996-04-25
|
15KB
|
759 lines
/***
POSIX driver/Microemacs 3.11a,
Copyright 1989-1995 D. Lawrence, C. Smith
Copyright 1992 H. Becker
***/
/**
1. FIONREAD is not defined in POSIX. TYPEAH should be 0.
**/
/** Include files **/
#include <stdio.h> /* Standard I/O definitions */
#include "estruct.h" /* Emacs definitions */
/** Do nothing routine **/
int scnothing()
{
return(0);
}
/** Include files **/
#include "eproto.h" /* Function definitions */
#include "edef.h" /* Global variable definitions */
#include "elang.h" /* Language definitions */
/** Kill predefined **/
#undef CTRL /* Problems with CTRL */
/** Overall include files **/
#include <sys/types.h> /* System type definitions */
#include <sys/stat.h> /* File status definitions */
#include <fcntl.h> /* I/O control definitions */
/** Additional include files **/
#include <signal.h> /* Signal definitions */
#include <termios.h> /* Terminal I/O definitions */
#include <unistd.h> /* unix i/o definitions */
/** Completion include files **/
/** Directory accessing: Try and figure this out... if you can! **/
#include <dirent.h> /* Directory entry definitions */
#define DIRENTRY dirent
/** Restore predefined definitions **/
#undef CTRL /* Restore CTRL */
#define CTRL 0x0100
/** Parameters **/
#define NKEYENT 300 /* Number of keymap entries */
#define NINCHAR 64 /* Input buffer size */
#define NOUTCHAR 256 /* Output buffer size */
#define MARGIN 8 /* Margin size */
#define SCRSIZ 64 /* Scroll for margin */
#define NPAUSE 10 /* # times thru update to pause */
#define MAXVTIME 1 /* x/10s max time for i/o delay */
/** CONSTANTS **/
#define TIMEOUT 255 /* No character available */
/** Type definitions **/
struct keyent { /* Key mapping entry */
struct keyent * samlvl; /* Character on same level */
struct keyent * nxtlvl; /* Character on next level */
unsigned char ch; /* Character */
int code; /* Resulting keycode */
};
char *reset = (char*) NULL; /* reset string kjc */
/** Local variables **/
static struct termios curterm; /* Current modes */
static struct termios oldterm; /* Original modes */
static int inbuf[NINCHAR]; /* Input buffer */
static int * inbufh = /* Head of input buffer */
inbuf;
static int * inbuft = /* Tail of input buffer */
inbuf;
static unsigned char keyseq[256]; /* Prefix escape sequence table */
static struct keyent keymap[NKEYENT]; /* Key map */
static struct keyent * nxtkey = /* Next free key entry */
keymap;
static DIR *dirptr = NULL; /* Current directory stream */
static char path[NFILEN]; /* Path of file to find */
static char rbuf[NFILEN]; /* Return file buffer */
static char *nameptr; /* Ptr past end of path in rbuf */
#if ANSI
#define ttbeep ansibeep
#define ttmove ansimove
#else /* ANSI */
#if TERMCAP
#define ttbeep tcapbeep
#define ttmove tcapmove
#endif
/** Terminal definition block **/
/*
int scclose(), ttgetc(), ttputc(), ttflush();
int ttmove(), sceeol(), sceeop(), ttbeep(), screv();
*/
int ttbeep(), ttmove();
#if COLOR
int scfcol(), scbcol();
#endif /* COLOR */
/** Open terminal device **/
int ttopen()
{
/* look for LINES, COLUMNS in env, use it */
int row, col;
char *cp;
if (NULL!=(cp=getenv("LINES"))) {
sscanf (cp, "%d", &row);
if (row) {
term.t_mrow= row-1;
term.t_nrow= row-1;
}
}
if (NULL!=(cp=getenv("COLUMNS"))) {
sscanf (cp, "%d", &col);
if (col) {
term.t_mcol= col;
term.t_ncol= col;
}
}
/* Get modes */
if (tcgetattr(STDIN_FILENO, &oldterm)) {
perror("Cannot tcgetattr");
return(-1);
}
/* Save to original mode variable */
curterm = oldterm;
/* Set new modes */
curterm.c_iflag &= ~(INLCR|ICRNL|IGNCR);
#if XONXOFF
curterm.c_iflag |= IXON | IXOFF;
#endif
curterm.c_lflag &= ~(ICANON|ISIG|ECHO);
curterm.c_cc[VMIN] = 1;
curterm.c_cc[VTIME] = 0;
/* Set tty mode */
if (tcsetattr(STDIN_FILENO, TCSANOW, &curterm)) {
perror("Cannot tcsetattr");
return(-1);
}
/* Success */
return(0);
}
/** Close terminal device **/
int ttclose()
{
/* Restore original terminal modes */
if (reset != (char*)NULL)
write(STDOUT_FILENO, reset, strlen(reset));
/* Set tty mode */
if (tcsetattr(STDIN_FILENO, TCSANOW, &oldterm))
return(-1);
/* Success */
return(0);
}
/** Flush output buffer to display **/
int ttflush()
{
/*
tcflush(STDOUT_FILENO, TCOFLUSH);
*/
fflush (stdout);
return(0);
}
/** Put character onto display **/
int ttputc(ch)
char ch; /* Character to display */
{
/*
return(write(STDOUT_FILENO, &ch, 1) != 1);
*/
fputc (ch, stdout);
}
/** Add character sequence to keycode entry **/
void addkey(seq, fn)
unsigned char * seq; /* Character sequence */
int fn; /* Resulting keycode */
{
int first;
struct keyent * cur, * nxtcur;
/* Skip on null sequences */
if (!seq)
return;
/* Skip single character sequences */
if (strlen(seq) < 2)
return;
/* If no keys defined, go directly to insert mode */
first = 1;
if (nxtkey != keymap) {
/* Start at top of key map */
cur = keymap;
/* Loop until matches exhast */
while (*seq) {
/* Do we match current character */
if (*seq == cur->ch) {
/* Advance to next level */
seq++;
cur = cur->nxtlvl;
first = 0;
} else {
/* Try next character on same level */
nxtcur = cur->samlvl;
/* Stop if no more */
if (nxtcur)
cur = nxtcur;
else
break;
}
}
}
/* Check for room in keymap */
if (strlen(seq) > NKEYENT - (nxtkey - keymap))
return;
/* If first character in sequence is inserted, add to prefix table */
if (first)
keyseq[*seq] = 1;
/* If characters are left over, insert them into list */
for (first = 1; *seq; first = 0) {
/* Make new entry */
nxtkey->ch = *seq++;
nxtkey->code = fn;
/* If root, nothing to do */
if (nxtkey != keymap) {
/* Set first to samlvl, others to nxtlvl */
if (first)
cur->samlvl = nxtkey;
else
cur->nxtlvl = nxtkey;
}
/* Advance to next key */
cur = nxtkey++;
}
}
/** Grab input characters, with wait **/
unsigned char grabwait()
{
unsigned char ch;
/* Change mode, if necessary */
if (curterm.c_cc[VTIME]) {
curterm.c_cc[VMIN] = 1;
curterm.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO, TCSANOW, &curterm);
}
/* Perform read */
if (read(0, &ch, 1) != 1) {
puts("** Horrible read error occured **");
exit(1);
}
/* Return new character */
return(ch);
}
/** Grab input characters, short wait **/
unsigned char grabnowait()
{
int count;
unsigned char ch;
/* Change mode, if necessary */
if (curterm.c_cc[VTIME] == 0) {
curterm.c_cc[VMIN] = 0;
curterm.c_cc[VTIME] = MAXVTIME;
tcsetattr(STDIN_FILENO, TCSANOW, &curterm);
}
/* Perform read */
count = read(0, &ch, 1);
if (count < 0) {
puts("** Horrible read error occured **");
exit(1);
}
if (count == 0)
return(TIMEOUT);
/* Return new character */
return(ch);
}
/** Queue input character **/
void qin(ch)
int ch; /* Character to add */
{
/* Check for overflow */
if (inbuft == &inbuf[sizeof(inbuf)]) {
/* Annoy user */
ttbeep();
return;
}
/* Add character */
*inbuft++ = ch;
}
/** Cook input characters **/
void cook()
{
unsigned char ch;
struct keyent * cur;
/* Get first character untimed */
ch = grabwait();
qin(ch);
/* Skip if the key isn't a special leading escape sequence */
if (keyseq[ch] == 0)
return;
/* Start at root of keymap */
cur = keymap;
/* Loop until keymap exhasts */
while (cur) {
/* Did we find a matching character */
if (cur->ch == ch) {
/* Is this the end */
if (cur->nxtlvl == NULL) {
/* Replace all character with new sequence */
inbuft = inbuf;
qin(cur->code);
return;
} else {
/* Advance to next level */
cur = cur->nxtlvl;
/* Get next character, timed */
ch = grabnowait();
if (ch == TIMEOUT)
return;
/* Queue character */
qin(ch);
}
} else
/* Try next character on same level */
cur = cur->samlvl;
}
}
/** Return cooked characters **/
int ttgetc()
{
int ch;
/* Loop until character found */
while (1) {
/* Get input from buffer, if available */
if (inbufh != inbuft) {
ch = *inbufh++;
if (inbufh == inbuft)
inbufh = inbuft = inbuf;
break;
} else
/* Fill input buffer */
cook();
}
/* Return next character */
return(ch);
}
#if TYPEAH
int typahead()
{
unsigned char ch;
/* See if internal buffer is non-empty */
if (inbufh != inbuft)
return(1);
/* Now check with system */
ch= grabnowait();
if (ch==TIMEOUT)
return 0;
qin (ch);
return 1;
}
#endif /* TYPEAH */
/* Surely more than just BSD systems do this */
/** Perform a stop signal **/
int bktoshell(f, n)
{
/* Reset the terminal and go to the last line */
vttidy();
/* Okay, stop... */
kill(getpid(), SIGTSTP);
/* We should now be back here after resuming */
/* Reopen the screen and redraw */
ttopen();
curwp->w_flag = WFHARD;
sgarbf = TRUE;
/* Success */
return(0);
}
/** Get time of day **/
char * timeset()
{
long int buf; /* Should be time_t */
char * sp, * cp;
char * ctime();
/* Get system time */
time(&buf);
/* Pass system time to converter */
sp = ctime(&buf);
/* Eat newline character */
for (cp = sp; *cp; cp++)
if (*cp == '\n') {
*cp = '\0';
break;
}
return(sp);
}
/** Callout to system to perform command **/
int callout(cmd)
char * cmd; /* Command to execute */
{
int status;
/* Close down */
ttmove(term.t_nrow, 0);
ttflush();
ttclose();
/* Do command */
status = system(cmd) == 0;
/* Restart system */
sgarbf = TRUE;
if (ttopen()) {
puts("** Error reopening terminal device **");
exit(1);
}
/* Success */
return(status);
}
/** Create subshell **/
int spawncli(f, n)
int f; /* Flags */
int n; /* Argument count */
{
char * sh;
/* Don't allow this command if restricted */
if (restflag)
return(resterr());
/* Get shell path */
sh = getenv("SHELL");
if (!sh)
sh = "/bin/sh";
/* Do shell */
return(callout(sh));
}
/** Spawn a command **/
int spawn(f, n)
int f; /* Flags */
int n; /* Argument count */
{
char line[NLINE];
int s;
/* Don't allow this command if restricted */
if (restflag)
return(resterr());
/* Get command line */
s = mlreply("!", line, NLINE);
if (!s)
return(s);
/* Perform the command */
s = callout(line);
/* if we are interactive, pause here */
if (clexec == FALSE) {
mlwrite("[End]");
ttflush();
ttgetc();
}
return(s);
}
/** Execute program **/
int execprg(f, n)
int f; /* Flags */
int n; /* Argument count */
{
/* Same as spawn */
return(spawn(f, n));
}
/** Pipe output of program to buffer **/
int pipecmd(f, n)
int f; /* Flags */
int n; /* Argument count */
{
char line[NLINE];
int s;
BUFFER * bp;
EWINDOW * wp;
static char filnam[] = "command";
/* Don't allow this command if restricted */
if (restflag)
return(resterr());
/* Get pipe-in command */
s = mlreply("@", line, NLINE);
if (!s)
return(s);
/* Get rid of the command output buffer if it exists */
bp = bfind(filnam, FALSE, 0);
if (bp) {
/* Try to make sure we are off screen */
wp = wheadp;
while (wp) {
if (wp->w_bufp == bp) {
onlywind(FALSE, 1);
break;
}
wp = wp->w_wndp;
}
if (!zotbuf(bp))
return(0);
}
/* Add output specification */
strcat(line, ">");
strcat(line, filnam);
/* Do command */
s = callout(line);
if (!s)
return(s);
/* Split the current window to make room for the command output */
if (!splitwind(FALSE, 1))
return(0);
/* ...and read the stuff in */
if (!getfile(filnam, FALSE))
return(0);
/* Make this window in VIEW mode, update all mode lines */
curwp->w_bufp->b_mode |= MDVIEW;
wp = wheadp;
while (wp) {
wp->w_flag |= WFMODE;
wp = wp->w_wndp;
}
/* ...and get rid of the temporary file */
unlink(filnam);
return(1);
}
/** Filter buffer through command **/
int filter(f, n)
int f; /* Flags */
int n; /* Argument count */
{
char line[NLINE], tmpnam[NFILEN];
int s;
BUFFER * bp;
static char bname1[] = "fltinp";
static char filnam1[] = "fltinp";
static char filnam2[] = "fltout";
/* Don't allow this command if restricted */
if (restflag)
return(resterr());
/* Don't allow filtering of VIEW mode buffer */
if (curbp->b_mode & MDVIEW)
return(rdonly());
/* Get the filter name and its args */
s = mlreply("#", line, NLINE);
if (!s)
return(s);
/* Setup the proper file names */
bp = curbp;
strcpy(tmpnam, bp->b_fname); /* Save the original name */
strcpy(bp->b_fname, bname1); /* Set it to our new one */
/* Write it out, checking for errors */
if (!writeout(filnam1, "w")) {
mlwrite("[Cannot write filter file]");
strcpy(bp->b_fname, tmpnam);
return(0);
}
/* Setup input and output */
strcat(line," <fltinp >fltout");
/* Perform command */
s = callout(line);
/* If successful, read in file */
if (s) {
s = readin(filnam2, FALSE);
if (s)
/* Mark buffer as changed */
bp->b_flag |= BFCHG;
}
/* Reset file name */
strcpy(bp->b_fname, tmpnam);
/* and get rid of the temporary file */
unlink(filnam1);
unlink(filnam2);
/* Show status */
if (!s)
mlwrite("[Execution failed]");
return(s);
}
/** Get first filename from pattern **/
char *getffile(fspec)
char *fspec; /* Filename specification */
{
int index, point, extflag;
/* First parse the file path off the file spec */
strcpy(path, fspec);
index = strlen(path) - 1;
while (index >= 0 && (path[index] != '/' &&
path[index] != '\\' && path[index] != ':'))
--index;
path[index+1] = '\0';
/* Check for an extension */
point = strlen(fspec) - 1;
extflag = FALSE;
while (point >= 0) {
if (fspec[point] == '.') {
extflag = TRUE;
break;
}
point--;
}
/* Open the directory pointer */
if (dirptr) {
closedir(dirptr);
dirptr = NULL;
}
dirptr = opendir((path[0] == '\0') ? "./" : path);
if (!dirptr)
return(NULL);
strcpy(rbuf, path);
nameptr = &rbuf[strlen(rbuf)];
/* ...and call for the first file */
return(getnfile());
}
/** Get next filename from pattern **/
char *getnfile()
{
int index;
struct DIRENTRY * dp;
struct stat fstat;
/* ...and call for the next file */
do {
dp = readdir(dirptr);
if (!dp)
return(NULL);
/* Check to make sure we skip all weird entries except directories */
strcpy(nameptr, dp->d_name);
} while (stat(rbuf, &fstat) ||
!(S_ISDIR(fstat.st_mode) !! S_ISREG(fstat.st_mode)));
/* if this entry is a directory name, say so */
if (S_ISDIR(fstat.st_mode))
strcat(rbuf, DIRSEPSTR);
/* Return the next file name! */
return(rbuf);
}