ast@cs.vu.nl (Andy Tanenbaum) (10/09/88)
: This is a shar archive. Extract with sh, not csh. : This archive ends with exit, so do not worry about trailing junk. : --------------------------- cut here -------------------------- PATH=/bin:/usr/bin:/usr/ucb echo Extracting 'assert.h' sed 's/^X//' > 'assert.h' << '+ END-OF-FILE ''assert.h' X#ifndef NDEBUG X#define assert(xxx) {if(!(xxx)){fprintf(stderr, "False assertion at line %d in file \"%s\"\n", __LINE__, __FILE__); exit(1);}} X#endif X X + END-OF-FILE assert.h chmod 'u=rw,g=r,o=r' 'assert.h' set `wc -c 'assert.h'` count=$1 case $count in 152) :;; *) echo 'Bad character count in ''assert.h' >&2 echo 'Count should be 152' >&2 esac echo Extracting 'brksize.s' sed 's/^X//' > 'brksize.s' << '+ END-OF-FILE ''brksize.s' X.define _brksize X.data X.globl endbss, _brksize X_brksize: .word endbss + END-OF-FILE brksize.s chmod 'u=rw,g=r,o=r' 'brksize.s' set `wc -c 'brksize.s'` count=$1 case $count in 70) :;; *) echo 'Bad character count in ''brksize.s' >&2 echo 'Count should be 70' >&2 esac echo Extracting 'catchsig.s' sed 's/^X//' > 'catchsig.s' << '+ END-OF-FILE ''catchsig.s' X.define _begsig X.globl _begsig X.globl _vectab, _M Xmtype = 2 | M+mtype = &M.m_type X_begsig: X push ax | after interrupt, save all regs X push bx X push cx X push dx X push si X push di X push bp X push ds X push es X mov bx,sp X mov bx,18(bx) | bx = signal number X mov ax,bx | ax = signal number X dec bx | vectab[0] is for sig 1 X add bx,bx | pointers are two bytes on 8088 X mov bx,_vectab(bx) | bx = address of routine to call X push _M+mtype | push status of last system call X push ax | func called with signal number as arg X call (bx) Xback: X pop ax | get signal number off stack X pop _M+mtype | restore status of previous system call X pop es | signal handling finished X pop ds X pop bp X pop di X pop si X pop dx X pop cx X pop bx X pop ax X pop dummy | remove signal number from stack X iret X X.data Xdummy: .word 0 + END-OF-FILE catchsig.s chmod 'u=rw,g=r,o=r' 'catchsig.s' set `wc -c 'catchsig.s'` count=$1 case $count in 814) :;; *) echo 'Bad character count in ''catchsig.s' >&2 echo 'Count should be 814' >&2 esac echo Extracting 'commands:makef' sed 's/^X//' > 'commands:makef' << '+ END-OF-FILE ''commands:makef' X# To make 'cp', type: make f=cp X# To make 'ls', type: make f=ls X# To make 'cat', type: make f=cat X# Get the idea? X X# To make everything, use: X# mkdir bin X# for i in *.c X# do make f=`basename $i .c` X# done X# X# Furthermore, many commands need a different memory allocation, so chmem must X# be run to change it. See the shell script 'changemem' in tools. X Xl=/usr/lib XCFLAGS= -F -Di8088 X Xfile: $l/libc.a $f.s X @cc -o bin/$f $f.s X @chmem =3072 bin/$f >/dev/null X @echo "$f done ." X X X + END-OF-FILE commands:makef chmod 'u=rw,g=r,o=r' 'commands:makef' set `wc -c 'commands:makef'` count=$1 case $count in 494) :;; *) echo 'Bad character count in ''commands:makef' >&2 echo 'Count should be 494' >&2 esac echo Extracting 'elle.man' sed 's/^X//' > 'elle.man' << '+ END-OF-FILE ''elle.man' X1. INTRODUCTION TO ELLE X ELLE (ELLE Looks Like Emacs) is an Emacs clone for MINIX. It was Xwritten by Ken Harrenstien of SRI. His e-mail address is klh@sri-nic.arpa. XELLE is not full Emacs but it has about 80 commands and is quite fast. X X1.1 Key bindings X Mined only has a small number of commands. All of them are either of Xthe form CTRL-x or are on the numeric keypad. Emacs, in contrast, has so Xmany commands, that not only are all the CTRL-x commands used up, but so Xare all the ESC x (escape followed by x; escape is not a shift character, Xlike CTRL). Even this is not enough, so CTRL-X is used as a prefix for Xadditional commands. Thus CTRL-X CTRL-L is a command, and so is CTRL-X K. XNote that what is conventionally written as CTRL-X K really means CTRL-X k. X X As a result, many Emacs commands need three or four key strokes to Xexecute. Some people think 3-4 key strokes is too many. XFor this reason, Emacs and ELLE allow users to assign their own key bindings. XIn ELLE this is done with "user profiles." A user profile is a file listing Xwhich function is invoked by which key stroke. The user profile is then Xcompiled by a program called ellec into binary form. When ELLE starts up Xit checks to see if a file .ellepro.b1 exists in $HOME. If it does, this Xfile is read in and overrides the default bindings. X X I have written a user profile that simulates the mined commands fairly Xwell. Its installation is described later. If you have never used Emacs, XI suggest that you use the mined profile. If you normally use Emacs, then Xdo not install the mined profile. You can also make your own. X X ELLE has a character-oriented view of the world, not a line oriented Xview, like ed. It does not have magic characters for searching, however, you Xcan use line feed in search patterns. For example, to find a line consisting Xof the three characters "foo" all by themselves on a line, using the mined Xbindings (see below), use the pattern: CTRL-\ CTRL-J f o o CTRL-\ CTRL-J. XThe CTRL-\ means to interpret the next character literally, in this case it Xis CTRL-J, which is line feed. You can also search for patterns involving Xmultiple lines. For example, to find a line ending in an "x" followed by a Xline beginning with a "y", use as pattern: x CTRL-\ CTRL-J y. X X2. MINED KEY BINDINGS X X These are the key bindings if the binary user profile, .ellepro.b1, Xis installed in $HOME. The ESCAPE key followed by a number followed by a Xcommand causes that command to be executed "number" times. This applies Xboth to control characters and insertable characters. CTRL-X refers to a X"control character." ESC x refers to an escape character followed by x. X^X Y refers to CTRL-X followed by y. To abort the current command and go Xback to the main loop of the editor, type CTRL-G, rather than CTRL-\. X Only a few commands are of the form CTRL-X Y. All of these are also Xbound to CTRL-X CTRL-Y, so you can hold down CTRL and then hit X Y, or Xrelease control after the X, as you prefer. X The key bindings that are not listed should not be used. Some of them Xactually do things. For example, the ANSI escape codes ESC [ x are bound Xto ^X Y for a variety of y. X Some commands work on regions. A region is defined as the text between Xthe most recently set mark and the cursor. X X X2.1 Mined Commands X XCURSOR MOTION X arrows Move the cursor in the indicated direction X CTRL-A Move cursor to start of current line X CTRL-Z Move cursor to end of current line X CTRL-F Move cursor forward word X CTRL-B Move cursor backward to start of previous word X XSCREEN MOTION X Home key Move to first character of the file X End key Move to last character of the file X PgUp key Scroll window up 22 lines (closer to start of the file) X PgDn key Scroll window down 22 lines (closer to end of the file) X CTRL-U Scroll window up 1 line X CTRL-D Scroll window down 1 line X ESC , Move to top of screen X CTRL-_ Move to bottom of screen X XMODIFYING TEXT X DEL key Delete the character under the cursor X Backsp Delete the character to left of the cursor X CTRL-N Delete the next word X CTRL-P Delete the previous word X CTRL-T Delete tail of line (all characters from cursor to end of line) X CTRL-O Open up the line (insert line feed and back up) X ESC G Get and insert a file at the cursor position (CTRL-G in mined) X XREGIONS X CTRL-^ Set mark at current position for use with CTRL-C and CTRL-K X CTRL-C Copy the text between the mark and the cursor into the buffer X CTRL-K Delete text between mark and cursor; also copy it to the buffer X CTRL-Y Yank contents of the buffer out and insert it at the cursor X XMISCELLANEOUS X numeric + Search forward (prompts for expression) X numeric \(em Search backward (prompts for expression) X CTRL-] ESC n CTRL-[ goes to line n (slightly different syntax than mined) X CTRL-R Global replace pattern with string (from cursor to end) X CTRL-L Replace pattern with string within the current line only X CTRL-W Write the edited file back to the disk X CTRL-S Fork off a shell (use CTRL-D to get back to the editor) X CTRL-G Abort whatever the editor was doing and wait for command (CTRL-\) X CTRL-E Redraw screen with cursor line positioned in the middle X CTRL-V Visit (edit) a new file X CTRL-Q Write buffer to a file X ESC X Exit the editor X X2.2 Non-Mined Commands X XCURSOR MOTION X ESC P Forward paragraph (a paragraph is a line beginning with a dot) X ESC ] Backward paragraph X ESC . Indent this line as much as the previous one X XMODIFYING TEXT X CTRL-\ Insert the next character (used for inserting control characters) X ESC T Transpose characters X ESC W Transpose words X ESC = Delete white space (horizontal space) X ESC | Delete blank lines (vertical space) X XREGIONS X ESC M Mark current paragraph X ESC ^ Exchange cursor and mark X ESC Y Yank back the next-to-the-last kill (CTRL-Y yanks the last one) X ESC A Append next kill to kill buffer X XKEYBOARD MACROS X ESC / Start Keyboard Macro X ESC \ End Keyboard Macro X ESC * View Keyboard Macro (the PrtSc key on the numeric pad is also a *) X ESC E Execute Keyboard Macro X XWINDOW MANAGEMENT X ^X 1 Enter one window mode X ^X 2 Enter two window mode X ^X L Make the current window larger X ^X P Make the window more petit/petite (Yes, Virginia, they are English) X ^X N Next window X ^X W New window X XBUFFER MANAGEMENT X numeric 5 Display the list of current files and buffers X ESC B Select a buffer X ESC S Select an existing buffer X ESC N Mark a buffer as NOT modified (even if it really is) X XUPPER AND LOW CASE MANIPULATION X ESC I Set first character of word to upper case X ESC C Capitalize current word X ESC O Make current word ordinary (i.e., lower case) X ESC U Set entire region between mark and cursor to upper case X ESC L Set entire region between mark and cursor to lower case X XMISCELLANEOUS X ESC F Find file and read it into its own buffer X ESC Z Incremental search X ESC Q Like CTRL-R, but queries at each occurrence (type ? for options) X ESC R Reset the user profile from a file X ESC H Help (ELLE prompts for the 1 or 2 character command to describe) X ESC ; Insert a comment in a C program (generates /* */ for you) X ^X X Exit the editor (same as ESC X and CTRL-X CTRL-X) X X XThe major differences between ELLE with the mined profile and mined are: X X1. The definition of a "word" is different for forward and backward word X2. The mark is set with CTRL-^ instead of CTRL-@ X3. Use CTRL-G to abort a command instead of CTRL-\ X4. Use CTRL-\ to literally insert the next character, instead of ALT X5. CTRL-E adjusts the window to put the cursor in the middle of it X6. To get and insert a file, use ESC G instead of CTRL-G X7. To go to line n, type ESC n CTRL-[ instead of CTRL-[ n X8. You exit with CTRL-X CTRL-X and then answer the question with "y". X9. There are many new commands, windows, larger files, etc. X X3. EMACS KEY BINDINGS X XCURSOR MOVEMENT X CTRL-F Forward one character. X CTRL-B Backward one character. X CTRL-H Same as CTRL-B: move backward one character. X ESC F Forward one word. X ESC B Backward one word. X CTRL-A Beginning of current line. X CTRL-E End of current line. X CTRL-N Next line (goes to the next line). X CTRL-P Previous line (goes to the previous line). X CTRL-V Beginning of next screenful. X ESC V Beginning of previous screenful. X ESC ] Forward Paragraph. X ESC [ Backward Paragraph. X ESC < Beginning of whole buffer. X ESC > End of whole buffer. X XDELETING X CTRL-D Deletes forward one character (the one the cursor is under). X DELETE Deletes backward one character (the one to left of cursor). X ESC D Kills forward one word. X ESC DEL Kills backward one word. X CTRL-K Kills the rest of the line (to the right of the cursor). X ESC \ Deletes spaces around the cursor. X CTRL-X CTRL-O Deletes blank lines around the cursor. X XCASE CHANGE X ESC C Capitalizes word : first letter becomes uppercase; rest lower X ESC L Makes the whole next word lowercase. X ESC U Makes the whole next word uppercase. X CTRL-X CTRL-L Makes whole region lowercase. X CTRL-X CTRL-U Makes whole region uppercase. X XSEARCHING (If no string is given, previous string is used) X CTRL-S Incremental Search forward; prompts "I-search:" X CTRL-R Reverse Incremental Search; prompts "R-search:" X During an incremental search, the following characters X have special effects: X "normal" chars - Begin searching immediately. X ^G - Cancel I-search, return to start. X DEL - Erase last char, return to last match. X ^S, ^R - Repeat search (or change direction). X ESC or CR - Exit I-search at current point. X X ESC % Query Replace. Asks for a search string, then X for the replacement string, and begins searching. X Stops at each match and waits for a command. X Type "?" to see your options. X CTRL-X % Replace String. Like Query Replace, but simply X replaces all matches, without stopping to ask. X XMARKING AREAS X CTRL-^ Set mark X CTRL-X CTRL-X Exchange cursor and mark. X ESC H Mark Paragraph. Sets mark and cursor to surround a para. X CTRL-W Wipe-out -- kills a "region": X ESC W Copy region. Like CTRL-W then CTRL-Y but does modify buffer X CTRL-Y Yanks-back (un-kills) whatever you have most recently killed. X ESC Y Yanks-back (un-kills) the next most recently killed text. X ESC CTRL-W Append Next Kill. Accumulates stuff from several kills X XFILLING TEXT X ESC Q Fill the paragraph to the size of the Fill Column. X ESC G Fill the region. X CTRL-X F Set Fill Column. ESC Q will use this line size. X CTRL-X . Set Fill Prefix. Asks for prefix string X CTRL-X T Toggles Auto Fill Mode. X XWINDOWS X CTRL-X 2 Make two windows (split screen). X CTRL-X 1 Make one window (delete window) (make one screen). X CTRL-X O Go to Other window. X CTRL-X ^ Grow window: makes current window bigger. X XBUFFERS X CTRL-X CTRL-F Find a file and make a buffer for it. X CTRL-X B Select Buffer: goes to specified buffer or makes new one X CTRL-X CTRL-B Show the names of the buffers used in this editing session. X CTRL-X K Kill Buffer. X ESC ~ Say buffer is not modified. X CTRL-X CTRL-M Toggle EOL mode (per-buffer flag). X XKEYBOARD MACRO X CTRL-X ( Start collecting a keyboard macro. X CTRL-X ) Stop collecting. X CTRL-X E Execute the collected macro. X CTRL-X * Display the collected macro. X XFILES X CTRL-X CTRL-I Insert a file where cursor is. X CTRL-X CTRL-R Read a new file into current buffer. X CTRL-X CTRL-V Same as ^X ^R above (reads a file). X CTRL-X CTRL-W Write buffer out to new file name. X CTRL-X CTRL-S Save file: write out buffer to its file name. X CTRL-X CTRL-E Write region out to new file name. X XMISCELLANEOUS X CTRL-X CTRL-Z Exit from ELLE. X CTRL-X ! Escape to shell (CTRL-D to return) X CTRL-O Open up line X LINEFEED Same as typing RETURN and TAB. X CTRL-T Transposes characters. X ESC T Transposes words. X CTRL-U Makes the next command happen four times. X CTRL-U number Makes the next command happen "number" times. X ESC number Same as CTRL-U number. X CTRL-L Refreshes screen. X CTRL-U CTRL-L Refresh only the line cursor is on. X CTRL-U n CTRL-L Change window so the cursor is on line n X CTRL-Q Quote: insert the next character no matter what it is. X CTRL-G Quit: use to avoid answering a question. X ESC ; Inserts comment (for writing C programs). X ESC I Inserts indentation equal to previous line. X ESC M Move to end of this line's indentation. X CTRL-_ Describes a command is command database is online X XUNUSED CONTROLS X CTRL-\ Special debugging command. Not for normal users! X CTRL-^ Special debugging command. Not for normal users! X CTRL-C Not used. X CTRL-Z Not used. X CTRL-] Not used. X X X4. INSTALLING ELLE ON MINIX X X Files: X X elle (executable binary of the editor) X ellec (executable binary of the profile compiler) X .ellepro.e (mined profile in source form) X .ellepro.b1 (mined profile in binary form) X help.dat (help file) X XHOW TO INSTALL ELLE X XStep 1: X Check to see if /etc/termcap is present and has an entry for 'minix'. X XStep 2: X Set the environment properly by typing: TERM=minix. You can also put X it in the appropriate .profile, but be sure to include a line: X export TERM. You can check the current environment with: printenv. X If the entry TERM=minix does not appear, ELLE will not work. X XStep 3: X Install 'elle' and 'ellec' in your /bin or /usr/bin directory. X XStep 4: X Install help.dat in /usr/src/elle/help.dat X XStep 5: X If you want to use the mined-like commands, install .ellepro.b1 in $HOME X XStep 6: X Type 'elle filename' and you are up and running. X X XHOW TO CREATE YOUR OWN USER PROFILE XStep 1: X Modify .ellepro.e to suit your taste X XStep 2: X Install .ellepro.e in $HOME X XStep 3: X Type: ellec -Profile X XStep 4: X Check to see if $HOME/.ellepro.b1 was created X + END-OF-FILE elle.man chmod 'u=rw,g=r,o=r' 'elle.man' set `wc -c 'elle.man'` count=$1 case $count in 14653) :;; *) echo 'Bad character count in ''elle.man' >&2 echo 'Count should be 14653' >&2 esac echo Extracting 'getutil.s' sed 's/^X//' > 'getutil.s' << '+ END-OF-FILE ''getutil.s' X.define _get_base, _get_size, _get_tot_mem X.globl _get_base, _get_size, _get_tot_mem X.globl endbss X X|*========================================================================* X| utilities * X|*========================================================================* X_get_base: | return click at which prog starts X mov ax,ds X ret X X_get_size: | return prog size in bytes (text+data+bss) X mov ax,#endbss | end is compiler label at end of bss X ret X X| Find out how much memory the machine has, including vectors, kernel MM, etc. X_get_tot_mem: X cli X push es X push di X mov ax,#16384 | start search at 256K (16384 clicks) X sub di,di XL1: mov es,ax X seg es X mov (di),#0xA5A4 | write random bit pattern to memory X xor bx,bx X seg es X mov bx,(di) | read back pattern just written X cmp bx,#0xA5A4 | compare with expected value X jne L2 | if different, no memory present X add ax,#4096 | advance counter by 64K X cmp ax,#0xA000 | stop seaching at 640K X jne L1 XL2: pop di X pop es X sti X ret + END-OF-FILE getutil.s chmod 'u=rw,g=r,o=r' 'getutil.s' set `wc -c 'getutil.s'` count=$1 case $count in 1045) :;; *) echo 'Bad character count in ''getutil.s' >&2 echo 'Count should be 1045' >&2 esac echo Extracting 'mined:makefile' sed 's/^X//' > 'mined:makefile' << '+ END-OF-FILE ''mined:makefile' XCFLAGS=-F -Di8088 Xl=/lib X Xmined: mined1.s mined2.s mined.h X @cc -i -o mined mined1.s mined2.s X + END-OF-FILE mined:makefile chmod 'u=rw,g=r,o=r' 'mined:makefile' set `wc -c 'mined:makefile'` count=$1 case $count in 96) :;; *) echo 'Bad character count in ''mined:makefile' >&2 echo 'Count should be 96' >&2 esac echo Extracting 'sendrec.s' sed 's/^X//' > 'sendrec.s' << '+ END-OF-FILE ''sendrec.s' X.define _send,_receive,_sendrec X X| See ../h/com.h for C definitions XSEND = 1 XRECEIVE = 2 XBOTH = 3 XSYSVEC = 32 X X|*========================================================================* X| send and receive * X|*========================================================================* X| send(), receive(), sendrec() all save bp, but destroy ax, bx, and cx. X.globl _send, _receive, _sendrec X_send: mov cx,*SEND | send(dest, ptr) X jmp L0 X X_receive: X mov cx,*RECEIVE | receive(src, ptr) X jmp L0 X X_sendrec: X mov cx,*BOTH | sendrec(srcdest, ptr) X jmp L0 X X L0: push bp | save bp X mov bp,sp | can't index off sp X mov ax,4(bp) | ax = dest-src X mov bx,6(bp) | bx = message pointer X int SYSVEC | trap to the kernel X pop bp | restore bp X ret | return X + END-OF-FILE sendrec.s chmod 'u=rw,g=r,o=r' 'sendrec.s' set `wc -c 'sendrec.s'` count=$1 case $count in 809) :;; *) echo 'Bad character count in ''sendrec.s' >&2 echo 'Count should be 809' >&2 esac echo Extracting 'setjmp.s' sed 's/^X//' > 'setjmp.s' << '+ END-OF-FILE ''setjmp.s' X.define _setjmp,_longjmp X.globl _setjmp, _longjmp X.text X_setjmp: mov bx,sp X mov ax,(bx) X mov bx,*2(bx) X mov (bx),bp X mov *2(bx),sp X mov *4(bx),ax X xor ax,ax X ret X X_longjmp: xor ax,ax X push bp X mov bp,sp X mov bx,*4(bp) X mov ax,*6(bp) X or ax,ax X jne L1 X inc ax XL1: mov cx,(bx) XL2: cmp cx,*0(bp) X je L3 X mov bp,*0(bp) X or bp,bp X jne L2 X hlt XL3: X mov bp,*0(bp) X mov sp,*2(bx) X mov cx,*4(bx) X mov bx,sp X mov (bx),cx X ret X X + END-OF-FILE setjmp.s chmod 'u=rw,g=r,o=r' 'setjmp.s' set `wc -c 'setjmp.s'` count=$1 case $count in 445) :;; *) echo 'Bad character count in ''setjmp.s' >&2 echo 'Count should be 445' >&2 esac echo Extracting 'sgtty.h' sed 's/^X//' > 'sgtty.h' << '+ END-OF-FILE ''sgtty.h' X/* Data structures for IOCTL. */ X Xstruct sgttyb { X char sg_ispeed; /* input speed */ X char sg_ospeed; /* output speed */ X char sg_erase; /* erase character */ X char sg_kill; /* kill character */ X int sg_flags; /* mode flags */ X}; X Xstruct tchars { X char t_intrc; /* SIGINT char */ X char t_quitc; /* SIGQUIT char */ X char t_startc; /* start output (initially CTRL-Q) */ X char t_stopc; /* stop output (initially CTRL-S) */ X char t_eofc; /* EOF (initially CTRL-D) */ X char t_brkc; /* input delimiter (like nl) */ X}; X X/* Field names */ X#define XTABS 0006000 /* do tab expansion */ X#define BITS8 0001400 /* 8 bits/char */ X#define BITS7 0001000 /* 7 bits/char */ X#define BITS6 0000400 /* 6 bits/char */ X#define BITS5 0000000 /* 5 bits/char */ X#define EVENP 0000200 /* even parity */ X#define ODDP 0000100 /* odd parity */ X#define RAW 0000040 /* enable raw mode */ X#define CRMOD 0000020 /* map lf to cr + lf */ X#define ECHO 0000010 /* echo input */ X#define CBREAK 0000002 /* enable cbreak mode */ X#define COOKED 0000000 /* neither CBREAK nor RAW */ X X/* Line speeds */ X#define B110 1 X#define B300 3 X#define B1200 12 X#define B2400 24 X#define B4800 48 X#define B9600 96 X X#define TIOCGETP (('t'<<8) | 8) X#define TIOCSETP (('t'<<8) | 9) X#define TIOCGETC (('t'<<8) | 18) X#define TIOCSETC (('t'<<8) | 17) + END-OF-FILE sgtty.h chmod 'u=rw,g=r,o=r' 'sgtty.h' set `wc -c 'sgtty.h'` count=$1 case $count in 1412) :;; *) echo 'Bad character count in ''sgtty.h' >&2 echo 'Count should be 1412' >&2 esac echo Extracting 'termcap.c' sed 's/^X//' > 'termcap.c' << '+ END-OF-FILE ''termcap.c' X/* termcap - print termcap settings Author: Terrence Holm */ X X#include <stdio.h> X X#define TC_BUFFER 1024 /* Size of termcap(3) buffer */ X Xchar *getenv(); Xchar *tgetstr(); X X/****************************************************************/ X/* */ X/* termcap [ type ] */ X/* */ X/* Prints out all of the termcap capabilities as described */ X/* in termcap(4). If "type" is not supplied then $TERM is */ X/* used. */ X/* */ X/****************************************************************/ X X Xmain( argc, argv ) X int argc; X char *argv[]; X X { X char *term; X char buffer[ TC_BUFFER ]; X X X /* Check for an argument */ X X if ( argc > 2 ) X Error( "Usage: %s [ type ]\n", argv[0] ); X X if ( argc == 2 ) X term = argv[1]; X else X term = getenv( "TERM" ); X X if ( term == NULL ) X Error( "termcap: $TERM is not defined\n", "" ); X X X /* Read in the termcap entry */ X X if ( tgetent( buffer, term ) != 1 ) X Error( "termcap: No termcap entry for %s\n", term ); X X X /* Print out the entry's contents */ X X printf( "TERM = %s\n\n", term ); X X if ( tgetflag( "am" ) == 1 ) X printf( "End of line wraps to next line (am)\n" ); X X if ( tgetflag( "bs" ) == 1 ) X printf( "Ctrl/H performs a backspace (bs)\n" ); X X printf( "Number of columns (co) = %d\n", tgetnum( "co" ) ); X printf( "Number of lines (li) = %d\n", tgetnum( "li" ) ); X X Print( "Clear to end of line", "ce" ); X Print( "Clear to end of screen", "cd" ); X Print( "Clear the whole screen", "cl" ); X X Print( "Start \"stand out\" mode", "so" ); X Print( "End \"stand out\" mode", "se" ); X Print( "Start underscore mode", "us" ); X Print( "End underscore mode", "ue" ); X Print( "Start blinking mode", "mb" ); X Print( "Start bold mode", "md" ); X Print( "Start reverse mode", "mr" ); X Print( "Return to normal mode", "me" ); X X Print( "Scroll backwards", "sr" ); X Print( "Cursor motion", "cm" ); X X Print( "Up one line", "up" ); X Print( "Down one line", "do" ); X Print( "Left one space", "le" ); X Print( "Right one space", "nd" ); X Print( "Move to top left corner", "ho" ); X X Print( "Generated by \"UP\"", "ku" ); X Print( "Generated by \"DOWN\"", "kd" ); X Print( "Generated by \"LEFT\"", "kl" ); X Print( "Generated by \"RIGHT\"", "kr" ); X Print( "Generated by \"HOME\"", "kh" ); X Print( "Generated by \"END\"", "k0" ); X Print( "Generated by \"PGUP\"", "k1" ); X Print( "Generated by \"PGDN\"", "k2" ); X Print( "Generated by numeric \"+\"", "k3" ); X Print( "Generated by numeric \"-\"", "k4" ); X Print( "Generated by numeric \"5\"", "k5" ); X X exit( 0 ); X } X X X X X X X/****************************************************************/ X/* */ X/* Print( comment, name ) */ X/* */ X/* If a termcap entry exists for "name", then */ X/* print out "comment" and the entry. Control */ X/* characters are printed as ^x. */ X/* */ X/****************************************************************/ X X XPrint( comment, name ) X char *comment; X char *name; X X { X char entry[ 50 ]; X char *p = entry; X X if ( tgetstr( name, &p ) == NULL ) X return; X X printf( "%-32s (%s) = ", comment, name ); X X for ( p = entry; *p != '\0'; ++p ) X if ( *p < ' ' ) X printf( "^%c", *p + '@' ); X else if ( *p == '\177' ) X printf( "^?" ); X else X putchar( *p ); X X putchar( '\n' ); X } X X X X X X X/****************************************************************/ X/* */ X/* Error( message, arg ) */ X/* */ X/* Printf the "message" and abort. */ X/* */ X/****************************************************************/ X X XError( message, arg ) X char *message; X char *arg; X X { X fprintf( stderr, message, arg ); X exit( 1 ); X } + END-OF-FILE termcap.c chmod 'u=rw,g=r,o=r' 'termcap.c' set `wc -c 'termcap.c'` count=$1 case $count in 3832) :;; *) echo 'Bad character count in ''termcap.c' >&2 echo 'Count should be 3832' >&2 esac echo Extracting 'tsort.c' sed 's/^X//' > 'tsort.c' << '+ END-OF-FILE ''tsort.c' X/* X * tsort - do a topological sort on the ordered pairs of names X * X * syntax - tsort [ file ] X * X * based on the discussion in 'The AWK programming Language', by X * Aho, Kernighan, & Weinberger. X * X * author: Monty Walls X * written: 1/28/88 X * Copyright: Copyright (c) 1988 by Monty Walls. X * Not derived from licensed software. X * X * Permission to copy and/or distribute granted under the X * following conditions: X * X * 1). This notice must remain intact. X * 2). The author is not responsible for the consequences of use X * this software, no matter how awful, even if they X * arise from defects in it. X * 3). Altered version must not be represented as being the X * original software. X * X * change log: X * possible bug in ungetc(), fixed readone() to avoid - 2/19/88 - mrw X * massive design error, rewrote dump logic - 3/15/88 - mrw X */ X X#include <stdio.h> X#include <errno.h> X#include <ctype.h> X X#define printmem(_s) (fprintf(stdout,"%s ",(_s))) X#define MAXNAMELEN 32 X#define MAXMEMBERS 1024 X Xstruct dependents { X struct node *nd; X struct dependents *next; X}; X Xstruct node { X char *name; X int pcnt, scnt, visited; X struct dependents *succ, *pred; X struct node *left, *right; X}; X Xchar *progname; X Xextern struct node *readnode(), *findnode(); Xextern char *malloc(), *xalloc(), *readone(), *strsave(); Xextern struct dependents *finddep(); Xextern void dumptree(), walktree(), emptytree(), addqueue(), walklist(); X Xextern int errno; Xextern char *sys_errlist[]; X Xstruct node *tree, *lastnode, *q[MAXMEMBERS]; Xstruct dependents *lastdepd; Xint node_cnt, rc, front, back; X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X progname = argv[0]; X if (argc > 1) X if (freopen(argv[1], "r", stdin) == (FILE *)NULL) { X fprintf(stderr,"Error: %s - %s\n",progname, sys_errlist[errno]); X exit(1); X } X X /* read in the tree of entries */ X while (readnode() != (struct node *)NULL) X ; X dumptree(tree); X fflush(stdout); X X if (node_cnt != back) { X fprintf(stderr,"Error: %s - input contains a cycle\n",progname); X rc = 1; X } X X exit(rc); X} X X Xstruct node * Xreadnode() X{ X char *s1, *s2; X register struct node *n1, *n2; X struct dependents *pd; X X if ((s1 = readone()) != (char *)NULL) { X if ((n1 = findnode(s1)) == (struct node *)NULL) { X /* is a new node so build it */ X n1 = (struct node *)xalloc(sizeof(struct node)); X n1->name = strsave(s1); X n1->succ = (struct dependents *)NULL; X n1->pred = (struct dependents *)NULL; X n1->left = (struct node *)NULL; X n1->right = (struct node *)NULL; X n1->pcnt = 0; X n1->scnt = 0; X n1->visited = 0; X linknode(n1); X } X if ((s2 = readone()) != (char *)NULL) { X if ((n2 = findnode(s2)) == (struct node *)NULL) { X /* is a new node so build it */ X n2 = (struct node *)xalloc(sizeof(struct node)); X n2->name = strsave(s2); X n2->succ = (struct dependents *)NULL; X n2->pred = (struct dependents *)NULL; X n2->left = (struct node *)NULL; X n2->right = (struct node *)NULL; X n2->pcnt = 0; X n2->scnt = 0; X n2->visited = 0; X linknode(n2); X } X if (n1 != n2) { X if (finddep(n2->pred,s1) == (struct dependents *)NULL) { X /* new dependence here */ X pd = (struct dependents *)xalloc(sizeof(struct dependents)); X pd->nd = n1; X pd->next = (struct dependents *)NULL; X n2->pcnt++; X if (n2->pred == (struct dependents *)NULL) X n2->pred = pd; X else X lastdepd->next = pd; X } X if (finddep(n1->succ,s2) == (struct dependents *)NULL) { X /* new dependence here */ X pd = (struct dependents *)xalloc(sizeof(struct dependents)); X pd->nd = n2; X pd->next = (struct dependents *)NULL; X n1->scnt++; X if (n1->succ == (struct dependents *)NULL) X n1->succ = pd; X else X lastdepd->next = pd; X } X } X return (n1); X } X else X return ((struct node *)NULL); X } X else X return ((struct node *)NULL); X} X Xvoid Xdumptree(top) Xregister struct node *top; X{ X walktree(top); /* get all entries in order with no predecessors */ X for (front = 1; front <= back; front++) { X printmem(q[front]->name); X walklist(q[front]->succ); X } X emptytree(top); /* dumps all isolated nodes left over */ X} X Xvoid Xwalklist(s) Xregister struct dependents *s; X{ X for (; s; s = s->next) { X if (--s->nd->pcnt == 0) { X addqueue(s->nd); X s->nd->visited = 1; X walklist(s->nd->succ); X } X } X} X Xvoid Xwalktree(t) Xregister struct node *t; X{ X if (t) { X node_cnt++; X walktree(t->right); X if (t->pcnt == 0) { X addqueue(t); X t->visited = 1; X } X walktree(t->left); X } X} X Xvoid Xemptytree(t) Xregister struct node *t; X{ X struct dependents *s; X X /* t - represents a remaining entry which is in a cycle */ X if (t) { X emptytree(t->right); X if (t->visited == 0) { X t->visited = 1; X printmem(t->name); X for (s = t->succ; s; s = s->next) X if (s->nd->visited == 0) { X fprintf(stderr,"Error: %s - %s and %s are in a cycle\n",progname, t->name, s->nd->name); X } X } X emptytree(t->left); X } X} X Xvoid Xaddqueue(t) Xstruct node *t; X{ X if (++back >= MAXMEMBERS) { X fprintf(stderr,"Error: %s - member queue overflow\n",progname); X exit(1); X } X else X q[back] = t; X} X Xchar * Xreadone() X{ X register int c, n = 0; X static char name[MAXNAMELEN]; X X /* eat up leading spaces */ X while ((c = getchar()) != EOF && isspace(c)) X ; X X if (c != EOF) { X name[n++] = c; /* save into name first non blank */ X while ((c = getchar()) != EOF && !isspace(c)) { X if (n < MAXNAMELEN) X name[n++] = c; X } X name[n] = '\0'; X return (name); X } X else X return ((char *)NULL); X X} X Xstruct node * Xfindnode(s) Xchar *s; X{ X register struct node *n; X register int cmp; X X if (tree) { X lastnode = n = tree; X while (n && n->name) { X lastnode = n; X if (!(cmp = strcmp(s,n->name))) X return (n); X else if (cmp > 0) X n = n->left; X else X n = n->right; X } X } X return ((struct node *)NULL); X} X Xstruct dependents * Xfinddep(dp, s) Xregister struct dependents *dp; Xregister char *s; X{ X lastdepd = (struct dependents *)NULL; X while (dp && dp->nd) { X lastdepd = dp; X if (strcmp(dp->nd->name,s) == 0) X return (dp); X else { X dp = dp->next; X } X } X return ((struct dependents *)NULL); X} X Xlinknode(n) Xregister struct node *n; X{ X register int cmp; X X if (tree) { X cmp = strcmp(n->name,lastnode->name); X if (cmp > 0) X lastnode->left = n; X else X lastnode->right = n; X } X else X tree = n; X} X Xchar * Xxalloc(n) Xint n; X{ X char *p; X X if ((p = malloc(n)) != (char *)NULL) X return (p); X else { X fprintf(stderr,"Error: %s out of memory\n",progname); X exit(1); X } X} X Xchar * Xstrsave(s) Xchar *s; X{ X char *p; X X p = xalloc(strlen(s)+1); X strcpy(p,s); X return (p); X} + END-OF-FILE tsort.c chmod 'u=rw,g=r,o=r' 'tsort.c' set `wc -c 'tsort.c'` count=$1 case $count in 6563) :;; *) echo 'Bad character count in ''tsort.c' >&2 echo 'Count should be 6563' >&2 esac echo Extracting 'who.c' sed 's/^X//' > 'who.c' << '+ END-OF-FILE ''who.c' X/* who - tell who is currently logged in Author: Andy Tanenbaum */ X X/* Who reads the file /usr/adm/wtmp and prints a list of who is curently X * logged in. The format of this file is a sequence of 20-character records, X * as defined by struct wtmprec below. There is an implicit assumption that X * all terminal names are of the form ttyn, where n is a single decimal digit. X */ X X#define SLOTS 10 X#define WTMPSIZE 8 X#define DIGIT 3 X Xchar *wtmpfile = "/usr/adm/wtmp"; X Xstruct wtmprec { X char wt_line[WTMPSIZE]; /* tty name */ X char wt_name[WTMPSIZE]; /* user id */ X long wt_time; /* time */ X} wtmp; X Xstruct wtmprec user[SLOTS]; Xextern char *ctime(); X Xmain() X{ X int fd; X X fd = open(wtmpfile, 0); X if (fd < 0) { X printf("The file %s cannot be opened.\n", wtmpfile); X printf("To enable login accounting (required by who),"); X printf("create an empty file with this name.\n"); X exit(1); X } X X readwtmp(fd); X printwtmp(); X} X X Xreadwtmp(fd) Xint fd; X{ X/* Read the /usr/adm/wtmp file and build up a log of current users. */ X X int i, ttynr; X X while (read(fd, &wtmp, sizeof(wtmp)) == sizeof(wtmp)) { X if (strcmp(wtmp.wt_line, "~") == 0) { X /* This line means that the system was rebooted. */ X for (i = 0; i < SLOTS; i++) user[i].wt_line[0] = 0; X continue; X } X ttynr = wtmp.wt_line[DIGIT] - '0'; X if (ttynr < 0 || ttynr >= SLOTS) continue; X if (wtmp.wt_name[0] == 0) { X user[ttynr].wt_line[0] = 0 ; X continue; X } X user[ttynr] = wtmp; X } X} X Xprintwtmp() X{ X struct wtmprec *w; X char *p; X X for (w = &user[0]; w < &user[SLOTS]; w++) { X if (w->wt_line[0] == 0) continue; X printf("%s %s ", w->wt_name, w->wt_line); X p = ctime(&w->wt_time); X *(p+16) = 0; X printf("%s\n", p); X } X} + END-OF-FILE who.c chmod 'u=rw,g=r,o=r' 'who.c' set `wc -c 'who.c'` count=$1 case $count in 1686) :;; *) echo 'Bad character count in ''who.c' >&2 echo 'Count should be 1686' >&2 esac echo Extracting 'whoami.c' sed 's/^X//' > 'whoami.c' << '+ END-OF-FILE ''whoami.c' X/* whoami - print the current user name Author: Terrence W. Holm */ X X#include <stdio.h> X#include <pwd.h> X Xstruct passwd *getpwuid(); X Xmain() X{ X struct passwd *pw_entry; X X pw_entry = getpwuid(geteuid()); X if (pw_entry == NULL) exit(1); X puts(pw_entry->pw_name); X exit(0); X} + END-OF-FILE whoami.c chmod 'u=rw,g=r,o=r' 'whoami.c' set `wc -c 'whoami.c'` count=$1 case $count in 279) :;; *) echo 'Bad character count in ''whoami.c' >&2 echo 'Count should be 279' >&2 esac exit 0