Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (02/04/90)
Submitted-by: overload!dillon (Matt Dillon) Posting-number: Volume 90, Issue 052 Archive-name: unix/uucp-1.03d/part08 #!/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 8 (of 16)." # Contents: SlowSetup.DOC src/dmail/load_mail.c src/uucico/gio.c # Wrapped by tadguy@xanth on Sat Feb 3 20:51:14 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'SlowSetup.DOC' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'SlowSetup.DOC'\" else echo shar: Extracting \"'SlowSetup.DOC'\" \(14853 characters\) sed "s/^X//" >'SlowSetup.DOC' <<'END_OF_FILE' X X SLOWSETUP.DOC X X Matthew Dillon X 891 Regal Rd. X Berkeley, Ca. 94708 X X pacbell.PacBell.COM!sorinc!overload!dillon X X X GETTING UUCP UP AND RUNNING FOR REAL X X X This UUCP distribution in general is not for the uninitiated. That is, X it is not user friendly. This particular document outlines a general X installation procedure. Be warned that there are a LOT of things you X will have to do to bring up UUCP on your machine. X X This document shows a TYPICAL setup. You will most likely want to X modify the example to fit your own needs. I cover all the points X though. X X (1) You made backups of the distribution floppies, right? DO NOT X MODIFY THE DISTRIBUTION FLOPPIES. The instructions below are X long and some are complex and you may wish to refer to the X original distribution diskettes if you accidently mess something X up. X X X (2A) Installing UUCP on a single floppy system. X X Well, it *is* possible, but difficult. you need to make as much X space as possible available on the main floppy. X X The second distribution disk contains only the source and manual X pages. I suggest you shuffle things around a bit. You already X have a copy of the first distribution diskette. I suggest you X format a new disk and put the MAN directory of the second X distribution disk on it. Note that there is a MAN directory X on the boot disk as well but this one contains only dmail.help X which you need to gain online help from dmail. X X The following executables are required on the boot floppy and X should not be moved off. You should move as many of the remaining X executables somewhere else as you can. X X Required Executables in C X X c/dmail X c/getty X c/rmail X c/uucico X c/rnews X c/uucp X c/unbatcher X c/dme (unless you configure your own editor) X c/sendmail X c/uux X c/uuxqt X X You will want to change the ASSIGNments in s/startup-sequence X as follows: X X Assign UUSPOOL: UUCP:SPOOL X Assign UUMAIL: UUCP:MAIL X Assign UUNEWS: UUCP:MAIL/NEWS X X These directories MUST be in nonvoltile storage or your USENET X node will be unreliable. X X (2B) Installing UUCP on a duel floppy system. X X In this case very little shuffling is required. I suggest X the second floppy be used for UUSPOOL:, UULIB:, UUMAIL:, UUNEWS:, X GETTY:, and UUPUB:. X X Format a new floppy (this will be your second floppy) and create X directories as follows: X X MakeDir df1:spool X MakeDir df1:mail X MakeDir df1:mail/news X MakeDir df1:pub X MakeDir df1:lib X X Modify the Assignments in s/startup-sequence of the boot floppy X as follows: X X Assign UUSPOOL: df1:spool X Assign UULIB: df1:lib X Assign UUMAIL: df1:mail X Assign UUNEWS: df1:mail/news X Assign GETTY: UULIB: X Assign UUPUB: df1:pub X X Copy df0:lib to df1:lib and either delete or rename df0:lib to X prevent confusion. What we have done is move all dynamic storage X to df1: .. files that will change a lot or require a lot of disk X space. Specifically, UULIB: was moved to DF1: because the X sequence number file is kept in UULIB: and this is updated for X each mail message sent. X X (2B) Installing UUCP on a Hard Drive X X Make a directory called UUCP on your hard drive somewhere. And X Assign UUCP: to it. Copy the contents of both distribution X floppies to your harddrive: X X (put first disk in DF0:) X 1> Copy df0: UUCP: ALL CLONE X (put second disk in DF0:) X 1> Copy df0: UUCP: ALL CLONE X X It is easiest to keep all the directories in one place. Note X that a MAN directory exists on both distribution floppies, simply X merge them together. X X Merge the startup-sequence on the boot floppy into your master X startup-sequence. Make sure you get all the Assigns and that X they are properly reassigned to the appropriate directory on X the harddisk. Most people normally make a master UUCP: assign X as a reference point to other assigns. X X X Be sure that UUSPOOL:, UUMAIL:, UUNEWS: and UUPUB: are assigned X to your hard disk instead of ram. X X You will most likely want to run DCron and Getty from your X startup-sequence. Be sure that UUCP:C is assigned *before* X these programs are run so they pick up the appropriate path. X X If Getty interferes with any terminal program you might use X you may be forced to BREAK it. Remember to restart it to X enable incomming UUCP calls again. X X DCron is an extremely useful utility to run, especially in X systems with hard disks. The only thing you have to watch out X for is to be sure to BREAK it (kill it) before shutting off your X machine. DCron writes to its log file and runs other programs X based on the date and you don't want to accidently turn off your X machine when DCron has just started up some other program that X may write to your hard disk. X X In the context of UUCP, DCron is normally used to automatically X poll systems in the wee hours while you are asleep, to trim X log files automagically, and maybe disable the modem's speaker X while you are asleep (at least, that is what I use it for). X X Most people with HDs running UUCP leave their Amiga's on 24 hours X a day. X X Other System Directories X X Merge the mountlist into your master mountlist and copy any X devices from l that you do not already have into your X master l directory. X X merge or copy uucp:s/crontab to s:crontab and uucp:s/.edrc to X s:.edrc . X X You can ignore files in uucp:system, they are standard system X files. X X ---- -- - - - - - - -- ---- X X (3) Other startup-sequence efficiency considerations X X UUCP relies heavily on the Amiga's multitasking capabilities. X Most programs execute other programs. Many programs in UUCP:C X may be made resident as shown by the pure bit being set. You X will probably at least want to make C:RUN resident if you haven't X already. X X Depending on available RAM you may want to make certain other X progams resident. Here are some suggestions: X X uucp:c/dme ; run by dmail to edit mail X uucp:c/uuxqt ; run by uucico to handle received files X uucp:c/rmail ; run by uuxqt to handle received mail X uucp:c/sendmail ; run by dmail to handle outgoing mail X X (note that uucp:c/sendmail and uucp:c/rmail are the same X executable just renamed) X X STACK: All programs should run with a stack of 8192. This X has been tested for all programs except RNews and ANews which X may require more. X X RNEWS: RNews currently takes a huge amount of memory and X will run only on machines with at least 1.5MB of ram. Even X with 1.5MB you may need to run rnews manually instead of having X it automatically run by uuxqt. In this case rename the rnews X executable to something else and create a dummy script file X in its place (named as 'rnews') with the script bit set. X X (4) System requirements X X Be sure you are running at least version 1.3 of the operating X system. The main consideration is that you are using at least X the 1.3 serial device. X X The NULL: device is required, this is in the l directory of X the boot floppy as already discussed. X X The UUSER: device is not required unless you want to start X getting fancy with the Getty. This is mainly a programmer's X tool. X X (5) Getty X X Normally one runs a Getty in his startup-sequence on the internal X serial port (from which you wish to receive calls). Currently X only one Getty may be run PER SERIAL DEVICE NAME, and using other X units of a given serial device will interfere with Getty's operation. X This is due to the difficulty of implementation in Getty and will X eventually be fixed (to fix the problem I have to patch into X the OpenDevice and CloseDevice vectors). X X So for now you can really only run Getty on the internal serial X device. X X Getty does its best to not interfere with comm programs and X the like, but if a comm program refuses to run because it X can't get exclusive access to the serial port you may have X to kill the Getty by BREAKing it from a CLI. X X Refer to the manual page MAN:Getty for more information (for X floppy based systems all manual pages are on the second X distribution diskette). X X (6) SHELL-STARTUP X X Assuming you are using the 1.3 Shell, the S:Shell-Startup file X normally contains at least a Path command and Stack command to X properly setup a newshell's path and stack. Be sure the stack is X at least 8192 for this distribution of UUCP and add the UUCP:C (or X wherever you have placed the distribution executables) to your path X list. Older UUCP distributions required a huge stack, this has X been fixed. X X (7) SITE-SETUP CONTROL FILES X X The following is a description of control and log files required X for UUCP and how you must modify them to install your system. X X (GETTY: is normally Assign'd to UULIB:) X X GETTY:Getty-Header X X This file contains the header line that is printed before a X login: prompt and is typically only two or three lines long. X The header usually contains your node name and the version of X the OS you are running under so people calling from term X programs know who you are. X X (Getty can be used to run things other than uucico) X X Modify accordingly. X X GETTY:Passwd X X The password file is used by Getty to authenticate login X requests. In the context of UUCP, remote UUCICOs that call X your machine up will provide a login and password. Getty X handles this and if the login is valid and the password matches X will run the appropriate program found in the password file. X X Getty also deals with such features as automatic disconnect on X timeout and logs times for all incomming and outgoing calls. X X In a serious system you should first remove all the junk X entries that come with the distribution. You need an entry X for each remote machine you want to be able to call you. You X do not necessarily need to give them logins that corrospond to X their machine names though this is how it is usually done. X X Other programs in the future will be able to be run from X a Getty. X X Later versions of UUCP will implement MAILER-DAEMON type X stuff like 'unknown user', in which case the password file X will be used to define which user names are valid on the X system. X X GETTY:LOGFILE X X The logfile is appended to by Getty whenever an incomming X call occurs or somebody takes over the serial port. It X logs connect and disconnect times for incomming calls and X usage for external programs. X X UULIB:Domain X X In nearly every case you will not need this file. X X Those of you who wish to do domain routing through X their machine or have more than one default for X unknown destinations should refer to the manual X page MAN:Domains. X X UULIB:.Signature X X .Signature is used by the Mail program and normally appended X to outgoing mail. X X Modify accordingly. X X UULIB:Seq X X The Seq file should exist but otherwise not be modified by X the user (except for setting it to a "1" once a year). This X file is atomically updated and used to provide unique filenames X and mail IDs for outgoing mail. X X UULIB:Security X X This file contains a list of allowed directories remote UUCP X transfers may read and write to. Refer to the Security manual X page. This file never contains the UUSPOOL: directory which X is implicitly read-write. X X You need not modify this file now but should keep it in mind. X It protects your system in as much as I have been able to X close the loopholes. Loopholes might still exist. X X UULIB:news.distribution X X This file contains a list of news distribution idents for X various areas and must normally be modified according to X where you are.. you need to be a UUCP guru to do this. Most X people can just leave it alone. X X UULIB:Config X X This file contains configuration information for many X executables in UUCP:C and should be modified accordingly. X X Be sure you modify at least the following entries. REFER TO X THE 'Assigns' MANUAL PAGE. X X NodeName X UserName X RealName X NewsFeed (not required if you don't care about news) X Organization X TimeZone X DefaultNode X X **** Take some time to pick a node name for yourself. It X should be no more than 8 characters long. Some UUCP sites X barf at node names longer than 6 chars so if you are not X sure of your neighbors pick one no more than 6 characters X long. Your site name should be in lower case. X X UULIB:L.Sys X X This file contains site information for sites that may call X you up or you may call up. X X You must modify this file appropriately before you can run UUCP, X refer to the 'L.Sys' manual page. X X UULIB:Aliases X X This is a mail aliases file with aproximately the same X power as /usr/lib/aliases on UNIX systems. You should X refer to the 'Aliases' manual page and modify this file as X appropriate for various defaults like 'postmaster'... to X whatever user name you pick for yourself. X X UUCP:S/Crontab X X This is a functional Crontab file for use with the DCron program. X This file is normally moved to S: (it is useless in UUCP:S). X X UUSPOOL:LOGFILE X X UUCICO and other programs log errors and other things to X this file. Normally you use DCron to clean up this and X other log files once daily to keep them from getting to large. X X X (8) TESTING / DMAIL X X You will next want to test your UUCP configuration. If testing X with a friend's Amiga running the same distribution simply X email to him, then one of you run uucico -s<remotesystem> X just like in QuickSetup.DOC, except this time you are using X the system name he picked instead of 'test1' or 'test2'. X X If the initial tests in QuickSetup.DOC worked and the system X is not working now check the following (common problems): X X (a) the login and password in your L.Sys file (that uucico uses X to login to the remote machine) matches the login and X password in the remote machine's Getty:Passwd file. X X (b) There is an entry for your node in the remote machine's X L.Sys file and vise versa X X (c) The telephone number is correct X X (d) the node names are all in lower case X X (e) you constructed the email address correctly (nodename!user) X X I suggest you get UUCP running with a friend before getting it X running with a UNIX system as it is easier to test it with a X friend. X X Assuming you email to the user name he picked for his UULIB:Config X 'UserName' entry and he did the same thing to you, entering X 'dmail' without any arguments will bring up the mail shell X and allow you to read the message after transfer via UUCico X is complete. You can check that the email actually arrived X into the right mail box in UUMAIL: by simply getting a directory X of UUMAIL: X X READ the manual page for DMail for information on the X construction of mail paths to other systems and users. X X END_OF_FILE if test 14853 -ne `wc -c <'SlowSetup.DOC'`; then echo shar: \"'SlowSetup.DOC'\" unpacked with wrong size! fi # end of 'SlowSetup.DOC' fi if test -f 'src/dmail/load_mail.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/dmail/load_mail.c'\" else echo shar: Extracting \"'src/dmail/load_mail.c'\" \(13593 characters\) sed "s/^X//" >'src/dmail/load_mail.c' <<'END_OF_FILE' X X/* X * LOAD_MAIL.C 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 = Entry[i].status = 0; 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 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 new_size, 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, "tmp: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 /* If NEW MAIL has come in, append that to the scratch file also */ X X new_size = (fseek (m_fi, 0, 2) >= 0) ? ftell(m_fi) : File_size; X if (File_size != new_size) { X fseek (m_fi, File_size, 0); X while (fgets (Buf, MAXFIELDSIZE, m_fi) != NULL) X fputs (Buf, fiscr); 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 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 (fseek (m_fi, 0, 2) < 0 || ftell(m_fi) != File_size) X load_mail(Entries, 1); 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 13593 -ne `wc -c <'src/dmail/load_mail.c'`; then echo shar: \"'src/dmail/load_mail.c'\" unpacked with wrong size! fi # end of 'src/dmail/load_mail.c' fi if test -f 'src/uucico/gio.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'src/uucico/gio.c'\" else echo shar: Extracting \"'src/uucico/gio.c'\" \(16481 characters\) sed "s/^X//" >'src/uucico/gio.c' <<'END_OF_FILE' X X/* X * GIO.C WINDOWED G PROTOCOL X * X * Rewritten from scratch, except the checksum routine which was X * rewritten but based on the old one. X * X * WINDOW SIZE: When changing the window size be sure there X * are enough buffers available for pending txs. X * X * GIO.C (c)Copyright 1989, Matthew Dillon, All Rights Reserved X */ X X#include <stdio.h> X#include <stdlib.h> X#include <exec/types.h> X#include <proto/all.h> X Xvoid FrameToPacket(); X Xextern int debug; Xextern int WindowOne; X X#define SUCCESS 0 X#define FAIL 1 X X#define MAGIC 0125252 X#define DLE 0x10 X#define WINDOWSIZE 2 /* WindowSize = 1 or 2 */ X#define SEGSIZEK 2 /* 64 bytes ?? */ X X#define SUB1(var) (((var)-1)&7) X Xtypedef unsigned char ubyte; Xtypedef unsigned short uword; X Xtypedef struct { X ubyte Dle; /* Literal ASCII DLE */ X ubyte K; /* data size 2^(K+4) except K=0 means no data */ X ubyte CL,CH; /* MAGIC - chksum(data) ^ C */ X ubyte C; X ubyte X; /* K ^ C0 ^ C1 ^ C */ X} Frame; X Xtypedef struct { X ubyte CType; /* bits 7-6 of C */ X ubyte CCmd; /* bits 5-3 of C */ X ubyte CSeq; /* bits 2-0 of C */ X ubyte PLen; /* pre-data (2 bytes) for SHORTDATA type */ X ubyte *Data; /* implies CType=LONGDATA or SHORTDATA */ X uword DLen; /* length of data */ X} Packet; X X#define CT_CONTROL (0 << 6) X#define CT_ALTCHN (1 << 6) X#define CT_LONGDATA (2 << 6) X#define CT_SHORTDATA (3 << 6) X#define CT_MASK (3 << 6) X X#define CC_CLOSE (1 << 3) X#define CC_RJ (2 << 3) X#define CC_SRJ (3 << 3) X#define CC_RR (4 << 3) X#define CC_INITC (5 << 3) X#define CC_INITB (6 << 3) X#define CC_INITA (7 << 3) X#define CC_MASK (7 << 3) X X#define SEQ_MASK 7 X X#define WAIT_ACK 1 X#define WAIT_DATA 2 X#define WAIT_CONTROL 3 X X#define MaxPktSize 4096 X Xchar RxBuf[MaxPktSize+4]; Xchar TxBuf[4][MaxPktSize+4]; X X /* TRANSMIT STAGE */ Xchar TxSeq = 0; /* Last send packet */ Xchar TxPend= 0; /* hasn't been acked yet */ Xuword TxWinSize; /* 1 or 2 */ Xuword TxSegSize; /* maximum segment size */ Xchar TxSegK; /* K for TxSegSize */ XPacket TxPacket[8]; /* contents of last packet */ X X /* RECEIVE STAGE */ Xchar RxSeq = 1; /* Next expected recv pkt */ Xchar RxRdy = 0; /* Has come in.. */ Xchar RxRetry = 4; Xchar RxNotAcked = 0; /* We have yet to ack it */ XPacket RxPacket; /* The packet that has come in */ X X/* X * Get Transmit Buffer. Note that some space to the left is available X */ X Xchar * XGetTxBuf() X{ X static int index = 0; X X index = (index + 1) & 3; X return(TxBuf[index] + 2); X} X Xint Xgwrdata(fi) XFILE *fi; X{ X int bytes; X char *buf = GetTxBuf(); X X if (debug > 7) X printf("GWRDATA: "); X X while ((bytes = fread(buf, 1, TxSegSize, fi)) >= 0) { X if (SendDataPacket(buf, bytes) != SUCCESS) { X if (debug > 7) X printf("GWR Failed\n"); X return(FAIL); X } X if (debug > 7) X printf("\nGWROK "); X if (bytes == 0) X break; X buf = GetTxBuf(); X } X if (debug > 7) X printf("\nGWFile Last Ack\n"); X while (TxPend) { X if (GetData(WAIT_ACK, NULL) == FAIL) X return(FAIL); X } X return (SUCCESS); X} X X/* X * Write message to the other guy. X * X * NOTE: LONGDATA packets used exclusively and \0 fill to end. X */ X Xint Xgwrmsg(str) Xchar *str; X{ X int len = strlen(str) + 1; /* type + str + \0 */ X X if (debug > 8) X printf("GWRMSG: %s\n", str); X X while (len > TxSegSize) { X char *buf = GetTxBuf(); X movmem(str, buf, TxSegSize); X if (debug > 8) X printf("GWR-SEND %d\n", TxSegSize); X if (SendDataPacket(buf, TxSegSize) != SUCCESS) X return(FAIL); X len -= TxSegSize; X str += TxSegSize; X } X X /* X * Find optimal packet size (remember, we must force LONGDATA X * X * Apparently packet sizes less than the agreed upon size are X * not allowed ??? X */ X X { X short siz = TxSegSize; X char *buf = GetTxBuf(); X#ifdef NOTDEF X short k = TxSegK; X X while (k > 1 && (siz >> 1) >= len) { X --k; X siz >>= 1; X } X#endif X if (debug > 8) X printf("GWR-FNL %d %d\n", len, siz); X X movmem(str, buf, len); X setmem(buf + len, siz - len, 0); X if (SendDataPacket(buf, siz) != SUCCESS) { X if (debug > 8) X printf("GWR-FAIL\n"); X return(FAIL); X } X } X if (debug > 8) X printf("GWR Last Ack\n"); X while (TxPend) { X if (GetData(WAIT_ACK, NULL) == FAIL) X return(FAIL); X } X return (SUCCESS); X} X Xint Xgrddata(fi) XFILE *fi; X{ X int bytes; X char *buf; X X if (debug > 7) X printf("GRDDATA\n"); X while ((bytes = RecvDataPacket(&buf)) > 0) { X if (debug > 7) X printf("GRDDATA blk %d\n", bytes); X fwrite(buf, 1, bytes, fi); X } X if (debug > 7) X printf("GRDDATA end %d\n", bytes); X if (bytes < 0) X return(FAIL); X else X return(SUCCESS); X} X Xgrdmsg(buf, maxlen) Xchar *buf; X{ X short i; X short n; X short slen; X char *ptr; X X i = 0; X if (debug > 8) X printf("GRDMSG\n"); X while ((n = RecvDataPacket(&ptr)) > 0) { X ptr[n] = 0; X slen = strlen(ptr); X if (slen > maxlen - 1) { X printf("GRDMSG: Buffer overflow!\n"); X return (FAIL); X } X movmem(ptr, buf + i, slen); X buf[i + slen] = 0; X if (slen != n) X break; X i += slen; X maxlen -= slen; X } X if (debug > 8) X printf("GRDMSGEND %d (%d) %s\n", n, i, buf); X if (n < 0) { X buf[0] = 0; X return(FAIL); X } X return(SUCCESS); X} X XSendDataPacket(buf, bytes) Xubyte *buf; Xint bytes; X{ X Packet P; X X /* X * If window exhausted we must wait for at least one ack. X */ X X if (TxPend == TxWinSize) { X if (GetData(WAIT_ACK, NULL) == FAIL) X return(FAIL); X } X X TxSeq = (TxSeq + 1) & 7; /* next Tx packet */ X X /* X * Figure out best fit packet size. Apparently packets smaller X * then the agreed upon size are not allowed ??? X */ X X#ifdef NOTDEF X { X short k = TxSegK; X P.DLen = TxSegSize; X while (k > 1 && P.DLen && (P.DLen >> 1) >= bytes) { X --k; X P.DLen >>= 1; X } X } X#else X P.DLen = TxSegSize; X#endif X X if (bytes < P.DLen) { X uword extra = P.DLen - bytes; X setmem(buf + bytes, extra, 0); X if (extra <= 127) { X P.PLen = 1; X buf[-1] = extra; X } else { X P.PLen = 2; X buf[-2] = 0x80 | extra; X buf[-1] = (extra >> 7); X } X P.CType = CT_SHORTDATA; X } else { X P.PLen = 0; X P.CType = CT_LONGDATA; X } X P.CCmd = TxSeq << 3; /* transmit sequence number */ X P.CSeq = (RxSeq - 1) & 7; /* last valid received pkt */ X P.Data = buf; X X if (debug > 8) X printf("WRITE PACKET %d %d\n", TxSeq, P.CSeq); X X if (RxNotAcked) /* We've acked the rx packet */ X RxNotAcked = 0; X X TxPacket[TxSeq & 7] = P; X ++TxPend; X X WritePacket(&TxPacket[TxSeq & 7], 1); X X return(SUCCESS); X} X XRecvDataPacket(pbuf) Xchar **pbuf; X{ X if (RxRdy == 0) { X if (GetData(WAIT_DATA, NULL) != SUCCESS) X return(-1); X } X *pbuf = RxPacket.Data; X RxRdy = 0; X return((int)RxPacket.DLen); X} X Xgturnon(master) X{ X Packet P; X short retry = 5; X short windowsize = WINDOWSIZE; /* our prefered window size */ X short segsize = SEGSIZEK; /* our prefered segment size */ X X if (WindowOne) X windowsize = 1; X X if (master) { X while (retry > 0) { X WriteCtlPacket(CC_INITA | windowsize); X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) { X if (P.CSeq && P.CSeq < windowsize) X windowsize = P.CSeq; X break; X } X --retry; X } X while (retry > 0) { X WriteCtlPacket(CC_INITB | (segsize - 1)); X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) { X if (P.CSeq < segsize - 1) X segsize = P.CSeq + 1; X break; X } X --retry; X } X while (retry > 0) { X WriteCtlPacket(CC_INITC | windowsize); X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) { X if (P.CSeq && P.CSeq < windowsize) X windowsize = P.CSeq; X break; X } X --retry; X } X } else { X while (retry > 0) { X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITA) { X WriteCtlPacket(CC_INITA | windowsize); X if (P.CSeq && windowsize > P.CSeq) X windowsize = P.CSeq; X break; X } X --retry; X } X while (retry > 0) { X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITB) { X WriteCtlPacket(CC_INITB | (segsize - 1)); X if (P.CSeq < segsize - 1) X segsize = P.CSeq + 1; X break; X } X --retry; X } X while (retry > 0) { X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_INITC) { X WriteCtlPacket(CC_INITC | windowsize); X if (P.CSeq && windowsize > P.CSeq) X windowsize = P.CSeq; X break; X } X --retry; X } X } X TxSegK = segsize; X TxSegSize = 1 << (TxSegK + 4); X TxWinSize = windowsize; X if (debug > 0) X printf("Window Size is %d\n", TxWinSize); X if (retry == 0) X return(FAIL); X return(SUCCESS); X} X Xgturnoff() X{ X Packet P; X X WriteCtlPacket(CC_CLOSE); X if (GetData(WAIT_CONTROL, &P) == SUCCESS && P.CCmd == CC_CLOSE) { X WriteCtlPacket(CC_RR | ((RxSeq - 1) & 7)); X return (SUCCESS); X } X return (FAIL); X} X XGetData(waitfor, p) XPacket *p; X{ X Packet P; X short timeout; X X /* X * If we haven't acked the last packet we received we must do X * so now before we can expect to receive another one! X */ X X if (waitfor == WAIT_ACK) X timeout = 20; X else if (waitfor == WAIT_DATA) X timeout = 40; X else X timeout = 40; X X for (;;) { X if (RxNotAcked) { X WriteCtlPacket(CC_RR | SUB1(RxSeq)); X RxNotAcked = 0; X } X if (ReadPacket(&P, timeout) == FAIL) { X if (waitfor == WAIT_DATA) { X if (RxRetry) { X --RxRetry; X if (debug > 8) X printf("\nWAIT-DATA, TIMEOUT, SEND RJ\n"); X WriteCtlPacket(CC_RJ | SUB1(RxSeq)); X continue; X } X } X if (waitfor == WAIT_ACK) { X if (RxRetry) { X --RxRetry; X if (debug > 8) X printf("\nWAIT-ACK, TIMEOUT, RETRY\n"); X WritePacket(&TxPacket[(TxSeq - TxPend + 1) & 7], 1); X continue; X } X } X if (debug > 8) X printf("COMPLETE FAILURE RxRetry = %d\n", RxRetry); X return(FAIL); X } X RxRetry = 4; X switch(P.CType) { X case CT_CONTROL: X switch(P.CCmd) { X case CC_CLOSE: /* End of communication ... not an ACK! */ X if (waitfor == WAIT_CONTROL) { X *p = P; X return(SUCCESS); X } X return(FAIL); X case CC_RJ: /* Reject packet (P.CSeq == last good packet) */ X /* resend last packet */ X X WritePacket(&TxPacket[(P.CSeq + 1) & 7], 1); X { X short i; X for (i = 0; i < TxPend; ++i) { X if (P.CSeq == ((TxSeq - i) & 7)) X break; X } X if (i == TxPend) X printf("RJ, bad seq no: %d expected %d-%d\n", P.CSeq, (TxSeq - TxPend + 1) & 7, TxSeq); X } X break; X case CC_SRJ: /* Selective Reject (P.CSeq == bad packet # ) */ X return(FAIL); X case CC_RR: /* Ack to packet (P.CSeq == packet # acked) */ X if (RecvdAck(P.CSeq) == SUCCESS && waitfor == WAIT_ACK) X return(SUCCESS); X break; X case CC_INITC: X case CC_INITB: X case CC_INITA: X if (waitfor == WAIT_CONTROL) { X *p = P; X return(SUCCESS); X } X return(FAIL); X } X break; X case CT_ALTCHN: X printf("ALTCHN packet ??\n"); X break; X case CT_LONGDATA: X case CT_SHORTDATA: X { X char rxseq = P.CCmd >> 3; X char txack = P.CSeq; X X if (RxRdy == 1) { X printf("Got two receive packets without me acking!\n"); X } X if (rxseq == SUB1(RxSeq)) { X RxNotAcked = 1; X continue; /* ignore resent pkts we already have */ X } else if (rxseq != RxSeq) { X if (rxseq == ((RxSeq + 1) & 7)) /* missed one (windowed) */ X WriteCtlPacket(CC_RJ | SUB1(RxSeq)); X printf("Received sequence %d, expected %d\n", rxseq, RxSeq); X break; X } else { X if (debug > 6) X printf("RECV SEQUENCE %d\n", rxseq); X } X X RecvdAck(txack); X X /* X * Delay sending the ACK back in case we can combine X * it with the next transmitted packet. X */ X X RxNotAcked = 1; /* we haven't ack'd the rx packet */ X X RxSeq = (RxSeq + 1) & 7; X RxRdy = 1; X RxPacket = P; X if (waitfor == WAIT_DATA) X return(SUCCESS); X if (TxPend == 0 && waitfor == WAIT_ACK) X return(SUCCESS); X } X break; X } X } X} X XRecvdAck(seq) Xchar seq; X{ X short i; X short seqbase = TxSeq - TxPend + 1; X X /* X * which packet was acked? X */ X X for (i = 0; i < TxPend; ++i) { X if (seq == ((seqbase + i) & 7)) X break; X } X if (i == TxPend) { X if (TxPend) X printf("He acked the wrong packet! %d expected %d\n", seq, TxSeq); X return(FAIL); X } X if (debug > 8) X printf("TxPend %d ->", TxPend); X TxPend = TxPend - i - 1; X if (debug > 8) X printf(" %d\n", TxPend); X return(SUCCESS); X} X XWriteCtlPacket(cc) X{ X Packet pk; X X pk.CType = CT_CONTROL; X pk.CCmd = cc & CC_MASK; X pk.CSeq = cc & SEQ_MASK; X pk.PLen = 0; X pk.DLen = 0; X WritePacket(&pk, 0); X return(SUCCESS); X} X XWritePacket(pk, async) XPacket *pk; X{ X Frame F; X uword sum; X X F.Dle = DLE; X F.C = pk->CType | pk->CCmd | pk->CSeq; X F.K = 9; X X if (pk->CType == CT_SHORTDATA || pk->CType == CT_LONGDATA) X F.K = LenToK(pk->DLen); X else X pk->DLen = 0; X X sum = MAGIC - (CheckSum(pk->Data - pk->PLen, pk->DLen) ^ F.C); X X F.CH = sum >> 8; X F.CL = sum; X F.X = F.K ^ F.CH ^ F.CL ^ F.C; X X if (debug > 8) X printf("WritePacket: F.K = %d F.C = %02x\n", F.K, F.C); X X if (async) X xwritea(&F, sizeof(F)); X else X xwrite(&F, sizeof(F)); /* write header */ X if (pk->DLen) { /* write data */ X if (async) X xwritea(pk->Data - pk->PLen, pk->DLen); X else X xwrite(pk->Data - pk->PLen, pk->DLen); X } X return(SUCCESS); X} X XReadPacket(pk, timeout) XPacket *pk; X{ X Frame F; X short c; X short i = 0; X X pk->Data = RxBuf; X pk->CType = 0xFF; X pk->CCmd = 0; X pk->CSeq = 0; X X if (debug > 8) X printf("ReadPacket\n"); X while ((c = xgetc(timeout)) != EOF) { X if (debug > 8) X printf("RP %d %02x\n", i, c); X X switch(i) { X case 0: X if (c == DLE) { X F.Dle = c; X ++i; X } X break; X case 1: X F.K = c; X ++i; X if (c == DLE) { /* K only valid 0-9 */ X F.Dle = c; X i = 1; X } X break; X case 2: X F.CL = c; X ++i; X break; X case 3: X F.CH = c; X ++i; X break; X case 4: X F.C = c; X ++i; X break; X case 5: X F.X = c; X if (F.X != (F.K ^ F.CH ^ F.CL ^ F.C)) { X printf("F.X failed: %02x %02x\n", F.X, (F.K ^ F.CH ^ F.CL ^ F.C)); X i = 0; X } else { /* get data segment if any */ X ++i; X } X break; X } X if (i == 6) X break; X } X if (debug > 8) X printf("RP Hdr i = %d, F.K = %d F.C = %02x\n", i, F.K, F.C); X X if (i == 6) { /* Receive Data Portion */ X uword pktsize = 1 << (F.K + 4); X uword n; X X if (F.K == 0 || F.K == 9) X pktsize = 0; /* FIXME is K=0 an illegal case? */ X X if (pktsize > MaxPktSize) { X printf("Protocol failure pktsize %d/%d/%d\n", pktsize, TxSegSize, MaxPktSize); X return (FAIL); X } X for (n = 0; n < pktsize; ++n) { X if ((c = xgetc(4)) == EOF) X break; X pk->Data[n] = c; X } X if (c != EOF) { X uword hissum; X uword oursum; X hissum = (F.CH << 8) | F.CL; X oursum = MAGIC - (CheckSum(pk->Data, pktsize) ^ F.C); X if (debug > 8) X printf("Got Data, checking: %04x %04x\n", hissum, oursum); X if (hissum == oursum) { X FrameToPacket(&F, pk, pk->Data); X return (SUCCESS); X } X } else { X FrameToPacket(&F, pk, pk->Data); /* mainly for pk->CType */ X return (FAIL); X } X } X /* X * Timeout, retry? X */ X return (FAIL); X} X XCheckSum(s, n) Xubyte *s; Xint n; X{ X uword sum; X uword x; X uword t; X X if (n == 0) X return(0); X sum = -1; X x = 0; X X while (n) { X if (sum & 0x8000) X sum = (sum << 1) | 1; X else X sum = (sum << 1); X X t = sum; X sum += *s++; X x += sum ^ n; X if (sum <= t) X sum ^= x; X --n; X } X return((int)sum); X} X Xvoid XFrameToPacket(fr, pk, data) XFrame *fr; XPacket *pk; Xubyte *data; X{ X pk->CType = fr->C & CT_MASK; X pk->CCmd = fr->C & CC_MASK; X pk->CSeq = fr->C & SEQ_MASK; X switch(pk->CType) { X case CT_LONGDATA: X pk->DLen = 1 << (fr->K + 4); X break; X case CT_SHORTDATA: X pk->DLen = 1 << (fr->K + 4); X if (pk->Data[0] & 0x80) { X pk->DLen -= (pk->Data[0] & 0x7F) | (pk->Data[1] << 7); X if (pk->DLen < 0) { X printf("DLEN ERROR %d\n", pk->DLen); X pk->DLen = 0; X } X pk->Data += 2; X } else { X pk->DLen -= *pk->Data; X ++pk->Data; X } X break; X default: X pk->DLen = 0; X break; X } X} X XLenToK(bytes) Xuword bytes; X{ X uword n = 32; X uword k = 1; X X while (n < bytes) { X n <<= 1; X ++k; X } X if (k > 8) { X printf("Soft error, LenToK: %d %d %d\n", bytes, n, k); X k = 8; X } X return((int)k); X} X END_OF_FILE if test 16481 -ne `wc -c <'src/uucico/gio.c'`; then echo shar: \"'src/uucico/gio.c'\" unpacked with wrong size! fi # end of 'src/uucico/gio.c' fi echo shar: End of archive 8 \(of 16\). cp /dev/null ark8isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 16 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 -- Submissions to comp.sources.amiga and comp.binaries.amiga should be sent to: amiga@cs.odu.edu or amiga@xanth.cs.odu.edu ( obsolescent mailers may need this address ) or ...!uunet!xanth!amiga ( very obsolescent mailers need this address ) Comments, questions, and suggestions should be addressed to ``amiga-request'' (please only use ``amiga'' for actual submissions) at the above addresses.