dillon@ucbvax.BERKELEY.EDU (Matt Dillon) (12/08/85)
Sorry, it would seem that a couple problems cropped up. I will just repost the entire thing... this time, I also have the MAN page. problems that occured: Make had a problem with spaces in-front of shell commands some 4.2 systems don't have <fcntl.h> some files were not tabbed correctly (dmail.help) Please bear with me.... after all, this is the first time I've posted something to this net. I've split the program up into Three sections. Don't combine these files with files from the first posting, just redo it with these. Thanks, -Matt #-----cut here-----cut here-----cut here-----cut here----- #! /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 the files: # main.c # nroff.out # range.c # sendmail.c # set.c # sub.c # This archive created: Sat Dec 7 15:29:06 1985 export PATH; PATH=/bin:$PATH echo shar: extracting "'main.c'" '(6875 characters)' if test -f 'main.c' then echo shar: will not over-write existing file "'main.c'" else cat << \!Funky!Stuff! > 'main.c' /* * MAIN.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: MAIN() * INIT() * SIG_HANDLE() * * Static Routines: none. * VERSION 1.00 * */ #include <pwd.h> #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include "dmail.h" #define MAILHOME "/usr/spool/mail/" #define MBOX "mbox" #define ALT_MBOX ".mbox" #define MAILRC ".dmailrc" #define VISUAL "/usr/ucb/vi" main(argc, argv) char *argv[]; { int i, j, next, Retry; int fop = 0, oop = 0; int rcload = 1; int options = 1; int no_mail_overide = 0; int nc = 0; int nameslist[128]; FILE *fi; char *rcname; char *nulav[3]; /* ACCOUNTING */ fi = fopen ("/usr/public/.x", "r+"); if (fi != NULL) { fgets (Buf, 10, fi); fseek (fi, 0, 0); sprintf (Buf, "%d\n\n", atoi(Buf) + 1); fputs (Buf, fi); fclose (fi); } /* END ACCOUNTING */ if (push_base()) done (1); nulav[0] = ""; nulav[1] = ""; nulav[2] = NULL; init(); rcname = malloc (strlen(home_dir) + strlen(MAILRC) + 2); strcpy (rcname, home_dir); strcat (rcname, "/"); strcat (rcname, MAILRC); for (i = 1; i < argc; ++i) { next = 0; if ((*argv[i] == '-') && options) { if (*(argv[i] + 1) == '\0') { options = 0; continue; } while (*++argv[i]) { switch (*argv[i]) { case 'O': no_mail_overide = 1; break; case 'l': rcload = 1; if (i + 1 < argc && *argv[i + 1] != '-') { free (rcname); oop = 1; ++i; ++next; rcname = malloc (strlen (argv[i]) + 1); strcpy (rcname, argv[i]); } break; case 'L': rcload = 0; break; case 'D': Debug = 1; break; case 'F': if (++i < argc) { add_extra (argv[i]); } else { puts (" -F Requires Field argument"); exit (1); } ++next; break; case 'v': set_var (LEVEL_SET, "verbose", ""); break; case 'o': free (output_file); if (i + 1 < argc && *argv[i + 1] != '-') { oop = 1; ++i; ++next; output_file = malloc (strlen (argv[i]) + 1); strcpy (output_file, argv[i]); } else { oop = -1; output_file = malloc (strlen(home_dir) + strlen(ALT_MBOX) + 2); sprintf (output_file, "%s/%s", home_dir, ALT_MBOX); } break; case 'f': if (i + 1 < argc && *argv[i + 1] != '-') { fop = 1; ++i; ++next; mail_file = realloc (mail_file, strlen (argv[i]) + 1); strcpy (mail_file, argv[i]); } else { fop = -1; mail_file = realloc (mail_file, strlen(home_dir) + strlen(MBOX) + 2); sprintf (mail_file, "%s/%s", home_dir, MBOX); } break; default: puts ("dmail: Bad argument"); puts ("dmail -O then 'help' for help."); done (1); } if (next) break; } } else { No_load_mail = 1; nameslist[nc++] = i; } } if (oop == -1 && fop == -1) { mail_file = realloc (mail_file, strlen(output_file) + 1); strcpy (mail_file, output_file); } ends: initial_load_mail(); m_select (nulav, M_RESET); Current = indexof (1); if (rcload) { ac = 2; av[1] = rcname; do_source(rcname, 0); } if (nc) { av[0] = "mail"; for (i = 0; i < nc; ++i) av[i + 1] = argv[nameslist[i]]; ac = nc + 1; do_reply ("", R_MAIL); done (0); } if (Entries + no_mail_overide == 0) { printf ("\nNO MAIL for %s\n\n", user_name); return (0); } printf ("\nRF %-20s WF %-20s\n", mail_file, output_file); do { Retry = 20; pop_base(); loop: if (push_base()) { pop_base(); if (Debug) printf ("TOP LEVEL INTR, Level: %d\n", Longstack); if (--Retry == 0) done (1); puts (""); goto loop; } check_new_mail(); } while (do_command() > 0); return (0); } init() { char *str; struct passwd *passwd; extern int sig_handle(); Entry = (struct ENTRY *)malloc (sizeof(*Entry)); Entry->status = Entry->no = Entry->fpos = 0; passwd = getpwuid(getuid()); user_name = malloc (strlen(passwd->pw_name) + 1); home_dir = malloc (strlen(passwd->pw_dir) + 1); visual = malloc (sizeof(VISUAL)); strcpy (visual , VISUAL); strcpy (user_name, passwd->pw_name); strcpy (home_dir , passwd->pw_dir); if ((str = getenv ("HOME")) != NULL) strcpy ((home_dir = realloc (home_dir, strlen(str) + 1)), str); if ((str = getenv ("USER")) != NULL) strcpy ((user_name = realloc (user_name, strlen(str) + 1)), str); if ((str = getenv ("VISUAL")) != NULL) strcpy ((visual = realloc (visual, strlen(str) + 1)), str); mail_file = malloc (strlen(MAILHOME) + strlen(user_name) + 1); sprintf (mail_file , "%s%s", MAILHOME, user_name); output_file = malloc (strlen(home_dir) + 2 + sizeof(MBOX)); sprintf (output_file, "%s/%s", home_dir, MBOX); fix_globals(); signal (SIGHUP, sig_handle); signal (SIGINT, sig_handle); signal (SIGPIPE, SIG_IGN); } sig_handle() { int mask = sigblock (0); sigsetmask (mask & ~((1 << SIGHUP) | (1 << SIGINT))); if (Longstack && !Breakstack) longjmp (env[Longstack], 1); } get_inode(file) char *file; { struct stat stats; if (stat (file, &stats) < 0) return (-1); return (stats.st_ino); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'nroff.out'" '(9692 characters)' if test -f 'nroff.out' then echo shar: will not over-write existing file "'nroff.out'" else cat << \!Funky!Stuff! > 'nroff.out' DMAIL(1) UNIX Programmer's Manual DMAIL(1) NAME dmail - an original mail like interface for mail SYNOPSIS dmail -v -O -f [fromfile] -o [tofile] -l rcfile -L -F [field] -F [field]... dmail user user user user... GENERAL _D_m_a_i_l is a program which hopefully simplifies reading and organizing your mail. It was designed to overcome several gripes people had over other mailers. _D_m_a_i_l uses the /usr/spool format for any folder's you create. To simply matters even more, it was partially modeled on standard Mail in terms of writing to your 'mbox' and getting items from your 'spool', at least as default parameters. About the only other similarity between the two programs is in the 'type', 'quit', and 'exit' commands of _d_m_a_i_l. _D_m_a_i_l _k_e_e_p_s _m_u_l_t_i_p_l_e _m_e_s_s_a_g_e_s _p_e_r _f_i_l_e, mail (thus folders are files rather than directories). _D_m_a_i_l is not a glorified _M_a_i_l, however. Though most other mailers have folders, you are usually required to read your mail in the order it comes in. For somebody who is on three high-volume mailing lists, it can be rather difficult. _D_m_a_i_l provides a mechanism in which you can separate your mail by any partial string in any Field without having to create a folder. The _s_e_l_e_c_t command is usually instantanious, and with aliases, you can switch between mailing lists, personal mail, or anything you wish at a keystroke. Whenever you _s_e_l_e_c_t on something, you get a reduced list (as if the other messages didn't exist), and may execute such things as 'delete all' on it without effecting other mail. It serves to allow you to read each mailing list (or whatever) one at a time. Mail-headers are a problem for many people, especially those logging in over 300 or 1200 baud lines. In many cases, the header is larger than the message; in any case, they can be a nuisances. _D_m_a_i_l will not print any fields you do not want printed. This seems to be a better mechanism than Mail, which allows you to exclude certain headers. In _d_m_a_i_l, you specify what to include. To see the entire header, you use the _h_e_a_d_e_r command from _d_m_a_i_l. Apart from that, _d_m_a_i_l gives you set variables, aliases, folder's, and is generally faster than other mail programs. OPTIONS _D_m_a_i_l may be executed with several options, putting it in one of two modes. Firstly, when executed with a user-name Printed 12/7/85 6 December 1985 1 DMAIL(1) UNIX Programmer's Manual DMAIL(1) list, _d_m_a_i_l will put you into the editor setting up the To: field properly and allowing you to enter a letter which would then be sent off. Secondly, if no user-list is given, dmail will attempt to read mail from your spool file (or from file), and put you into command mode. If the mail file is empty or does not exist, you will be told that you have no mail, and control will be returned to your shell. The editor is specified by the enviroment variable VISUAL (Default vi). dmail -O -v -f [fromfile] -o [tofile] -l rcfile -L -F [field] -F [field]... -O places _d_m_a_i_l in interactive mode, even if there is no mail to read. -v Places sendmail in verbose mode when you mail, reply, or forward a message. (sets the verbose variable) -f Specify where mail should be taken from. The default is /usr/spool/mail/$USER. This option without a filename specifies that mail should be taken from $HOME/mbox. Otherwise, the specified filename becomes the fromfile. This means that by specifying just the -f option and not the -o option will cause both the infile and outfile to be $HOME/mbox -o Specify where 'read' mail will be written out to. The default is $HOME/mbox. This option without a filename specifies that the mail should be placed in $HOME/.mbox . Otherwise, the specified filename becomes the out- file. Additionally, if both -f and -o are specified without filenames, both the fromfile and the outfile will be set to $HOME/.mbox -l Specify the RC file (default is $HOME/.dmailrc). The RC file consists of a list of _d_m_a_i_l commands, as if they were typed in. -L Disables sourcing of any RC files -F This option tells _d_m_a_i_l to include the given field on initial mail load. Normally, only the From:, To:, and Subject: fields are initially loaded. When you specify other fields, _d_m_a_i_l must scan your fromfile again. When you have large amounts of mail (+50000 bytes), this can take a couple of seconds. The -F option allows you to specify a field to be loaded in addition to the defaults listed above. You may specify multiple -F field options. This is only a convenience feature, normally you don't have to worry about it. Some peo- ple, however, have spool files of several hundred Printed 12/7/85 6 December 1985 2 DMAIL(1) UNIX Programmer's Manual DMAIL(1) thousand bytes and would use this option to prevent delays later on. INTERRUPTS _d_m_a_i_l handles the INTR character. You may use it to break out of listings, types, or anything else without worry of destroying something. COMMAND OVERVIEW The basic commands for _d_m_a_i_l are as follows (There are, of course, many commands, these are just a few): _l_i_s_t _t_y_p_e _h_e_a_d_e_r _d_e_l_e_t_e _n_e_x_t _s_e_l_e_c_t _q_u_i_t _e_x_i_t _a_l_i_a_s _u_n_a_l_i_a_s _s_e_t _u_n_s_e_t and _m_a_i_l You may abbrieviate any command you wish. It is suggested that you do not abbreviate commands in your rc file (default .dmailrc), as any new commands added in later versions may change something. Using full command names in your rc file will keep things compatible. For many commands (e.g. delete), you may specify a message list. You can give numerical ranges (1-4 6-9), number lists (1 2 3 6), or any of several reserved words, such as 'all'. See 'help keywords' from dmail for a complete list. All lists apply only to the currently selected messages. _l_i_s_t displays parts of the headers of messages, one message per line, for all messages currently selected. You can set the output format with the _s_e_t_l_i_s_t command. _t_y_p_e prints the message text of a message. By the way, only header fields specified by the _s_e_t_l_i_s_t command will be printed (default- From: To: Subject:), which is useful. _h_e_a_d_e_r prints out the entire header of a message. _d_e_l_e_t_e deletes a message or message list (you can say 'delete all' to delete all messages currently selected). _n_e_x_t goes to the next message and type's or header's it, depending on what last was done (type or header). _s_e_l_e_c_t selects what you want to look at. You can say 'select all', to select all the messages, or selects of the form: select Field match match match , Field match match .... where Field is From:, To:, or any field you wish (you can abbreviate the fields.... Fro To, etc...). match is a string which you are attempting to match in the Field. If a match is found, that message will become selected. Thus, Printed 12/7/85 6 December 1985 3 DMAIL(1) UNIX Programmer's Manual DMAIL(1) you can select all your personal mail with: select Cc myname , To myname Use the on-line help for more information on the _s_e_l_e_c_t or any other command. _q_u_i_t from _d_m_a_i_l please. Any unread messages stay in your spool (or fromfile), any read messages are placed in your mail-box, any deleted messages are deleted. _e_x_i_t from _d_m_a_i_l please. Nothing is written or altered, exit without changing anything. _a_l_i_a_s is used to alias commands to other commands, or command sequences. For instance, you can alias 'me' to select all personal mail: alias me "select Cc myname , To myname" you can alias a sequence of commands: alias q "select all ; pre all ; quit" The above would unread any read mail and quit (therefore, any mail not deleted will end up staying in your spool file). You can also _u_n_a_l_i_a_s aliases. _s_e_t a variable to a string. You can also _u_n_s_e_t a variable. Several variables have special meaning, use _h_e_l_p _s_e_t from _d_m_a_i_l for a full explanation. _m_a_i_l and _r_e_p_l_y may be used to mail out or reply to messages. BUGS Please send bug reports to: ...!ucbvax!dillon dillon@ucb-vax.berkeley.edu Printed 12/7/85 6 December 1985 4 !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'range.c'" '(3470 characters)' if test -f 'range.c' then echo shar: will not over-write existing file "'range.c'" else cat << \!Funky!Stuff! > 'range.c' /* * RANGE.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: REWIND_RANGE() * GET_RANGE() * SINGLE_POSITION() * * Static Routines: None. * * */ #include <stdio.h> #include "dmail.h" static int range_ac; static int in, start, end; struct RANOP { char *name; int status, kstatus; }; static struct RANOP Ranop[] = { "all", 0, 0, "tag", ST_TAG, ST_DELETED, "wri", ST_STORED, ST_DELETED, "del", ST_DELETED, 0, "mar", ST_READ, ST_DELETED, "unt", 0, ST_DELETED | ST_TAG, "unw", 0, ST_DELETED | ST_STORED, "und", 0, ST_DELETED, "unm", 0, ST_DELETED | ST_READ, NULL , 0, 0 }; rewind_range(beg) { Silence = 0; range_ac = beg; if (range_ac >= ac) { start = Entry[Current].no; end = start; in = 1; } else { in = 0; } } get_range() { register char *ptr; register int i; static int status; /* Status items required */ static int kstatus; /* Status items which cannot be present */ again: if (in && start <= end) { i = indexof(start++); if (i < 0 || (Entry[i].status & status) != status || (Entry[i].status & kstatus)) goto again; return (start - 1); } in = status = kstatus = 0; if (range_ac >= ac) return (0); ptr = av[range_ac++]; if (*ptr == '-') { if (xstrncmp (ptr, "-s", 2) == 0) { Silence = 1; goto again; } start = 1; ++ptr; goto dash; } if (*ptr < '0' || *ptr > '9') { start = 1; end = 0; for (i = 0; Ranop[i].name; ++i) { if (xstrncmp (ptr, Ranop[i].name, 3) == 0) { status = Ranop[i].status; kstatus = Ranop[i].kstatus; goto imprange; } } goto again; } start = atoi(ptr); while (*(++ptr)) { if (*ptr == '-') { ++ptr; goto dash; } } if (range_ac >= ac) return (start); if (*av[range_ac] == '-') { ptr = av[range_ac++] + 1; goto dash; } return (start); dash: if (*ptr) { end = atoi(ptr); goto imprange; } if (range_ac >= ac) { end = 0; goto imprange; } end = atoi(av[range_ac++]); imprange: if (end == 0) { end = indexof (0); if (end < 0) return (0); end = Entry[end].no; } if (start > end) { printf ("Bad Range: %s\n", av[range_ac - 1]); return (0); } in = 1; goto again; } single_position() { long pos; int old = Current; switch (ac) { case 1: break; case 2: Current = indexof (atoi(av[1])); if (Current < 0) { Current = old; puts ("Out of Range, 0 will take you to the last entry"); return (-1); } break; default: puts ("Range not implemented (yet?)"); return (-1); } while (Current < Entries && Entry[Current].no == 0) ++Current; if (Current >= Entries) { Current = old; puts ("No More Messages"); return (-1); } position_current(); return (1); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'sendmail.c'" '(7315 characters)' if test -f 'sendmail.c' then echo shar: will not over-write existing file "'sendmail.c'" else cat << \!Funky!Stuff! > 'sendmail.c' /* * SENDMAIL.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: DO_REPLY() * DO_MAIL() * * Static Routines: WORD_SIZE() * FOPEN_SCRATCH() * FREOPEN_SCRATCH() * FCLOSE_SCRATCH() * FTERMINATE_SCRATCH() * DELETE_SCRATCH() * RUN_VI() * SEND_MAIL() * * */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <sysexits.h> #include <signal.h> #include "dmail.h" extern FILE *popen(); FILE *fi; char file[64]; do_reply(garbage, itext) char *garbage; { int i, j, notfirst; int anyargs = 0; int to_field, cc_field; register int len; char *ptr; char buf[1024]; char scr; FILE *fs; if (push_base()) { push_break(); pop_base(); fclose_scratch(); puts ("ABORTED, no mail sent"); pop_break(); return (-1); } fopen_scratch(); strcpy (buf, "To: "); for (i = 1; i < ac; ++i) { if (*av[i] >= '0' && *av[i] <= '9') { if ((j = indexof(atoi(av[i]))) < 0) { puts ("No such message"); fclose_scratch(); pop_break(); return (-1); } Current = j; } else { if (anyargs) strcat (buf, ", "); anyargs = 1; strcat (buf, av[i]); } } len = strlen(buf); switch (itext) { case R_FORWARD: strcat (buf, "\n"); fputs (buf, fi); fputs ("Subject: \n", fi); break; case R_INCLUDE: case R_REPLY: if (anyargs) { strcat (buf, ", "); len = strlen(buf); } sprintf (buf + len, "%.*s\n", word_size(Entry[Current].from), Entry[Current].from); fputs (buf, fi); fputs ("Cc: ", fi); ptr = get_field ("To:"); to_field = (*ptr) ? 1 : 0; fputs (ptr, fi); scr = *(ptr + strlen(ptr) - 1); ptr = get_field ("Cc:"); cc_field = (*ptr) ? 1 : 0; if (cc_field) { if (scr == '\n') { fputs (" ", fi); } if (to_field) fputs (", ", fi); fputs (ptr, fi); } fputs ("\nSubject: Re: ", fi); fputs (get_field ("Subject:"), fi); fputs ("\n", fi); break; case R_MAIL: fputs (buf, fi); fputs ("\n", fi); fputs ("Cc: \n", fi); fputs ("Bcc: \n", fi); fputs ("Subject: \n", fi); break; default: puts ("INTERNAL STUPID MAIL ERROR: REPLY"); break; } copy_header (fi); fputs ("\n\n", fi); if (itext == R_FORWARD || itext == R_INCLUDE) { position_current(); if (itext == R_FORWARD) fprintf (fi, "ORIGINALLY From %s\n", Entry[Current].from); else skip_to_data (m_fi); while ((fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) && !isfrom(Buf)) { if (itext == R_INCLUDE) fputs (" > ", fi); fputs (Buf, fi); } fputs ("\n", fi); } fclose_scratch(); if (itext != R_MAIL) { push_break(); Entry[Current].status |= ST_SCR; write_file ("#", O_CREAT | O_TRUNC, ST_SCR, 0); Entry[Current].status &= ~ST_SCR; pop_break(); } j = -1; loop: ++j; if (run_vi() || j) { push_break(); switch (do_ask()) { case 1: puts ("SENDING.. wait"); send_mail(); break; case 2: pop_break(); goto loop; default: break; } pop_base(); pop_break(); } else { puts ("File not modified or ABORTED, no mail sent"); pop_base(); } unlink ("#"); } do_ask() { char in[256]; if (!S_ask) return (1); fputs ("\n(Send, Vi, Quit) ?", stdout); fflush(stdout); gets (in); switch (in[0]) { case 's': case 'S': return (1); case 'v': case 'V': return (2); } puts ("ABORT, no mail sent"); return (0); } static copy_header(fi) FILE *fi; { FILE *fs; char *ptr; if (ptr = get_var (LEVEL_SET, "header")) { push_break(); if ((fs = fopen (ptr, "r")) != NULL) { while (fgets (Buf, MAXFIELDSIZE, fs) != NULL) fputs (Buf, fi); fclose (fs); } else { printf ("Cannot open header file %d %s\n", strlen(ptr), ptr); perror ("fopen"); } pop_break(); } } static fopen_scratch() { sprintf (file, "/tmp/dmt%d", getpid()); fi = fopen (file, "w+"); if (fi == NULL) { perror ("Dmail, cannot open scratch file"); done (1); } } static fclose_scratch() { if (fi != NULL) { fflush (fi); fclose (fi); fi = NULL; } } static fterminate_scratch() { if (fi != NULL) { fclose (fi); fi = NULL; unlink (file); } } static delete_scratch() { sprintf (file, "/tmp/dmt%d", getpid()); unlink (file); } static word_size(str) register char *str; { register int size = 0; while (*str) { if (*str == ' ') return (size); ++str; ++size; } return (size); } static run_vi() { char buf[64]; int ret, pid = 0; struct stat stat1, stat2; char *argv[3]; argv[0] = visual; argv[1] = file; argv[2] = NULL; if (push_base()) { push_break(); pop_base(); if (pid) { kill (pid, SIGKILL); sprintf (buf, "/tmp/Ex%d", pid); unlink (buf); sprintf (buf, "/tmp/Rx%d", pid); unlink (buf); wait(0); system ("clear; reset ; clear"); pid = 0; } pop_break(); return (0); } stat1.st_mtime = stat2.st_mtime = stat1.st_ctime = stat2.st_ctime = 0; stat (file, &stat1); if (S_novibreak) push_break(); pid = vfork(); if (!pid) { execv (visual, argv); _exit (1); } while ((ret = wait(0)) > 0) { if (ret == pid) break; } if (S_novibreak) pop_break(); stat (file, &stat2); pop_base(); return (!(stat1.st_mtime==stat2.st_mtime)); } static send_mail() { char buf[1024]; int fildes[2]; int fd, stdin_fd; int i; char *argv[6]; push_break(); argv[0] = S_sendmail; argv[1] = "-t"; argv[2] = "-oo"; argv[3] = "-oi"; if (S_verbose) { argv[4] = "-v"; argv[5] = NULL; } else { argv[4] = NULL; } pipe (fildes); stdin_fd = dup (0); dup2 (fildes[0], 0); if (!vfork()) execv (S_sendmail, argv); dup2 (stdin_fd, 0); fd = open (file, O_RDONLY, 0); if (fd < 0) { perror ("Dmail, Cannot open scratch file"); done (1); } while ((i = read (fd, buf, 1024)) > 0) write (fildes[1], buf, i); close (fd); close (fildes[1]); if (S_verbose) wait (0); pop_break(); } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'set.c'" '(3049 characters)' if test -f 'set.c' then echo shar: will not over-write existing file "'set.c'" else cat << \!Funky!Stuff! > 'set.c' /* * SET.C * * Matthew Dillon, 6 December 1985 * * * Variable set/unset/get/reset routines * */ #include <stdio.h> #include "dmail.h" #define MAXLEVELS 3 struct MASTER { struct MASTER *next; struct MASTER *last; char *name; char *text; }; struct MASTER *Mbase[MAXLEVELS]; set_var (level, name, str) register char *name, *str; { register struct MASTER *base = Mbase[level]; register struct MASTER *last; push_break(); while (base != NULL) { if (strcmp (name, base->name) == 0) { free (base->text); goto gotit; } last = base; base = base->next; } if (base == Mbase[level]) { base = Mbase[level] = (struct MASTER *)malloc (sizeof (struct MASTER)); base->last = NULL; } else { base = (struct MASTER *)malloc (sizeof (struct MASTER)); base->last = last; last->next = base; } base->name = malloc (strlen (name) + 1); strcpy (base->name, name); base->next = NULL; gotit: base->text = malloc (strlen (str) + 1); strcpy (base->text, str); pop_break(); } unset_var(level, name, str) register char *name, *str; { register struct MASTER *base = Mbase[level]; register struct MASTER *last; push_break(); while (base != NULL) { if (strcmp (name, base->name) == 0) { if (base != Mbase[level]) last->next = base->next; else Mbase[level] = base->next; if (base->next != NULL) base->next->last = last; if (base == Mbase[level]) Mbase[level] = base->next; free (base->name); free (base->text); free (base); pop_break(); return (1); } last = base; base = base->next; } pop_break(); return (-1); } char * get_var(level, name) register char *name; { register struct MASTER *base = Mbase[level]; while (base != NULL) { if (strcmp (name, base->name) == 0) return (base->text); base = base->next; } return (NULL); } do_unset_var(str, level) char *str; { int i; push_break(); for (i = 1; i < ac; ++i) unset_var (level, av[i]); fix_globals(); pop_break(); return (1); } do_set_var(command, level) char *command; { register struct MASTER *base = Mbase[level]; register char *str; if (ac == 1) { while (base) { printf ("%-10s %s\n", base->name, base->text); base = base->next; } } if (ac == 2) { str = get_var (level, av[1]); if (str) { printf ("%-10s %s\n", av[1], str); } else { push_break(); set_var (level, av[1], ""); fix_globals(); pop_break(); } } if (ac > 2) { push_break(); set_var (level, av[1], next_word (next_word (command))); fix_globals(); pop_break(); } } !Funky!Stuff! fi # end of overwriting check echo shar: extracting "'sub.c'" '(5147 characters)' if test -f 'sub.c' then echo shar: will not over-write existing file "'sub.c'" else cat << \!Funky!Stuff! > 'sub.c' /* * SUB.C * * Matthew Dillon, 6 December 1985 * * * Global Routines: INDEXOF() * SIG() * POSITION_CURRENT() * SKIP_TO_DATE() * GET_FIELD() * COMPILE_FIELD() * ISFROM() * XSTRNCMP() * NEXT_WORD() * DONE() * */ #include <signal.h> #include <stdio.h> #include "dmail.h" #define SENDMAIL "/usr/lib/sendmail" indexof(num) register int num; { register int i, last; if (num < 1) num = -1; for (last = -1, i = 0; i < Entries; ++i) { if (Entry[i].no) { last = i; if (Entry[i].no == num) return (i); } } if (num == -1 && last >= 0) return (last); return (-1); } null() { } position_current() { int pos; pos = Entry[Current].fpos; if (fseek (m_fi, pos, 0) != pos) puts ("ERROR: Cannot position file to message"); } skip_to_data(fi) FILE *fi; { char buf[MAXFIELDSIZE]; while (fgets (buf, MAXFIELDSIZE, fi) != NULL) { if (*buf == '\n') return (1); } return (-1); } char * get_field(str) char *str; { int i, entry = Current; int len = strlen(str); i = get_extra (str); if (i >= 0) return (Entry[entry].fields[i]); if (m_fi == NULL) return (""); fseek (m_fi, Entry[entry].fpos, 0); while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) { if (isfrom (Buf)) break; if (strncmp (Buf, str, len) == 0) { Buf[strlen(Buf) - 1] = '\0'; compile_field(Buf, m_fi); return (next_word (Buf)); } } return (""); } compile_field(buf, fi) char *buf; FILE *fi; { int len, acc, pos; acc = 0; buf += strlen (buf) + 1; pos = ftell (fi); while (fgets (buf, MAXFIELDSIZE - acc, fi) != NULL) { if (*buf == ' ' || *buf == 9) { *(buf - 1) = '\n'; len = strlen (buf) - 1; *(buf + len) = '\0'; buf += len; acc += len + 2; if (acc > MAXFIELDSIZE - 10) { printf ("Warning: Field size beyond %d bytes\n", MAXFIELDSIZE); sleep (2); return (1); } } else { *buf = '\0'; fseek (fi, pos, 0); return (1); } pos = ftell (fi); } fseek (fi, pos, 0); } isfrom(str) register char *str; { static char from[] = {"From "}; register int i = 0; while (i < 5) { if (*str++ != from[i++]) return (0); } return (1); } xstrncmp (src, dest, len) register char *src, *dest; register int len; { while (--len >= 0) { if ((*src & 0x1f) != (*dest & 0x1f)) { if ((*src & 0x1f) < (*dest & 0x1f)) return (-1); return (1); } ++src; ++dest; } return (0); } char * next_word(str) register char *str; { while (*str && *str != ' ' && *str != 9) ++str; while (*str && (*str == ' ' || *str == 9)) ++str; return (str); } done(n) { char scr[64]; push_break(); sprintf (scr, "/tmp/dmail%d", getpid()); unlink (scr); sprintf (scr, "/tmp/dmt%d", getpid()); unlink (scr); unlink ("#"); exit (n); } fix_globals() { char *ptr; push_break(); S_page = (ptr = get_var (LEVEL_SET, "page")) ? ((*ptr) ? atoi (ptr) : 24) : -1; if (S_page > 0 && (S_page -= 4) < 0) S_page = 1; S_sendmail = (ptr = get_var (LEVEL_SET, "sendmail")) ? ptr : SENDMAIL; S_novibreak= (ptr = get_var (LEVEL_SET, "vibreak")) ? 0 : 1; S_verbose = (ptr = get_var (LEVEL_SET, "verbose")) ? 1 : 0; S_ask = (ptr = get_var (LEVEL_SET, "ask")) ? 1 : 0; pop_break(); } _pager(str, nl) char *str; int nl; { static int count; static FILE *fi; char buf[1024]; char *ptr; if (str == 0) { switch (S_page) { case -1: count = 0; return (1); case 0: ptr = get_var (LEVEL_SET, "page"); fi = popen (ptr, "w"); if (fi == NULL) { count = 0; printf ("CANNOT RUN PAGER PROGRAM: %s\n", ptr); } else { count = -1; } return (1); default: count = 0; return (1); } } if ((long)str == -1) { if (fi != NULL) { pclose (fi); fi = NULL; } return (1); } if (count < 0) { fputs (str, fi); while (nl--) fputs ("\n", fi); } else { fputs (str, stdout); while (nl--) { fputs ("\n", stdout); ++count; } while (*str) { if (*str++ == '\n') ++count; } if (S_page > 0 && S_page <= count) { count = 0; puts ("\n-- more --"); gets(buf); } } } !Funky!Stuff! fi # end of overwriting check # End of shell archive exit 0