Cover V02, I06
Article
Listing 1
Listing 2

nov93.tar


Listing 1: j/jsee

1: #
2: # j/jsee:   Personal Journal Management Program
3: #           Written by Leor Zolman, 3/93
4:
5: DEBUG=N     # If Y, use current dir for JOURN_DIR and show debug info
6:
7: #
8: # Usages:
9: #   j  [ - (or) -e (or) -ekey ] [journal-dir]
10: #   jsee [ - (or) -e (or) -ekey ] [journal-dir (or) journal-file-basename ]
11: #
12: #
13: # Encryption Control
14: # ------------------
15: #
16: # Whether or not j/jsee employs encryption is controlled by the command
17: # line format and several environment variables:
18: #
19: # JCRYPT            If defined as Y outside j/jsee, encryption is enabled
20: #                       by default, unless superceded by the "-" option
21: # ASK_CRYPT         Y to have j/jsee verify encryption if JCRYPT is true
22: #
23: #
24: # With no configuration whatsoever, encryption is disabled by default.
25: # If the command line options -e or -e<key> are used, then encryption is
26: # enabled.
27: #
28: # Encryption may be turned on by default for all j/jsee sessions by
29: # setting JCRYPT to Y in your environment.  Then, if ASK_CRYPT is set to Y in
30: # the code, then j/jsee will ask for a confirmation before using encryption.
31: # If JCRYPT is Y and ASK_CRYPT is N, no confirmation is required.
32: #
33: # If the "-" option appears on the command line, encryption is NEVER used.
34: # Use this to disable encryption regardless of the value of JCRYPT in
35: # your shell environment.
36: #
37: #
38: # Getting the value of the encryption key from the user
39: # -----------------------------------------------------
40: #
41: # CRYPT_KEY_VAR     Name of env var containing encryption key
42: #
43: # It is not a good idea to store the encryption key in any file on the system,
44: # nor to supply it on the j/jsee command line via the -e<key> option (for
45: # security reasons.) So, there needs to be a secure way for the user to inform
46: # j/jsee of the key value. If the user assigns a value to the environment
47: # variable whose name is stored in CRYPT_KEY_VAR before running j/jsee (as,
48: # for example, through use of the key() shell function), then j/jsee uses
49: # that value as the encryption key. If the variable named by CRYPT_KEY_VAR
50: # is null, then j/jsee prompts the user to enter the encryption key at
51: # each run.
52: #
53: # How j/jsee supplies the encryption key to the crypt program
54: # -----------------------------------------------------------
55: #
56: # CRYPT_HAS_K       Y if your version of crypt supports the -k option
57: #
58: # If CRYPT_HAS_K is N, then j/jsee is obliged to include the encryption
59: # key as part of the crypt command line (least secure, since the key
60: # is potentially visible to users running the ps command at just the
61: # right moment.)
62: #
63: # If CRYPT_HAS_K is Y, then j/jsee passes the key to crypt by making sure
64: # that the environment variable named by CRYPT_KEY_VAR contains the key
65: # value, and specifying -k alone on the crypt command line.
66: #
67: #
68: # What j does:
69: # ------------
70: #
71: # j creates a journal entry and appends it to the appropriate current monthly
72: # incremental journal file in the JOURN_DIR directory (or, if the subdir
73: # argument was given, the named subdirectory of JOURN_DIR).  If encryption is
74: # used, then a journal file having an extension of ".txe" is used; otherwise,
75: # the journal file having the extension ".txt" is used. By having two files
76: # for each month, one encrypted (.txe) and one plain (.txt), we avoid the
77: # potential inadvertant mixing of encrypted and non-encrypted text within a
78: # a single file.
79: #
80: # When using j, the journal filename (less extension) is always of the
81: # form YY-MM, where YY is the 2-digit year and MM is the two-digit
82: # month (with leading 0's if required.)
83: #
84: #
85: # What jsee does:
86: # ---------------
87: #
88: # When invoked without any name argument, jsee brings up the current month's
89: # cumulative journal file on the screen in your editor, and you may edit
90: # it as desired. This form is used to make changes to an existing entry,
91: # as opposed to creating a new entry. Whether the encrypted or non-
92: # encrypted file is used depends on whether encryption is enabled (as
93: # described above).
94: #
95: # When the argument to jsee is the name of a subdirectory of the $JOURN_DIR
96: # directory, then jsee operates on the current month's cumulative journal
97: # file in the named subdirectory.
98: #
99: # When supplied an explicit journal pathname (without extension), then
100: # jsee operates on the file whose pathname is specified. In this case,
101: # $JOURN_DIR is NOT pre-pended to the filename, so a conventional full
102: # or relative path name must be specified. The extension implicitly added
103: # to the supplied pathname is dependent upon the encryption status as
104: # determined above.
105: #
106: #
107: # Automatic encryption key synchronization
108: # ----------------------------------------
109: #
110: # Both j and jsee guard against inadvertant mixed encryption keys being
111: # applied to the same single montly journal file. Whenever encryption is
112: # called for in conjunction with the examination of (jsee) or appending
113: # to (j) a cumulative monthly journal file, the cumulative file is first
114: # decrypted using the specified key and the first line is examined for
115: # the presence of the signature text "Journal" (whenever a cumulative
116: # journal file is created, a line containing that text is always written
117: # at the beginning). If the signature text is not found, no further action
118: # is taken. Users should never delete or insert any lines before this
119: # signature header line.
120: #
121:
122: ######### User-Customizable Definitions #################################
123:
124: JOURN_DIR=$HOME/.Journ  # Directory where journal text kept
125: [ $DEBUG = Y ] && JOURN_DIR=.       # When debugging, force current dir
126:
127: # System-dependent features:
128:
129:
130: if [ -z "$CRYPT_KEY_VAR" ]      # If already set, don't mess with it...
131: then
132:     CRYPT_KEY_VAR=CRYPTKEY      # env var holding key (for use with  -k)
133: #   CRYPT_KEY_VAR=CrYpTkEy      # SCO Unix variation
134: fi
135:
136: #CRYPT_HAS_K=N          # XENIX's crypt does not support -k option
137: CRYPT_HAS_K=Y           # SCO UNIX's crypt does support -k option
138:
139: ASK_CRYPT=N             # Y=Query encryption if JCRYPT true, N=assume yes
140:
141: EDITOR=/usr/local/e.old # Text editor
142: EPSILON=N               # Y if using Epsilon as text editor
143: MICRO_EMACS=Y           # Y if using microEMACS as text editor
144: TABS="\t\t\t\t\t\t\t\t" # string to precede date string for each entry
145:
146: FILEPERMS=600           # Permissions to assign to cumulative text files
147: DIRPERMS=700            # Perms to assign to JOURN_DIR and its subdirs
148:
149: ############ End of User-Customizable Definitions ###########################
150:
151: cmdname=`basename $0`   # j or jsee
152: crypt=N                 # start out without encryption (by default)
153:
154: jdir=$JOURN_DIR         # default Journal directory
155: monthly=`date +"%y-%m"`
156: jfile=$monthly          # default Journal file
157: name_given=N            # whether or not name parameter supplied
158:
159: usage() {
160:     echo "Usages:"
161:     echo "  j    [-[e[key]]] [journal-subdir]"
162:     echo "  jsee [-[e[key]]] [journal-subdir (or) journal-file-basename]"
163:     exit 0
164: }
165:
166: #
167: # ed_invoke():  Invoke the text editor on the named file, with
168: #               initializations and command line usage approproate
169: #               to the particular editor used (microEMACS and Epsilon
170: #               initializations pre-configured.)
171: #               Exit the program if the file is not changed after the
172: #               editing session.
173: #
174:
175: ed_invoke() {
176:     sav_stats=`ls -l $1`
177:
178:     if [ $MICRO_EMACS = Y ]; then
179:         echo    "find-file $1
180:                 set \$hardtab 4
181:                 add-mode \"wrap\"
182:                 end-of-file" > /tmp/erc$$
183:         $EDITOR @/tmp/erc$$
184:         rm /tmp/erc$$
185:     elif [ $EPSILON = Y ]; then
186:         $EDITOR $1 +3
187:     else
188:         $EDITOR $1
189:     fi
190:     clear
191:
192:     if [ ! -f $1 ]; then
193:         echo "Arghhh! The file $1 has disappeared! What did you DO? Aborting."
194:         exit 1
195:     fi
196:
197:     if [ "`ls -l $1`" = "$sav_stats" ]; then
198:         echo "You didn't change anything. No update performed."
199:         rm $1
200:         exit 0
201:     fi
202: }
203:
204:
205: #
206: # get_key():    Obtain the encryption key.
207: #               If the environment variable named by CRYPT_KEY_VAR is
208: #               defined, then use its value as the encryption key.
209: #               If not, then prompt the user for the key string and
210: #               read it from the standard input (without echo).
211: #
212:
213: get_key() {
214:     eval "key=\$$CRYPT_KEY_VAR"
215:     if [ -z "$key" ]; then                      # key defined in environment?
216:         trap "stty echo; exit 1" 1 2 3 14 15    # if not, prompt for it now
217:         stty -echo
218:         echo "Enter encryption key: \c"
219:         read key
220:         stty echo
221:         echo
222:         if [ -z "$key" ]; then
223:             echo "Null key invalid. Must enter some text."
224:             exit 1
225:         fi
226:     fi
227: }
228:
229:
230: #
231: # test_k(): if crypt program supports -k option (CRYPT_HAS_K is Y), then
232: #           set the key variable named by CRYPT_KEY_VAR to the key value
233: #           stored in the $key variable.
234: #
235:
236: test_k() {                                  # determine if we can use -k:
237:     if [ $CRYPT_HAS_K = Y ]                 # if -k supported,
238:     then
239:         eval "$CRYPT_KEY_VAR=$key"          # export key into environment
240:         eval "export $CRYPT_KEY_VAR"
241:         key=-k                              # use -k alone in crypt commands
242:     fi
243: }
244:
245: #
246: # ask():    ask user a yes/no question
247: #           Return Y on std output if answer is yes, else N.
248: #           usage: ask "string"
249: #           ( " (y/n)? " automatically appended to the string)
250: #
251:
252: ask()
253: {
254:     while true
255:     do
256:         echo "$1 (y/n)? \c" >&2
257:         read answer
258:         case $answer in
259:             [Nn]*) echo "N"
260:                  break;;
261:             [Yy]*) echo "Y"
262:                 break;;
263:             *) echo 'Please answer "y" or "n"...' >&2
264:         esac
265:     done
266: }
267:
268:
269: echo "Electronic Journal Management System v3.0\n"
270:
271: #
272: # Create master journal directory if not already there
273: #
274:
275: if [ ! -d $JOURN_DIR ]; then
276:     echo "Master Journal directory $JOURN_DIR does not exist. Creating..."
277:     if mkdir $JOURN_DIR
278:     then
279:         echo "$JOURN_DIR created successfully."
280:         chmod $DIRPERMS $JOURN_DIR
281:     else
282:         echo "Could not create $JOURN_DIR. Aborting."
283:         exit 1
284:     fi
285: fi
286:
287: #
288: # Process command line arguments:
289: #
290:
291: case $# in
292:     1)  if echo $1 | grep "^-" >/dev/null
293:         then
294:             OPTS=$1
295:         else
296:             name_given=Y
297:             case $cmdname in
298:                 j)      jdir=$jdir/$1;;
299:                 jsee)   jfile=$1;;
300:             esac
301:         fi;;
302:     2)  if echo $1 | grep "^-" >/dev/null
303:         then
304:             OPTS=$1
305:             case $cmdname in
306:                 j)      jdir=$jdir/$2;;
307:                 jsee)   jfile=$2;;
308:             esac
309:         elif echo $2 | grep "^-" >/dev/null
310:         then
311:             OPTS=$2
312:             case $cmdname in
313:                 j)      jdir=$jdir/$1;;
314:                 jsee)   jfile=$1;;
315:             esac
316:         else
317:             usage
318:         fi
319:         name_given=Y;;
320: esac
321:
322: if [ $DEBUG = Y ]; then
323:     echo "OPTS = $OPTS, jdir = $jdir, jfile = $jfile, crypt = $crypt"
324: fi
325:
326: if [ "$OPTS" = - ]; then                # disable encryption?
327:     crypt=N
328: elif echo "$OPTS" | grep "^-e" >/dev/null   # -e option specified?
329: then
330:     crypt=Y                             # yes. turn on encryption.
331:     if [ "$OPTS" = -e ]; then           # -e alone?
332:         get_key
333:     else                                # -ekey specified....
334:         key=`echo $OPTS | sed s/-e//p`  # extract key from cmd line
335:     fi
336:     test_k                              # choose best way to pass crypt key
337: elif [ "$JCRYPT" = Y ]; then            # encryption flag in environment set?
338:     if [ $ASK_CRYPT = Y ]; then         # if so, does user need to verify?
339:         crypt=`ask "Encrypt"`           # yes, prompt user for verification
340:     else
341:         crypt=Y                         # no, just go ahead and use encryption
342:     fi
343:
344:     if [ $crypt = Y ]; then
345:         get_key                         # get the key
346:         test_k                          # and use -k if possible
347:     fi
348: fi
349:
350: if [ $crypt = Y ]; then
351:     EXT=txe
352: else
353:     EXT=txt
354: fi
355:
356: if [ $cmdname = jsee ]; then
357:     case $name_given in
358:         N)  if [ ! -r $jdir/$jfile.$EXT ]; then
359:                 echo "No file $jdir/$jfile.$EXT."
360:                 exit 1
361:             fi;;
362:         Y)  if [ ! -r $jfile.$EXT ]; then
363:                 save_name=$jfile.$EXT
364:                 jdir=$JOURN_DIR/$jfile
365:                 jfile=$monthly.$EXT
366:                 if [ ! -r $jdir/$jfile ]; then
367:                     echo "Can't locate filespec \"$save_name\""
368:                     exit 1
369:                 fi
370:             fi;;
371:     esac
372: fi
373:
374: if [ $DEBUG  = Y ]; then
375:     echo "crypt=$crypt, key=$key, \c"
376:     echo "\$$CRYPT_KEY_VAR=\c"
377:     eval "echo \$$CRYPT_KEY_VAR"
378:     echo "jdir = $jdir"
379:     echo "Press Return to continue...."
380:     read dummy
381: fi
382:
383: #
384: # Check to make sure an explicitly named j subdirectory exists
385: #
386:
387: if [ $cmdname = j -a ! -d $jdir ]; then
388:     echo "Journal sub-directory $jdir does not exist. Creating it..."
389:     if mkdir $jdir
390:     then
391:         chmod $DIRPERMS $jdir
392:         echo "$jdir created successfully."
393:         sleep 1
394:     else
395:         echo "Could not create $jdir. Aborting."
396:         exit 1
397:     fi
398: fi
399:
400: #
401: # Establish name of cumulative journal file we'll be working with:
402: #
403:
404: jfile=$jdir/$jfile
405: if [ $cmdname = jsee -a -r $jfile ]; then
406:     :
407: else
408:     jfile=$jfile.$EXT
409: fi
410:
411: [ $DEBUG = Y ] && echo "jfile = $jfile"
412:
413: #
414: # Initialize a new monthly cumulative file, if necessary:
415: #
416:
417: if [ ! -f $jfile ]; then        # only necessary if it doesn't already exist
418:     touch $jfile
419:     if [ $? -eq  0 ]; then
420:         echo "Created new monthly journal file $jfile."
421:         sleep 1
422:     else
423:         echo "Could not create new journal file $jfile. Aborting."
424:         exit 1
425:     fi
426:     chmod $FILEPERMS $jfile     # Assign perms to journal file
427:
428:     if [ $crypt = Y ]; then     # if encrypting, insert sig line
429:         echo "\
430: --- `logname`'s encrypted Journal file for `date \"+%h %y\"` ------------------\
431: \n\n" | crypt $key >> $jfile
432:     else
433:         echo "\
434: --- `logname`'s plain text Journal file for `date \"+%h %y\"` ------------------\
435: \n\n" >> $jfile
436:     fi
437: else                            # journal file does exist...
438:     if [ $crypt = Y ]; then     # check key synchronization
439:         crypt $key < $jfile | head -1 | grep Journal >/dev/null
440:         if [ $? -ne 0 ]; then   # abort if no sig text after decryption
441:             echo "Current journal file $jfile encrypted with a different key."
442:             exit 1
443:         fi
444:     fi
445: fi
446:
447: #
448: # Perform jsee logic:
449: #
450:
451: if [ $cmdname = jsee ]; then
452:     touch /tmp/jsee$$
453:     chmod $FILEPERMS /tmp/jsee$$
454:     if [ $crypt = Y ]; then                 # If using encrption, then:
455:         crypt $key <$jfile >>/tmp/jsee$$    # decrypt into temp file
456:         ed_invoke /tmp/jsee$$               # edit the temp file
457:         crypt $key </tmp/jsee$$ >$jfile     # encrypt back into cum. file
458:         rm /tmp/jsee$$                      # remove temp file
459:     else
460:         ed_invoke $jfile                    # Simple edit if no encryption.
461:     fi
462:     echo "Journal file $jfile updated."
463:     exit 0
464: fi
465:
466: #
467: # Perform j logic:
468: #
469:
470: date=`date "+%a  %h %d, 19%y"`                  # initialize new entry file
471: [ $crypt = Y ] && cryptmsg="  (Encrypted)"      # include encryption notice
472: echo "$TABS$date$cryptmsg\n" >> /tmp/journ$$
473:
474: echo "Starting up your text editor on a new journal entry. . ."
475:
476: ed_invoke /tmp/journ$$                          # create the new entry
477:
478: if [ $crypt = Y ]; then                         # if encrypting,
479:     crypt $key < $jfile | cat - /tmp/journ$$ |  # decrypt cum. file, append
480:                  crypt $key  > /tmp/journ2$$    # new entry, re-encrypt,
481:     mv /tmp/journ2$$ $jfile                     # and replace originl cum. file
482:     chmod $FILEPERMS $jfile
483: else                                            # if not encrypting,
484:     cat /tmp/journ$$ >> $jfile                  # then just append the entry
485: fi
486:
487: rm /tmp/journ$$
488: clear
489: echo "Entry appended onto journal file $jfile."