#! /bin/sh
# NAME
#
# remind -- print reminders of upcoming events
#
# USAGE
#
# remind -- show reminders for next seven days
# remind [year] month day message -- add reminder to database
#
# DESCRIPTION
#
# Remind maintains a database of reminders in the .reminders file,
# in the user's home directory, each a single line of the form
#
# [year] month day message
#
# Year is optional, and must be an integer greater than 99; if no
# year is given, the reminder applies to all years (for instance,
# birthdays).
#
# If remind is called with no arguments, it writes to standard
# output all reminders that occur within the next seven days. If
# remind is called with arguments giving a date and message, a
# reminder is added to the database. Any time remind is called,
# all past reminders are deleted from the database.
#
# EXAMPLE
#
# $ date
# Sun Jun 30 19:45:38 CDT 2019
# $ remind 4 2 Anne birthday
# $ remind 10 13 Kate birthday
# $ remind 7 4 Independence Day
# $ remind 2019 7 2 lunch with Pat
# $ remind 2019 5 13 dentist 2:00pm
# $ remind
# 7 4 Independence Day
# 2019 7 2 lunch with Pat
# $ cat ./reminders
# 4 2 Anne birthday
# 10 13 Kate birthday
# 7 4 Independence Day
# 2019 7 2 lunch with Pat
#
# INSTALLATION
#
# Copy this file to /usr/local/bin/remind, then chmod +x.
REMINDERFILE =/ home/ $( whoami ) / .reminders
TEMPFILE =$( mktemp )
if [ $# -gt 0 ]
then PRINTING =0 ; echo "$*" >> $REMINDERFILE
else PRINTING =1
fi
gawk '
# _The_Awk_Programming_Language_ by Aho, Kernighan and Weinberger
# daynum function from solution to Exercise 3.8
# only valid from 1901 to 2099; performs no validation
function daynum(y, m, d, days, i, n) { # 1 == Jan 1, 1901
split("31 28 31 30 31 30 31 31 30 31 30 31", days)
# 365 days per year, plus one for each leap year
n = (y-1901) * 365 + int((y-1901)/4)
if (y % 4 == 0) days[2]++ # leap year from 1901 to 2099
for (i = 1; i < m; i++) n += days[i]
return n + d }
BEGIN {
tempfile = "' $TEMPFILE '"
printing = ' $PRINTING '
"date +%Y%m%d" | getline datestring
year = substr(datestring,1,4)
today = daynum(year,
substr(datestring,5,2)+0,
substr(datestring,7,2)+0) }
$1 < 100 || ($1 >= 100 && daynum($1, $2, $3) >= today) {
print $0 >> "' $TEMPFILE '" }
printing && $1 < 100 &&
today <= daynum(year, $1, $2) &&
daynum(year, $1, $2) <= today + 7
printing && $1 >= 100 &&
today <= daynum($1, $2, $3) &&
daynum($1, $2, $3) <= today + 7
' $REMINDERFILE
mv $TEMPFILE $REMINDERFILE
# PLB 6/30/2019
IyEgL2Jpbi9zaAoKIyAgIE5BTUUKIyAgIAojICAgICAgIHJlbWluZCAtLSBwcmludCByZW1pbmRlcnMgb2YgdXBjb21pbmcgZXZlbnRzCiMgICAKIyAgIFVTQUdFCiMgICAKIyAgICAgICByZW1pbmQgLS0gc2hvdyByZW1pbmRlcnMgZm9yIG5leHQgc2V2ZW4gZGF5cwojICAgICAgIHJlbWluZCBbeWVhcl0gbW9udGggZGF5IG1lc3NhZ2UgLS0gYWRkIHJlbWluZGVyIHRvIGRhdGFiYXNlCiMgICAKIyAgIERFU0NSSVBUSU9OCiMgICAKIyAgICAgICBSZW1pbmQgbWFpbnRhaW5zIGEgZGF0YWJhc2Ugb2YgcmVtaW5kZXJzIGluIHRoZSAucmVtaW5kZXJzIGZpbGUsCiMgICAgICAgaW4gdGhlIHVzZXIncyBob21lIGRpcmVjdG9yeSwgZWFjaCBhIHNpbmdsZSBsaW5lIG9mIHRoZSBmb3JtCiMgICAKIyAgICAgICAgICAgW3llYXJdIG1vbnRoIGRheSBtZXNzYWdlCiMgICAKIyAgICAgICBZZWFyIGlzIG9wdGlvbmFsLCBhbmQgbXVzdCBiZSBhbiBpbnRlZ2VyIGdyZWF0ZXIgdGhhbiA5OTsgaWYgbm8KIyAgICAgICB5ZWFyIGlzIGdpdmVuLCB0aGUgcmVtaW5kZXIgYXBwbGllcyB0byBhbGwgeWVhcnMgKGZvciBpbnN0YW5jZSwKIyAgICAgICBiaXJ0aGRheXMpLgojICAgCiMgICAgICAgSWYgcmVtaW5kIGlzIGNhbGxlZCB3aXRoIG5vIGFyZ3VtZW50cywgaXQgd3JpdGVzIHRvIHN0YW5kYXJkCiMgICAgICAgb3V0cHV0IGFsbCByZW1pbmRlcnMgdGhhdCBvY2N1ciB3aXRoaW4gdGhlIG5leHQgc2V2ZW4gZGF5cy4gSWYKIyAgICAgICByZW1pbmQgaXMgY2FsbGVkIHdpdGggYXJndW1lbnRzIGdpdmluZyBhIGRhdGUgYW5kIG1lc3NhZ2UsIGEKIyAgICAgICByZW1pbmRlciBpcyBhZGRlZCB0byB0aGUgZGF0YWJhc2UuIEFueSB0aW1lIHJlbWluZCBpcyBjYWxsZWQsCiMgICAgICAgYWxsIHBhc3QgcmVtaW5kZXJzIGFyZSBkZWxldGVkIGZyb20gdGhlIGRhdGFiYXNlLgojICAgCiMgICBFWEFNUExFCiMgICAKIyAgICAgICAkIGRhdGUKIyAgICAgICBTdW4gSnVuIDMwIDE5OjQ1OjM4IENEVCAyMDE5CiMgICAgICAgJCByZW1pbmQgNCAyIEFubmUgYmlydGhkYXkKIyAgICAgICAkIHJlbWluZCAxMCAxMyBLYXRlIGJpcnRoZGF5CiMgICAgICAgJCByZW1pbmQgNyA0IEluZGVwZW5kZW5jZSBEYXkKIyAgICAgICAkIHJlbWluZCAyMDE5IDcgMiBsdW5jaCB3aXRoIFBhdAojICAgICAgICQgcmVtaW5kIDIwMTkgNSAxMyBkZW50aXN0IDI6MDBwbQojICAgICAgICQgcmVtaW5kCiMgICAgICAgNyA0IEluZGVwZW5kZW5jZSBEYXkKIyAgICAgICAyMDE5IDcgMiBsdW5jaCB3aXRoIFBhdAojICAgICAgICQgY2F0IC4vcmVtaW5kZXJzCiMgICAgICAgNCAyIEFubmUgYmlydGhkYXkKIyAgICAgICAxMCAxMyBLYXRlIGJpcnRoZGF5CiMgICAgICAgNyA0IEluZGVwZW5kZW5jZSBEYXkKIyAgICAgICAyMDE5IDcgMiBsdW5jaCB3aXRoIFBhdAojCiMgICBJTlNUQUxMQVRJT04KIwojICAgICAgIENvcHkgdGhpcyBmaWxlIHRvIC91c3IvbG9jYWwvYmluL3JlbWluZCwgdGhlbiBjaG1vZCAreC4KClJFTUlOREVSRklMRT0vaG9tZS8kKHdob2FtaSkvLnJlbWluZGVycwpURU1QRklMRT0kKG1rdGVtcCkKCmlmIFsgJCMgLWd0IDAgXQp0aGVuIFBSSU5USU5HPTA7IGVjaG8gIiQqIiA+PiAkUkVNSU5ERVJGSUxFCmVsc2UgUFJJTlRJTkc9MQpmaQoKZ2F3ayAnCgogICAgIyBfVGhlX0F3a19Qcm9ncmFtbWluZ19MYW5ndWFnZV8gYnkgQWhvLCBLZXJuaWdoYW4gYW5kIFdlaW5iZXJnZXIKICAgICMgZGF5bnVtIGZ1bmN0aW9uIGZyb20gc29sdXRpb24gdG8gRXhlcmNpc2UgMy44CiAgICAjIG9ubHkgdmFsaWQgZnJvbSAxOTAxIHRvIDIwOTk7IHBlcmZvcm1zIG5vIHZhbGlkYXRpb24KICAgIGZ1bmN0aW9uIGRheW51bSh5LCBtLCBkLCAgICBkYXlzLCBpLCBuKSB7ICMgMSA9PSBKYW4gMSwgMTkwMQogICAgICAgIHNwbGl0KCIzMSAyOCAzMSAzMCAzMSAzMCAzMSAzMSAzMCAzMSAzMCAzMSIsIGRheXMpCiAgICAgICAgIyAzNjUgZGF5cyBwZXIgeWVhciwgcGx1cyBvbmUgZm9yIGVhY2ggbGVhcCB5ZWFyCiAgICAgICAgbiA9ICh5LTE5MDEpICogMzY1ICsgaW50KCh5LTE5MDEpLzQpCiAgICAgICAgaWYgKHkgJSA0ID09IDApIGRheXNbMl0rKyAjIGxlYXAgeWVhciBmcm9tIDE5MDEgdG8gMjA5OQogICAgICAgIGZvciAoaSA9IDE7IGkgPCBtOyBpKyspIG4gKz0gZGF5c1tpXQogICAgICAgIHJldHVybiBuICsgZCB9CgogICAgQkVHSU4gewogICAgICAgIHRlbXBmaWxlID0gIickVEVNUEZJTEUnIgogICAgICAgIHByaW50aW5nID0gICckUFJJTlRJTkcnCiAgICAgICAgImRhdGUgKyVZJW0lZCIgfCBnZXRsaW5lIGRhdGVzdHJpbmcKICAgICAgICB5ZWFyID0gc3Vic3RyKGRhdGVzdHJpbmcsMSw0KQogICAgICAgIHRvZGF5ID0gZGF5bnVtKHllYXIsCiAgICAgICAgICAgICAgICAgICAgICAgc3Vic3RyKGRhdGVzdHJpbmcsNSwyKSswLAogICAgICAgICAgICAgICAgICAgICAgIHN1YnN0cihkYXRlc3RyaW5nLDcsMikrMCkgfQoKICAgICQxIDwgMTAwIHx8ICgkMSA+PSAxMDAgJiYgZGF5bnVtKCQxLCAkMiwgJDMpID49IHRvZGF5KSB7CiAgICAgICAgcHJpbnQgJDAgPj4gIickVEVNUEZJTEUnIiB9CgogICAgcHJpbnRpbmcgJiYgJDEgPCAxMDAgJiYKICAgIHRvZGF5IDw9IGRheW51bSh5ZWFyLCAkMSwgJDIpICYmCiAgICBkYXludW0oeWVhciwgJDEsICQyKSA8PSB0b2RheSArIDcKCiAgICBwcmludGluZyAmJiAkMSA+PSAxMDAgJiYKICAgIHRvZGF5IDw9IGRheW51bSgkMSwgJDIsICQzKSAmJgogICAgZGF5bnVtKCQxLCAkMiwgJDMpIDw9IHRvZGF5ICsgNwoKJyAkUkVNSU5ERVJGSUxFCgptdiAkVEVNUEZJTEUgJFJFTUlOREVSRklMRQoKIyBQTEIgNi8zMC8yMDE5