[comp.sources.amiga] v90i185: UUCP 1.06D - UNIX compatible uucp/news/mail system, Part07/12

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (06/28/90)

Submitted-by: Matt Dillon <@uunet.uu.net:overload!dillon>
Posting-number: Volume 90, Issue 185
Archive-name: unix/uucp-1.06d/part07

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 7 (of 12)."
# Contents:  uucp2/src/dmail/execom.c uucp2/src/dmail/load_mail.c
#   uucp2/src/uuser/uuser.c
# Wrapped by tadguy@xanth on Thu Jun 28 08:21:29 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'uucp2/src/dmail/execom.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp2/src/dmail/execom.c'\"
else
echo shar: Extracting \"'uucp2/src/dmail/execom.c'\" \(12837 characters\)
sed "s/^X//" >'uucp2/src/dmail/execom.c' <<'END_OF_FILE'
X
X/*
X *  EXECOM.C
X *
X *  $Header: Beta:src/uucp/src/dmail/RCS/execom.c,v 1.1 90/02/02 12:03:41 dillon Exp Locker: dillon $
X *
X *  (C) Copyright 1985-1990 by Matthew Dillon,  All Rights Reserved.
X *
X *  Routines to parse and execute command lines.
X *
X *  Global Routines:	DO_COMMAND()
X *			EXEC_COMMAND()
X *			FIX()
X *
X *  Static Routines:	E_COMMAND()
X *			BREAKOUT()
X *			FIND_COMMAND()
X */
X
X
X#include <pwd.h>
X#include <stdio.h>
X#include <string.h>
X#include "dmail.h"
X#include "execom.h"
X
X#define F_EXACT     0
X#define F_ABBR	    1
X#define SCRBUF	    1024
X
Xextern char *breakout();
X
Xextern int do_quit(), do_exit(), do_help(), do_list(), do_setlist();
Xextern int do_select(), do_type(), do_header(), do_next(), do_mark();
Xextern int do_unmark(), do_reply(), do_delnext(), do_rlist();
Xextern int do_write(), do_shell(), do_set_var(), do_unset_var();
Xextern int do_number(), do_cd(), do_source(), do_defer(), do_echo();
Xextern int do_go(), do_break();
X
Xextern int do_if(), do_else(), do_endif();
Xextern int do_ver(), do_delprev();
X
Xstruct COMMAND Command[] = {
X	do_number   , 0,	0,		    "",
X	do_mark     , 0,	ST_DELETED,	    "delete",
X	do_unmark   , 0,	ST_DELETED,	    "undelete",
X	do_header   , 0,	0,		    "header",
X	do_type     , 0,	0,		    "type",
X	do_echo     , 0,	0,		    "echo",
X	do_go	    , 0,	0,		    "go",
X	do_reply    , 0,	R_REPLY,	    "reply",
X	do_reply    , 0,	R_INCLUDE,	    "Reply",
X	do_reply    , 0,	R_MAIL, 	    "mail",
X	do_reply    , 0,	R_FORWARD,	    "forward",
X	do_select   , 0,	0,		    "select",
X	do_select   , 0,	1,		    "reselect",
X	do_defer    , 0,	1,		    "defer",
X	do_list     , 0,	0,		    "list",
X	do_rlist    , 0,	0,		    "rlist",
X	do_next     , 0,	1,		    "next",
X	do_next     , 0,	-1,		    "back",
X	do_next     , 0,	2,		    "_next",
X	do_next     , 0,	-2,		    "_back",
X	do_delnext  , 0,	0,		    "dt",
X	do_delprev  , 0,	0,		    "db",
X	do_set_var  , 0,	0,		    "set",
X	do_unset_var, 0,	0,		    "unset",
X	do_set_var  , 0,	1,		    "alias",
X	do_unset_var, 0,	1,		    "unalias",
X	do_set_var  , C_NO,	2,		    "malias",
X	do_unset_var, C_NO,	2,		    "munalias",
X	do_setlist  , 0,	0,		    "setlist",
X	do_cd	    , 0,	0,		    "cd",
X	do_source   , 0,	0,		    "source",
X	do_unmark   , 0,	ST_READ | ST_STORED,"preserve",
X	do_mark     , 0,	ST_READ,	    "mark",
X	do_mark     , 0,	ST_TAG, 	    "tag",
X	do_unmark   , 0,	ST_TAG, 	    "untag",
X	do_unmark   , 0,	ST_STORED,	    "unwrite",
X	do_write    , 0,	0,		    "write",
X	do_shell    , 0,	0,		    "!",
X	do_exit     , 0,	0,		    "x",
X	do_quit     , 0,	0,		    "quit",
X	do_exit     , 0,	1,		    "xswitch",
X	do_quit     , 0,	1,		    "qswitch",
X	do_help     , 0,	0,		    "help",
X	do_help     , 0,	0,		    "?",
X	do_break    , 0,	0,		    "nobreak",
X	do_break    , 0,	1,		    "breakok",
X	do_if	    , C_COND,	0,		    "if",
X	do_else     , C_COND,	0,		    "else",
X	do_endif    , C_COND,	0,		    "endif",
X	do_ver	    , 0,	0,		    "version",
X	NULL	    , 0,	0,		    NULL };
X
Xchar *Desc[] = {
X	"",
X	"<list>                   mark messages for deletion",
X	"<list>                   UNDELETE & UNMARK messages",
X	"[msg]                    Display header of a message",
X	"[msg]                    type a message",
X	"args....                 Echo to the screen",
X	"#                        Go to a message, don't print out",
X	"                         reply to mail",
X	"                         reply to mail, include recv'd text",
X	"user user ...            send mail to users",
X	"user user ...            forward mail to users",
X	"Field [!]match [match][ , Field match.]  SELECT from entire message list",
X	"Field [!]match [match][ , Field match.]  SELECT from current message list",
X	"                         De-select any read messages",
X	"<list>                   list mail as specified by SETLIST",
X	"[+/-][N]                 list relative to current position",
X	"[msg]                    type/header next or message #",
X	"[msg]                    type/header previous or message #",
X	"[msg]                    go to next or message #",
X	"[msg]                    go to previous or message #",
X	"                         delete current, type next",
X	"                         delete current, type prev",
X	"[var [string]]           set a variable",
X	"var var var ...          unset a variable",
X	"[var [string]]           set an alias",
X	"var var var ...          unset an alias",
X	"[var [string]]           set a mail alias",
X	"var var var ...          unset a mail alias",
X	"[-s] [cols] Field [cols] Field...    SET LIST format for LIST",
X	"path                     CD to a directory",
X	"file                     Source a file",
X	"<list>                   UNREAD & UNMARK messages",
X	"<list>                   mark messages as 'read'",
X	"<list>                   tag messages for whatever",
X	"<list>                   untag messages",
X	"<list>                   unwrite messages",
X	"file <list>              append messages to a file, delete on quit",
X	"[command]                execute a shell [command]",
X	"                         EXIT, do not save changes",
X	"                         QUIT, update files",
X	"from to                  Exit and switch to a new from/to file",
X	"from to                  Quit and switch to a new from/to file",
X	"[topic]                  help on a topic",
X	"[topic]                  alternate form of HELP",
X	"                         Disable INTR (stackable)",
X	"                         Enable  INTR (stackable)",
X	"[!]variable              conditionals (stackable)",
X	"",
X	"",
X	"                         Print the version number",
X	NULL };
X
X
Xdo_command()
X{
X    static char comline[1024];
X
X    if (Current >= 0 && Current < Entries)
X	printf("%3d:", Entry[Current].no);
X    else
X	printf("nul:");
X    fflush (stdout);
X    if (gets (comline) == NULL)
X	done (1);
X    exec_command(comline);
X    return (1);
X}
X
X
X
X/*
X * EXEC_COMMAND()
X *
X *
X */
X
X
Xstruct MLIST {
X    struct MLIST *next;
X};
X
Xstatic struct MLIST *Mlist;
X
Xchar *
Xmpush(amount)
Xint amount;
X{
X    struct MLIST *ml;
X
X    push_break();
X    ml = (struct MLIST *)malloc (amount + sizeof(*Mlist));
X    ml->next = Mlist;
X    Mlist = ml;
X    pop_break();
X    return ((char *)Mlist + sizeof(*Mlist));
X}
X
X
Xchar *
Xmpop()
X{
X    char *old = NULL;
X
X    push_break();
X    if (Mlist == NULL) {
X	puts ("MLIST INTERNAL ERROR");
X    } else {
X	old = (char *)Mlist + sizeof(*Mlist);
X	xfree (Mlist);
X	Mlist = Mlist->next;
X    }
X    pop_break();
X    return (old);
X}
X
Xvoid
Xmrm()
X{
X    push_break();
X    while (Mlist) {
X	xfree (Mlist);
X	Mlist = Mlist->next;
X    }
X    pop_break();
X}
X
X
Xexec_command(base)
Xchar *base;
X{
X    char *str;
X    int i;
X
X    if (push_base()) {
X	push_break();
X	pop_base();
X	mrm();
X	pop_break();
X	return (-1);
X    }
X    strcpy (str = mpush(strlen(base) + 1), base);
X    i = e_command(str);
X    if (mpop() != str)
X	puts ("POP ERROR");
X    pop_base();
X    return (i);
X}
X
X
Xstatic
Xe_command(base)
Xchar *base;
X{
X    char *com, *start, *avline, *alias;
X    int flag = 0;
X    int i, pcount, len, ccno;
X
Xloop:
X    com = breakout (&base, &flag);
X    if (*com == '\0') {
X	if (flag > 1)
X	    return (1);
X	goto loop;
X    }
X    if ((ccno = find_command(com, F_EXACT)) < 0) {
X	if (*com == '$')
X	    alias = get_var (LEVEL_SET, com + 1);
X	else
X	    alias = get_var (LEVEL_ALIAS, com);
X	if (alias == NULL) {
X	    if ((ccno = find_command (com, F_ABBR)) < 0) {
X		if (!XDisable)
X		    printf ("%s Command Not found\n", com);
X		return (XDisable ? 1 : -1);
X	    } else {
X		goto good_command;
X	    }
X	}
X
X	/* At this point, base points to arguments */
X
X	start = (flag == 0) ? base : "";
X	while (flag == 0) {             /* find ';' or end of string        */
X	    flag = -1;			/* disable breakout's "" terminator */
X	    breakout (&base, &flag);
X	}
X
X	/*
X	 * At this point, start points to all arguments, base set up for next
X	 * string
X	 */
X
X	if (*alias == '%') {
X	    int xx = 0;
X	    char *select;
X
X	    alias = strcpy (mpush (strlen(alias) + 1), alias);
X	    select = breakout (&alias, &xx);
X	    set_var (LEVEL_SET, select + 1, start);
X	    i = e_command (alias);
X	    unset_var (LEVEL_SET, select + 1);
X	    mpop();
X	} else {
X	    com = mpush (strlen(alias) + strlen(start) + 2);
X	    strcpy (com, alias);
X	    strcat (com, (flag == 1) ? ";" : " ");
X	    strcat (com, start);
X	    i = e_command (com);
X	    if (mpop() != com)
X		puts ("ME BAE ERROR");
X	}
X	if (i < 0)
X	    return (-1);
X	if (flag > 1)
X	    return (1);
X	goto loop;
X    }
Xgood_command:
X    if (XDisable && (Command[ccno].stat & C_COND) == 0) {
X	while (flag < 1)
X	    breakout (&base, &flag);
X	if (flag > 1)
X	    return (1);
X	goto loop;
X    }
X    if (Command[ccno].stat & C_NO  &&  XDebug == 0) {
X	printf ("%s  Is currently being developed\n", Command[ccno].name);
X	return (-1);
X    }
X    if (XDebug)
X	printf ("Good command, Raw: %s\n", com);
X    i = pcount = 0;
X    av[i] = mpush (strlen(com) + 1);
X    ++pcount;
X    strcpy (av[i++], com);
X    while (flag < 1) {
X	com = breakout (&base, &flag);
X	if (XDebug)
X	    printf ("BREAKOUT %d %s\n", strlen(com), com);
X	if (*com == '\0')
X	    continue;
X	switch (*com) {
X	case '~':
X	    if (com[1] == '/'  ||  com[1] == '\0') {
X		av[i] = mpush (strlen(home_dir) + strlen(com + 1) + 1);
X		++pcount;
X		strcpy (av[i], home_dir);
X		strcat (av[i], com + 1);
X	    } else {
X		struct passwd *passwd;
X		char *user = com;
X
X		while (*com) {
X		    if (*com == '/') {
X			*com = '\0';
X			++com;
X			break;
X		    }
X		    ++com;
X		}
X		if ((passwd = getpwnam(user)) == NULL) {
X		    printf ("USER %s Not found\n", user);
X		    while (pcount--)
X			mpop();
X		    return (-1);
X		}
X		av[i] = mpush (strlen(passwd->pw_dir) + strlen(com) + 2);
X		++pcount;
X		strcpy (av[i], passwd->pw_dir);
X		if (*com) {
X		    strcat (av[i], "/");
X		    strcat (av[i], com);
X		}
X	    }
X	    break;
X	case '\"':
X	    av[i] = com + 1;
X	    while (*++com && *com != '\"');
X	    *com = '\0';
X	    break;
X	case '$':
X	    if (*(com + 1) == '$') {
X		av[i] = getenv(com + 2);
X		if (av[i] == NULL) {
X		    printf ("Env. Var %s not found\n", com + 2);
X		    av[i] = com;
X		}
X#ifdef AMIGA
X		av[i] = strcpy (mpush(strlen(av[i]) + 1), av[i]);
X		++pcount;
X#endif
X	    }  else {
X		av[i] = get_var (LEVEL_SET, com + 1);
X		if (av[i] == NULL)
X		    av[i] = com;
X		av[i] = strcpy (mpush(strlen(av[i]) + 1), av[i]);
X		++pcount;
X	    }
X	    break;
X	default:
X	    av[i] = com;
X	    break;
X	}
X	++i;
X    }
X    av[i] = NULL;
X    ac = i;
X    for (len = 0, i = 0; i < ac; ++i)
X	len += strlen (av[i]) + 1;
X    avline = mpush (len + 1);
X    *avline = '\0';
X    for (i = 0; i < ac; ++i) {
X	strcat (avline, av[i]);
X	if (i + 1 < ac)
X	    strcat (avline, " ");
X    }
X    if (XDebug)
X	printf ("DEST: %s\n", avline);
X    i = (*Command[ccno].func)(avline, Command[ccno].val);
X    if (mpop() != avline)
X	puts ("AVLINE ERROR");
X    while (pcount--)
X	mpop();
X    fix();
X    if (i < 0)
X	return (i);
X    if (flag < 2)
X	goto loop;
X    return (1);
X}
X
X
X/*
X * BREAKOUT
X *
X * Breakout next argument.  If FLAG is set to 1 on return, the argument
X * returned is the last in the command.  If FLAG is set to 2 on return, the
X * argument returned is the last, period.
X *
X */
X
Xstatic char *
Xbreakout(base, flag)
Xint *flag;
Xchar **base;
X{
X    register char *str, *scr;
X
Xloop:
X    str = *base;			/* next start		*/
X    while (*str == ' ' || *str == 9)    /* skip spaces and such */
X	++str;
X    switch (*str) {
X    case '\0':                          /* no more arguments    */
X	*flag = 2;
X	*base = str;
X	return (str);
X    case ';':                           /* no more args in this command */
X	*flag = 1;
X	*str = '\0';
X	*base = str + 1;
X	return (str);
X    }
X    scr = str;
X    for (;;) {                          /* valid argument of somesort   */
X	switch (*scr) {
X	case ' ':
X	case 9:
X	    if (*flag >= 0)
X		*scr = '\0';
X	    *base = scr + 1;
X	    *flag = 0;
X	    return (str);
X	case '\"':
X	    ++scr;
X	    while (*scr && (*scr++ != '\"'));   /* place to end of quote */
X	    break;
X	case '\0':
X	    *flag = 2;
X	    *base = scr;
X	    return (str);
X	case ';':
X	    *flag = 1;
X	    *base = scr + 1;
X	    *scr = '\0';
X	    return (str);
X	default:
X	    ++scr;
X	}
X    }
X}
X
X
X
Xfix()
X{
X    register int i;
X
X    for (i = (Current < 0) ? 0 : Current; i < Entries; ++i) {
X	if (Entry[i].no  &&  !(Entry[i].status & ST_DELETED)) {
X	    Current = i;
X	    return (1);
X	}
X    }
X    if (Current >= Entries) {
X	Current = Entries - 1;
X    /* Can become -1 if no entries  */
X    }
X    for (i = Current; i >= 0; --i) {
X	if (Entry[i].no  &&  !(Entry[i].status & ST_DELETED)) {
X	    Current = i;
X	    return (-1);
X	}
X    }
X    Current = -1;
X    return (-1);
X}
X
X
Xstatic
Xfind_command(str, arg)
Xchar *str;
Xint arg;
X{
X    int i;
X    int len = strlen (str);
X
X    if (*str >= '0'  &&  *str <= '9')
X	return (0);
X    for (i = 0; Command[i].func; ++i) {
X	if (strncmp (str, Command[i].name, len) == 0) {
X	    if (arg == F_ABBR)
X		return (i);
X	    if (strcmp (str, Command[i].name) == 0)
X		return (i);
X	    return (-1);
X	}
X    }
X    return (-1);
X}
X
END_OF_FILE
if test 12837 -ne `wc -c <'uucp2/src/dmail/execom.c'`; then
    echo shar: \"'uucp2/src/dmail/execom.c'\" unpacked with wrong size!
