This assignment is designed to give you familiarity with two
things. The first is scripting with
POSIX-compatible
shells. The second is Emacs,
the classic programmable text editor
that is a prototype for
modern integrated
development environments (IDEs). Software developers should be expert in both shell scripting and
IDEs, even if they don’t necessarily use POSIXish shells or Emacs
per se.
Do this assignment on the SEASnet GNU/Linux servers
lnxsrv11,
lnxsrv13, or lnxsrv15,
with /usr/local/cs/bin
prepended to your PATH.
You can do this by executing the shell command "export
PATH=/usr/local/cs/bin:$PATH" after logging in, or more
conveniently by putting that shell command into
your $HOME/.profile file (but test this file by logging
in via a separate session before logging out of your first session!).
As this course has no textbook, a main goal of this assignment is
covering how you can discover details about this assignment’s topic,
details that may not be covered in lecture. You can get
many of the details by following all the links in this assignment
and getting the gist of those web pages (which is something you should do,
unless the text around a link says that you don’t need to all
of the referenced document).
However, this won’t
suffice for everything and you’ll need to do some learning-by-doing
to do the assignment well. The idea is that you
can put this experience to good use later in this course (and in
real life!) when you need to come up to speed with a large software
ecosystem. That being said, don’t let yourself get discouraged
if a detail cannot be found by reading the online documentation.
If you need a hint, ask a TA or an LA.
(This assignment is not intended to be done without any hints!)
Laboratory: GNU/Linux and Emacs scavenger hunt
Emacs comes with a builtin tutorial.
To take it, start Emacs and type control-H followed
by lower-case T (in Emacs notation, C-h t).
The
Emacs Editor, version 29.3 (2024). This is fairly long
and you are not expected to read it all.
Lab 1.0: Getting started with GNU/Linux and Emacs
Log into SEASnet.
Make sure your PATH is set correctly (see above).
Run the shell command type emacs which should
report that it is /usr/local/cs/bin/emacs.
Run the shell command emacs --version which
should report that it is version 29.3.
Run the shell command emacs to enter a editing session.
Type control-H followed by t
("C-h t", in Emacs-ese). This should drop you
into the Emacs tutorial.
Take the tutorial.
Run the Emacs command M-x open-dribble-file to create
a dribble file lab1.drib in your home directory
that records everything you type for the remaining parts
of this assignment.
If you do multiple Emacs sessions, name your dribble
files lab2.drib, lab3.drib, etc.
(You need to generate dribble files only for this assignment;
we won’t bother with dribble files in later assignments.)
For the following lab exercises,
use intelligent ways of answering the questions. For example, if
asked to move to the first occurrence of the word "scrumptious", do not
merely use cursor keys to move the cursor by hand; instead, use the
builtin search capabilities to find "scrumptious" quickly.
Lab 1.1: Moving around in Emacs
Download a copy of the web page you’re looking at into a
file named assign1.html. You can do this
with the following shell command:
Use the shell command cp
to make three copies of this file. Call the copies
exer1.html, exer2.html, and exer3.html.
Use Emacs to edit the file exer1.html.
Use searching to move the cursor to just after the first occurrence of the string "UTF-8" (all upper-case).
Now move the cursor to the start of the first later occurrence of the word "scavenger".
Now move the cursor to the start of the first later occurrence of the word "self-referential".
Now move the cursor to the start of the first later occurrence of the word "arrow".
Now move the cursor to the end of the current line.
Now move the cursor to the beginning of the current line.
Did you move the cursor using the arrow keys instead of using Emacs’s
searching capabilities? If so, please learn how to search, and repeat the
above steps by doing searching.
When you are done, exit Emacs.
Lab 1.2: Deleting text in Emacs
Use Emacs to edit the file exer2.html. The idea is to
delete its HTML comments; the resulting page should display the same
text as the original.
Delete the 71st line, which is an HTML comment.
<!-- HTML comments look like this, but the comment you delete
has different text inside. -->
Delete the HTML comment containing the text
"DELETE-ME DELETE-ME DELETE-ME".
Delete the HTML comment containing the text "https://en.wikipedia.org/wiki/HTML_comment#Comments".
There are two more HTML comments; delete them too.
Once again, try to accomplish the tasks using a small number of keystrokes.
When you are done, save the file and exit back to the command line. You can
check your work by using a browser to view exer2.html. Also,
check that you haven’t deleted something that you want to keep, by using
the following command:
The output file exer2.diff should describe only text
that you wanted to remove. Don’t remove exer2.diff;
you’ll need it later.
Lab 1.3: Inserting text in Emacs
Use Emacs to edit the file exer3.html.
Change the first two instances of "Assignment 1" to "Assignment 27".
Change the first instance of "UTF-8" to "US-ASCII".
Ooops! The file is not ASCII so you need to fix the file so that
it is ASCII.
Most of its non-ASCII characters are the
Unicode
character “’”
(RIGHT SINGLE QUOTATION MARK U+2019);
fix these by replacing each one with an ASCII
“'”
(U+0027 APOSTROPHE). Use M-x replace-string
to do this systematically.
Find the first remaining character in the file that is not ASCII.
You can find the next
non-ASCII character by searching for the regular
expression "[^[:ascii:]]".
Remove every
line that contains a non-ASCII character other than the U+2019
characters you already replaced.
When you finish, save the text file and exit Emacs. As before,
use the diff command to check your work.
Lab 1.4: Other editing tasks in Emacs
In addition to inserting and deleting text, there are other common tasks
that you should know, like copy and paste, search and replace, and undo.
Execute the command "cat exer2.html exer2.diff >exer4.html"
to create a file exer4.html that contains a copy of exer2.html followed by a copy of exer2.diff.
Use Emacs to edit the file exer4.html.
The idea is to edit the file so that it looks identical
to exer1.html on a browser, but the file itself is a
little bit different internally.
Go to the end of the file. Copy the new lines in the last chunk
of diff output, and paste them into the correct location earlier in the file.
Repeat the process, until the earlier part of the file is identical
to what was in the original.
Delete the last part of the file, which contains the diff output.
… except we didn’t really want to do that, so undo the deletion.
Turn the diff output into a comment, by surrounding it with
"<!--" and "-->".
If the diff output itself contains end-comment markers "-->",
escape them by replacing each such "-->" with
"-->".
Now let’s try some search and replaces.
Search the text document for the pattern "<ol>".
How many instances did you find?
Use the search and
replace function to replace them all with the final-caps
equivalent "<oL>".
Check your work with viewing exer4.html with an HTML
browser, and by running the shell command "diff -u
exer1.html exer4.html >exer4.diff". The only differences
should be changes from "<ol>" to "<oL>",
and a long HTML comment at the end.
Lab 1.5: Exploring the operating system outside Emacs
Use the commands that you learned in class to find
answers to the following questions. Don’t use a search engine like Google to
find previous editions of this assignment and/or its answers, and
don’t ask your neighbor, don’t use GitHub, etc.
When you find a new command, run it so you can see exactly how it
works.
Where are the sh, sleep, and type
commands located?
What executable programs in /usr/bin
have names that are exactly three characters
long and start with the two letters se,
and what do they do?
When you execute the command named by the symbolic
link /usr/local/cs/bin/emacs, which file actually is
executed?
What is the version number of the /usr/bin/gcc program?
of the plain gcc program? Why are they different programs?
The chmod program changes permissions on a file. What
does the symbolic mode u+sx,o-w mean, in terms of permissions?
Use the find command to find all directories
that are located under (or are the same as) the
directory /usr/local/cs,
and that were modified after the directory /usr/local/cs/lib
was modified.
Sort the directory names
alphabetically and list just the first five names,
or list them all if there are fewer than five names.
How many regular files are in the Python source code distribution
located in the directory matching the globbing
pattern /usr/local/cs/src/python/Python-*? Do not count
directories or symbolic links or anything else; just regular files.
How many of the files in /usr/local/cs/bin
are symbolic links?
What is the oldest file in the /usr/lib64
directory? Use the last-modified time to determine age. Specify the
name of the file without the /usr/lib64/ prefix. Don’t ignore
files whose names start with ".", but do ignore
files under subdirectories of /usr/lib64/.
Consider files of all types, that is, your answer might be
a regular file, or a directory, or something else.
In Emacs, what commands have transpose in their name?
What does the Emacs yank function do, and how
can you easily invoke it using keystrokes?
Use the ps command to find your own login shell’s process,
all that process’s ancestors, and all its descendants. Some
ps options that you might find useful include
-e, -f, -j, -l,
-t, -H, and -T.
Lab 1.6: Doing commands in Emacs
Do these tasks all within Emacs. Don’t use a shell subcommand
if you can avoid it.
Create a new directory named "cs35L-lab1" that’s right under
your home directory.
In that directory, create a C source file hello.c
that contains the following text. Take care to get the text exactly
right, with no trailing spaces or empty lines, with the
initial # in the leftmost column of the first line, and
with all other lines indented to match exactly as shown:
#include <stdio.h>
int
main (void)
{
for (;;)
{
int c = getchar ();
if (c < 0)
{
if (ferror (stdin))
perror ("stdin");
else
fprintf (stderr, "EOF on input\n");
return 1;
}
if (putchar (c) < 0 || (c == '\n' && fclose (stdout) != 0))
{
perror ("stdout");
return 1;
}
if (c == '\n')
return 0;
}
}
Compile this file, using the Emacs M-x compile command.
Run the compiled program from Emacs using the M-! command,
and put the program’s standard output into a file
named hello-a1 and its standard error into a file
hello-a2.
Same as before, except run the program with standard
input being closed,
and put the program’s standard output and error into
hello-b1 and hello-b2, respectively.
Here, “closed” does not mean the standard input is an empty file;
it means that standard input is not open at all, to any file.
You can arrange for this via
the <&-
shell syntax.
Same as before, except run the program with standard
input being the file /etc/passwd,
and put the program’s standard output and error into
hello-c1 and hello-c2.
Same as before, except run the program with standard
input being the file /etc/passwd
and standard output being the file /dev/full,
and put the program’s standard error into hello-d2.
Homework: Scripting in the shell
For the homework assume you’re in the standard C or POSIXlocale. The
shell command locale
should output LC_CTYPE="C"
or LC_CTYPE="POSIX". If it doesn’t, use the following
shell command:
The Open Group,
Shell Command Language (2018). This is the standard
for POSIX shells, and you are not expected to read it all, though it
can be handy to refer to it.
Read enough about the shell to understand how to do
I/O redirection and pipes.
For each command tr,
sort, comm, read the command’s man page and
use that to deduce what the command should do given its operands
shown below.
Examine the SEASnet file /usr/share/dict/linux.words, which
contains a list of English words, one per line.
Each word consists of one or more ASCII characters.
Use sort with < and >
to sort this file
and put the sorted output into a file sorted.words.
Then, take a text file containing the HTML in this
assignment’s web page, and run the following commands with that
text file being standard input. Also, look generally at what each command outputs (in
particular, how its output differs from that of the previous command),
and why.
Let’s take the last command
as the crude implementation of an
English spelling checker.
This implementation mishandles the input file
/usr/share/dict/linux.words!
Verify this by running a command like this and inspecting the output:
Write a shell script named myspell
that fixes this problem.
Your script should read from standard input and write
misspelled words to standard output, for a suitable
definition of "word" that is broader than just
a maximal sequence of ASCII alphabetic characters,
but is no broader than need be.
The shell command:
./myspell </usr/share/dict/linux.words
should output nothing, because
the dictionary by definition contains only correctly-spelled words.
Submit
Submit the following files within a compressed tarball named
assign1.tgz.
lab1.drib and any later dribble files that you generate.
The hello-?? files of Lab 1.6.
myspell. This should not have
a file name extension; for example, it should not
be myspell.sh.
notes.txt, a text file containing any other
notes or comments that you’d like us to see.
All files other than the .drib files should use
GNU/Linux style,
i.e., UTF-8
encoding with LF-terminated lines.
The shell command:
tar -tvf assign1.tgz
should output a list of file names that contains myspell
etc., with sizes and other metainformation about the files.