Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!rutgers!ames!ptsfa!ihnp4!inuxc!iuvax!isrnix!mr From: mr@isrnix.UUCP (a.k.a regoli@silver.bacs.indiana.edu) Newsgroups: comp.sys.ibm.pc Subject: Repost: EMACS 3.8L Source (Part 1 of 9) Message-ID: <869@isrnix.UUCP> Date: Fri, 31-Jul-87 15:23:34 EDT Article-I.D.: isrnix.869 Posted: Fri Jul 31 15:23:34 1987 Date-Received: Sun, 2-Aug-87 08:53:25 EDT Sender: mr@isrnix.UUCP Organization: indiana university, bloomington Lines: 2183 ]:[ hello! since everyone in the country wrote to me at least once saying that this didn't reach them in its entirety, i thought i would give it one last try. a note: my "makeshar" program has a bug in it that will report a zero character file length upon extraction with /bin/sh. don't worry: it's lying. the files extract perfectly. this is the source distribution for EMACS version 3.8L for the pee cee. extract this and the other 8 parts using /bin/sh. --mr --cut-- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # ansi.c # basic.c # bind.c # buffer.c # crypt.c # This archive created: Fri Jul 31 13:54:11 1987 # By: michael regoli (indiana university, bloomington) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'ansi.c'" '(0 character)' if test -f 'ansi.c' then echo shar: "will not over-write existing file 'ansi.c'" else cat << \SHAR_EOF > 'ansi.c' /* * The routines in this file provide support for ANSI style terminals * over a serial line. The serial I/O services are provided by routines in * "termio.c". It compiles into nothing if not an ANSI device. */ #define termdef 1 /* don't define "term" external */ #include #include "estruct.h" #include "edef.h" #if ANSI #if AMIGA #define NROW 23 /* Screen size. */ #define NCOL 77 /* Edit if you want to. */ #else #define NROW 25 /* Screen size. */ #define NCOL 80 /* Edit if you want to. */ #endif #define NPAUSE 100 /* # times thru update to pause */ #define MARGIN 8 /* size of minimim margin and */ #define SCRSIZ 64 /* scroll size for extended lines */ #define BEL 0x07 /* BEL character. */ #define ESC 0x1B /* ESC character. */ extern int ttopen(); /* Forward references. */ extern int ttgetc(); extern int ttputc(); extern int ttflush(); extern int ttclose(); extern int ansimove(); extern int ansieeol(); extern int ansieeop(); extern int ansibeep(); extern int ansiopen(); extern int ansirev(); extern int ansiclose(); extern int ansikopen(); extern int ansikclose(); extern int ansicres(); #if COLOR extern int ansifcol(); extern int ansibcol(); int cfcolor = -1; /* current forground color */ int cbcolor = -1; /* current background color */ #endif /* * Standard terminal interface dispatch table. Most of the fields point into * "termio" code. */ TERM term = { NROW-1, NROW-1, NCOL, NCOL, MARGIN, SCRSIZ, NPAUSE, ansiopen, ansiclose, ansikopen, ansikclose, ttgetc, ttputc, ttflush, ansimove, ansieeol, ansieeop, ansibeep, ansirev, ansicres #if COLOR , ansifcol, ansibcol #endif }; #if COLOR ansifcol(color) /* set the current output color */ int color; /* color to set */ { if (color == cfcolor) return; ttputc(ESC); ttputc('['); ansiparm(color+30); ttputc('m'); cfcolor = color; } ansibcol(color) /* set the current background color */ int color; /* color to set */ { if (color == cbcolor) return; ttputc(ESC); ttputc('['); ansiparm(color+40); ttputc('m'); cbcolor = color; } #endif ansimove(row, col) { ttputc(ESC); ttputc('['); ansiparm(row+1); ttputc(';'); ansiparm(col+1); ttputc('H'); } ansieeol() { ttputc(ESC); ttputc('['); ttputc('K'); } ansieeop() { #if COLOR ansifcol(gfcolor); ansibcol(gbcolor); #endif ttputc(ESC); ttputc('['); ttputc('J'); } ansirev(state) /* change reverse video state */ int state; /* TRUE = reverse, FALSE = normal */ { #if COLOR int ftmp, btmp; /* temporaries for colors */ #endif ttputc(ESC); ttputc('['); ttputc(state ? '7': '0'); ttputc('m'); #if COLOR if (state == FALSE) { ftmp = cfcolor; btmp = cbcolor; cfcolor = -1; cbcolor = -1; ansifcol(ftmp); ansibcol(btmp); } #endif } ansicres() /* change screen resolution */ { return(TRUE); } spal(dummy) /* change pallette settings */ { /* none for now */ } ansibeep() { ttputc(BEL); ttflush(); } ansiparm(n) register int n; { register int q,r; q = n/10; if (q != 0) { r = q/10; if (r != 0) { ttputc((r%10)+'0'); } ttputc((q%10) + '0'); } ttputc((n%10) + '0'); } ansiopen() { #if V7 | USG | BSD register char *cp; char *getenv(); if ((cp = getenv("TERM")) == NULL) { puts("Shell variable TERM not defined!"); exit(1); } if (strcmp(cp, "vt100") != 0) { puts("Terminal type not 'vt100'!"); exit(1); } #endif strcpy(sres, "NORMAL"); revexist = TRUE; ttopen(); } ansiclose() { #if COLOR ansifcol(7); ansibcol(0); #endif ttclose(); } ansikopen() /* open the keyboard (a noop here) */ { } ansikclose() /* close the keyboard (a noop here) */ { } #if FLABEL fnclabel(f, n) /* label a function key */ int f,n; /* default flag, numeric argument [unused] */ { /* on machines with no function keys...don't bother */ return(TRUE); } #endif #else ansihello() { } #endif SHAR_EOF chmod +x 'ansi.c' fi echo shar: "extracting 'basic.c'" '(0 character)' if test -f 'basic.c' then echo shar: "will not over-write existing file 'basic.c'" else cat << \SHAR_EOF > 'basic.c' /* * The routines in this file move the cursor around on the screen. They * compute a new value for the cursor, then adjust ".". The display code * always updates the cursor location, so only moves between lines, or * functions that adjust the top line in the window and invalidate the * framing, are hard. */ #include #include "estruct.h" #include "edef.h" /* * Move the cursor to the * beginning of the current line. * Trivial. */ gotobol(f, n) { curwp->w_doto = 0; return (TRUE); } /* * Move the cursor backwards by "n" characters. If "n" is less than zero call * "forwchar" to actually do the move. Otherwise compute the new cursor * location. Error if you try and move out of the buffer. Set the flag if the * line pointer for dot changes. */ backchar(f, n) register int n; { register LINE *lp; if (n < 0) return (forwchar(f, -n)); while (n--) { if (curwp->w_doto == 0) { if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) return (FALSE); curwp->w_dotp = lp; curwp->w_doto = llength(lp); curwp->w_flag |= WFMOVE; } else curwp->w_doto--; } return (TRUE); } /* * Move the cursor to the end of the current line. Trivial. No errors. */ gotoeol(f, n) { curwp->w_doto = llength(curwp->w_dotp); return (TRUE); } /* * Move the cursor forwards by "n" characters. If "n" is less than zero call * "backchar" to actually do the move. Otherwise compute the new cursor * location, and move ".". Error if you try and move off the end of the * buffer. Set the flag if the line pointer for dot changes. */ forwchar(f, n) register int n; { if (n < 0) return (backchar(f, -n)); while (n--) { if (curwp->w_doto == llength(curwp->w_dotp)) { if (curwp->w_dotp == curbp->b_linep) return (FALSE); curwp->w_dotp = lforw(curwp->w_dotp); curwp->w_doto = 0; curwp->w_flag |= WFMOVE; } else curwp->w_doto++; } return (TRUE); } gotoline(f, n) /* move to a particular line. argument (n) must be a positive integer for this to actually do anything */ { register int status; /* status return */ char arg[NSTRING]; /* buffer to hold argument */ /* get an argument if one doesnt exist */ if (f == FALSE) { if ((status = mlreply("Line to GOTO: ", arg, "")) != TRUE) { mlwrite("[Aborted]"); return(status); } n = atoi(arg); } if (n < 1) /* if a bogus argument...then leave */ return(FALSE); /* first, we go to the start of the buffer */ curwp->w_dotp = lforw(curbp->b_linep); curwp->w_doto = 0; return(forwline(f, n-1)); } /* * Goto the beginning of the buffer. Massive adjustment of dot. This is * considered to be hard motion; it really isn't if the original value of dot * is the same as the new value of dot. Normally bound to "M-<". */ gotobob(f, n) { curwp->w_dotp = lforw(curbp->b_linep); curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Move to the end of the buffer. Dot is always put at the end of the file * (ZJ). The standard screen code does most of the hard parts of update. * Bound to "M->". */ gotoeob(f, n) { curwp->w_dotp = curbp->b_linep; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Move forward by full lines. If the number of lines to move is less than * zero, call the backward line function to actually do it. The last command * controls how the goal column is set. Bound to "C-N". No errors are * possible. */ forwline(f, n) { register LINE *dlp; if (n < 0) return (backline(f, -n)); /* if we are on the last line as we start....fail the command */ if (curwp->w_dotp == curbp->b_linep) return(FALSE); /* if the last command was not note a line move, reset the goal column */ if ((lastflag&CFCPCN) == 0) curgoal = getccol(FALSE); /* flag this command as a line move */ thisflag |= CFCPCN; /* and move the point down */ dlp = curwp->w_dotp; while (n-- && dlp!=curbp->b_linep) dlp = lforw(dlp); /* reseting the current position */ curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } /* * This function is like "forwline", but goes backwards. The scheme is exactly * the same. Check for arguments that are less than zero and call your * alternate. Figure out the new line and call "movedot" to perform the * motion. No errors are possible. Bound to "C-P". */ backline(f, n) { register LINE *dlp; if (n < 0) return (forwline(f, -n)); /* if we are on the last line as we start....fail the command */ if (lback(curwp->w_dotp) == curbp->b_linep) return(FALSE); /* if the last command was not note a line move, reset the goal column */ if ((lastflag&CFCPCN) == 0) curgoal = getccol(FALSE); /* flag this command as a line move */ thisflag |= CFCPCN; /* and move the point up */ dlp = curwp->w_dotp; while (n-- && lback(dlp)!=curbp->b_linep) dlp = lback(dlp); /* reseting the current position */ curwp->w_dotp = dlp; curwp->w_doto = getgoal(dlp); curwp->w_flag |= WFMOVE; return (TRUE); } #if WORDPRO gotobop(f, n) /* go back to the beginning of the current paragraph here we look for a or or combination to delimit the beginning of a paragraph */ int f, n; /* default Flag & Numeric argument */ { register int suc; /* success of last backchar */ if (n < 0) /* the other way...*/ return(gotoeop(f, -n)); while (n-- > 0) { /* for each one asked for */ /* first scan back until we are in a word */ suc = backchar(FALSE, 1); while (!inword() && suc) suc = backchar(FALSE, 1); curwp->w_doto = 0; /* and go to the B-O-Line */ /* and scan back until we hit a or or a */ while (lback(curwp->w_dotp) != curbp->b_linep) if (llength(curwp->w_dotp) != 0 && lgetc(curwp->w_dotp, curwp->w_doto) != TAB && lgetc(curwp->w_dotp, curwp->w_doto) != ' ') curwp->w_dotp = lback(curwp->w_dotp); else break; /* and then forward until we are in a word */ suc = forwchar(FALSE, 1); while (suc && !inword()) suc = forwchar(FALSE, 1); } curwp->w_flag |= WFMOVE; /* force screen update */ return(TRUE); } gotoeop(f, n) /* go forword to the end of the current paragraph here we look for a or or combination to delimit the beginning of a paragraph */ int f, n; /* default Flag & Numeric argument */ { register int suc; /* success of last backchar */ if (n < 0) /* the other way...*/ return(gotobop(f, -n)); while (n-- > 0) { /* for each one asked for */ /* first scan forward until we are in a word */ suc = forwchar(FALSE, 1); while (!inword() && suc) suc = forwchar(FALSE, 1); curwp->w_doto = 0; /* and go to the B-O-Line */ if (suc) /* of next line if not at EOF */ curwp->w_dotp = lforw(curwp->w_dotp); /* and scan forword until we hit a or or a */ while (curwp->w_dotp != curbp->b_linep) { if (llength(curwp->w_dotp) != 0 && lgetc(curwp->w_dotp, curwp->w_doto) != TAB && lgetc(curwp->w_dotp, curwp->w_doto) != ' ') curwp->w_dotp = lforw(curwp->w_dotp); else break; } /* and then backward until we are in a word */ suc = backchar(FALSE, 1); while (suc && !inword()) { suc = backchar(FALSE, 1); } curwp->w_doto = llength(curwp->w_dotp); /* and to the EOL */ } curwp->w_flag |= WFMOVE; /* force screen update */ return(TRUE); } #endif /* * This routine, given a pointer to a LINE, and the current cursor goal * column, return the best choice for the offset. The offset is returned. * Used by "C-N" and "C-P". */ getgoal(dlp) register LINE *dlp; { register int c; register int col; register int newcol; register int dbo; col = 0; dbo = 0; while (dbo != llength(dlp)) { c = lgetc(dlp, dbo); newcol = col; if (c == '\t') newcol |= 0x07; else if (c<0x20 || c==0x7F) ++newcol; ++newcol; if (newcol > curgoal) break; col = newcol; ++dbo; } return (dbo); } /* * Scroll forward by a specified number of lines, or by a full page if no * argument. Bound to "C-V". The "2" in the arithmetic on the window size is * the overlap; this value is the default overlap value in ITS EMACS. Because * this zaps the top line in the display window, we have to do a hard update. */ forwpage(f, n) register int n; { register LINE *lp; if (f == FALSE) { n = curwp->w_ntrows - 2; /* Default scroll. */ if (n <= 0) /* Forget the overlap */ n = 1; /* if tiny window. */ } else if (n < 0) return (backpage(f, -n)); #if CVMVAS else /* Convert from pages */ n *= curwp->w_ntrows; /* to lines. */ #endif lp = curwp->w_linep; while (n-- && lp!=curbp->b_linep) lp = lforw(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * This command is like "forwpage", but it goes backwards. The "2", like * above, is the overlap between the two windows. The value is from the ITS * EMACS manual. Bound to "M-V". We do a hard update for exactly the same * reason. */ backpage(f, n) register int n; { register LINE *lp; if (f == FALSE) { n = curwp->w_ntrows - 2; /* Default scroll. */ if (n <= 0) /* Don't blow up if the */ n = 1; /* window is tiny. */ } else if (n < 0) return (forwpage(f, -n)); #if CVMVAS else /* Convert from pages */ n *= curwp->w_ntrows; /* to lines. */ #endif lp = curwp->w_linep; while (n-- && lback(lp)!=curbp->b_linep) lp = lback(lp); curwp->w_linep = lp; curwp->w_dotp = lp; curwp->w_doto = 0; curwp->w_flag |= WFHARD; return (TRUE); } /* * Set the mark in the current window to the value of "." in the window. No * errors are possible. Bound to "M-.". */ setmark(f, n) { curwp->w_markp = curwp->w_dotp; curwp->w_marko = curwp->w_doto; mlwrite("[Mark set]"); return (TRUE); } /* * Swap the values of "." and "mark" in the current window. This is pretty * easy, bacause all of the hard work gets done by the standard routine * that moves the mark about. The only possible error is "no mark". Bound to * "C-X C-X". */ swapmark(f, n) { register LINE *odotp; register int odoto; if (curwp->w_markp == NULL) { mlwrite("No mark in this window"); return (FALSE); } odotp = curwp->w_dotp; odoto = curwp->w_doto; curwp->w_dotp = curwp->w_markp; curwp->w_doto = curwp->w_marko; curwp->w_markp = odotp; curwp->w_marko = odoto; curwp->w_flag |= WFMOVE; return (TRUE); } SHAR_EOF chmod +x 'basic.c' fi echo shar: "extracting 'bind.c'" '(0 character)' if test -f 'bind.c' then echo shar: "will not over-write existing file 'bind.c'" else cat << \SHAR_EOF > 'bind.c' /* This file is for functions having to do with key bindings, descriptions, help commands and startup file. written 11-feb-86 by Daniel Lawrence */ #include #include "estruct.h" #include "edef.h" #include "epath.h" extern int meta(), cex(), unarg(), ctrlg(); /* dummy prefix binding functions */ deskey(f, n) /* describe the command for a certain key */ { register int c; /* command character to describe */ register char *ptr; /* string pointer to scan output strings */ register KEYTAB *ktp; /* pointer into the command table */ register int found; /* matched command flag */ register NBIND *nptr; /* pointer into the name binding table */ char outseq[80]; /* output buffer for command sequence */ /* prompt the user to type us a key to describe */ mlwrite(": describe-key "); /* get the command sequence to describe */ c = getckey(FALSE); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ if (discmd) { ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); TTputc(' '); /* space it out */ } /* find the right ->function */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } if (!found) strcpy(outseq,"Not Bound"); else { /* match it against the name binding table */ nptr = &names[0]; strcpy(outseq,"[Bad binding]"); while (nptr->n_func != NULL) { if (nptr->n_func == ktp->k_fp) { strcpy(outseq, nptr->n_name); break; } ++nptr; } } /* output the command sequence */ ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); } cmdstr(c, seq) /* change a key command to a string we can print out */ int c; /* sequence to translate */ char *seq; /* destination string for sequence */ { char *ptr; /* pointer into current position in sequence */ ptr = seq; /* apply meta sequence if needed */ if (c & META) { *ptr++ = 'M'; *ptr++ = '-'; } /* apply ^X sequence if needed */ if (c & CTLX) { *ptr++ = '^'; *ptr++ = 'X'; } /* apply SPEC sequence if needed */ if (c & SPEC) { *ptr++ = 'F'; *ptr++ = 'N'; } /* apply control sequence if needed */ if (c & CTRL) { *ptr++ = '^'; } c = c & 255; /* strip the prefixes */ /* and output the final sequence */ *ptr++ = c; *ptr = 0; /* terminate the string */ } help(f, n) /* give me some help!!!! bring up a fake buffer and read the help file into it with view mode */ { register WINDOW *wp; /* scaning pointer to windows */ register BUFFER *bp; /* buffer pointer to help */ char *fname; /* ptr to file returned by flook() */ /* first check if we are already here */ bp = bfind("emacs.hlp", FALSE, BFINVS); if (bp == NULL) { fname = flook(pathname[1], FALSE); if (fname == NULL) { mlwrite("[Help file is not online]"); return(FALSE); } } /* split the current window to make room for the help stuff */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); if (bp == NULL) { /* and read the stuff in */ if (getfile(fname, FALSE) == FALSE) return(FALSE); } else swbuffer(bp); /* make this window in VIEW mode, update all mode lines */ curwp->w_bufp->b_mode |= MDVIEW; curwp->w_bufp->b_flag |= BFINVS; wp = wheadp; while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } return(TRUE); } int (*fncmatch(fname))() /* match fname to a function in the names table and return any match or NULL if none */ char *fname; /* name to attempt to match */ { register NBIND *ffp; /* pointer to entry in name binding table */ /* scan through the table, returning any match */ ffp = &names[0]; while (ffp->n_func != NULL) { if (strcmp(fname, ffp->n_name) == 0) return(ffp->n_func); ++ffp; } return(NULL); } /* bindtokey: add a new key to the key binding table */ bindtokey(f, n) int f, n; /* command arguments [IGNORED] */ { register unsigned int c;/* command key to bind */ register (*kfunc)(); /* ptr to the requexted function to bind to */ register char *ptr; /* ptr to dump out input key string */ register KEYTAB *ktp; /* pointer into the command table */ register int found; /* matched command flag */ char outseq[80]; /* output buffer for keystroke sequence */ int (*getname())(); /* prompt the user to type in a key to bind */ mlwrite(": bind-to-key "); /* get the function name to bind it to */ kfunc = getname(); if (kfunc == NULL) { mlwrite("[No such function]"); return(FALSE); } if (discmd) { TTputc(' '); /* space it out */ TTflush(); } /* get the command sequence to bind */ c = getckey((kfunc == meta) || (kfunc == cex) || (kfunc == unarg) || (kfunc == ctrlg)); /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ if (discmd) { ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); } /* if the function is a prefix key */ if (kfunc == meta || kfunc == cex || kfunc == unarg || kfunc == ctrlg) { /* search for an existing binding for the prefix key */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_fp == kfunc) unbindchar(ktp->k_code); ++ktp; } /* reset the appropriate global prefix variable */ if (kfunc == meta) metac = c; if (kfunc == cex) ctlxc = c; if (kfunc == unarg) reptc = c; if (kfunc == ctrlg) abortc = c; } /* search the table to see if it exists */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } if (found) { /* it exists, just change it then */ ktp->k_fp = kfunc; } else { /* otherwise we need to add it to the end */ /* if we run out of binding room, bitch */ if (ktp >= &keytab[NBINDS]) { mlwrite("Binding table FULL!"); return(FALSE); } ktp->k_code = c; /* add keycode */ ktp->k_fp = kfunc; /* and the function pointer */ ++ktp; /* and make sure the next is null */ ktp->k_code = 0; ktp->k_fp = NULL; } return(TRUE); } /* unbindkey: delete a key from the key binding table */ unbindkey(f, n) int f, n; /* command arguments [IGNORED] */ { register int c; /* command key to unbind */ register char *ptr; /* ptr to dump out input key string */ char outseq[80]; /* output buffer for keystroke sequence */ /* prompt the user to type in a key to unbind */ mlwrite(": unbind-key "); /* get the command sequence to unbind */ c = getckey(FALSE); /* get a command sequence */ /* change it to something we can print as well */ cmdstr(c, &outseq[0]); /* and dump it out */ if (discmd) { ptr = &outseq[0]; while (*ptr) TTputc(*ptr++); } /* if it isn't bound, bitch */ if (unbindchar(c) == FALSE) { mlwrite("[Key not bound]"); return(FALSE); } return(TRUE); } unbindchar(c) int c; /* command key to unbind */ { register KEYTAB *ktp; /* pointer into the command table */ register KEYTAB *sktp; /* saved pointer into the command table */ register int found; /* matched command flag */ /* search the table to see if the key exists */ ktp = &keytab[0]; found = FALSE; while (ktp->k_fp != NULL) { if (ktp->k_code == c) { found = TRUE; break; } ++ktp; } /* if it isn't bound, bitch */ if (!found) return(FALSE); /* save the pointer and scan to the end of the table */ sktp = ktp; while (ktp->k_fp != NULL) ++ktp; --ktp; /* backup to the last legit entry */ /* copy the last entry to the current one */ sktp->k_code = ktp->k_code; sktp->k_fp = ktp->k_fp; /* null out the last one */ ktp->k_code = 0; ktp->k_fp = NULL; return(TRUE); } desbind(f, n) /* describe bindings bring up a fake buffer and list the key bindings into it with view mode */ #if APROP { buildlist(TRUE, ""); } apro(f, n) /* Apropos (List functions that match a substring) */ { char mstring[NSTRING]; /* string to match cmd names to */ int status; /* status return */ status = mlreply("Apropos string: ", mstring, NSTRING - 1); if (status != TRUE) return(status); return(buildlist(FALSE, mstring)); } buildlist(type, mstring) /* build a binding list (limited or full) */ int type; /* true = full list, false = partial list */ char *mstring; /* match string if a partial list */ #endif { #if ST520 & LATTICE #define register #endif register WINDOW *wp; /* scanning pointer to windows */ register KEYTAB *ktp; /* pointer into the command table */ register NBIND *nptr; /* pointer into the name binding table */ register BUFFER *bp; /* buffer to put binding list into */ char *strp; /* pointer int string to send */ int cpos; /* current position to use in outseq */ char outseq[80]; /* output buffer for keystroke sequence */ /* split the current window to make room for the binding list */ if (splitwind(FALSE, 1) == FALSE) return(FALSE); /* and get a buffer for it */ bp = bfind("Binding list", TRUE, 0); if (bp == NULL || bclear(bp) == FALSE) { mlwrite("Can not display binding list"); return(FALSE); } /* let us know this is in progress */ mlwrite("[Building binding list]"); /* disconect the current buffer */ if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } /* connect the current window to this buffer */ curbp = bp; /* make this buffer current in current window */ bp->b_mode = 0; /* no modes active in binding list */ bp->b_nwnd++; /* mark us as more in use */ wp = curwp; wp->w_bufp = bp; wp->w_linep = bp->b_linep; wp->w_flag = WFHARD|WFFORCE; wp->w_dotp = bp->b_dotp; wp->w_doto = bp->b_doto; wp->w_markp = NULL; wp->w_marko = 0; /* build the contents of this window, inserting it line by line */ nptr = &names[0]; while (nptr->n_func != NULL) { /* add in the command name */ strcpy(outseq, nptr->n_name); cpos = strlen(outseq); #if APROP /* if we are executing an apropos command..... */ if (type == FALSE && /* and current string doesn't include the search string */ strinc(outseq, mstring) == FALSE) goto fail; #endif /* search down any keys bound to this */ ktp = &keytab[0]; while (ktp->k_fp != NULL) { if (ktp->k_fp == nptr->n_func) { /* padd out some spaces */ while (cpos < 25) outseq[cpos++] = ' '; /* add in the command sequence */ cmdstr(ktp->k_code, &outseq[cpos]); while (outseq[cpos] != 0) ++cpos; /* and add it as a line into the buffer */ strp = &outseq[0]; while (*strp != 0) linsert(1, *strp++); lnewline(); cpos = 0; /* and clear the line */ } ++ktp; } /* if no key was bound, we need to dump it anyway */ if (cpos > 0) { outseq[cpos] = 0; strp = &outseq[0]; while (*strp != 0) linsert(1, *strp++); lnewline(); } fail: /* and on to the next name */ ++nptr; } curwp->w_bufp->b_mode |= MDVIEW;/* put this buffer view mode */ curbp->b_flag &= ~BFCHG; /* don't flag this as a change */ wp->w_dotp = lforw(bp->b_linep);/* back to the beginning */ wp->w_doto = 0; wp = wheadp; /* and update ALL mode lines */ while (wp != NULL) { wp->w_flag |= WFMODE; wp = wp->w_wndp; } mlwrite(""); /* clear the mode line */ return(TRUE); } #if APROP strinc(source, sub) /* does source include sub? */ char *source; /* string to search in */ char *sub; /* substring to look for */ { char *sp; /* ptr into source */ char *nxtsp; /* next ptr into source */ char *tp; /* ptr into substring */ /* for each character in the source string */ sp = source; while (*sp) { tp = sub; nxtsp = sp; /* is the substring here? */ while (*tp) { if (*nxtsp++ != *tp) break; else tp++; } /* yes, return a success */ if (*tp == 0) return(TRUE); /* no, onward */ sp++; } return(FALSE); } #endif /* get a command key sequence from the keyboard */ unsigned int getckey(mflag) int mflag; /* going for a meta sequence? */ { register unsigned int c; /* character fetched */ #if MSC register unsigned char *tp; /* pointer into the token */ #else register char *tp; /* pointer into the token */ #endif char tok[NSTRING]; /* command incoming */ /* check to see if we are executing a command line */ if (clexec) { macarg(tok); /* get the next token */ /* parse it up */ tp = &tok[0]; c = 0; /* first, the META prefix */ if (*tp == 'M' && *(tp+1) == '-') { c = META; tp += 2; } /* next the function prefix */ if (*tp == 'F' && *(tp+1) == 'N') { c |= SPEC; tp += 2; } /* control-x as well... */ if (*tp == '^' && *(tp+1) == 'X') { c |= CTLX; tp += 2; } /* a control char? */ if (*tp == '^' && *(tp+1) != 0) { c |= CTRL; ++tp; } /* make sure we are not lower case (not with function keys)*/ if (c >= 'a' && c <= 'z' && !(c & SPEC)) c -= 32; /* the final sequence... */ c |= *tp; return(c); } /* or the normal way */ if (mflag) c = get1key(); else c = getcmd(); return(c); } /* execute the startup file */ startup(sfname) char *sfname; /* name of startup file (null if default) */ { char *fname; /* resulting file name to execute */ /* look up the startup file */ if (*sfname != 0) fname = flook(sfname, TRUE); else fname = flook(pathname[0], TRUE); /* if it isn't around, don't sweat it */ if (fname == NULL) return(TRUE); /* otherwise, execute the sucker */ return(dofile(fname)); } /* Look up the existance of a file along the normal or PATH environment variable. Look first in the HOME directory if asked and possible */ char *flook(fname, hflag) char *fname; /* base file name to search for */ int hflag; /* Look in the HOME environment variable first? */ { register char *home; /* path to home directory */ register char *path; /* environmental PATH variable */ register char *sp; /* pointer into path spec */ register int i; /* index */ register int status; /* return status */ static char fspec[NSTRING]; /* full path spec to search */ char *getenv(); #if ((MSDOS) & (LATTICE | AZTEC | MSC)) | V7 | USG | BSD if (hflag) { home = getenv("HOME"); if (home != NULL) { /* build home dir file spec */ strcpy(fspec, home); strcat(fspec, "/"); strcat(fspec, fname); /* and try it out */ status = ffropen(fspec); if (status == FIOSUC) { ffclose(); return(fspec); } } } /* get the PATH variable */ path = getenv("PATH"); if (path != NULL) while (*path) { /* build next possible file spec */ sp = fspec; while (*path && (*path != PATHCHR)) *sp++ = *path++; *sp++ = '/'; *sp = 0; strcat(fspec, fname); /* and try it out */ status = ffropen(fspec); if (status == FIOSUC) { ffclose(); return(fspec); } if (*path == PATHCHR) ++path; } #endif /* look it up via the old table method */ for (i=2; i < NPNAMES; i++) { strcpy(fspec, pathname[i]); strcat(fspec, fname); /* and try it out */ status = ffropen(fspec); if (status == FIOSUC) { ffclose(); return(fspec); } } return(NULL); /* no such luck */ } SHAR_EOF chmod +x 'bind.c' fi echo shar: "extracting 'buffer.c'" '(0 character)' if test -f 'buffer.c' then echo shar: "will not over-write existing file 'buffer.c'" else cat << \SHAR_EOF > 'buffer.c' /* * Buffer management. * Some of the functions are internal, * and some are actually attached to user * keys. Like everyone else, they set hints * for the display system. */ #include #include "estruct.h" #include "edef.h" /* * Attach a buffer to a window. The * values of dot and mark come from the buffer * if the use count is 0. Otherwise, they come * from some other window. */ usebuffer(f, n) { register BUFFER *bp; register int s; char bufn[NBUFN]; if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE) return (s); if ((bp=bfind(bufn, TRUE, 0)) == NULL) return (FALSE); return(swbuffer(bp)); } nextbuffer(f, n) /* switch to the next buffer in the buffer list */ int f, n; /* default flag, numeric argument */ { register BUFFER *bp; /* eligable buffer to switch to*/ register BUFFER *bbp; /* eligable buffer to switch to*/ /* make sure the arg is legit */ if (f == FALSE) n = 1; if (n < 1) return(FALSE); bbp = curbp; while (n-- > 0) { /* advance to the next buffer */ bp = bbp->b_bufp; /* cycle through the buffers to find an eligable one */ while (bp == NULL || bp->b_flag & BFINVS) { if (bp == NULL) bp = bheadp; else bp = bp->b_bufp; /* don't get caught in an infinite loop! */ if (bp == bbp) return(FALSE); } bbp = bp; } return(swbuffer(bp)); } swbuffer(bp) /* make buffer BP current */ BUFFER *bp; { register WINDOW *wp; if (--curbp->b_nwnd == 0) { /* Last use. */ curbp->b_dotp = curwp->w_dotp; curbp->b_doto = curwp->w_doto; curbp->b_markp = curwp->w_markp; curbp->b_marko = curwp->w_marko; } curbp = bp; /* Switch. */ if (curbp->b_active != TRUE) { /* buffer not active yet*/ /* read it in and activate it */ readin(curbp->b_fname, TRUE); curbp->b_dotp = lforw(curbp->b_linep); curbp->b_doto = 0; curbp->b_active = TRUE; } curwp->w_bufp = bp; curwp->w_linep = bp->b_linep; /* For macros, ignored. */ curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */ if (bp->b_nwnd++ == 0) { /* First use. */ curwp->w_dotp = bp->b_dotp; curwp->w_doto = bp->b_doto; curwp->w_markp = bp->b_markp; curwp->w_marko = bp->b_marko; return (TRUE); } wp = wheadp; /* Look for old. */ while (wp != NULL) { if (wp!=curwp && wp->w_bufp==bp) { curwp->w_dotp = wp->w_dotp; curwp->w_doto = wp->w_doto; curwp->w_markp = wp->w_markp; curwp->w_marko = wp->w_marko; break; } wp = wp->w_wndp; } return (TRUE); } /* * Dispose of a buffer, by name. * Ask for the name. Look it up (don't get too * upset if it isn't there at all!). Get quite upset * if the buffer is being displayed. Clear the buffer (ask * if the buffer has been changed). Then free the header * line and the buffer header. Bound to "C-X K". */ killbuffer(f, n) { register BUFFER *bp; register int s; char bufn[NBUFN]; if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE) return(s); if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */ return (TRUE); if(bp->b_flag & BFINVS) /* Deal with special buffers */ return (TRUE); /* by doing nothing. */ return(zotbuf(bp)); } zotbuf(bp) /* kill the buffer pointed to by bp */ register BUFFER *bp; { register BUFFER *bp1; register BUFFER *bp2; register int s; if (bp->b_nwnd != 0) { /* Error if on screen. */ mlwrite("Buffer is being displayed"); return (FALSE); } if ((s=bclear(bp)) != TRUE) /* Blow text away. */ return (s); free((char *) bp->b_linep); /* Release header line. */ bp1 = NULL; /* Find the header. */ bp2 = bheadp; while (bp2 != bp) { bp1 = bp2; bp2 = bp2->b_bufp; } bp2 = bp2->b_bufp; /* Next one in chain. */ if (bp1 == NULL) /* Unlink it. */ bheadp = bp2; else bp1->b_bufp = bp2; free((char *) bp); /* Release buffer block */ return (TRUE); } namebuffer(f,n) /* Rename the current buffer */ int f, n; /* default Flag & Numeric arg */ { register BUFFER *bp; /* pointer to scan through all buffers */ char bufn[NBUFN]; /* buffer to hold buffer name */ /* prompt for and get the new buffer name */ ask: if (mlreply("Change buffer name to: ", bufn, NBUFN) != TRUE) return(FALSE); /* and check for duplicates */ bp = bheadp; while (bp != NULL) { if (bp != curbp) { /* if the names the same */ if (strcmp(bufn, bp->b_bname) == 0) goto ask; /* try again */ } bp = bp->b_bufp; /* onward */ } strcpy(curbp->b_bname, bufn); /* copy buffer name to structure */ curwp->w_flag |= WFMODE; /* make mode line replot */ mlerase(); return(TRUE); } /* List all of the active buffers. First update the special buffer that holds the list. Next make sure at least 1 window is displaying the buffer list, splitting the screen if this is what it takes. Lastly, repaint all of the windows that are displaying the list. Bound to "C-X C-B". A numeric argument forces it to list invisable buffers as well. */ listbuffers(f, n) { register WINDOW *wp; register BUFFER *bp; register int s; if ((s=makelist(f)) != TRUE) return (s); if (blistp->b_nwnd == 0) { /* Not on screen yet. */ if ((wp=wpopup()) == NULL) return (FALSE); bp = wp->w_bufp; if (--bp->b_nwnd == 0) { bp->b_dotp = wp->w_dotp; bp->b_doto = wp->w_doto; bp->b_markp = wp->w_markp; bp->b_marko = wp->w_marko; } wp->w_bufp = blistp; ++blistp->b_nwnd; } wp = wheadp; while (wp != NULL) { if (wp->w_bufp == blistp) { wp->w_linep = lforw(blistp->b_linep); wp->w_dotp = lforw(blistp->b_linep); wp->w_doto = 0; wp->w_markp = NULL; wp->w_marko = 0; wp->w_flag |= WFMODE|WFHARD; } wp = wp->w_wndp; } return (TRUE); } /* * This routine rebuilds the * text in the special secret buffer * that holds the buffer list. It is called * by the list buffers command. Return TRUE * if everything works. Return FALSE if there * is an error (if there is no memory). Iflag * indecates weather to list hidden buffers. */ makelist(iflag) int iflag; /* list hidden buffer flag */ { register char *cp1; register char *cp2; register int c; register BUFFER *bp; register LINE *lp; register int s; register int i; long nbytes; /* # of bytes in current buffer */ char b[7+1]; char line[128]; blistp->b_flag &= ~BFCHG; /* Don't complain! */ if ((s=bclear(blistp)) != TRUE) /* Blow old text away */ return (s); strcpy(blistp->b_fname, ""); if (addline("AC MODES Size Buffer File") == FALSE || addline("-- ----- ---- ------ ----") == FALSE) return (FALSE); bp = bheadp; /* For all buffers */ /* build line to report global mode settings */ cp1 = &line[0]; *cp1++ = ' '; *cp1++ = ' '; *cp1++ = ' '; /* output the mode codes */ for (i = 0; i < NUMMODES; i++) if (gmode & (1 << i)) *cp1++ = modecode[i]; else *cp1++ = '.'; strcpy(cp1, " Global Modes"); if (addline(line) == FALSE) return(FALSE); /* output the list of buffers */ while (bp != NULL) { /* skip invisable buffers if iflag is false */ if (((bp->b_flag&BFINVS) != 0) && (iflag != TRUE)) { bp = bp->b_bufp; continue; } cp1 = &line[0]; /* Start at left edge */ /* output status of ACTIVE flag (has the file been read in? */ if (bp->b_active == TRUE) /* "@" if activated */ *cp1++ = '@'; else *cp1++ = ' '; /* output status of changed flag */ if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */ *cp1++ = '*'; else *cp1++ = ' '; *cp1++ = ' '; /* Gap. */ /* output the mode codes */ for (i = 0; i < NUMMODES; i++) { if (bp->b_mode & (1 << i)) *cp1++ = modecode[i]; else *cp1++ = '.'; } *cp1++ = ' '; /* Gap. */ nbytes = 0L; /* Count bytes in buf. */ lp = lforw(bp->b_linep); while (lp != bp->b_linep) { nbytes += (long)llength(lp)+1L; lp = lforw(lp); } ltoa(b, 7, nbytes); /* 6 digit buffer size. */ cp2 = &b[0]; while ((c = *cp2++) != 0) *cp1++ = c; *cp1++ = ' '; /* Gap. */ cp2 = &bp->b_bname[0]; /* Buffer name */ while ((c = *cp2++) != 0) *cp1++ = c; cp2 = &bp->b_fname[0]; /* File name */ if (*cp2 != 0) { while (cp1 < &line[2+1+5+1+6+1+NBUFN]) *cp1++ = ' '; while ((c = *cp2++) != 0) { if (cp1 < &line[128-1]) *cp1++ = c; } } *cp1 = 0; /* Add to the buffer. */ if (addline(line) == FALSE) return (FALSE); bp = bp->b_bufp; } return (TRUE); /* All done */ } ltoa(buf, width, num) char buf[]; int width; long num; { buf[width] = 0; /* End of string. */ while (num >= 10) { /* Conditional digits. */ buf[--width] = (int)(num%10L) + '0'; num /= 10L; } buf[--width] = (int)num + '0'; /* Always 1 digit. */ while (width != 0) /* Pad with blanks. */ buf[--width] = ' '; } /* * The argument "text" points to * a string. Append this line to the * buffer list buffer. Handcraft the EOL * on the end. Return TRUE if it worked and * FALSE if you ran out of room. */ addline(text) char *text; { register LINE *lp; register int i; register int ntext; ntext = strlen(text); if ((lp=lalloc(ntext)) == NULL) return (FALSE); for (i=0; ib_linep->l_bp->l_fp = lp; /* Hook onto the end */ lp->l_bp = blistp->b_linep->l_bp; blistp->b_linep->l_bp = lp; lp->l_fp = blistp->b_linep; if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */ blistp->b_dotp = lp; /* move it to new line */ return (TRUE); } /* * Look through the list of * buffers. Return TRUE if there * are any changed buffers. Buffers * that hold magic internal stuff are * not considered; who cares if the * list of buffer names is hacked. * Return FALSE if no buffers * have been changed. */ anycb() { register BUFFER *bp; bp = bheadp; while (bp != NULL) { if ((bp->b_flag&BFINVS)==0 && (bp->b_flag&BFCHG)!=0) return (TRUE); bp = bp->b_bufp; } return (FALSE); } /* * Find a buffer, by name. Return a pointer * to the BUFFER structure associated with it. * If the buffer is not found * and the "cflag" is TRUE, create it. The "bflag" is * the settings for the flags in in buffer. */ BUFFER * bfind(bname, cflag, bflag) register char *bname; { register BUFFER *bp; register BUFFER *sb; /* buffer to insert after */ register LINE *lp; char *malloc(); bp = bheadp; while (bp != NULL) { if (strcmp(bname, bp->b_bname) == 0) return (bp); bp = bp->b_bufp; } if (cflag != FALSE) { if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) return (NULL); if ((lp=lalloc(0)) == NULL) { free((char *) bp); return (NULL); } /* find the place in the list to insert this buffer */ if (bheadp == NULL || strcmp(bheadp->b_bname, bname) > 0) { /* insert at the beginning */ bp->b_bufp = bheadp; bheadp = bp; } else { sb = bheadp; while (sb->b_bufp != NULL) { if (strcmp(sb->b_bufp->b_bname, bname) > 0) break; sb = sb->b_bufp; } /* and insert it */ bp->b_bufp = sb->b_bufp; sb->b_bufp = bp; } /* and set up the other buffer fields */ bp->b_active = TRUE; bp->b_dotp = lp; bp->b_doto = 0; bp->b_markp = NULL; bp->b_marko = 0; bp->b_flag = bflag; bp->b_mode = gmode; bp->b_nwnd = 0; bp->b_linep = lp; strcpy(bp->b_fname, ""); strcpy(bp->b_bname, bname); #if CRYPT bp->b_key[0] = 0; #endif lp->l_fp = lp; lp->l_bp = lp; } return (bp); } /* * This routine blows away all of the text * in a buffer. If the buffer is marked as changed * then we ask if it is ok to blow it away; this is * to save the user the grief of losing text. The * window chain is nearly always wrong if this gets * called; the caller must arrange for the updates * that are required. Return TRUE if everything * looks good. */ bclear(bp) register BUFFER *bp; { register LINE *lp; register int s; if ((bp->b_flag&BFINVS) == 0 /* Not scratch buffer. */ && (bp->b_flag&BFCHG) != 0 /* Something changed */ && (s=mlyesno("Discard changes")) != TRUE) return (s); bp->b_flag &= ~BFCHG; /* Not changed */ while ((lp=lforw(bp->b_linep)) != bp->b_linep) lfree(lp); bp->b_dotp = bp->b_linep; /* Fix "." */ bp->b_doto = 0; bp->b_markp = NULL; /* Invalidate "mark" */ bp->b_marko = 0; return (TRUE); } unmark(f, n) /* unmark the current buffers change flag */ int f, n; /* unused command arguments */ { curbp->b_flag &= ~BFCHG; curwp->w_flag |= WFMODE; return(TRUE); } SHAR_EOF chmod +x 'buffer.c' fi echo shar: "extracting 'crypt.c'" '(0 character)' if test -f 'crypt.c' then echo shar: "will not over-write existing file 'crypt.c'" else cat << \SHAR_EOF > 'crypt.c' /* Crypt: Encryption routines for MicroEMACS written by Dana Hoggatt and Daniel Lawrence */ #include #include "estruct.h" #include "edef.h" #if CRYPT setkey(f, n) /* reset encryption key of current buffer */ int f; /* default flag */ int n; /* numeric argument */ { register int status; /* return status */ int odisinp; /* original vlaue of disinp */ char key[NPAT]; /* new encryption string */ /* turn command input echo off */ odisinp = disinp; disinp = FALSE; /* get the string to use as an encrytion string */ status = mlreply("Encryption String: ", key, NPAT - 1); disinp = odisinp; if (status != TRUE) return(status); /* and encrypt it */ crypt((char *)NULL, 0); crypt(key, strlen(key)); /* and save it off */ strcpy(curbp->b_key, key); mlwrite(" "); /* clear it off the bottom line */ return(TRUE); } /********** * * crypt - in place encryption/decryption of a buffer * * (C) Copyright 1986, Dana L. Hoggatt * 1216, Beck Lane, Lafayette, IN * * When consulting directly with the author of this routine, * please refer to this routine as the "DLH-POLY-86-B CIPHER". * * This routine was written for Dan Lawrence, for use in V3.8 of * MicroEMACS, a public domain text/program editor. * * I kept the following goals in mind when preparing this function: * * 1. All printable characters were to be encrypted back * into the printable range, control characters and * high-bit characters were to remain unaffected. this * way, encrypted would still be just as cheap to * transmit down a 7-bit data path as they were before. * * 2. The encryption had to be portable. The encrypted * file from one computer should be able to be decrypted * on another computer. * * 3. The encryption had to be inexpensive, both in terms * of speed and space. * * 4. The system needed to be secure against all but the * most determined of attackers. * * For encryption of a block of data, one calls crypt passing * a pointer to the data block and its length. The data block is * encrypted in place, that is, the encrypted output overwrites * the input. Decryption is totally isomorphic, and is performed * in the same manner by the same routine. * * Before using this routine for encrypting data, you are expected * to specify an encryption key. This key is an arbitrary string, * to be supplied by the user. To set the key takes two calls to * crypt(). First, you call * * crypt(NULL, vector) * * This resets all internal control information. Typically (and * specifically in the case on MICRO-emacs) you would use a "vector" * of 0. Other values can be used to customize your editor to be * "incompatable" with the normally distributed version. For * this purpose, the best results will be obtained by avoiding * multiples of 95. * * Then, you "encrypt" your password by calling * * crypt(pass, strlen(pass)) * * where "pass" is your password string. Crypt() will destroy * the original copy of the password (it becomes encrypted), * which is good. You do not want someone on a multiuser system * to peruse your memory space and bump into your password. * Still, it is a better idea to erase the password buffer to * defeat memory perusal by a more technical snooper. * * For the interest of cryptologists, at the heart of this * function is a Beaufort Cipher. The cipher alphabet is the * range of printable characters (' ' to '~'), all "control" * and "high-bit" characters are left unaltered. * * The key is a variant autokey, derived from a wieghted sum * of all the previous clear text and cipher text. A counter * is used as salt to obiterate any simple cyclic behavior * from the clear text, and key feedback is used to assure * that the entire message is based on the original key, * preventing attacks on the last part of the message as if * it were a pure autokey system. * * Overall security of encrypted data depends upon three * factors: the fundamental cryptographic system must be * difficult to compromise; exhaustive searching of the key * space must be computationally expensive; keys and plaintext * must remain out of sight. This system satisfies this set * of conditions to within the degree desired for MicroEMACS. * * Though direct methods of attack (against systems such as * this) do exist, they are not well known and will consume * considerable amounts of computing time. An exhaustive * search requires over a billion investigations, on average. * * The choice, entry, storage, manipulation, alteration, * protection and security of the keys themselves are the * responsiblity of the user. * **********/ crypt(bptr, len) register char *bptr; /* buffer of characters to be encrypted */ register unsigned len; /* number of characters in the buffer */ { register int cc; /* current character being considered */ static long key = 0; /* 29 bit encipherment key */ static int salt = 0; /* salt to spice up key with */ if (!bptr) { /* is there anything here to encrypt? */ key = len; /* set the new key */ salt = len; /* set the new salt */ return; } while (len--) { /* for every character in the buffer */ cc = *bptr; /* get a character out of the buffer */ /* only encipher printable characters */ if ((cc >= ' ') && (cc <= '~')) { /** If the upper bit (bit 29) is set, feed it back into the key. This assures us that the starting key affects the entire message. **/ key &= 0x1FFFFFFFL; /* strip off overflow */ if (key & 0x10000000L) { key ^= 0x0040A001L; /* feedback */ } /** Down-bias the character, perform a Beaufort encipherment, and up-bias the character again. We want key to be positive so that the left shift here will be more portable and the mod95() faster **/ cc = mod95((int)(key % 95) - (cc - ' ')) + ' '; /** the salt will spice up the key a little bit, helping to obscure any patterns in the clear text, particularly when all the characters (or long sequences of them) are the same. We do not want the salt to go negative, or it will affect the key too radically. It is always a good idea to chop off cyclics to prime values. **/ if (++salt >= 20857) { /* prime modulus */ salt = 0; } /** our autokey (a special case of the running key) is being generated by a wieghted checksum of clear text, cipher text, and salt. **/ key = key + key + cc + *bptr + salt; } *bptr++ = cc; /* put character back into buffer */ } return; } static int mod95(val) register int val; { /* The mathematical MOD does not match the computer MOD */ /* Yes, what I do here may look strange, but it gets the job done, and portably at that. */ while (val >= 9500) val -= 9500; while (val >= 950) val -= 950; while (val >= 95) val -= 95; while (val < 0) val += 95; return (val); } #else nocrypt() { } #endif SHAR_EOF chmod +x 'crypt.c' fi exit 0 # End of shell aer iner