fi
# end of 'uucp2/src/dmail/execom.c'
fi
if test -f 'uucp2/src/dmail/load_mail.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp2/src/dmail/load_mail.c'\"
else
echo shar: Extracting \"'uucp2/src/dmail/load_mail.c'\" \(13945 characters\)
sed "s/^X//" >'uucp2/src/dmail/load_mail.c' <<'END_OF_FILE'
X
X/*
X *  LOAD_MAIL.C
X *
X *  $Header: Beta:src/uucp/src/dmail/RCS/load_mail.c,v 1.1 90/02/02 12:03:35 dillon Exp Locker: dillon $
X *
X *  (C) Copyright 1985-1990 by Matthew Dillon,  All Rights Reserved.
X *
X *  file-io routines to scan the mail file and load required information.
X *
X *
X *  Global Routines:	HOLD_LOAD()         hold on loading mail after change
X *			NOHOLD_LOAD()       hold off.. load if changes
X *			LOAD_CHANGES()      reload mail if changed
X *			LOAD_MAIL()         load/reload mail
X *			SAVE_FILE()         save mail items back to spool
X *			CHECK_NEW_MAIL()    check for new mail
X *			WRITE_FILE()        append mail items to a file
X *			GET_EXTRA_OVR()     ret index of Field (create if not)
X *			ADD_EXTRA()         add another field (reloads mail)
X *			DELETE_EXTRA()      delete a field
X *			GET_EXTRA()         ret index of Field, or error
X *			M_SELECT()          select on current message list
X *
X *
X *  Static Routines:	LOAD_HASH()         load hash table from fields list
X *			FREE_ENTRY()        unload EVERYTHING
X *			FREE_TABLE()        unload all Fields table
X *			LOAD_FILE()         raw file loading/counting
X *
X *
X */
X
X#include <stdio.h>
X#include <sys/file.h>
X#include "dmail.h"
X
Xvoid do_flock();
Xvoid free_table();
Xvoid load_hash();
X
X#define NOHOLD	0
X#define HOLD	1
X
X#define NO_BASE     0
X#define NO_FIELDS   1
X#define ENTRY_OK    2
X
Xstruct FIND Find[MAXTYPE + 1] = {
X	"From:"   , 5, 1, 0,
X	"To:"     , 3, 1, 0,
X	"Subject:", 8, 1, 0 };
X
Xstatic int  File_size;
Xstatic int  changed, load_hold;
Xstatic int  Hash[256];
X
Xstatic char *quo_quo = "";
X
Xvoid
Xhold_load()
X{
X    load_hold = 1;
X}
X
Xvoid
Xnohold_load()
X{
X    void load_changes();
X    load_hold = 0;
X    load_changes();
X}
X
Xvoid
Xload_changes()
X{
X    if (changed  &&  !load_hold)
X	load_mail(Entries, 1);
X}
X
Xinitial_load_mail()
X{
X    if (load_mail (0, 0) < 0)
X	return (-1);
X    return ((Entries) ? 1 : -1);
X}
X
X
Xstatic
Xload_mail(at, from0)
X{
X    FILE *fi;
X    int i, count, file_size;
X
X    if (No_load_mail)
X	return (-1);
X    push_break();
X    load_hash();
X    if (from0)
X	free_table (0, HOLD);
X    else
X	free_table (at, NOHOLD);
X    fi = fopen (mail_file, "r+");
X    if (m_fi != NULL)
X	fclose (m_fi);
X    m_fi = fopen (mail_file, "r+");
X    if (fi == NULL  ||  m_fi == NULL) {
X	pop_break();
X	return (-1);
X    }
X    do_flock (fileno(m_fi), LOCK_EX);
X    if (at)
X	fseek (fi, Entry[at].fpos, 0);
X    else
X	fseek (fi, 0, 0);
X    count = Entries;
X    while (search_from(fi))
X	++count;
X    if (Entries != count) {
X	if (!lmessage_overide)
X	    printf ("%d Other Items loaded\n", count - Entries);
X	lmessage_overide = 0;
X	Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry) * (count + 1));
X	bzero (&Entry[Entries], sizeof(*Entry) * (count + 1 - Entries));
X    }
X    Entries = count;
X    for (i = at; i < Entries; ++i) {
X	Entry[i].no  = 0;
X	Entry[i].status = 0;
X    }
X    Entry[i].fpos = File_size = file_size = ftell (fi);
X    fclose (fi);
X    load_file ((from0) ? 0 : at);
X    if (file_size != File_size) {       /* Last entry incomplete?       */
X	free_table (Entries - 1, NOHOLD);
X    }
X    changed = 0;
X    if (SelAll)
X	m_select (Nulav, 0);
X    flock (fileno(m_fi), LOCK_UN);
X    pop_break();
X    return (1);
X}
X
Xvoid
Xdo_flock(fd, stat)
X{
X    if (flock(fd, stat | LOCK_NB) < 0) {
X	puts ("File in use, Waiting for lock");
X	flock (fd, stat);
X	puts ("Have lock");
X    }
X}
X
Xstatic
Xload_file(at)
Xint at;
X{
X    FILE *fi;
X    char *next, *ptr;
X    int i, bit, maxbit, len, count, havefrom;
X
X    maxbit = 0;
X    for (i = 0; Find[i].search != NULL; ++i)
X	maxbit = (maxbit << 1) | 1;
X    fi = fopen (mail_file, "r");
X    count = -1;
X    havefrom = 0;
X    while (havefrom  ||  search_from (fi)) {
X	havefrom = 0;
X	if (++count >= Entries)
X	    break;
X	len = strlen(Buf) - 1;
X	Buf[len] = '\0';
X	next = next_word(Buf);
X	len -= next - Buf;
X	Entry[count].fpos = ftell (fi);
X	Entry[count].from = malloc (len + 1);
X	bcopy (next, Entry[count].from, len + 1);
X
X	/* SEARCH FIELD LIST */
X
X	bit = 0;
X	if (XDebug)
X	    printf ("No %d  ---------------------\n", count + 1);
X	while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
X	    if (Buf[0] == '\n')
X		break;
X	    if (isfrom(Buf)) {
X		havefrom = 1;
X		break;
X	    }
X	    len = strlen(Buf) - 1;
X	    Buf[len] = '\0';
X	    if (XDebug)
X		printf ("CHECK: %s\n", Buf);
X	    next = next_word(Buf);
X	    len -= next - Buf;
X	    if (Hash[*Buf] == 0)
X		continue;
X	    if (Hash[*Buf] > 0) {
X		i = Hash[*Buf] & 0xff;
X		if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
X		    goto found;
X		continue;
X	    }
X	    for (i = -Hash[*Buf] & 0xff; Find[i].search; ++i) {
X		if (*Find[i].search != *Buf)
X		    break;
X		if (strncmp (Find[i].search, Buf, Find[i].len) == 0)
X		    goto found;
X	    }
X	    continue;
Xfound:
X	    if (XDebug)
X		printf ("Found: %d %s\n", i, Buf);
X	    if (Find[i].notnew == 0) {
X		Find[i].notnew = 1;
X		ptr = Buf;
X		while (*ptr  &&  *ptr != ':')
X		    ++ptr;
X		++ptr;
X		Find[i].search =
X			realloc (Find[i].search, ptr - Buf + 1);
X		strncpy (Find[i].search, Buf, ptr - Buf);
X		*(Find[i].search + (ptr - Buf)) = '\0';
X		Find[i].len = strlen(Find[i].search);
X	    }
X	    compile_field (Buf, fi);
X	    Entry[count].fields[i] =
X		    malloc (strlen(next) + 1);
X	    strcpy (Entry[count].fields[i], next);
X	    if ((bit |= (1 << i)) == maxbit)
X		break;
X	}
X	if (bit != maxbit) {
X	    for (i = 0; Find[i].search != NULL; ++i) {
X		if (((1 << i) & bit) == 0) {
X		    Entry[count].fields[i] = quo_quo;
X		}
X	    }
X	}
X    }
X    File_size = ftell (fi);
X    fclose (fi);
X    return (1);
X}
X
X
Xstatic void
Xload_hash()
X{
X    register int i, c;
X
X    bzero (Hash, sizeof(Hash));
X    for (i = 0; Find[i].search; ++i) {
X	c = *Find[i].search;
X	if (Hash[c] > 0)
X	    Hash[c] = -Hash[c];
X	if (Hash[c] == 0)
X	    Hash[c] = i | 0x100;
X    }
X}
X
X
Xvoid
Xfree_entry()
X{
X    free_table(0, NOHOLD);
X    Entry = (struct ENTRY *)realloc (Entry, sizeof(*Entry));
X    bzero (Entry[0].fields, sizeof(Entry[0].fields));
X    File_size = Entries = 0;
X    Entry->status = Entry->no = Entry->fpos = Current = 0;
X    Listsize = 3;
X    if (m_fi) {
X	fclose (m_fi);
X	m_fi = NULL;
X    }
X}
X
X
Xstatic void
Xfree_table(at, hold)
X{
X    int i, j;
X
X    for (i = at; i < Entries; ++i) {
X	xfree (Entry[i].from);
X	for (j = 0; Find[j].search != NULL; ++j) {
X	    if (Entry[i].fields[j] != quo_quo)
X		xfree (Entry[i].fields[j]);
X	}
X    }
X    Entries = (hold == HOLD) ? Entries : at;
X    File_size = (at) ? Entry[Entries].fpos : 0;
X}
X
Xstatic
Xsearch_from(fi)
XFILE *fi;
X{
X    while (fgets (Buf, MAXFIELDSIZE, fi) != NULL) {
X	if (isfrom (Buf))
X	    return (1);
X    }
X    return (0);
X}
X
X
Xsave_file(reload, mark, notmark)
X{
X    FILE *fiscr;
X    int fdscr;
X    int i, count;
X    char scratch[64];
X
X    for (i = 0; i < Entries; ++i) {
X	if ((Entry[i].status & mark) != mark  ||
X		(~Entry[i].status & notmark) != notmark)
X	    break;
X    }
X    if (i == Entries) {
X	m_select (Nulav, M_RESET);
X	puts ("No Changes Made");
X	return (Entries);
X    }
X    if (m_fi == NULL)
X	return (-1);
X    count = 0;
X    sprintf(scratch, "t:dmail%d", getpid());
X    do_flock (fileno(m_fi), LOCK_EX);
X    fdscr = open (scratch, O_RDWR | O_CREAT | O_TRUNC, MAILMODE);
X#ifdef AMIGA	    /*	fix bug in Lattice C fdopen */
X    fiscr = fopen("nil:", "w");
X    fclose(fiscr);
X#endif
X    fiscr = fdopen (fdscr, "a+");
X    for (i = 0; i < Entries; ++i) {
X	if ((Entry[i].status & mark) == mark  &&
X		(~Entry[i].status & notmark) == notmark) {
X	    ++count;
X	    fputs ("From ", fiscr);
X	    fputs (Entry[i].from, fiscr);
X	    putc ('\n', fiscr);
X	    fseek (m_fi, Entry[i].fpos, 0);
X	    while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
X		if (isfrom(Buf))
X		    break;
X		fputs (Buf, fiscr);
X	    }
X	}
X    }
X
X    /*
X     *	If new mail has come in, append to the scratch file as well.
X     *	NOTE: for some machines like the Amiga an already open descriptor
X     *	      does not know about any new data, thus we cannot simply
X     *	      use m_fi .
X     */
X
X    {
X	FILE *fi;
X
X	if (fi = fopen(mail_file, "r")) {
X	    fseek(fi, File_size, 0);
X	    while (fgets(Buf, MAXFIELDSIZE, fi))
X		fputs(Buf, fiscr);
X	    fclose(fi);
X	}
X    }
X
X    /* Write scratch file back to mail file, or try to */
X
X    fflush (fiscr);
X    fflush (m_fi);
X
X    lseek (fdscr, 0 ,0);
X#ifdef UNIX
X    lseek (fileno(m_fi), 0, 0);
X    while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
X	write (fileno(m_fi), Buf, i);
X    ftruncate (fileno(m_fi), lseek (fileno(m_fi), 0, 1));
X#else
X    fclose(m_fi);
X    if (m_fi = fopen (mail_file, "w")) {
X	while ((i = read (fdscr, Buf, MAXFIELDSIZE)) > 0)
X	    write (fileno(m_fi), Buf, i);
X	fclose(m_fi);
X	m_fi = fopen (mail_file, "r+");
X    }
X    if (m_fi == NULL) {
X	printf("Unable to re-open %s !\n", mail_file);
X	return(-1);
X    }
X#endif
X    if (lseek (fileno(m_fi), 0, 2) == 0  &&  !reload) {
X	if (Did_cd == 0) {
X	    fclose(m_fi);
X	    m_fi = NULL;
X	    if (unlink (mail_file) == 0)
X		printf ("%s  Removed\n", mail_file);
X	    else
X		printf ("0 messages left in %s\n", mail_file);
X	}
X    }
X    fclose (fiscr);
X    if (m_fi)
X	fclose (m_fi);          /* Effectively unlocks the descriptor */
X    m_fi = NULL;
X    unlink (scratch);
X    if (reload) {
X	free_entry();
X	load_mail(0, 0);
X    }
X    m_select (Nulav, M_RESET);
X    return (count);
X}
X
Xvoid
Xcheck_new_mail()
X{
X    FILE *fi;
X
X    push_break();
X    if (m_fi == NULL) {
X	m_fi = fopen (mail_file, "r+");
X	if (m_fi == NULL) {
X	    pop_break();
X	    return;
X	}
X    }
X    if (fi = fopen(mail_file, "r")) {
X	if (fseek(fi, 0, 2) < 0 || ftell(fi) != File_size)
X	    load_mail(Entries, 1);
X	fclose(fi);
X    }
X    pop_break();
X}
X
X
Xwrite_file(file, modes, mark, notmark)
Xchar *file;
X{
X    int i, fd = 1, notopen = 1;
X    FILE *fi = NULL;
X
X    for (i = 0; i < Entries; ++i) {
X	if ((Entry[i].status & mark) == mark  &&
X		(~Entry[i].status & notmark) == notmark) {
X	    if (notopen) {
X		notopen = 0;
X		fd = open (file, O_APPEND | O_WRONLY | modes, MAILMODE);
X		if (fd < 0)
X		    return (-1);
X		do_flock (fd, LOCK_EX);
X#ifdef AMIGA	    /*	fix bug in Lattice C fdopen */
X		fi = fopen("nil:", "w");
X		fclose(fi);
X#endif
X		fi = fdopen (fd, "a");
X
X#ifdef NOTDEF
X		if (fi) {
X		    printf("ptr     %08lx\n", fi->_ptr);
X		    printf("rcnt    %08lx\n", fi->_rcnt);
X		    printf("wcnt    %08lx\n", fi->_wcnt);
X		    printf("base    %08lx\n", fi->_base);
X		    printf("size    %08lx\n", fi->_size);
X		    printf("flag    %08lx\n", fi->_flag);
X		    printf("file    %08lx\n", fi->_file);
X		    return(-1);
X		}
X#endif
X	    }
X	    fputs ("From ", fi);
X	    fputs (Entry[i].from, fi);
X	    putc ('\n', fi);
X	    if (m_fi) {
X		fseek (m_fi, Entry[i].fpos, 0);
X		while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) {
X		    if (isfrom(Buf))
X			break;
X		    fputs (Buf, fi);
X		}
X	    }
X	}
X    }
X    if (!notopen)
X	fclose (fi);
X    return (1);
X}
X
X/*
X * Basic scheme: Each entry has a fields list.	Each entry in the fields list
X * is guarenteed to be a valid malloc'd pointer (except some may be set to
X * quo_quo).
X *
X * The find[] struct array holds the field name and length, the index
X * corresponding to the index into the field[] in an Entry.
X *
X * The header and width arrays hold the list format.
X */
X
Xget_extra_ovr(str)
Xchar *str;
X{
X    register int i;
X
X    i = get_extra (str);
X    if (i < 0) {
X	i = add_extra (str);
X	load_changes();
X    }
X    return (i);
X}
X
X
X/*
X * If there's room to add it, append to end.
X * Else Find oldest field which doesn't exist in the setlist and replace it
X *  with the new one.
X */
X
Xadd_extra(str)
Xchar *str;
X{
X    register int i, j, j_age, k;
X
X    for (i = EXSTART; i < MAXTYPE; ++i) {
X	if (Find[i].search == NULL)
X	    break;
X	++Find[i].age;
X    }
X    if (i == MAXTYPE) {                 /* No room to add onto end */
X	j = j_age = -1;
X	for (i = EXSTART; i < MAXTYPE; ++i) {
X	    for (k = 0; k < Listsize; ++k) {
X		if (i == header[k])
X		    break;
X	    }
X	    if (k == Listsize  &&  Find[i].age > j_age) {
X		j = i;
X		j_age = Find[i].age;
X	    }
X	}
X	i = j;
X    }
X    if (i < 0)
X	return (-1);
X    push_break();
X    if (Find[i].search != NULL)
X	xfree (Find[i].search);
X    Find[i].len = strlen(str);
X    Find[i].search = malloc (Find[i].len + 1);
X    Find[i].notnew = Find[i].age = 0;
X    strcpy (Find[i].search, str);
X    changed = 1;
X    for (j = 0; j < Entries; ++j) {
X	if (Entry[j].fields[i] && Entry[j].fields[i] != quo_quo)
X	    xfree (Entry[j].fields[i]);
X	Entry[j].fields[i] = quo_quo;
X    }
X    pop_break();
X    return (i);
X}
X
X
Xget_extra(str)
Xchar *str;
X{
X    int i;
X
X    for (i = 0; Find[i].search; ++i) {
X	if (strncmp (str, Find[i].search, strlen(str)) == 0) {
X	    Find[i].age = 0;
X	    return (i);
X	}
X    }
X    return (-1);
X}
X
X
Xm_select(sav, mode)
Xregister char *sav[];
X{
X    char *ptr, *dest;
X    char l_map[256];
X    int idx[MAXLIST], ix = 0;
X    int ok, not, len, scr;
X    register int i, j, avi;
X
X    for (i = 0;i < 256; ++i)
X	l_map[i] = i;
X    for (i = 'A'; i <= 'Z'; ++i)
X	l_map[i] += 'a' - 'A';
X    hold_load();
X    i = 0;
X    idx[ix++] = get_extra_ovr (sav[i++]);
X    for (; sav[i]; ++i) {
X	if (strcmp (sav[i], ",") == 0  &&  sav[i + 1])
X	    idx[ix++] = get_extra_ovr (sav[++i]);
X    }
X    idx[ix] = -1;
X    nohold_load();
X    j = 1;
X    push_break();
X    for (i = 0; i < Entries; ++i) {
X	if (mode == M_CONT  &&  Entry[i].no == 0)
X	    continue;
X	ix = ok = 0;
X	avi = 1;
X	while ((ptr = sav[avi]) != NULL) {
X	    if (ptr[0] == ','  &&  ptr[1] == '\0' && sav[avi+1]) {
X		++ix;
X		avi += 2;
X		continue;
X	    }
X	    if (not = (*ptr == '!'))
X		++ptr;
X	    len = strlen (ptr);
X	    dest = Entry[i].fields[idx[ix]];
X	    if (*ptr == '\0') {
X		ok = 1;
X		goto gotit;
X	    }
X	    while (*dest) {
X		scr = 0;
X		while (l_map[dest[scr]] == l_map[ptr[scr]] && ptr[scr])
X		    ++scr;
X		if (ptr[scr] == '\0') {
X		    ok = 1;
X		    goto gotit;
X		}
X		++dest;
X	    }
X	    ++avi;
X	}
Xgotit:
X	Entry[i].no = (ok ^ not) ? j++ : 0;
X    }
X    pop_break();
X    if (Current < 0)
X	Current = 0;
X    if (Entries) {
X	if (Entry[Current].no == 0) {
X	    Current = indexof (1);
X	    if (Current < 0) {
X		 Current = 0;
X		 return (-1);
X	    }
X	}
X    } else {
X	Current = -1;
X    }
X    return (1);
X}
X
X
END_OF_FILE
if test 13945 -ne `wc -c <'uucp2/src/dmail/load_mail.c'`; then
    echo shar: \"'uucp2/src/dmail/load_mail.c'\" unpacked with wrong size!
fi
# end of 'uucp2/src/dmail/load_mail.c'
fi
if test -f 'uucp2/src/uuser/uuser.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp2/src/uuser/uuser.c'\"
else
echo shar: Extracting \"'uucp2/src/uuser/uuser.c'\" \(13776 characters\)
sed "s/^X//" >'uucp2/src/uuser/uuser.c' <<'END_OF_FILE'
X
X/*
X *  UUSER.C UUSER:devicename/unitnumber/options
X *	    UUSER:serial.device/0/R1000
X *
X *  $Header: Beta:src/uucp/src/uuser/RCS/uuser.c,v 1.1 90/02/02 12:10:15 dillon Exp Locker: dillon $
X *
X *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
X *
X *  options:
X *	Rn	Set read timeout when no data available to n millisecs
X *	C0	Ignore carrier detect
X *
X *  features:
X *	1K asynchronous write capability (write 0 bytes to sync up)
X *	programmable read-timeout (Getty starts procs up w/ 1sec to)
X *
X *	combined together, you can easily implement 100% efficient
X *	protocols even with that 1 second read timeout!
X */
X
X#include <exec/types.h>
X#include <exec/memory.h>
X#include <devices/serial.h>
X#include <devices/timer.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <libraries/filehandler.h>
X#include <hardware/cia.h>
X#include <stdio.h>
X#include "protos.h"
X#include "version.h"
X
XIDENT(".02");
X
X#define WRITEBUFSIZE	1024
X#define MPC (MEMF_PUBLIC|MEMF_CLEAR)        /* options to AllocMem()    */
X
X#define BTOC(x, type)   ((type *)((long)x << 2))
X#define CTOB(x)         ((BPTR)((long)x >> 2))
X
X#define DOS_FALSE    0L
X#define DOS_TRUE     -1L
X
Xtypedef struct IOExtSer     IOS;
Xtypedef struct timerequest  IOT;
Xtypedef struct IORequest    IOR;
Xtypedef struct timeval	    TimeVal;
X
Xtypedef struct FileLock     LOCK;
Xtypedef struct DosPacket    Packet;
Xtypedef struct Process	    PROC;
Xtypedef struct DeviceNode   DEVNODE;
Xtypedef struct FileHandle   FH;
Xtypedef struct Message	    MSG;
Xtypedef struct Node	    NODE;
Xtypedef struct List	    LIST;
Xtypedef struct MsgPort	    PORT;
X
Xtypedef struct SHandle {
X    NODE    Node;
X    IOT     Iot;		/* wait-for-char and read req	*/
X    IOS     Ios;
X    IOS     Iosr;		/* 1005 			*/
X    IOS     Iosw;		/* 1005,1006			*/
X    char    IotIP;
X    char    IosrIP;
X    char    IoswIP;
X    char    RxIn[1];		/* one char buffer		*/
X    char    *TxOut;		/* asynch write buffer		*/
X    Packet  *RPacket;		/* current pending read packet	*/
X    Packet  *WPacket;		/* current pending write packet */
X    short   Flags;
X    LIST    RxWait;		/* requests waiting for data	*/
X    LIST    TxWait;		/* requests waiting to write	*/
X    LIST    CxWait;		/* wait for char		*/
X    TimeVal ReadTo;
X} SHandle;
X
X#define HF_IGNORECD	0x01
X#define HF_CDLOST	0x02
X#define HF_RTO		0x04
X#define HF_DONTLOCK	0x08	/* if G option for from-getty	*/
X
Xextern Packet *taskwait();      /* wait for a message           */
X
X/* long SysBase;	    /* required to make Exec calls  */
Xchar ScrBuf[256];		/* Scratch buffer		*/
XPORT *IoSink;
XLIST HanList;
XLIST NodList;
XIOT  Iot;			/* Iot master, also used for CD */
Xchar IotIP;
X
Xvoid	AttemptRead();
Xvoid	AttemptWrite();
Xvoid	AbortPackets();
Xvoid	StartTimer();
X
Xvoid
X_main()
X{
X    PROC	*myproc;
X    DEVNODE	*mynode;
X    UBYTE	notdone;
X    long	mask;
X
X/*    SysBase = *(long *)4;  */
X    IoSink = CreatePort(NULL, 0L);
X    NewList(&HanList);
X    NewList(&NodList);
X
X    Iot.tr_node.io_Message.mn_ReplyPort = IoSink;
X    OpenDevice("timer.device", UNIT_VBLANK, &Iot.tr_node, 0L);
X    Iot.tr_node.io_Command = TR_ADDREQUEST;
X    Iot.tr_time.tv_secs = 4;
X    Iot.tr_time.tv_micro= 0;
X    SendIO(&Iot);
X    IotIP = 1;
X
X    myproc  = (PROC *)FindTask(0L);
X
X    /*
X     * INITIAL STARTUP MESSAGE
X     */
X
X    {
X	Packet *mypkt;
X
X	mypkt	= taskwait(myproc);
X	mynode	= BTOC(mypkt->dp_Arg3, DEVNODE);
X	mynode->dn_Task = &myproc->pr_MsgPort;
X	returnpkt(mypkt, myproc, DOS_TRUE, 0L);
X    }
X
Xloop:
X    notdone = 1;
X    mask = (1 << IoSink->mp_SigBit) | (1 << myproc->pr_MsgPort.mp_SigBit);
X    while (notdone) {
X	Packet *mypkt;		 /* dos packet received      */
X	IOR *ior;
X	SHandle *handle;
X	long type;		    /* type of packet		*/
X
X	ior = (IOR *)GetMsg(IoSink);
X	mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
X	if (mypkt)
X	    mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
X	while (mypkt == NULL && ior == NULL) {
X	    Wait(mask);
X	    ior = (IOR *)GetMsg(IoSink);
X	    mypkt = (Packet *)GetMsg(&myproc->pr_MsgPort);
X	    if (mypkt)
X		mypkt = (Packet *)(((MSG *)mypkt)->mn_Node.ln_Name);
X	}
X
X	/*
X	 *  Make sure there is at least one free node in node list
X	 */
X
X	if (NodList.lh_Head == (NODE *)&NodList.lh_Tail) {
X	    NODE *pknode = AllocMem(sizeof(NODE), MPC);
X	    AddTail(&NodList, pknode);
X	}
X
X	/*
X	 *  Returned IO request, sift through lists to find it.
X	 */
X
X	if (ior) {
X	    if (ior == &Iot.tr_node) {      /*  Check for carrier lost */
X		for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
X		    if (!(handle->Flags & HF_IGNORECD) && !(handle->Flags & HF_CDLOST)) {
X			handle->Ios.IOSer.io_Command = SDCMD_QUERY;
X			DoIO((IOR *)&handle->Ios);
X			if (handle->Ios.io_Status & CIAF_COMCD) {
X			    handle->Flags |= HF_CDLOST;
X			    AbortPackets(handle, myproc);
X			}
X		    }
X		}
X		if (HanList.lh_Head == (NODE *)&HanList.lh_Tail) {
X		    IotIP = 0;
X		} else {
X		    Iot.tr_time.tv_secs = 4;
X		    Iot.tr_time.tv_micro= 0;
X		    SendIO(&Iot.tr_node);
X		    IotIP = 1;
X		}
X	    } else
X	    for (handle = (SHandle *)HanList.lh_Head; handle != (SHandle *)&HanList.lh_Tail; handle = (SHandle *)handle->Node.ln_Succ) {
X		if (ior == (IOR *)&handle->Iosr) {
X		    handle->IosrIP = 0;
X		    if (handle->RPacket) {
X			returnpkt(handle->RPacket, myproc, handle->Iosr.IOSer.io_Actual, 0L);
X			handle->RPacket = NULL;
X		    }
X		    if (handle->IotIP) {
X			AbortIO(&handle->Iot.tr_node);
X			WaitIO(&handle->Iot.tr_node);
X			handle->IotIP = 0;
X		    }
X		    AttemptRead(handle, myproc);
X		}
X		if (ior == (IOR *)&handle->Iosw) {
X		    handle->IoswIP = 0;
X		    if (handle->WPacket) {
X			handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
X			handle->Iosw.IOSer.io_Length= handle->WPacket->dp_Arg3 - handle->WPacket->dp_Res1;
X			SendIO((IOR *)&handle->Iosw);
X			handle->IoswIP = 1;
X			handle->WPacket->dp_Res1 = handle->WPacket->dp_Arg3;
X			returnpktplain(handle->WPacket, myproc);
X			handle->WPacket = NULL;
X		    } else {
X			AttemptWrite(handle, myproc);
X		    }
X		}
X		if (ior == (IOR *)&handle->Iot.tr_node) {
X		    handle->IotIP = 0;
X		    if ((handle->Flags & HF_RTO) && handle->IosrIP) {
X			AbortIO((IOR *)&handle->Iosr);
X		    }
X		}
X	    }
X	}
X
X	if (mypkt) {
X	    mypkt->dp_Res1 = DOS_TRUE;	/* default return value     */
X	    mypkt->dp_Res2 = 0; 	/* default no error	    */
X	    type = mypkt->dp_Type;	/* packet type		    */
X
X	    /*
X	     *	Extract pipe pointer (only applies to read/write)
X	     */
X
X	    handle = (SHandle *)mypkt->dp_Arg1;     /*  READ/WRITE only */
X
X	    switch(type) {
X	    case ACTION_FINDINPUT:
X	    case ACTION_FINDOUTPUT:
X	    case ACTION_FINDUPDATE:
X		if (IotIP == 0)
X		    StartTimer(4);
X		{
X		    FH	 *fh = BTOC(mypkt->dp_Arg1, FH);
X		    char *path = BTOC(mypkt->dp_Arg3, char);
X		    char *unit;
X		    long n;
X
X		    movmem(path + 1, ScrBuf, *path);
X		    ScrBuf[*path] = 0;
X		    path = ScrBuf;
X
X		    handle = AllocMem(sizeof(SHandle), MPC);
X
X		    if (strcmp(ScrBuf, "*") == 0)
X			strcpy(ScrBuf, "serial.device/0");
X		    for (unit = path; *unit && *unit != '/'; ++unit) {
X			if (*unit == ':')
X			    path = unit + 1;
X		    }
X		    if (*unit == '/') {
X			char *opts;
X
X			*unit = 0;
X			++unit;
X			for (opts = unit; *opts && *opts != '/'; ++opts);
X			while (*opts) {
X			    n = atoi(opts + 1);
X			    switch(*opts) {
X			    case '/':
X				break;
X			    case 'R':
X				handle->ReadTo.tv_secs = n / 1000;
X				handle->ReadTo.tv_micro= (n % 1000) * 1000;
X				handle->Flags |= HF_RTO;
X				break;
X			    case 'C':
X				handle->Flags |= HF_IGNORECD;
X				break;
X			    case 'G':
X				if (n)
X				    handle->Flags |= HF_DONTLOCK;
X				break;
X			    }
X			    ++opts;
X			}
X		    }
X
X		    /* proc = (PROC *)mypkt->dp_Port->mp_SigTask; */
X
X		    /*
X		     * Open the device
X		     */
X
X		    handle->Ios.IOSer.io_Message.mn_ReplyPort = IoSink;
X		    handle->Ios.io_SerFlags = SERF_XDISABLED | SERF_RAD_BOOGIE | SERF_SHARED;
X		    if (OpenDevice(path, atoi(unit), (IOR *)&handle->Ios, 0L)) {
X			FreeMem(handle, sizeof(SHandle));
X			mypkt->dp_Res1 = DOS_FALSE;
X			mypkt->dp_Res2 = ERROR_OBJECT_NOT_FOUND;
X			returnpktplain(mypkt, myproc);
X			break;
X		    }
X		    fh->fh_Arg1 = (long)handle;
X		    fh->fh_Port = (struct MsgPort *)DOS_TRUE;
X
X		    handle->Iosr = handle->Ios;
X		    handle->Iosw = handle->Ios;
X		    handle->Iosr.IOSer.io_Command = CMD_READ;
X		    handle->Iosw.IOSer.io_Command = CMD_WRITE;
X		    handle->Iot = Iot;
X		    NewList(&handle->RxWait);
X		    NewList(&handle->TxWait);
X		    NewList(&handle->CxWait);
X		    AddTail(&HanList, &handle->Node);
X		    returnpktplain(mypkt, myproc);
X		}
X		break;
X	    case ACTION_END:
X		Remove(&handle->Node);
X		AbortPackets(handle, myproc);
X		if (handle->IotIP) {
X		    AbortIO((IOR *)&handle->Iot);
X		    WaitIO((IOR *)&handle->Iot);
X		    handle->IotIP = 0;
X		}
X		CloseDevice((IOR *)&handle->Ios);
X		returnpktplain(mypkt, myproc);
X		if (handle->TxOut)
X		    FreeMem(handle->TxOut, WRITEBUFSIZE);
X		FreeMem(handle, sizeof(SHandle));
X		break;
X	    case ACTION_READ:
X		{
X		    NODE *pknode = RemHead(&NodList);
X		    mypkt->dp_Res1 = 0;
X		    pknode->ln_Name = (char *)mypkt;
X		    AddTail(&handle->RxWait, pknode);
X		    AttemptRead(handle, myproc);
X		}
X		break;
X	    case ACTION_WRITE:
X		{
X		    NODE *pknode = RemHead(&NodList);
X		    mypkt->dp_Res1 = 0;
X		    pknode->ln_Name = (char *)mypkt;
X		    AddTail(&handle->TxWait, pknode);
X		    AttemptWrite(handle, myproc);
X		}
X		break;
X	    case ACTION_WAIT_CHAR:
X	    default:
X		returnpkt(mypkt, myproc, DOS_FALSE, ERROR_ACTION_NOT_KNOWN);
X		break;
X	    }
X	}
X    }
X
X    /*
X     *	Can only exit if no messages pending.  There might be a window
X     *	here, but there is nothing that can be done about it.
X     */
X
X    Forbid();
X    if (taskpktrdy(myproc)) {
X	Permit();
X	goto loop;
X    }
X    mynode->dn_Task = FALSE;
X    Permit();
X
X    if (IotIP) {
X	AbortIO(&Iot.tr_node);
X	WaitIO(&Iot.tr_node);
X    }
X    CloseDevice(&Iot.tr_node);
X
X    /* we are a process "so we fall off the end of the world" */
X    /* MUST fall through */
X}
X
Xvoid
XAttemptRead(handle, myproc)
XSHandle *handle;
XPROC *myproc;
X{
X    Packet *mypkt;
X    NODE *pknode;
X
X    if (handle->Flags & HF_CDLOST) {
X	AbortPackets(handle, myproc);
X	return;
X    }
Xloop:
X    if (handle->IosrIP == 0 && (pknode = RemHead(&handle->RxWait))) {
X	long n;
X
X	AddTail(&NodList, pknode);
X
X	mypkt = (Packet *)pknode->ln_Name;
X
X	/*
X	 *  special case.  If you read 0 bytes, 0 is returned if data
X	 *  is pending, else -1, and NO timeout occurs.
X	 */
X
X	handle->Ios.IOSer.io_Command = SDCMD_QUERY;
X	DoIO((IOR *)&handle->Ios);
X
X	if (mypkt->dp_Arg3 == 0) {
X	    if (handle->Ios.IOSer.io_Actual > 0)
X		returnpkt(mypkt, myproc, DOS_FALSE, 0L);     /* 0=data rdy */
X	    else
X		returnpkt(mypkt, myproc, DOS_TRUE, 0L);    /* -1=data not rdy */
X	    goto loop;
X	}
X
X	if ((n = handle->Ios.IOSer.io_Actual) > 0) {
X	    if (n > mypkt->dp_Arg3)
X		n = mypkt->dp_Arg3;
X	    handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
X	    handle->Iosr.IOSer.io_Length = n;
X	    DoIO((IOR *)&handle->Iosr);
X	    mypkt->dp_Res1 = handle->Iosr.IOSer.io_Actual;
X	    returnpktplain(mypkt, myproc);
X	    goto loop;
X	}
X	handle->Iosr.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
X	handle->Iosr.IOSer.io_Length = 1;
X	SendIO((IOR *)&handle->Iosr);
X	handle->IosrIP = 1;
X	handle->RPacket = mypkt;
X
X	if (handle->Flags & HF_RTO) {
X	    if (handle->IotIP) {
X		AbortIO(&handle->Iot.tr_node);
X		WaitIO(&handle->Iot.tr_node);
X	    }
X	    handle->Iot.tr_time = handle->ReadTo;
X	    SendIO(&handle->Iot.tr_node);
X	    handle->IotIP = 1;
X	}
X    }
X}
X
Xvoid
XAttemptWrite(handle, myproc)
XSHandle *handle;
XPROC *myproc;
X{
X    Packet *mypkt;
X    NODE *pknode;
X
X    if (handle->Flags & HF_CDLOST) {
X	AbortPackets(handle, myproc);
X	return;
X    }
X    if (handle->IoswIP == 0 && (pknode = RemHead(&handle->TxWait))) {
X	AddTail(&NodList, pknode);
X
X	mypkt = (Packet *)pknode->ln_Name;
X
X	if (handle->TxOut == NULL)
X	    handle->TxOut = AllocMem(WRITEBUFSIZE, MPC);
X
X	if (mypkt->dp_Arg3 <= WRITEBUFSIZE) {   /* fully asynch */
X	    movmem((char *)mypkt->dp_Arg2, handle->TxOut, mypkt->dp_Arg3);
X	    handle->Iosw.IOSer.io_Data = (APTR)handle->TxOut;
X	    handle->Iosw.IOSer.io_Length = mypkt->dp_Arg3;
X	    SendIO(&handle->Iosw);
X	    mypkt->dp_Res1 = mypkt->dp_Arg3;
X	    returnpktplain(mypkt, myproc);
X	    handle->WPacket = NULL;
X	} else {				/*  semi-asynch */
X	    long n = mypkt->dp_Arg3 - WRITEBUFSIZE;
X	    handle->Iosw.IOSer.io_Data = (APTR)mypkt->dp_Arg2;
X	    handle->Iosw.IOSer.io_Length = n;
X	    SendIO(&handle->Iosw);
X	    movmem((char *)mypkt->dp_Arg2 + n, handle->TxOut, WRITEBUFSIZE);
X	    mypkt->dp_Res1 += n;
X	    handle->WPacket = mypkt;
X	}
X	handle->IoswIP = 1;
X    }
X}
X
Xvoid
XAbortPackets(handle, myproc)
XSHandle *handle;
X{
X    NODE *pknode;
X    Packet *mypkt;
X
X    if (handle->RPacket)
X	returnpktplain(handle->RPacket, myproc);
X
X    if (handle->WPacket)
X	returnpktplain(handle->WPacket, myproc);
X
X    if (handle->IosrIP) {
X	AbortIO((IOR *)&handle->Iosr);
X	WaitIO((IOR *)&handle->Iosr);
X	handle->IosrIP = 0;
X    }
X    if (handle->IoswIP) {
X	AbortIO((IOR *)&handle->Iosw);
X	WaitIO((IOR *)&handle->Iosw);
X	handle->IoswIP = 0;
X    }
X
X    handle->RPacket = NULL;
X    handle->WPacket = NULL;
X
X    while (pknode = RemHead(&handle->RxWait)) {
X	mypkt = (Packet *)pknode->ln_Name;
X	if (mypkt->dp_Arg3 == 0)
X	    mypkt->dp_Res1 = 0;     /* for poll, return data rdy */
X	else
X	    mypkt->dp_Res1 = -1;
X	returnpktplain(mypkt, myproc);
X	AddTail(&NodList, pknode);
X    }
X
X    while (pknode = RemHead(&handle->TxWait)) {
X	mypkt = (Packet *)pknode->ln_Name;
X	mypkt->dp_Res1 = -1;
X	returnpktplain(mypkt, myproc);
X	AddTail(&NodList, pknode);
X    }
X}
X
Xvoid
XStartTimer(secs)
X{
X    if (IotIP) {
X	AbortIO(&Iot.tr_node);
X	WaitIO(&Iot.tr_node);
X    }
X    Iot.tr_time.tv_secs = secs;
X    Iot.tr_time.tv_micro= 0;
X    SendIO(&Iot.tr_node);
X    IotIP = 1;
X}
X
X
END_OF_FILE
if test 13776 -ne `wc -c <'uucp2/src/uuser/uuser.c'`; then
    echo shar: \"'uucp2/src/uuser/uuser.c'\" unpacked with wrong size!
fi
# end of 'uucp2/src/uuser/uuser.c'
fi
echo shar: End of archive 7 \(of 12\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.