diff --git a/ChangeLog b/ChangeLog index ec3127b2..e42a3c32 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,40 @@ $Id$ + WARNING: This code contains unfinished changes, if you use the bbs + then do not use this version. + This code also contains changes in the hydra code, this + should be safe to use because the code is disabled for + endusers. + + +v0.39.0 09-Oct-2003 + + general: + Added menu setup switches for doors: Singe user door and + hidden from lists. + Added configure settings for zlib, disabled for endusers. + + mbsebbs: + The whoson list displays the doorname if set in the menus. + If a door is single user and the door is in use, the second + user can't start the door but gets a message about this + situation. + + mbsetup: + Added menu settings for single user door and hide door. Added + setting for the door name in the menus and removed the never + used password for the menu (Was only present in the setup). + + mbcico: + Started adding code for zlib compression of hydra packets. + Not functional yet and disabled by configure. + + lang: + Added language prompt 20. + + examples: + Updated English and Spanish menus with the new door settings. + v0.38.0 26-Dec-2002 - 03-Oct-2003 diff --git a/config.h.in b/config.h.in index 02af0c3f..50bc2286 100644 --- a/config.h.in +++ b/config.h.in @@ -302,3 +302,6 @@ /* Define if you have the header file. */ #undef HAVE_ICONV_H +/* Define if you have the header file. */ +#undef HAVE_ZLIB_H + diff --git a/configure.in b/configure.in index 10c05d09..e47d9f61 100644 --- a/configure.in +++ b/configure.in @@ -131,6 +131,7 @@ AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(malloc.h sys/file.h sys/ioctl.h sys/time.h termios.h syslog.h sys/vfs.h unistd.h netinet/in.h regex.h) AC_CHECK_HEADERS(sys/resource.h usersec.h utime.h ulimit.h gshadow.h shadow.h) AC_CHECK_HEADERS(limits.h utmp.h utmpx.h lastlog.h rpc/key_prot.h) +dnl AC_CHECK_HEADERS(zlib.h) FIXME: enable when ready for endusers. AC_CHECK_HEADERS(iconv.h) AC_STRUCT_TIMEZONE diff --git a/examples/menus-en.tar b/examples/menus-en.tar index fb7748c5..060adae7 100644 Binary files a/examples/menus-en.tar and b/examples/menus-en.tar differ diff --git a/examples/menus-es.tar b/examples/menus-es.tar index a6e48243..e6b54bfa 100644 Binary files a/examples/menus-es.tar and b/examples/menus-es.tar differ diff --git a/html/images/e_menu.png b/html/images/e_menu.png index 75cd9003..07d92c9b 100644 Binary files a/html/images/e_menu.png and b/html/images/e_menu.png differ diff --git a/html/index.htm b/html/index.htm index b986ed63..f471b9fd 100755 --- a/html/index.htm +++ b/html/index.htm @@ -13,8 +13,8 @@
-

MBSE BBS System Guide v0.38.0

-
Last update 03-Oct-2003
+

MBSE BBS System Guide v0.39.0

+
Last update 11-Oct-2003

diff --git a/html/menus/index.htm b/html/menus/index.htm index 2caa67b2..9b6516ff 100644 --- a/html/menus/index.htm +++ b/html/menus/index.htm @@ -12,11 +12,10 @@

-
Last update 06-Mar-2002
-

 

+

Last update 11-Oct-2003
+

MBSE BBS Menu System

-

MBSE BBS Menu System

-

Menus sections: +

Menus sections: Global menus  File areas  Message areas  @@ -104,7 +103,7 @@ display and finally show the prompt. this menu. This field is ignored when AutoExec is set to Yes.

  • Type nr. this is the menu type to execute. For a description -of all available types see below.
  • +of all available types see the links at the top of this page.
  • Optional data. Some menus need optional data, for example the function goto another menu needs the name of that menu file here.
  • @@ -123,15 +122,6 @@ everyone must be able to execute. You may want to restrict access to certain areas to users older than 18 years. If you leave this to 0, every one can execute this menu. -
  • Max. lvl. The maximum level a user must have to execute this -menu. If you leave this at 0 then the maximum level has no effect.
  • - -
  • Password. You can protect the menu selection with a password. -If this field is empty, no password check is done.
  • - -
  • Credit. How much credit a user must have to execute this menu -selection. This field is not in use yet.
  • -
  • Lo-colors. The normal display color for the display line.
  • @@ -139,25 +129,40 @@ selection. This field is not in use yet.
  • AutoExec. If this is an automatic executed selection.
  • -
  • No door.sys Suppress writing of a door.sys file in the users -home directory. This item is only visible with menu type 7.
  • +
  • Door Name The name of the door that will be displayed to other users. +This name is also used to count the same doors running if the door only allows a +single user. It is important that you use the same name in every language menu +file for the same door. This item is only visible with menu type 7.
  • Y2K style Writes the dates in the door.sys file in the new style, with 4 digit year numbers, else the old 2 digit style is used. This item is only visible with menu type 7.
  • -
  • Use Comport Writes real comport to the door.sys file, this is -for dosemu with the vmodem patch. This item is only visible with menu +
  • No door.sys Suppress writing of a door.sys file in the users +home directory. This item is only visible with menu type 7.
  • + +
  • Use Comport Writes COM1: with 19200 as baudrate to the door.sys file, +this is for dosemu with the vmodem patch. This item is only visible with menu type 7.
  • Run nosuid If set to Yes the door will run in non-suid mode. -You need this to run DOS doors using dosemu. This item is only visible +Most doors need this. This item is only visible with menu type 7.
  • No Prompt If set to Yes then when the door is finished there will be no prompt to press Enter, instead the bbs menu will show up immediatly. This item is only visible with menu type 7.
  • +
  • Single User Set to yes of the door only allows one user at the same +time. Make sure you have set a unique name that must be the same for the door in +every language file so that the bbs is able to count the instances of the door +running. This item is only visible with menu type 7.
  • + +
  • Hidden door Set to yes to hide the door from being visible for other +users. If someone is using that door the whoson list displays "External Door" +instead of the door name. This may be good to hide some special sysop only +doors. This item is only visible with menu type 7.
  • +

     

    diff --git a/lang/Language.xref b/lang/Language.xref index 5c9a2b56..bacffa9e 100644 --- a/lang/Language.xref +++ b/lang/Language.xref @@ -18,7 +18,7 @@ 17 file.c |This is not a plain textfile. 18 user.c |You may only login 19 user.c |times at the same time -20 .c | +20 door.c |The door is in use by another user, try again later 21 .c | 22 .c | 23 .c | diff --git a/lang/dutch.txt b/lang/dutch.txt index 2fae01c6..433ee6f3 100644 --- a/lang/dutch.txt +++ b/lang/dutch.txt @@ -18,7 +18,7 @@ HR|Exporteer naar (H)ome of (R)egels directory: |Dit is geen normaal tekst bestand |U mag maar |keer tegelijk inloggen -| +|De door is in gebruik door een andere gebruiker, probeer het later nog eens | | | diff --git a/lang/english.txt b/lang/english.txt index 89b9056d..aff3985e 100644 --- a/lang/english.txt +++ b/lang/english.txt @@ -18,7 +18,7 @@ HR|Export to (H)ome or (R)ules directory: |This is not a plain textfile. |You may only login |times at the same time -| +|The door is in use by another user, try again later | | | diff --git a/lang/galego.txt b/lang/galego.txt index 697e7fbb..949363c5 100644 --- a/lang/galego.txt +++ b/lang/galego.txt @@ -18,7 +18,7 @@ HR|Exportar |This is not a plain textfile. |You may only login |times at the same time -| +|The door is in use by another user, try again later | | | diff --git a/lang/german.txt b/lang/german.txt index 3b7b0150..c851cbd3 100644 --- a/lang/german.txt +++ b/lang/german.txt @@ -18,7 +18,7 @@ HR|Export in (H)ome oder (R)ules Direktorie: |Dies ist keine Textdatei. |Du darfst nur |mal gleichzeitig eingewaehlt sein -| +|The door is in use by another user, try again later | | | diff --git a/lang/germandu.txt b/lang/germandu.txt index a6217f25..21c92343 100644 --- a/lang/germandu.txt +++ b/lang/germandu.txt @@ -18,7 +18,7 @@ HR|Export in (H)ome oder (R)ules Direktorie: |Dies ist keine Textdatei. |Du darfst nur |mal gleichzeitig eingewaehlt sein -| +|The door is in use by another user, try again later | | | diff --git a/lang/italian.txt b/lang/italian.txt index a70276be..803904cb 100644 --- a/lang/italian.txt +++ b/lang/italian.txt @@ -18,7 +18,7 @@ HR|Export to (H)ome or (R)ules directory: |This is not a plain textfile. |You may only login |times at the same time -| +|The door is in use by another user, try again later | | | diff --git a/lang/spanish.txt b/lang/spanish.txt index 439e1829..e8317fed 100644 --- a/lang/spanish.txt +++ b/lang/spanish.txt @@ -18,7 +18,7 @@ PR|Exportar al directorio (P)ersonal o de (R)eglas: |This is not a plain textfile. |You may only login |times at the same time -| +|The door is in use by another user, try again later | | | diff --git a/lib/crc.c b/lib/crc.c index 46698cfb..fc06cdac 100644 --- a/lib/crc.c +++ b/lib/crc.c @@ -236,11 +236,12 @@ unsigned long StringCRC32(char *str) /* * Update CRC32, first initialize CRC with 0xffffffff. */ -unsigned long crc32(int octet, unsigned long crc) +/* +unsigned long update_crc32(int octet, unsigned long crc) { return (crc32tab[((int)crc ^ ((long)octet)) & 0xff] ^ ((((unsigned long)crc) >> 8) & 0x00ffffff)); } - +*/ /* diff --git a/lib/libs.h b/lib/libs.h index e6425ef6..9bfad028 100644 --- a/lib/libs.h +++ b/lib/libs.h @@ -1,11 +1,11 @@ /***************************************************************************** * + * $Id$ * File ..................: libs.h * Purpose ...............: Libraries include list - * Last modification date : 05-Aug-2001 * ***************************************************************************** - * Copyright (C) 1997-2001 + * Copyright (C) 1997-2003 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 @@ -86,6 +86,9 @@ #ifdef HAVE_ICONV_H #include #endif +#ifdef HAVE_ZLIB_H +#include +#endif #pragma pack(1) diff --git a/lib/structs.h b/lib/structs.h index b5df4018..05f36d2a 100644 --- a/lib/structs.h +++ b/lib/structs.h @@ -839,7 +839,7 @@ struct menufile { securityrec MenuSecurity; /* Menu Security Level */ int Age; /* Minimum Age to use menu */ unsigned int xMaxSecurity; - char Password[15]; /* Menu Password */ + char DoorName[15]; /* Door name */ char TypeDesc[30]; /* Menu Type Description */ #ifdef __i386__ unsigned AutoExec : 1; /* Auto Exec Menu Type */ @@ -848,10 +848,12 @@ struct menufile { unsigned Comport : 1; /* Vmodem comport mode */ unsigned NoSuid : 1; /* Execute door nosuid */ unsigned NoPrompt : 1; /* No prompt after door */ + unsigned SingleUser : 1; /* Single user door */ + unsigned HideDoor : 1; /* Hide door from lists */ #else /* All bits swapped */ - unsigned xxLE_Dummy1 : 1; - unsigned xxLE_Dummy2 : 1; + unsigned HideDoor : 1; /* Hide door from lists */ + unsigned SingleUser : 1; /* Single user door */ unsigned NoPrompt : 1; /* No prompt after door */ unsigned NoSuid : 1; /* Execute noduid */ unsigned Comport : 1; /* Vmodem comport mode */ @@ -859,7 +861,7 @@ struct menufile { unsigned NoDoorsys : 1; /* Suppress door.sys */ unsigned AutoExec : 1; /* Auto Exec Menu Type */ #endif - long xCredit; + long xUnused; int HiForeGnd; /* High ForeGround color */ int HiBackGnd; /* High ForeGround color */ int ForeGnd; /* Normal ForeGround color */ diff --git a/mbcico/hydra.c b/mbcico/hydra.c index c8c7a892..9fc013bc 100644 --- a/mbcico/hydra.c +++ b/mbcico/hydra.c @@ -98,6 +98,9 @@ static struct h_flags_struct { { (char *)"C32", HOPT_CRC32 }, { (char *)"DEV", HOPT_DEVICE }, { (char *)"FPT", HOPT_FPT }, +#ifdef HAVE_ZLIB_H + { (char *)"PLZ", HOPT_CANPLZ }, +#endif { NULL , 0x0L } }; @@ -107,15 +110,15 @@ static int txoptions, rxoptions; static char *put_long(char *buffer, long val) { #if defined(__i386__) - *(unsigned long *) buffer = (unsigned long) val; + *(unsigned long *) buffer = (unsigned long) val; #else - buffer[0] = (unsigned long) val & 0xff; - buffer[1] = ((unsigned long) val >> 8) & 0xff; - buffer[2] = ((unsigned long) val >> 16) & 0xff; - buffer[3] = ((unsigned long) val >> 24) & 0xff; + buffer[0] = (unsigned long) val & 0xff; + buffer[1] = ((unsigned long) val >> 8) & 0xff; + buffer[2] = ((unsigned long) val >> 16) & 0xff; + buffer[3] = ((unsigned long) val >> 24) & 0xff; #endif - return buffer; + return buffer; } @@ -123,12 +126,10 @@ static char *put_long(char *buffer, long val) static long get_long(char *buffer) { #if defined(__i386__) - return *(long *) buffer; + return *(long *) buffer; #else - return ((unsigned long) ((unsigned char) buffer[0])) | - ((unsigned long) ((unsigned char) buffer[1]) << 8) | - ((unsigned long) ((unsigned char) buffer[2]) << 16) | - ((unsigned long) ((unsigned char) buffer[3]) << 24); + return ((unsigned long) ((unsigned char) buffer[0])) | ((unsigned long) ((unsigned char) buffer[1]) << 8) | + ((unsigned long) ((unsigned char) buffer[2]) << 16) | ((unsigned long) ((unsigned char) buffer[3]) << 24); #endif } @@ -137,29 +138,32 @@ static long get_long(char *buffer) char *PktS(int); char *PktS(int c) { - switch (c) { - case 'A' : return (char *)"START"; - case 'B' : return (char *)"INIT"; - case 'C' : return (char *)"INITACK"; - case 'D' : return (char *)"FINFO"; - case 'E' : return (char *)"FINFOACK"; - case 'F' : return (char *)"DATA"; - case 'G' : return (char *)"DATAACK"; - case 'H' : return (char *)"RPOS"; - case 'I' : return (char *)"EOF"; - case 'J' : return (char *)"EOFACK"; - case 'K' : return (char *)"END"; - case 'L' : return (char *)"IDLE"; - case 'M' : return (char *)"DEVDATA"; - case 'N' : return (char *)"DEVDACK"; - case 'a' : return (char *)"PKTEND"; - case 'b' : return (char *)"BINPKT"; - case 'c' : return (char *)"HEXPKT"; - case 'd' : return (char *)"ASCPKT"; - case 'e' : return (char *)"UUEPKT"; - default: break; - } - return (char *)""; + switch (c) { + case 'A' : return (char *)"START"; + case 'B' : return (char *)"INIT"; + case 'C' : return (char *)"INITACK"; + case 'D' : return (char *)"FINFO"; + case 'E' : return (char *)"FINFOACK"; + case 'F' : return (char *)"DATA"; + case 'G' : return (char *)"DATAACK"; + case 'H' : return (char *)"RPOS"; + case 'I' : return (char *)"EOF"; + case 'J' : return (char *)"EOFACK"; + case 'K' : return (char *)"END"; + case 'L' : return (char *)"IDLE"; + case 'M' : return (char *)"DEVDATA"; + case 'N' : return (char *)"DEVDACK"; +#ifdef HAVE_ZLIB_H + case 'O' : return (char *)"ZIPDATA"; +#endif + case 'a' : return (char *)"PKTEND"; + case 'b' : return (char *)"BINPKT"; + case 'c' : return (char *)"HEXPKT"; + case 'd' : return (char *)"ASCPKT"; + case 'e' : return (char *)"UUEPKT"; + default: break; + } + return (char *)""; } @@ -195,28 +199,28 @@ int put_binbyte(char *outbuf, char c) int put_hexbyte(char *outbuf, char c) { - static const char hexdigit[] = "0123456789abcdef"; - register int count = 0; + static const char hexdigit[] = "0123456789abcdef"; + register int count = 0; - if (c & 0x80) { - *outbuf++ = '\\'; - *outbuf++ = hexdigit[(c >> 4) & 0x0f]; - *outbuf++ = hexdigit[c & 0x0f]; - count = 3; - } else if ((c < 32) || (c == 127)) { - *outbuf++ = H_DLE; - *outbuf++ = c ^ 0x40; - count = 2; - } else if (c == '\\') { - *outbuf++ = '\\'; - *outbuf++ = '\\'; - count = 2; - } else { - *outbuf++ = c; - count = 1; - } + if (c & 0x80) { + *outbuf++ = '\\'; + *outbuf++ = hexdigit[(c >> 4) & 0x0f]; + *outbuf++ = hexdigit[c & 0x0f]; + count = 3; + } else if ((c < 32) || (c == 127)) { + *outbuf++ = H_DLE; + *outbuf++ = c ^ 0x40; + count = 2; + } else if (c == '\\') { + *outbuf++ = '\\'; + *outbuf++ = '\\'; + count = 2; + } else { + *outbuf++ = c; + count = 1; + } - return count; + return count; } @@ -225,127 +229,127 @@ int put_hexbyte(char *outbuf, char c) /* TODO: error handling */ enum HyPktTypes hyrxpkt(char *rxbuf, int *rxlen, int tot) { - static char rxencbuf[H_BUFLEN]; - static enum HyPktTypes pkttype = H_NOPKT; - static char *inbuf = rxencbuf, *outbuf; - int c, i, n; - static int rxdle = 0; - static enum HyPktFormats format; + static char rxencbuf[H_BUFLEN]; + static enum HyPktTypes pkttype = H_NOPKT; + static char *inbuf = rxencbuf, *outbuf; + int c, i, n; + static int rxdle = 0; + static enum HyPktFormats format; - while ((c = GETCHAR(tot)) >= 0) { - if (rxoptions & HOPT_HIGHBIT) - c &= 0x7f; + while ((c = GETCHAR(tot)) >= 0) { + if (rxoptions & HOPT_HIGHBIT) + c &= 0x7f; - n = c; - if (rxoptions & HOPT_HIGHCTL) - n &= 0x7f; + n = c; + if (rxoptions & HOPT_HIGHCTL) + n &= 0x7f; - if ((n != H_DLE) - && (((rxoptions & HOPT_XONXOFF) && ((n == XON) || (n == XOFF))) - || ((rxoptions & HOPT_CTLCHRS) && ((n < 32) || (n == 127))))) - continue; + if ((n != H_DLE) + && (((rxoptions & HOPT_XONXOFF) && ((n == XON) || (n == XOFF))) + || ((rxoptions & HOPT_CTLCHRS) && ((n < 32) || (n == 127))))) + continue; - if ((rxdle) || (c == H_DLE)) { - switch (c) { - case H_DLE: - rxdle++; - if (rxdle >= 5) { - inbuf = rxencbuf; - return H_CANCEL; - } - break; + if ((rxdle) || (c == H_DLE)) { + switch (c) { + case H_DLE: + rxdle++; + if (rxdle >= 5) { + inbuf = rxencbuf; + return H_CANCEL; + } + break; - case HCHR_PKTEND: - switch (format) { - case HCHR_BINPKT: - *rxlen = inbuf - rxencbuf; - memcpy(rxbuf, rxencbuf, *rxlen); - break; + case HCHR_PKTEND: + switch (format) { + case HCHR_BINPKT: + *rxlen = inbuf - rxencbuf; + memcpy(rxbuf, rxencbuf, *rxlen); + break; - case HCHR_HEXPKT: - outbuf = rxencbuf; - *rxlen = 0; + case HCHR_HEXPKT: + outbuf = rxencbuf; + *rxlen = 0; - while (outbuf < inbuf) { - if ((*outbuf == '\\') && (*++outbuf != '\\')) { - i = *outbuf++; - n = *outbuf++; + while (outbuf < inbuf) { + if ((*outbuf == '\\') && (*++outbuf != '\\')) { + i = *outbuf++; + n = *outbuf++; - if ((i -= '0') > 9) - i -= ('a' - ':'); - if ((n -= '0') > 9) - n -= ('a' - ':'); + if ((i -= '0') > 9) + i -= ('a' - ':'); + if ((n -= '0') > 9) + n -= ('a' - ':'); - if ((i & ~0x0f) || (n & ~ 0x0f)) { - Syslog('+', "Hydra: RXPKT assert"); - die(MBERR_FTRANSFER); - break; - } - - rxbuf[*rxlen] = (i << 4) | n; - *rxlen += 1; - } else { - rxbuf[*rxlen] = *outbuf++; - *rxlen += 1; - } - } - break; - - case HCHR_ASCPKT: - case HCHR_UUEPKT: - default: + if ((i & ~0x0f) || (n & ~ 0x0f)) { Syslog('+', "Hydra: RXPKT assert"); die(MBERR_FTRANSFER); - } + break; + } - if ((format != HCHR_HEXPKT) && (rxoptions & HOPT_CRC32)) { - n = h_crc32test(crc32ccitt(rxbuf, *rxlen)); - *rxlen -= 4; /* remove CRC-32 */ + rxbuf[*rxlen] = (i << 4) | n; + *rxlen += 1; } else { - n = h_crc16test(crc16ccitt(rxbuf, *rxlen)); - *rxlen -= 2; /* remove CRC-16 */ + rxbuf[*rxlen] = *outbuf++; + *rxlen += 1; } + } + break; - *rxlen -= 1; /* remove packet type */ - pkttype = rxbuf[*rxlen]; - - /* check if CRC test succeeded */ - if (n) { - inbuf = rxencbuf; - Syslog('h', "Hydra: RXPKT rcvd %s", PktS(pkttype)); - return pkttype; - } else { - Syslog('+', "Hydra: RXPKT CRC test failed"); - } - break; - - case HCHR_BINPKT: - case HCHR_HEXPKT: case HCHR_ASCPKT: - case HCHR_UUEPKT: + case HCHR_UUEPKT: + default: + Syslog('+', "Hydra: RXPKT assert"); + die(MBERR_FTRANSFER); + } + + if ((format != HCHR_HEXPKT) && (rxoptions & HOPT_CRC32)) { + n = h_crc32test(crc32ccitt(rxbuf, *rxlen)); + *rxlen -= 4; /* remove CRC-32 */ + } else { + n = h_crc16test(crc16ccitt(rxbuf, *rxlen)); + *rxlen -= 2; /* remove CRC-16 */ + } + + *rxlen -= 1; /* remove packet type */ + pkttype = rxbuf[*rxlen]; + + /* check if CRC test succeeded */ + if (n) { + inbuf = rxencbuf; + Syslog('h', "Hydra: RXPKT rcvd %s", PktS(pkttype)); + return pkttype; + } else { + Syslog('+', "Hydra: RXPKT CRC test failed"); + } + break; + + case HCHR_BINPKT: + case HCHR_HEXPKT: + case HCHR_ASCPKT: + case HCHR_UUEPKT: format = c; inbuf = rxencbuf; rxdle = 0; break; - default: + default: *inbuf++ = c ^ 0x40; rxdle = 0; break; - } - } else { - *inbuf++ = c; - } + } + } else { + *inbuf++ = c; } + } - Syslog('h', "GETCHAR returned %i", c); + Syslog('h', "GETCHAR returned %i", c); - if ((c == TERROR) || (c == EOFILE) || (c == HANGUP)) { - return H_CARRIER; - } + if ((c == TERROR) || (c == EOFILE) || (c == HANGUP)) { + return H_CARRIER; + } - return H_NOPKT; + return H_NOPKT; } @@ -353,1334 +357,1330 @@ enum HyPktTypes hyrxpkt(char *rxbuf, int *rxlen, int tot) /* TODO: support packet prefix string */ void hytxpkt(enum HyPktTypes pkttype, char *txbuf, int txlen) { - static char txencbuf[H_BUFLEN]; - char *outbuf, *inbuf; - enum HyPktFormats format; + static char txencbuf[H_BUFLEN]; + char *outbuf, *inbuf; + enum HyPktFormats format; - if (pkttype == 'G') - Syslog('h', "ACK 0x%02x%02x%02x%02x", txbuf[0], txbuf[1], txbuf[2], txbuf[3]); + if (pkttype == HPKT_DATAACK) + Syslog('h', "ACK 0x%02x%02x%02x%02x", txbuf[0], txbuf[1], txbuf[2], txbuf[3]); - /* - * some packets have to be transferred in HEX mode - */ - if ((pkttype == HPKT_START) || (pkttype == HPKT_INIT) || - (pkttype == HPKT_INITACK) || (pkttype == HPKT_END) || - (pkttype == HPKT_IDLE)) { - format = HCHR_HEXPKT; + /* + * some packets have to be transferred in HEX mode + */ + if ((pkttype == HPKT_START) || (pkttype == HPKT_INIT) || (pkttype == HPKT_INITACK) || + (pkttype == HPKT_END) || (pkttype == HPKT_IDLE)) { + format = HCHR_HEXPKT; + } else { + /* do we need to strip high bit */ + if (txoptions & HOPT_HIGHBIT) { + if ((txoptions & HOPT_CTLCHRS) && (txoptions & HOPT_CANUUE)) { + format = HCHR_UUEPKT; /* use UUE packet encoding */ + } else if (txoptions & HOPT_CANASC) { + format = HCHR_ASCPKT; /* we can use ASCII packet encoding */ + } else { + format = HCHR_HEXPKT; /* fall back to hex packet encoding */ + } } else { - /* do we need to strip high bit */ - if (txoptions & HOPT_HIGHBIT) { - if ((txoptions & HOPT_CTLCHRS) && (txoptions & HOPT_CANUUE)) { - format = HCHR_UUEPKT; /* use UUE packet encoding */ - } else if (txoptions & HOPT_CANASC) { - format = HCHR_ASCPKT; /* we can use ASCII packet encoding */ - } else { - format = HCHR_HEXPKT; /* fall back to hex packet encoding */ - } - } else { - format = HCHR_BINPKT; /* we can use binary packet encoding */ - } + format = HCHR_BINPKT; /* we can use binary packet encoding */ } + } + + /* + * Append format byte to data + */ + txbuf[txlen] = pkttype; + txlen++; + + /* + * check if we can use 32-bit CRC's + */ + if ((format != HCHR_HEXPKT) && (txoptions & HOPT_CRC32)) { + unsigned long crc; /* - * Append format byte to data + * Calc CRC-32 of data + pkttype */ - txbuf[txlen] = pkttype; - txlen++; + crc = ~crc32ccitt(txbuf, txlen); /* - * check if we can use 32-bit CRC's + * Append one's complement of CRC to data, lowbyte first */ - if ((format != HCHR_HEXPKT) && (txoptions & HOPT_CRC32)) { - unsigned long crc; + txbuf[txlen++] = crc; + txbuf[txlen++] = crc >> 8; + txbuf[txlen++] = crc >> 16; + txbuf[txlen++] = crc >> 24; + } else { + unsigned short crc; - /* - * Calc CRC-32 of data + pkttype - */ - crc = ~crc32ccitt(txbuf, txlen); + /* + * Calc CRC-16 of data + pkttype + */ + crc = ~crc16ccitt(txbuf, txlen); - /* - * Append one's complement of CRC to data, lowbyte first - */ - txbuf[txlen++] = crc; - txbuf[txlen++] = crc >> 8; - txbuf[txlen++] = crc >> 16; - txbuf[txlen++] = crc >> 24; - } else { - unsigned short crc; + /* + * Append one's complement of CRC to data, lowbyte first + */ + txbuf[txlen++] = crc; + txbuf[txlen++] = crc >> 8; + } - /* - * Calc CRC-16 of data + pkttype - */ - crc = ~crc16ccitt(txbuf, txlen); + inbuf = txbuf; - /* - * Append one's complement of CRC to data, lowbyte first - */ - txbuf[txlen++] = crc; - txbuf[txlen++] = crc >> 8; - } + outbuf = txencbuf; + *outbuf++ = H_DLE; + *outbuf++ = format; - inbuf = txbuf; - - outbuf = txencbuf; - *outbuf++ = H_DLE; - *outbuf++ = format; - - /* encode packet data */ - switch (format) { + /* encode packet data */ + switch (format) { case HCHR_BINPKT: - while (txlen > 0) { - outbuf += put_binbyte(outbuf, *inbuf); - inbuf++; - txlen--; - } - break; + while (txlen > 0) { + outbuf += put_binbyte(outbuf, *inbuf); + inbuf++; + txlen--; + } + break; case HCHR_HEXPKT: - while (txlen > 0) { - outbuf += put_hexbyte(outbuf, *inbuf); - inbuf++; - txlen--; - } - break; + while (txlen > 0) { + outbuf += put_hexbyte(outbuf, *inbuf); + inbuf++; + txlen--; + } + break; /* ASCII and UUE packets are not yet supported */ case HCHR_ASCPKT: case HCHR_UUEPKT: default: - Syslog('+', "Hydra: TXPKT assert"); - die(MBERR_FTRANSFER); - } + Syslog('+', "Hydra: TXPKT assert"); + die(MBERR_FTRANSFER); + } - *outbuf++ = H_DLE; - *outbuf++ = HCHR_PKTEND; + *outbuf++ = H_DLE; + *outbuf++ = HCHR_PKTEND; - if ((pkttype != HPKT_DATA) && (format != HCHR_BINPKT)) { - *outbuf++ = '\r'; - *outbuf++ = '\n'; - } + if ((pkttype != HPKT_DATA) +#ifdef HAVE_ZLIB_H + && (pkttype != HPKT_ZIPDATA) +#endif + && (format != HCHR_BINPKT)) { + *outbuf++ = '\r'; + *outbuf++ = '\n'; + } - Syslog('h', "Hydra: TXPKT send %s", PktS(pkttype)); - PUT(txencbuf, outbuf - txencbuf); + Syslog('h', "Hydra: TXPKT send %s", PktS(pkttype)); + PUT(txencbuf, outbuf - txencbuf); - return; + return; } int put_flags(char *buf, unsigned long Flags) { - int i, count = 0; + int i, count = 0; - for (i = 0; h_flags[i].val; i++) { - if (Flags & h_flags[i].val) { - if (count > 0) { - *buf++ = ','; - count++; - } + for (i = 0; h_flags[i].val; i++) { + if (Flags & h_flags[i].val) { + if (count > 0) { + *buf++ = ','; + count++; + } - strcpy(buf, h_flags[i].str); - buf += H_FLAGLEN; - count += H_FLAGLEN; - } + strcpy(buf, h_flags[i].str); + buf += H_FLAGLEN; + count += H_FLAGLEN; } + } - *buf = 0; - return count; + *buf = 0; + return count; } unsigned long get_flags(char *buf) { - unsigned long Flags = 0L; - char *p; - int i; + unsigned long Flags = 0L; + char *p; + int i; - for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { - for (i = 0; h_flags[i].val; i++) { - if (!strcmp(p, h_flags[i].str)) { - Flags |= h_flags[i].val; - break; - } - } + for (p = strtok(buf, ","); p != NULL; p = strtok(NULL, ",")) { + for (i = 0; h_flags[i].val; i++) { + if (!strcmp(p, h_flags[i].str)) { + Flags |= h_flags[i].val; + break; + } } + } - return Flags; + return Flags; } int resync(off_t off) { - return 0; + return 0; } int hydra_batch(int role, file_list *to_send) { - static char txbuf[H_BUFLEN], rxbuf[H_BUFLEN]; - struct stat txstat; /* file stat being transmitted */ - FILE *txfp = NULL; /* file currently being transmitted */ - FILE *rxfp = NULL; /* file currently being received */ - char *inbuf, *outbuf; - int rxlen, txlen; /* length of receive/transmit buffer */ - long txwindow, rxwindow; /* window sizes */ - long txpos; - off_t rxpos; /* file positions */ - long stxpos, srxpos; - long longnum; - int hdxlink = FALSE; - int txretries, rxretries; - int txlastack, txsyncid; - int rxlastsync, rxsyncid; - int rxlastdatalen; - int blksize; - int goodbytes; - int goodneeded; - enum HyTxStates txstate; - enum HyRxStates rxstate; - int txwaitpkt, rxwaitpkt; - enum HyPktTypes pkttype; - int waitputget = 0; - struct timeval txstarttime, txendtime; - struct timeval rxstarttime, rxendtime; - struct timezone tz; - int sverr; + static char txbuf[H_BUFLEN], rxbuf[H_BUFLEN]; + struct stat txstat; /* file stat being transmitted */ + FILE *txfp = NULL; /* file currently being transmitted */ + FILE *rxfp = NULL; /* file currently being received */ + char *inbuf, *outbuf; + int rxlen, txlen; /* length of receive/transmit buffer */ + long txwindow, rxwindow; /* window sizes */ + long txpos; + off_t rxpos; /* file positions */ + long stxpos, srxpos; + long longnum; + int hdxlink = FALSE; + int txretries, rxretries; + int txlastack, txsyncid; + int rxlastsync, rxsyncid; + int rxlastdatalen; + int blksize; + int goodbytes; + int goodneeded; + enum HyTxStates txstate; + enum HyRxStates rxstate; + enum HyCompStates compstate; + int txwaitpkt, rxwaitpkt; + enum HyPktTypes pkttype; + int waitputget = 0; + struct timeval txstarttime, txendtime; + struct timeval rxstarttime, rxendtime; + struct timezone tz; + int sverr; - Syslog('h', "Hydra: resettimers"); - RESETTIMERS(); + Syslog('h', "Hydra: resettimers"); + RESETTIMERS(); - txpos = rxpos = 0; - stxpos = srxpos = 0; - txretries = rxretries = 0; - txlastack = txsyncid = 0; - rxlastsync = rxsyncid = 0; - rxlastdatalen = 0; - blksize = 512; - goodbytes = 0; - goodneeded = 1024; - Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - txstate = HTX_START; - txoptions = HTXI_OPTIONS; - txstarttime.tv_sec = txstarttime.tv_usec = txendtime.tv_sec = txendtime.tv_usec = 0; - rxstarttime.tv_sec = rxstarttime.tv_usec = rxendtime.tv_sec = rxendtime.tv_usec = 0; - tz.tz_minuteswest = tz.tz_dsttime = 0; - rxstate = HRX_INIT; - rxoptions = HRXI_OPTIONS; + txpos = rxpos = 0; + stxpos = srxpos = 0; + txretries = rxretries = 0; + txlastack = txsyncid = 0; + rxlastsync = rxsyncid = 0; + rxlastdatalen = 0; + blksize = 512; + goodbytes = 0; + goodneeded = 1024; + Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + txstate = HTX_START; + txoptions = HTXI_OPTIONS; + txstarttime.tv_sec = txstarttime.tv_usec = txendtime.tv_sec = txendtime.tv_usec = 0; + rxstarttime.tv_sec = rxstarttime.tv_usec = rxendtime.tv_sec = rxendtime.tv_usec = 0; + tz.tz_minuteswest = tz.tz_dsttime = 0; + rxstate = HRX_INIT; + rxoptions = HRXI_OPTIONS; + compstate = HCMP_NONE; - while ((txstate != HTX_DONE) && (txstate != HTX_Abort)) { - /* - * Is transmitter waiting for packet? - */ - txwaitpkt = ((txstate == HTX_SWAIT) || (txstate == HTX_INITACK) - || ((txstate == HTX_RINIT) && (rxstate == HRX_INIT)) - || (txstate == HTX_FINFOACK) || (txstate == HTX_DATA) - || (txstate == HTX_DATAACK) - || ((txstate == HTX_XWAIT) && (rxstate != HRX_DONE)) - || (txstate == HTX_EOFACK) || (txstate == HTX_ENDACK) - || (txstate == HTX_REND)); + while ((txstate != HTX_DONE) && (txstate != HTX_Abort)) { + /* + * Is transmitter waiting for packet? + */ + txwaitpkt = ((txstate == HTX_SWAIT) || (txstate == HTX_INITACK) + || ((txstate == HTX_RINIT) && (rxstate == HRX_INIT)) + || (txstate == HTX_FINFOACK) || (txstate == HTX_DATA) || (txstate == HTX_DATAACK) + || ((txstate == HTX_XWAIT) && (rxstate != HRX_DONE)) + || (txstate == HTX_EOFACK) || (txstate == HTX_ENDACK) || (txstate == HTX_REND)); - /* - * Is receiver waiting for packet? - */ - rxwaitpkt = ((rxstate == HRX_INIT) || (rxstate == HRX_FINFO) || - (rxstate == HRX_DATA) || (rxstate == HRX_DONE)); + /* + * Is receiver waiting for packet? + */ + rxwaitpkt = ((rxstate == HRX_INIT) || (rxstate == HRX_FINFO) || (rxstate == HRX_DATA) || (rxstate == HRX_DONE)); - /* - * Do we have to wait for a packet? - */ - if (txwaitpkt && rxwaitpkt) { - /* - * Don't wait for a packet if transmitter is in DATA state - */ - if ((txstate == HTX_DATA) || ((txstate == HTX_REND) && (rxstate == HRX_DONE))) { - if (txstate == HTX_DATA) { - waitputget = WAITPUTGET(-1); - if (waitputget & 1) { - pkttype = hyrxpkt(rxbuf, &rxlen, 0); - } else { - pkttype = H_NOPKT; - } - } else { - pkttype = hyrxpkt(rxbuf, &rxlen, 0); - } - } else { - pkttype = hyrxpkt(rxbuf, &rxlen, -1); - } - - if ((pkttype == H_CARRIER) || (EXPIRED(TIMERNO_BRAIN))) { - Syslog('h', "Hydra: BRAIN timer expired"); - txstate = HTX_Abort; - break; - } - } else { + /* + * Do we have to wait for a packet? + */ + if (txwaitpkt && rxwaitpkt) { + /* + * Don't wait for a packet if transmitter is in DATA state + */ + if ((txstate == HTX_DATA) || ((txstate == HTX_REND) && (rxstate == HRX_DONE))) { + if (txstate == HTX_DATA) { + waitputget = WAITPUTGET(-1); + if (waitputget & 1) { + pkttype = hyrxpkt(rxbuf, &rxlen, 0); + } else { pkttype = H_NOPKT; + } + } else { + pkttype = hyrxpkt(rxbuf, &rxlen, 0); } + } else { + pkttype = hyrxpkt(rxbuf, &rxlen, -1); + } - /* - * Special handling for RPOS packet - */ - if ((pkttype == HPKT_RPOS) && (rxlen == 12) + if ((pkttype == H_CARRIER) || (EXPIRED(TIMERNO_BRAIN))) { + Syslog('h', "Hydra: BRAIN timer expired"); + txstate = HTX_Abort; + break; + } + } else { + pkttype = H_NOPKT; + } + + /* + * Special handling for RPOS packet + */ + if ((pkttype == HPKT_RPOS) && (rxlen == 12) && ((txstate == HTX_DATA) || (txstate == HTX_DATAACK) || (txstate == HTX_XWAIT) || (txstate == HTX_EOFACK))) { - long rpos_pos = get_long(rxbuf); - long rpos_blksize = get_long(rxbuf + 4); - long rpos_id = get_long(rxbuf + 8); + long rpos_pos = get_long(rxbuf); + long rpos_blksize = get_long(rxbuf + 4); + long rpos_id = get_long(rxbuf + 8); - if (rpos_pos < 0) { - /* - * this differs from the protocol definition: txpos is used - * instead of rxpos (I think it's wrong in the protocol - * definition as in the example source also txpos is used) - */ - if ((rpos_pos == -2) && (txpos != -2) && (txstate == HTX_EOFACK)) { - txpos = -2; - txstate = HTX_EOF; - } else { - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - txstate = HTX_SkipFile; - } - } + if (rpos_pos < 0) { + /* + * this differs from the protocol definition: txpos is used + * instead of rxpos (I think it's wrong in the protocol + * definition as in the example source also txpos is used) + */ + if ((rpos_pos == -2) && (txpos != -2) && (txstate == HTX_EOFACK)) { + txpos = -2; + txstate = HTX_EOF; + } else { + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + txstate = HTX_SkipFile; + } + } - if (rpos_id == txsyncid) { - txretries++; + if (rpos_id == txsyncid) { + txretries++; - if (txretries >= 10) { - Syslog('+', "Hydra: too many errors"); - txstate = HTX_Abort; - break; - } - } else { - if (rpos_pos >= 0) { - txpos = rpos_pos; - txsyncid = rpos_id; - txretries = 1; - blksize = rpos_blksize; - goodbytes = 0; - goodneeded += 1024; - if (goodneeded > 8192) - goodneeded = 8192; + if (txretries >= 10) { + Syslog('+', "Hydra: too many errors"); + txstate = HTX_Abort; + break; + } + } else { + if (rpos_pos >= 0) { + txpos = rpos_pos; + txsyncid = rpos_id; + txretries = 1; + blksize = rpos_blksize; + goodbytes = 0; + goodneeded += 1024; + if (goodneeded > 8192) + goodneeded = 8192; - /* if we receive an RPOS packet in EOFACK-state we have to - change back to DATA-state */ - if (txstate == HTX_EOFACK) - txstate = HTX_DATA; + /* + * if we receive an RPOS packet in EOFACK-state we have to + * change back to DATA-state + */ + if (txstate == HTX_EOFACK) + txstate = HTX_DATA; - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - } - } + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + } + } - pkttype = H_NOPKT; /* packet has already been processed */ + pkttype = H_NOPKT; /* packet has already been processed */ + } + + + switch (txstate) { + /* + * initiate Hydra session + */ + case HTX_START: + Syslog('h', "SM 'HTX' entering 'START'"); + if (txretries < 10) { + PUT((char *)"hydra\r", 6); /* send AutoStart string */ + hytxpkt(HPKT_START, txbuf, 0); + Syslog('h', "Hydra: set TX timer %d", H_START); + SETTIMER(TIMERNO_TX, H_START); + txstate = HTX_SWAIT; + } else { + Syslog('+', "Hydra: transmitter start TIMEOUT"); + txstate = HTX_Abort; + break; + } + break; + + /* + * wait for START packet + */ + case HTX_SWAIT: + Syslog('h', "SM 'HTX' entering 'SWAIT'"); + if (((pkttype == HPKT_START) && (rxlen == 0)) || (pkttype == HPKT_INIT)) { + txretries = 0; + Syslog('h', "Hydra: reset TX timer"); + RESETTIMER(TIMERNO_TX); + Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + txstate = HTX_INIT; + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('+', "Hydra: transmitter timeout (HTX_SWAIT)"); + txretries++; + txstate = HTX_START; + } + break; + + /* + * send INIT packet + */ + case HTX_INIT: + Syslog('h', "SM 'HTX' entering 'INIT'"); + if (txretries < 10) { + outbuf = txbuf; + + /* Application ID string */ + outbuf += sprintf(outbuf, "%08lx%s,%s", H_REVSTAMP, "mbcico", VERSION) + 1; + + /* Supported options */ + outbuf += put_flags(outbuf, HCAN_OPTIONS) + 1; + Syslog('h', "Hydra: supported options: %08lx", HCAN_OPTIONS); + + /* Desired options */ + outbuf += put_flags(outbuf, HDEF_OPTIONS & HCAN_OPTIONS & ~HUNN_OPTIONS) + 1; + Syslog('h', "Hydra: desired options : %08lx", HDEF_OPTIONS & HCAN_OPTIONS & ~HUNN_OPTIONS); + + /* Desired transmitter and receiver window size */ + outbuf += sprintf(outbuf, "%08lx%08lx", H_TXWINDOW, H_RXWINDOW) + 1; + + /* Packet prefix string */ + *outbuf++ = 0; + + hytxpkt(HPKT_INIT, txbuf, outbuf - txbuf); + + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); + SETTIMER(TIMERNO_TX, H_MINTIMER/2); + txstate = HTX_INITACK; + } else { + Syslog('+', "Hydra: too many errors waiting for INITACK"); + txstate = HTX_Abort; + break; + } + break; + + /* + * wait for an INIT acknowledge packet + */ + case HTX_INITACK: + Syslog('h', "SM 'HTX' entering 'INITACK'"); + if ((pkttype == HPKT_INITACK) && (rxlen == 0)) { + txretries = 0; + Syslog('h', "Hydra: reset TX timer"); + RESETTIMER(TIMERNO_TX); + Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + txstate = HTX_RINIT; + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('+', "Hydra: tx timeout"); + txretries++; + txstate = HTX_INIT; + } + break; + + /* + * wait for receiver to leave INIT state + */ + case HTX_RINIT: + Syslog('h', "SM 'HTX' entering 'RINIT'"); + if (rxstate != HRX_INIT) + txstate = HTX_NextFile; + break; + + /* + * prepare next file for transmitting + */ + case HTX_NextFile: + Syslog('h', "SM 'HTX' entering 'NextFile'"); + /* + * skip file with NULL remote name + */ + while (to_send && (to_send->remote == NULL)) { + execute_disposition(to_send); + to_send = to_send->next; } + if (to_send) { + struct flock txflock; - switch (txstate) { - /* - * initiate Hydra session - */ - case HTX_START: - Syslog('h', "SM 'HTX' entering 'START'"); - if (txretries < 10) { - PUT((char *)"hydra\r", 6); /* send AutoStart string */ - hytxpkt(HPKT_START, txbuf, 0); - Syslog('h', "Hydra: set TX timer %d", H_START); - SETTIMER(TIMERNO_TX, H_START); - txstate = HTX_SWAIT; + if (to_send->remote == NULL) + break; + + txflock.l_type=F_RDLCK; + txflock.l_whence=0; + txflock.l_start=0L; + txflock.l_len=0L; + + txfp = fopen(to_send->local, "r"); + if (txfp == NULL) { + sverr = errno; + if ((sverr == ENOENT) || (sverr == EINVAL)) { + Syslog('+', "File %s doesn't exist, removing", MBSE_SS(to_send->local)); + execute_disposition(to_send); // Added 18-10-99 MB. } else { - Syslog('+', "Hydra: transmitter start TIMEOUT"); - txstate = HTX_Abort; - break; + WriteError("$Hydra: cannot open file %s, skipping", MBSE_SS(to_send->local)); } + to_send = to_send->next; break; + } - /* - * wait for START packet - */ - case HTX_SWAIT: - Syslog('h', "SM 'HTX' entering 'SWAIT'"); - if (((pkttype == HPKT_START) && (rxlen == 0)) || (pkttype == HPKT_INIT)) { - txretries = 0; - Syslog('h', "Hydra: reset TX timer"); - RESETTIMER(TIMERNO_TX); - Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - txstate = HTX_INIT; - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('+', "Hydra: transmitter timeout (HTX_SWAIT)"); - txretries++; - txstate = HTX_START; - } + if (fcntl(fileno(txfp), F_SETLK, &txflock) != 0) { + WriteError("$Hydra: cannot lock file %s, skipping", MBSE_SS(to_send->local)); + fclose(txfp); + to_send = to_send->next; break; + } - /* - * send INIT packet - */ - case HTX_INIT: - Syslog('h', "SM 'HTX' entering 'INIT'"); - if (txretries < 10) { - outbuf = txbuf; - - /* Application ID string */ - outbuf += sprintf(outbuf, "%08lx%s,%s", H_REVSTAMP, "mbcico", VERSION) + 1; - - /* Supported options */ - outbuf += put_flags(outbuf, HCAN_OPTIONS) + 1; - Syslog('h', "Hydra: supported options: %08lx", HCAN_OPTIONS); - - /* Desired options */ - outbuf += put_flags(outbuf, HDEF_OPTIONS & HCAN_OPTIONS & ~HUNN_OPTIONS) + 1; - Syslog('h', "Hydra: desired options : %08lx", HDEF_OPTIONS & HCAN_OPTIONS & ~HUNN_OPTIONS); - - /* Desired transmitter and receiver window size */ - outbuf += sprintf(outbuf, "%08lx%08lx", H_TXWINDOW, H_RXWINDOW) + 1; - - /* Packet prefix string */ - *outbuf++ = 0; - - hytxpkt(HPKT_INIT, txbuf, outbuf - txbuf); - - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); - SETTIMER(TIMERNO_TX, H_MINTIMER/2); - txstate = HTX_INITACK; - } else { - Syslog('+', "Hydra: too many errors waiting for INITACK"); - txstate = HTX_Abort; - break; - } + if (stat(to_send->local, &txstat) != 0) { + WriteError("$Hydra: cannot access \"%s\", skipping",MBSE_SS(to_send->local)); + fclose(txfp); + to_send = to_send->next; break; + } - /* - * wait for an INIT acknowledge packet - */ - case HTX_INITACK: - Syslog('h', "SM 'HTX' entering 'INITACK'"); - if ((pkttype == HPKT_INITACK) && (rxlen == 0)) { - txretries = 0; - Syslog('h', "Hydra: reset TX timer"); - RESETTIMER(TIMERNO_TX); - Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - txstate = HTX_RINIT; + Syslog('+', "Hydra: send \"%s\" as \"%s\"", MBSE_SS(to_send->local), MBSE_SS(to_send->remote)); + Syslog('+', "Hydra: size %lu bytes, dated %s",(unsigned long)txstat.st_size, date(txstat.st_mtime)); + gettimeofday(&txstarttime, &tz); + } - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('+', "Hydra: tx timeout"); - txretries++; - txstate = HTX_INIT; - } - break; + txstate = HTX_ToFName; + break; /* TODO: fallthrough */ - /* - * wait for receiver to leave INIT state - */ - case HTX_RINIT: - Syslog('h', "SM 'HTX' entering 'RINIT'"); - if (rxstate != HRX_INIT) - txstate = HTX_NextFile; - break; + case HTX_ToFName: + Syslog('h', "SM 'HTX' entering 'ToFName'"); + txsyncid = 0; + txretries = 0; + Syslog('h', "Hydra: reset TX timer"); + RESETTIMER(TIMERNO_TX); + txstate = HTX_FINFO; + break; /* TODO: fallthrough */ + + /* + * transmit File Information packet + */ + case HTX_FINFO: + Syslog('h', "SM 'HTX' entering 'FINFO'"); + if (txretries >= 10) { + txstate = HTX_Abort; + break; + } else { + if (to_send) { + txlen = sprintf(txbuf, "%08lx%08lx%08lx%08lx%08lx", + mtime2sl(txstat.st_mtime+(txstat.st_mtime%2)), + (long)(txstat.st_size), 0UL, 0UL, 0UL); - /* - * prepare next file for transmitting - */ - case HTX_NextFile: - Syslog('h', "SM 'HTX' entering 'NextFile'"); /* - * skip file with NULL remote name + * convert file name to DOS-format */ - while (to_send && (to_send->remote == NULL)) { - execute_disposition(to_send); - to_send = to_send->next; + outbuf = xstrcpy(to_send->remote); + name_mangle(outbuf); + strcpy(txbuf + txlen, outbuf); + free(outbuf); + for(; txbuf[txlen]; txlen++) { + txbuf[txlen] = tolower(txbuf[txlen]); } + txlen++; - if (to_send) { - struct flock txflock; + strcpy(txbuf + txlen, to_send->remote); + txlen += strlen(to_send->remote) + 1; + } else { + txbuf[0] = 0; + txlen = 1; + } - if (to_send->remote == NULL) - break; + hytxpkt(HPKT_FINFO, txbuf, txlen); - txflock.l_type=F_RDLCK; - txflock.l_whence=0; - txflock.l_start=0L; - txflock.l_len=0L; + if (txretries > 0) { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); + SETTIMER(TIMERNO_TX, H_MINTIMER/2); + } else { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); + SETTIMER(TIMERNO_TX, H_MINTIMER); + } - txfp = fopen(to_send->local, "r"); - if (txfp == NULL) { - sverr = errno; - if ((sverr == ENOENT) || (sverr == EINVAL)) { - Syslog('+', "File %s doesn't exist, removing", MBSE_SS(to_send->local)); - execute_disposition(to_send); // Added 18-10-99 MB. - } else { - WriteError("$Hydra: cannot open file %s, skipping", MBSE_SS(to_send->local)); - } - to_send = to_send->next; - break; - } + txstate = HTX_FINFOACK; + } + break; - if (fcntl(fileno(txfp), F_SETLK, &txflock) != 0) { - WriteError("$Hydra: cannot lock file %s, skipping", MBSE_SS(to_send->local)); - fclose(txfp); - to_send = to_send->next; - break; - } + /* + * get FINFOACK packet + */ + case HTX_FINFOACK: + Syslog('h', "SM 'HTX' entering 'FINFOACK'"); + if ((pkttype == HPKT_FINFOACK) && (rxlen == 4)) { + txpos = get_long(rxbuf); + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - if (stat(to_send->local, &txstat) != 0) { - WriteError("$Hydra: cannot access \"%s\", skipping",MBSE_SS(to_send->local)); - fclose(txfp); - to_send = to_send->next; - break; - } + if (to_send == NULL) { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); + SETTIMER(TIMERNO_TX, H_MINTIMER); + txstate = HTX_REND; + } else if (txpos >= 0L) { + if (txpos > 0L) + Syslog('+', "Hydra: restart from %lu", txpos); + stxpos = txpos; + txretries = 0; + txlastack = 0; + Syslog('h', "Hydra: reset TX timer"); + RESETTIMER(TIMERNO_TX); + txstate = HTX_DATA; + } else if (txpos == -1) { + Syslog('+', "Hydra: Receiver already has this file, skipping"); + fclose(txfp); + execute_disposition(to_send); + to_send = to_send->next; + txstate = HTX_NextFile; + } else if (txpos == -2) { + Syslog('+', "Hydra: receiver requested to skip this file for now"); + fclose(txfp); + to_send = to_send->next; + txstate = HTX_NextFile; + } - Syslog('+', "Hydra: send \"%s\" as \"%s\"", MBSE_SS(to_send->local), MBSE_SS(to_send->remote)); - Syslog('+', "Hydra: size %lu bytes, dated %s",(unsigned long)txstat.st_size, date(txstat.st_mtime)); - gettimeofday(&txstarttime, &tz); + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('+', "Hydra: transmitter timeout (HTX_FINFOACK)"); + txretries++; + txstate = HTX_FINFO; + } + break; + + case HTX_DATA: + Syslog('h', "SM 'HTX' entering 'DATA'"); + Syslog('h', "txwindow=%d txpos=%d txlastack=%d", txwindow, txpos, txlastack); + if ((rxstate != HRX_DONE) && (hdxlink)) { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); + SETTIMER(TIMERNO_TX, H_MINTIMER); + txstate = HTX_XWAIT; + } else if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { + longnum = get_long(rxbuf); + + Syslog('h', "received 'DATAACK' (0x%08lx)", longnum); + + if (longnum > txlastack) { + txlastack = longnum; + } + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if ((txwindow) && (txpos >= txlastack + txwindow)) { + /* + * We have to wait for an ACK before we can continue + */ + if (txretries > 0) { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); + SETTIMER(TIMERNO_TX, H_MINTIMER/2); + } else { + Syslog('H', "HYDRA: SET TX TIMER %D", H_MINTIMER); + SETTIMER(TIMERNO_TX, H_MINTIMER); + } + txstate = HTX_DATAACK; + break; + } else { + /* + * check if there is enough room in output + */ + if ((waitputget & 2) == 0) { + break; + } + + fseek(txfp, txpos, SEEK_SET); + put_long(txbuf, txpos); + Nopper(); + Syslog('h', "Check for more frames here?"); + txlen = fread(txbuf + 4, 1, blksize, txfp); + Syslog('h', "Hydra: send DATA (0x%08lx) %lu", txpos, txlen); + + if (txlen == 0) { + if (ferror(txfp)) { + WriteError("$Hydra: error reading from file"); + txstate = HTX_SkipFile; + } else { + txstate = HTX_EOF; } + } else { + // FIXME: Here we must add the compression code + txpos += txlen; + sentbytes += txlen; + goodbytes += txlen; + txlen += 4; + hytxpkt(HPKT_DATA, txbuf, txlen); - txstate = HTX_ToFName; - break; /* TODO: fallthrough */ + if (goodbytes > goodneeded) { + blksize *= 2; + if (blksize > H_MAXBLKLEN) { + blksize = H_MAXBLKLEN; + } + } + } + } + break; - case HTX_ToFName: - Syslog('h', "SM 'HTX' entering 'ToFName'"); - txsyncid = 0; + case HTX_SkipFile: + Syslog('h', "SM 'HTX' entering 'SkipFile'"); + /* + * this differs from the protocol definition: -2 is used + * instead of -1 (I think it's wrong in the protocol + * definition as in the example source also -2 is used) + * MB: No, I don't think this is wrong, -1 means file already + * there, -2 means skip for now, try another time. + */ + txpos = -2; + txretries = 0; + txstate = HTX_EOF; + break; + + case HTX_DATAACK: + Syslog('h', "SM 'HTX' entering 'DATAACK'"); + if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { + longnum = get_long(rxbuf); + + if ((longnum > txlastack) && (txpos < longnum + txwindow)) { + txlastack = longnum; txretries = 0; Syslog('h', "Hydra: reset TX timer"); RESETTIMER(TIMERNO_TX); - txstate = HTX_FINFO; - break; /* TODO: fallthrough */ + txstate = HTX_DATA; + } - /* - * transmit File Information packet - */ - case HTX_FINFO: - Syslog('h', "SM 'HTX' entering 'FINFO'"); - if (txretries >= 10) { - txstate = HTX_Abort; - break; - } else { - if (to_send) { - txlen = sprintf(txbuf, "%08lx%08lx%08lx%08lx%08lx", - mtime2sl(txstat.st_mtime+(txstat.st_mtime%2)), - (long)(txstat.st_size), 0UL, 0UL, 0UL); + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (txretries >= 10) { + Syslog('+', "Hydra: too many errors"); + txstate = HTX_Abort; + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('+', "Hydra: tx timeout"); + txretries++; + txstate = HTX_DATA; + } + break; - /* - * convert file name to DOS-format - */ - outbuf = xstrcpy(to_send->remote); - name_mangle(outbuf); - strcpy(txbuf + txlen, outbuf); - free(outbuf); - for(; txbuf[txlen]; txlen++) { - txbuf[txlen] = tolower(txbuf[txlen]); - } - txlen++; + case HTX_XWAIT: + Syslog('h', "SM 'HTX' entering 'XWAIT'"); + if (rxstate == HRX_DONE) { + Syslog('h', "Hydra: reset RX timer"); + RESETTIMER(TIMERNO_RX); + txstate = HTX_DATA; + } else if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { + longnum = get_long(rxbuf); + if (longnum > txlastack) { + txlastack = longnum; + } + pkttype = H_NOPKT; /* packet has already been processed */ - strcpy(txbuf + txlen, to_send->remote); - txlen += strlen(to_send->remote) + 1; - } else { - txbuf[0] = 0; - txlen = 1; - } + } else if (pkttype == HPKT_RPOS) { + /* + * Handle RPOS in state DATA but stay in this state + */ + pkttype = H_NOPKT; /* packet has already been processed */ - hytxpkt(HPKT_FINFO, txbuf, txlen); + } else if ((pkttype == HPKT_IDLE) && (rxlen == 0)) { + hdxlink = FALSE; + Syslog('h', "Hydra: reset TX timer"); + RESETTIMER(TIMERNO_TX); + txstate = HTX_DATA; + pkttype = H_NOPKT; /* packet has already been processed */ - if (txretries > 0) { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); - SETTIMER(TIMERNO_TX, H_MINTIMER/2); - } else { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); - SETTIMER(TIMERNO_TX, H_MINTIMER); - } + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('h', "Hydra: TX timer expired"); + hytxpkt(HPKT_IDLE, txbuf, 0); + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); + SETTIMER(TIMERNO_TX, H_MINTIMER); + } + break; - txstate = HTX_FINFOACK; - } - break; + case HTX_EOF: + Syslog('h', "SM 'HTX' entering 'EOF'"); + if (txretries >= 10) { + txstate = HTX_Abort; + break; + } else { + put_long(txbuf, txpos); + hytxpkt(HPKT_EOF, txbuf, 4); - /* - * get FINFOACK packet - */ - case HTX_FINFOACK: - Syslog('h', "SM 'HTX' entering 'FINFOACK'"); - if ((pkttype == HPKT_FINFOACK) && (rxlen == 4)) { - txpos = get_long(rxbuf); - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + if (txretries > 0) { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); + SETTIMER(TIMERNO_TX, H_MINTIMER/2); + } else { + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); + SETTIMER(TIMERNO_TX, H_MINTIMER); + } + Syslog('h', "Hydra: entering TX EOFACK"); + txstate = HTX_EOFACK; + } + break; - if (to_send == NULL) { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); - SETTIMER(TIMERNO_TX, H_MINTIMER); - txstate = HTX_REND; - } else if (txpos >= 0L) { - if (txpos > 0L) - Syslog('+', "Hydra: restart from %lu", txpos); - stxpos = txpos; - txretries = 0; - txlastack = 0; - Syslog('h', "Hydra: reset TX timer"); - RESETTIMER(TIMERNO_TX); - txstate = HTX_DATA; - } else if (txpos == -1) { - Syslog('+', "Hydra: Receiver already has this file, skipping"); - fclose(txfp); - execute_disposition(to_send); - to_send = to_send->next; - txstate = HTX_NextFile; - } else if (txpos == -2) { - Syslog('+', "Hydra: receiver requested to skip this file for now"); - fclose(txfp); - to_send = to_send->next; - txstate = HTX_NextFile; - } + case HTX_EOFACK: + Syslog('h', "SM 'HTX' entering 'EOFACK'"); + if ((pkttype == HPKT_EOFACK) && (rxlen == 0)) { + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('+', "Hydra: transmitter timeout (HTX_FINFOACK)"); - txretries++; - txstate = HTX_FINFO; - } - break; + /* + * calculate time needed and bytes transferred + */ + gettimeofday(&txendtime, &tz); - case HTX_DATA: - Syslog('h', "SM 'HTX' entering 'DATA'"); - Syslog('h', "txwindow=%d txpos=%d txlastack=%d", txwindow, txpos, txlastack); - if ((rxstate != HRX_DONE) && (hdxlink)) { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); - SETTIMER(TIMERNO_TX, H_MINTIMER); - txstate = HTX_XWAIT; - } else if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { - longnum = get_long(rxbuf); + /* close transmitter file */ + fclose(txfp); - Syslog('h', "received 'DATAACK' (0x%08lx)", longnum); + if (txpos >= 0) { + stxpos = txpos - stxpos; + Syslog('+', "Hydra: OK %s", transfertime(txstarttime, txendtime, stxpos, TRUE)); + execute_disposition(to_send); + } else { + Syslog('+', "Hydra: transmitter skipped file after %ld seconds", + txendtime.tv_sec - txstarttime.tv_sec); + } - if (longnum > txlastack) { - txlastack = longnum; - } + to_send = to_send->next; + txstate = HTX_NextFile; - pkttype = H_NOPKT; /* packet has already been processed */ - } else if ((txwindow) && (txpos >= txlastack + txwindow)) { - /* - * We have to wait for an ACK before we can continue - */ - if (txretries > 0) { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); - SETTIMER(TIMERNO_TX, H_MINTIMER/2); - } else { - Syslog('H', "HYDRA: SET TX TIMER %D", H_MINTIMER); - SETTIMER(TIMERNO_TX, H_MINTIMER); - } - txstate = HTX_DATAACK; - break; - } else { - /* - * check if there is enough room in output - */ - if ((waitputget & 2) == 0) { - break; - } + pkttype = H_NOPKT; /* packet has already been processed */ + } else if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { + longnum = get_long(rxbuf); + txlastack = longnum; - fseek(txfp, txpos, SEEK_SET); - put_long(txbuf, txpos); - Nopper(); - Syslog('h', "Check for more frames here?"); - txlen = fread(txbuf + 4, 1, blksize, txfp); - Syslog('h', "Hydra: send DATA (0x%08lx) %lu", txpos, txlen); + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('+', "Hydra: transmitter timeout (HTX_EOFACK)"); + txretries++; + txstate = HTX_EOF; + } + break; - if (txlen == 0) { - if (ferror(txfp)) { - WriteError("$Hydra: error reading from file"); - txstate = HTX_SkipFile; - } else { - txstate = HTX_EOF; - } - } else { - txpos += txlen; - sentbytes += txlen; - goodbytes += txlen; - txlen += 4; - hytxpkt(HPKT_DATA, txbuf, txlen); + case HTX_REND: + Syslog('h', "SM 'HTX' entering 'REND'"); + if (rxstate == HRX_DONE) { + txretries = 0; + txstate = HTX_END; + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('h', "Hydra: TX timer expired"); + hytxpkt(HPKT_IDLE, txbuf, 0); + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); + SETTIMER(TIMERNO_TX, H_MINTIMER/2); + } + break; - if (goodbytes > goodneeded) { - blksize *= 2; - if (blksize > H_MAXBLKLEN) { - blksize = H_MAXBLKLEN; - } - } - } - } - break; + case HTX_END: + Syslog('h', "SM 'HTX' entering 'END'"); + if (txretries >= 10) { + txstate = HTX_Abort; + break; + } else { + hytxpkt(HPKT_END, txbuf, 0); + hytxpkt(HPKT_END, txbuf, 0); + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); + SETTIMER(TIMERNO_TX, H_MINTIMER/2); + txstate = HTX_ENDACK; + } + break; - case HTX_SkipFile: - Syslog('h', "SM 'HTX' entering 'SkipFile'"); - /* - * this differs from the protocol definition: -2 is used - * instead of -1 (I think it's wrong in the protocol - * definition as in the example source also -2 is used) - * MB: No, I don't think this is wrong, -1 means file already - * there, -2 means skip for now, try another time. - */ - txpos = -2; - txretries = 0; - txstate = HTX_EOF; - break; + case HTX_ENDACK: + Syslog('h', "SM 'HTX' entering 'ENDACK'"); + if ((pkttype == HPKT_END) && (rxlen == 0)) { + hytxpkt(HPKT_END, txbuf, 0); + hytxpkt(HPKT_END, txbuf, 0); + hytxpkt(HPKT_END, txbuf, 0); + txstate = HTX_DONE; - case HTX_DATAACK: - Syslog('h', "SM 'HTX' entering 'DATAACK'"); - if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { - longnum = get_long(rxbuf); + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (EXPIRED(TIMERNO_TX)) { + Syslog('+', "Hydra: transmitter timeout (HTX_ENDACK)"); + txretries++; + txstate = HTX_END; + } + break; - if ((longnum > txlastack) && (txpos < longnum + txwindow)) { - txlastack = longnum; - txretries = 0; - Syslog('h', "Hydra: reset TX timer"); - RESETTIMER(TIMERNO_TX); - txstate = HTX_DATA; - } + case HTX_DONE: + case HTX_Abort: + /* nothing to do */ + break; - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (txretries >= 10) { - Syslog('+', "Hydra: too many errors"); - txstate = HTX_Abort; - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('+', "Hydra: tx timeout"); - txretries++; - txstate = HTX_DATA; - } - break; + default: + die(MBERR_FTRANSFER); + } /* switch (txstate) */ - case HTX_XWAIT: - Syslog('h', "SM 'HTX' entering 'XWAIT'"); - if (rxstate == HRX_DONE) { - Syslog('h', "Hydra: reset RX timer"); - RESETTIMER(TIMERNO_RX); - txstate = HTX_DATA; - } else if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { - longnum = get_long(rxbuf); - if (longnum > txlastack) { - txlastack = longnum; - } - pkttype = H_NOPKT; /* packet has already been processed */ + switch (rxstate) { + case HRX_INIT: + Syslog('h', "SM 'HRX' entering 'INIT'"); + if (pkttype == HPKT_INIT) { + /* TODO: some checking, error handling */ - } else if (pkttype == HPKT_RPOS) { - /* - * Handle RPOS in state DATA but stay in this state - */ - pkttype = H_NOPKT; /* packet has already been processed */ + /* Skip application ID */ + Syslog('+', "Hydra: remote \"%s\"", rxbuf+8); + inbuf = rxbuf + strlen(rxbuf) + 1; +// Syslog('+', "Hydra: inbuf=\"%s\"", inbuf); - } else if ((pkttype == HPKT_IDLE) && (rxlen == 0)) { - hdxlink = FALSE; - Syslog('h', "Hydra: reset TX timer"); - RESETTIMER(TIMERNO_TX); - txstate = HTX_DATA; - pkttype = H_NOPKT; /* packet has already been processed */ - - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('h', "Hydra: TX timer expired"); - hytxpkt(HPKT_IDLE, txbuf, 0); - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); - SETTIMER(TIMERNO_TX, H_MINTIMER); - } - break; - - case HTX_EOF: - Syslog('h', "SM 'HTX' entering 'EOF'"); - if (txretries >= 10) { - txstate = HTX_Abort; - break; - } else { - put_long(txbuf, txpos); - hytxpkt(HPKT_EOF, txbuf, 4); - - if (txretries > 0) { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); - SETTIMER(TIMERNO_TX, H_MINTIMER/2); - } else { - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); - SETTIMER(TIMERNO_TX, H_MINTIMER); - } - Syslog('h', "Hydra: entering TX EOFACK"); - txstate = HTX_EOFACK; - } - break; - - case HTX_EOFACK: - Syslog('h', "SM 'HTX' entering 'EOFACK'"); - if ((pkttype == HPKT_EOFACK) && (rxlen == 0)) { - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - - /* - * calculate time needed and bytes transferred - */ - gettimeofday(&txendtime, &tz); - - /* close transmitter file */ - fclose(txfp); - - if (txpos >= 0) { - stxpos = txpos - stxpos; - Syslog('+', "Hydra: OK %s", transfertime(txstarttime, txendtime, stxpos, TRUE)); - execute_disposition(to_send); - } else { - Syslog('+', "Hydra: transmitter skipped file after %ld seconds", - txendtime.tv_sec - txstarttime.tv_sec); - } - - to_send = to_send->next; - txstate = HTX_NextFile; - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if ((pkttype == HPKT_DATAACK) && (rxlen == 4)) { - longnum = get_long(rxbuf); - txlastack = longnum; - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('+', "Hydra: transmitter timeout (HTX_EOFACK)"); - txretries++; - txstate = HTX_EOF; - } - break; - - case HTX_REND: - Syslog('h', "SM 'HTX' entering 'REND'"); - if (rxstate == HRX_DONE) { - txretries = 0; - txstate = HTX_END; - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('h', "Hydra: TX timer expired"); - hytxpkt(HPKT_IDLE, txbuf, 0); - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); - SETTIMER(TIMERNO_TX, H_MINTIMER/2); - } - break; - - case HTX_END: - Syslog('h', "SM 'HTX' entering 'END'"); - if (txretries >= 10) { - txstate = HTX_Abort; - break; - } else { - hytxpkt(HPKT_END, txbuf, 0); - hytxpkt(HPKT_END, txbuf, 0); - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER/2); - SETTIMER(TIMERNO_TX, H_MINTIMER/2); - txstate = HTX_ENDACK; - } - break; - - case HTX_ENDACK: - Syslog('h', "SM 'HTX' entering 'ENDACK'"); - if ((pkttype == HPKT_END) && (rxlen == 0)) { - hytxpkt(HPKT_END, txbuf, 0); - hytxpkt(HPKT_END, txbuf, 0); - hytxpkt(HPKT_END, txbuf, 0); - txstate = HTX_DONE; - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (EXPIRED(TIMERNO_TX)) { - Syslog('+', "Hydra: transmitter timeout (HTX_ENDACK)"); - txretries++; - txstate = HTX_END; - } - break; - - case HTX_DONE: - case HTX_Abort: - /* nothing to do */ - break; - - default: - die(MBERR_FTRANSFER); - } /* switch (txstate) */ - - switch (rxstate) { - case HRX_INIT: - Syslog('h', "SM 'HRX' entering 'INIT'"); - if (pkttype == HPKT_INIT) { - /* TODO: some checking, error handling */ - - /* Skip application ID */ - Syslog('+', "Hydra: remote \"%s\"", rxbuf+8); - inbuf = rxbuf + strlen(rxbuf) + 1; -// Syslog('+', "Hydra: inbuf=\"%s\"", inbuf); - - inbuf += strlen(inbuf) + 1; + inbuf += strlen(inbuf) + 1; - rxoptions = (HDEF_OPTIONS & HCAN_OPTIONS) | HUNN_OPTIONS; + rxoptions = (HDEF_OPTIONS & HCAN_OPTIONS) | HUNN_OPTIONS; - /* - * get supported options - */ - rxoptions |= get_flags(inbuf); - inbuf += strlen(inbuf) + 1; + /* + * get supported options + */ + rxoptions |= get_flags(inbuf); + inbuf += strlen(inbuf) + 1; - /* - * get desired options - */ - rxoptions &= get_flags(rxbuf + strlen(rxbuf) + 1); - rxoptions &= HCAN_OPTIONS; + /* + * get desired options + */ + rxoptions &= get_flags(rxbuf + strlen(rxbuf) + 1); + rxoptions &= HCAN_OPTIONS; - /* - * set options - */ - txoptions = rxoptions; - put_flags(txbuf, rxoptions); - Syslog('h', "Hydra: options: %s (%08lx)", txbuf, rxoptions); + /* + * set options + */ + txoptions = rxoptions; + put_flags(txbuf, rxoptions); + Syslog('h', "Hydra: options: %s (%08lx)", txbuf, rxoptions); - /* - * get desired window sizes - */ - txwindow = rxwindow = 0; - sscanf(inbuf, "%08lx%08lx", &rxwindow, &txwindow); + /* + * get desired window sizes + */ + txwindow = rxwindow = 0; + sscanf(inbuf, "%08lx%08lx", &rxwindow, &txwindow); - if (rxwindow < 0) - rxwindow = 0; + if (rxwindow < 0) + rxwindow = 0; - if (H_RXWINDOW && ((rxwindow == 0) || (rxwindow > H_RXWINDOW))) - rxwindow = H_RXWINDOW; + if (H_RXWINDOW && ((rxwindow == 0) || (rxwindow > H_RXWINDOW))) + rxwindow = H_RXWINDOW; - if (txwindow < 0) - txwindow = 0; + if (txwindow < 0) + txwindow = 0; - if (H_TXWINDOW && ((txwindow == 0) || (txwindow > H_TXWINDOW))) - txwindow = H_TXWINDOW; + if (H_TXWINDOW && ((txwindow == 0) || (txwindow > H_TXWINDOW))) + txwindow = H_TXWINDOW; - Syslog('h', "Hydra: txwindow=%d, rxwindow=%d", txwindow, rxwindow); + Syslog('h', "Hydra: txwindow=%d, rxwindow=%d", txwindow, rxwindow); - hytxpkt(HPKT_INITACK, txbuf, 0); - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - rxstate = HRX_FINFO; + hytxpkt(HPKT_INITACK, txbuf, 0); + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + rxstate = HRX_FINFO; - pkttype = H_NOPKT; /* packet has already been processed */ - } - break; + pkttype = H_NOPKT; /* packet has already been processed */ + } + break; - case HRX_FINFO: - Syslog('h', "SM 'HRX' entering 'FINFO'"); - if (pkttype == HPKT_FINFO) { - /* - * check if we have received an `End of batch' FINFO packet - */ - if ((rxlen == 1) && (rxbuf[0] == 0)) { - put_long(txbuf, 0); - hytxpkt(HPKT_FINFOACK, txbuf, 4); + case HRX_FINFO: + Syslog('h', "SM 'HRX' entering 'FINFO'"); + if (pkttype == HPKT_FINFO) { + /* + * check if we have received an `End of batch' FINFO packet + */ + if ((rxlen == 1) && (rxbuf[0] == 0)) { + put_long(txbuf, 0); + hytxpkt(HPKT_FINFOACK, txbuf, 4); - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - rxstate = HRX_DONE; - } - /* - * check if FINFO packet is at least long enough to contain - * file information - */ - else if ((rxlen > 41) && (rxbuf[rxlen - 1] == 0)) { - time_t timestamp; - time_t orgstamp; - long filesize; - char dosname[8 + 1 + 3 + 1], *Name; + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + rxstate = HRX_DONE; + } + /* + * check if FINFO packet is at least long enough to contain + * file information + */ + else if ((rxlen > 41) && (rxbuf[rxlen - 1] == 0)) { + time_t timestamp; + time_t orgstamp; + long filesize; + char dosname[8 + 1 + 3 + 1], *Name; - sscanf(rxbuf, "%08lx%08lx%*08x%*08x%*08x", ×tamp, &filesize); + sscanf(rxbuf, "%08lx%08lx%*08x%*08x%*08x", ×tamp, &filesize); - /* convert timestamp to UNIX time */ - orgstamp = timestamp; - timestamp = sl2mtime(timestamp); + /* convert timestamp to UNIX time */ + orgstamp = timestamp; + timestamp = sl2mtime(timestamp); - /* - * check if DOS conforming file name is max. 8+1+3 chars long - */ - if (strlen(rxbuf + 40) <= 12) { - strcpy(dosname, rxbuf + 40); - } else { - strcpy(dosname, "BadWazoo"); - } + /* + * check if DOS conforming file name is max. 8+1+3 chars long + */ + if (strlen(rxbuf + 40) <= 12) { + strcpy(dosname, rxbuf + 40); + } else { + strcpy(dosname, "BadWazoo"); + } - /* - * check if real file name is specified - */ - if ((strlen(rxbuf + 40) + 41) < rxlen) { - Name = rxbuf + strlen(rxbuf + 40) + 41; + /* + * check if real file name is specified + */ + if ((strlen(rxbuf + 40) + 41) < rxlen) { + Name = rxbuf + strlen(rxbuf + 40) + 41; - /* - * use DOS-filename if real- and DOS-name only - * differ in case sensitivity - */ - if (strcasecmp(Name, dosname) == 0) { - Name = dosname; - } - } else { - Name = dosname; - } + /* + * use DOS-filename if real- and DOS-name only + * differ in case sensitivity + */ + if (strcasecmp(Name, dosname) == 0) { + Name = dosname; + } + } else { + Name = dosname; + } - Syslog('+', "Hydra: receive \"%s\" (%ld bytes) dated %s", + Syslog('+', "Hydra: receive \"%s\" (%ld bytes) dated %s", Name, filesize, date(timestamp)); - rxfp = openfile(Name, timestamp, filesize, &rxpos, resync); - gettimeofday(&rxstarttime, &tz); + rxfp = openfile(Name, timestamp, filesize, &rxpos, resync); + gettimeofday(&rxstarttime, &tz); - /* check for error opening file */ - if (rxfp) { - srxpos = rxpos; - rxstate = HRX_ToData; - } else { - if (filesize == rxpos) { - /* Skip this file, it's already here */ - Syslog('+', "Hydra: Skipping file %s", Name); - put_long(txbuf, -1); - } else { - /* Skip this file for now if error opening file */ - put_long(txbuf, -2); - } - hytxpkt(HPKT_FINFOACK, txbuf, 4); - - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - } - } - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (pkttype == HPKT_INIT) { - hytxpkt(HPKT_INITACK, txbuf, 0); - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if ((pkttype == HPKT_EOF) && (rxlen == 4)) { - hytxpkt(HPKT_EOFACK, txbuf, 0); - - pkttype = H_NOPKT; /* packet has already been processed */ - } - break; - - case HRX_ToData: - Syslog('h', "SM 'HRX' entering 'ToData'"); - put_long(txbuf, rxpos); - hytxpkt(HPKT_FINFOACK, txbuf, 4); - - rxsyncid = 0; - rxlastsync = 0; - rxretries = 0; - Syslog('h', "Hydra: reset RX timer"); - RESETTIMER(TIMERNO_RX); - Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - rxstate = HRX_DATA; - break; - - case HRX_DATA: - Syslog('h', "SM 'HRX' entering 'DATA'"); - if ((pkttype == HPKT_DATA) && (rxlen > 4)) { - longnum = get_long(rxbuf); - Syslog('h', "Hydra: rcvd DATA (0x%08lx, 0x%08lx) %lu", longnum, rxpos, rxlen-4); - Nopper(); - - if (longnum == rxpos) { - if (fwrite(rxbuf + 4, 1, rxlen - 4, rxfp) != (rxlen - 4)) { - WriteError("$Hydra: error writing to file"); - rxpos = -2; - } else { - rxlastdatalen = rxlen - 4; - rxpos += rxlen - 4; - rcvdbytes += rxlen - 4; - rxretries = 0; - rxlastsync = rxpos; - Syslog('h', "Hydra: reset RX timer"); - RESETTIMER(TIMERNO_RX); - Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - if (rxwindow) { - put_long(txbuf, rxpos); - hytxpkt(HPKT_DATAACK, txbuf, 4); - } - } - } else { - if (rxpos >= 0) { - Syslog('+', "Hydra: received bad rxpos"); - } - rxstate = HRX_BadPos; - } - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if ((pkttype == HPKT_EOF) && (rxlen == 4)) { - longnum = get_long(rxbuf); - - if (longnum == rxpos) { - /* - * calculate time and CPU usage needed - */ - gettimeofday(&rxendtime, &tz); - - if (rxpos >= 0) { - rxfp = NULL; - if (!closefile()) { - srxpos = rxpos - srxpos; - - Syslog('+', "Hydra: OK %s", - transfertime(rxstarttime, rxendtime, srxpos, FALSE)); - - rxstate = HRX_OkEOF; - } else { - Syslog('+', "Hydra: error closing file"); - rxpos = -2; - - /* - * Note: the following state change isn't 100 % - * conformant with the Hydra protocol specification. - */ - rxstate = HRX_BadPos; - } - } else { - Syslog('+', "Hydra: receiver skipped file after %ld seconds", - rxendtime.tv_sec - rxstarttime.tv_sec); - - if (rxfp) { - closefile(); - rxfp = NULL; - } - - rxstate = HRX_OkEOF; - } - } else if (longnum == -2) { - if (rxfp) { - closefile(); - rxfp = NULL; - } - - rxstate = HRX_OkEOF; - } else { - if (longnum >= 0) { - Syslog('+', "Hydra: received bad rxpos"); - } - rxstate = HRX_BadPos; /* TODO: fallthrough */ - } - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (pkttype == HPKT_FINFO) { - put_long(txbuf, rxpos); - hytxpkt(HPKT_FINFOACK, txbuf, 4); - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if ((pkttype == HPKT_IDLE) && (rxlen == 0) && (hdxlink == FALSE)) { - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if (EXPIRED(TIMERNO_RX)) { - Syslog('h', "Hydra: RX timer expired"); - rxstate = HRX_HdxLink; - } - break; - - case HRX_BadPos: - Syslog('h', "SM 'HRX' entering 'BadPos'"); - longnum = get_long(rxbuf); - - if (longnum <= rxlastsync) { - rxretries = 0; - Syslog('h', "Hydra: reset RX timer"); - RESETTIMER(TIMERNO_RX); - } - rxlastsync = longnum; - rxstate = HRX_Timer; - break; - - case HRX_Timer: - Syslog('h', "SM 'HRX' entering 'Timer'"); - if ((!RUNNING(TIMERNO_RX)) || (EXPIRED(TIMERNO_RX))) { - Syslog('h', "Hydra: RX timer expired"); - rxstate = HRX_HdxLink; + /* check for error opening file */ + if (rxfp) { + srxpos = rxpos; + rxstate = HRX_ToData; } else { - rxstate = HRX_DATA; - } - break; - - case HRX_HdxLink: - Syslog('h', "SM 'HRX' entering 'HdxLink'"); - if ((rxretries > 4) && (txstate != HTX_REND) && (role == 0) && (hdxlink == FALSE)) { - rxretries = 0; - hdxlink = TRUE; - } - rxstate = HRX_Retries; - break; /* TODO: fallthrough */ - - case HRX_Retries: - Syslog('h', "SM 'HRX' entering 'Retries'"); - rxretries++; - if (rxretries >= 10) { - Syslog('+', "Hydra: too many errors"); - txstate = HTX_Abort; - } else if (rxretries == 1) { - rxsyncid++; - } - rxstate = HRX_RPos; - break; /* TODO: fallthrough */ - - case HRX_RPos: - Syslog('h', "SM 'HRX' entering 'RPos'"); - rxlastdatalen /= 2; - if (rxlastdatalen < 64) - rxlastdatalen = 64; - - put_long(txbuf, rxpos); - put_long(txbuf + 4, rxlastdatalen); - put_long(txbuf + 8, rxsyncid); - - hytxpkt(HPKT_RPOS, txbuf, 12); - Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); - SETTIMER(TIMERNO_RX, H_MINTIMER); - rxstate = HRX_DATA; - break; - - case HRX_OkEOF: - Syslog('h', "SM 'HRX' entering 'OkEOF'"); - hytxpkt(HPKT_EOFACK, txbuf, 0); - Syslog('h', "Hydra: reset RX timer"); - RESETTIMER(TIMERNO_RX); - Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - rxstate = HRX_FINFO; - break; - - case HRX_DONE: - Syslog('h', "SM 'HRX' entering 'DONE'"); - if (pkttype == HPKT_FINFO) { + if (filesize == rxpos) { + /* Skip this file, it's already here */ + Syslog('+', "Hydra: Skipping file %s", Name); + put_long(txbuf, -1); + } else { + /* Skip this file for now if error opening file */ put_long(txbuf, -2); - hytxpkt(HPKT_FINFOACK, txbuf, 4); - - pkttype = H_NOPKT; /* packet has already been processed */ - } else if ((pkttype == HPKT_IDLE) && (rxlen == 0)) { - Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); - SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); - - pkttype = H_NOPKT; /* packet has already been processed */ + } + hytxpkt(HPKT_FINFOACK, txbuf, 4); + + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); } - break; + } - } /* switch(rxstate) */ + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (pkttype == HPKT_INIT) { + hytxpkt(HPKT_INITACK, txbuf, 0); - if (pkttype != H_NOPKT) { - Syslog('h', "Hydra: rcvd packet %s - ignored", PktS(pkttype)); - pkttype = H_NOPKT; /* ignore received packet */ + pkttype = H_NOPKT; /* packet has already been processed */ + } else if ((pkttype == HPKT_EOF) && (rxlen == 4)) { + hytxpkt(HPKT_EOFACK, txbuf, 0); + + pkttype = H_NOPKT; /* packet has already been processed */ } + break; - } /* while() */ + case HRX_ToData: + Syslog('h', "SM 'HRX' entering 'ToData'"); + put_long(txbuf, rxpos); + hytxpkt(HPKT_FINFOACK, txbuf, 4); - Syslog('h', "Hydra: resettimers"); - RESETTIMERS(); + rxsyncid = 0; + rxlastsync = 0; + rxretries = 0; + Syslog('h', "Hydra: reset RX timer"); + RESETTIMER(TIMERNO_RX); + Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + rxstate = HRX_DATA; + break; - if (txstate == HTX_Abort) { - /* check if file is still open */ - if (rxfp) { - rxfp = NULL; - closefile(); + case HRX_DATA: + Syslog('h', "SM 'HRX' entering 'DATA'"); + // FIXME: Here the zlib extensions. + if ((pkttype == HPKT_DATA) && (rxlen > 4)) { + longnum = get_long(rxbuf); + Syslog('h', "Hydra: rcvd DATA (0x%08lx, 0x%08lx) %lu", longnum, rxpos, rxlen-4); + Nopper(); + + if (longnum == rxpos) { + if (fwrite(rxbuf + 4, 1, rxlen - 4, rxfp) != (rxlen - 4)) { + WriteError("$Hydra: error writing to file"); + rxpos = -2; + } else { + rxlastdatalen = rxlen - 4; + rxpos += rxlen - 4; + rcvdbytes += rxlen - 4; + rxretries = 0; + rxlastsync = rxpos; + Syslog('h', "Hydra: reset RX timer"); + RESETTIMER(TIMERNO_RX); + Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + if (rxwindow) { + put_long(txbuf, rxpos); + hytxpkt(HPKT_DATAACK, txbuf, 4); + } + } + } else { + if (rxpos >= 0) { + Syslog('+', "Hydra: received bad rxpos"); + } + rxstate = HRX_BadPos; + } + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if ((pkttype == HPKT_EOF) && (rxlen == 4)) { + longnum = get_long(rxbuf); + + if (longnum == rxpos) { + /* + * calculate time and CPU usage needed + */ + gettimeofday(&rxendtime, &tz); + + if (rxpos >= 0) { + rxfp = NULL; + if (!closefile()) { + srxpos = rxpos - srxpos; + + Syslog('+', "Hydra: OK %s", transfertime(rxstarttime, rxendtime, srxpos, FALSE)); + + rxstate = HRX_OkEOF; + } else { + Syslog('+', "Hydra: error closing file"); + rxpos = -2; + + /* + * Note: the following state change isn't 100 % + * conformant with the Hydra protocol specification. + */ + rxstate = HRX_BadPos; + } + } else { + Syslog('+', "Hydra: receiver skipped file after %ld seconds", rxendtime.tv_sec - rxstarttime.tv_sec); + + if (rxfp) { + closefile(); + rxfp = NULL; + } + + rxstate = HRX_OkEOF; + } + } else if (longnum == -2) { + if (rxfp) { + closefile(); + rxfp = NULL; + } + + rxstate = HRX_OkEOF; + } else { + if (longnum >= 0) { + Syslog('+', "Hydra: received bad rxpos"); + } + rxstate = HRX_BadPos; /* TODO: fallthrough */ + } + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (pkttype == HPKT_FINFO) { + put_long(txbuf, rxpos); + hytxpkt(HPKT_FINFOACK, txbuf, 4); + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if ((pkttype == HPKT_IDLE) && (rxlen == 0) && (hdxlink == FALSE)) { + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if (EXPIRED(TIMERNO_RX)) { + Syslog('h', "Hydra: RX timer expired"); + rxstate = HRX_HdxLink; } + break; - Syslog('+', "Hydra: signal CAN to remote"); - FLUSHOUT(); - /* 8 times CAN and 10 times BS */ - PUT((char *)"\030\030\030\030\030\030\030\030\010\010\010\010\010\010\010\010\010\010", 18); - sleep(4); /* wait a few seconds... */ - FLUSHIN(); + case HRX_BadPos: + Syslog('h', "SM 'HRX' entering 'BadPos'"); + longnum = get_long(rxbuf); - return MBERR_FTRANSFER; + if (longnum <= rxlastsync) { + rxretries = 0; + Syslog('h', "Hydra: reset RX timer"); + RESETTIMER(TIMERNO_RX); + } + rxlastsync = longnum; + rxstate = HRX_Timer; + break; + + case HRX_Timer: + Syslog('h', "SM 'HRX' entering 'Timer'"); + if ((!RUNNING(TIMERNO_RX)) || (EXPIRED(TIMERNO_RX))) { + Syslog('h', "Hydra: RX timer expired"); + rxstate = HRX_HdxLink; + } else { + rxstate = HRX_DATA; + } + break; + + case HRX_HdxLink: + Syslog('h', "SM 'HRX' entering 'HdxLink'"); + if ((rxretries > 4) && (txstate != HTX_REND) && (role == 0) && (hdxlink == FALSE)) { + rxretries = 0; + hdxlink = TRUE; + } + rxstate = HRX_Retries; + break; /* TODO: fallthrough */ + + case HRX_Retries: + Syslog('h', "SM 'HRX' entering 'Retries'"); + rxretries++; + if (rxretries >= 10) { + Syslog('+', "Hydra: too many errors"); + txstate = HTX_Abort; + } else if (rxretries == 1) { + rxsyncid++; + } + rxstate = HRX_RPos; + break; /* TODO: fallthrough */ + + case HRX_RPos: + Syslog('h', "SM 'HRX' entering 'RPos'"); + rxlastdatalen /= 2; + if (rxlastdatalen < 64) + rxlastdatalen = 64; + + put_long(txbuf, rxpos); + put_long(txbuf + 4, rxlastdatalen); + put_long(txbuf + 8, rxsyncid); + + hytxpkt(HPKT_RPOS, txbuf, 12); + Syslog('h', "Hydra: set TX timer %d", H_MINTIMER); + SETTIMER(TIMERNO_RX, H_MINTIMER); + rxstate = HRX_DATA; + break; + + case HRX_OkEOF: + Syslog('h', "SM 'HRX' entering 'OkEOF'"); + hytxpkt(HPKT_EOFACK, txbuf, 0); + Syslog('h', "Hydra: reset RX timer"); + RESETTIMER(TIMERNO_RX); + Syslog('h', "Hydra: set BRAIN timer %d", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + rxstate = HRX_FINFO; + break; + + case HRX_DONE: + Syslog('h', "SM 'HRX' entering 'DONE'"); + if (pkttype == HPKT_FINFO) { + put_long(txbuf, -2); + hytxpkt(HPKT_FINFOACK, txbuf, 4); + + pkttype = H_NOPKT; /* packet has already been processed */ + } else if ((pkttype == HPKT_IDLE) && (rxlen == 0)) { + Syslog('h', "Hydra: set BRAIN timer", H_BRAINDEAD); + SETTIMER(TIMERNO_BRAIN, H_BRAINDEAD); + + pkttype = H_NOPKT; /* packet has already been processed */ + } + break; + + } /* switch(rxstate) */ + + if (pkttype != H_NOPKT) { + Syslog('h', "Hydra: rcvd packet %s - ignored", PktS(pkttype)); + pkttype = H_NOPKT; /* ignore received packet */ } - return MBERR_OK; + } /* while() */ + + Syslog('h', "Hydra: resettimers"); + RESETTIMERS(); + + if (txstate == HTX_Abort) { + /* check if file is still open */ + if (rxfp) { + rxfp = NULL; + closefile(); + } + + Syslog('+', "Hydra: signal CAN to remote"); + FLUSHOUT(); + /* 8 times CAN and 10 times BS */ + PUT((char *)"\030\030\030\030\030\030\030\030\010\010\010\010\010\010\010\010\010\010", 18); + sleep(4); /* wait a few seconds... */ + FLUSHIN(); + + return MBERR_FTRANSFER; + } + + return MBERR_OK; } int hydra(int role) { - int rc; - fa_list *eff_remote, tmpl; - file_list *tosend = NULL, *request = NULL, *respond = NULL, *tmpfl; - char *nonhold_mail; + int rc; + fa_list *eff_remote, tmpl; + file_list *tosend = NULL, *request = NULL, *respond = NULL, *tmpfl; + char *nonhold_mail; - Syslog('+', "Hydra: start transfer"); - session_flags |= SESSION_HYDRA; /* Hydra special file requests */ + Syslog('+', "Hydra: start transfer"); + session_flags |= SESSION_HYDRA; /* Hydra special file requests */ - if (emsi_remote_lcodes & LCODE_NPU) { - Syslog('+', "Hydra: remote requested \"no pickup\", no send"); - eff_remote = NULL; - } else if (emsi_remote_lcodes & LCODE_PUP) { - Syslog('+', "Hydra: remote requested \"pickup primary\""); - tmpl.addr = remote->addr; - tmpl.next = NULL; - eff_remote = &tmpl; - } else { - eff_remote = remote; - } + if (emsi_remote_lcodes & LCODE_NPU) { + Syslog('+', "Hydra: remote requested \"no pickup\", no send"); + eff_remote = NULL; + } else if (emsi_remote_lcodes & LCODE_PUP) { + Syslog('+', "Hydra: remote requested \"pickup primary\""); + tmpl.addr = remote->addr; + tmpl.next = NULL; + eff_remote = &tmpl; + } else { + eff_remote = remote; + } - if (role) { -// if (localoptions & NOHOLD) - nonhold_mail = (char *)ALL_MAIL; -// else -// nonhold_mail = (char *)NONHOLD_MAIL; - } else { - nonhold_mail = (char *)ALL_MAIL; - } + nonhold_mail = (char *)ALL_MAIL; - if (emsi_remote_lcodes & LCODE_HAT) { - Syslog('+', "Hydra: remote requested \"hold all traffic\", no send"); - tosend = NULL; - } else { - tosend = create_filelist(eff_remote, nonhold_mail, 0); - } + if (emsi_remote_lcodes & LCODE_HAT) { + Syslog('+', "Hydra: remote requested \"hold all traffic\", no send"); + tosend = NULL; + } else { + tosend = create_filelist(eff_remote, nonhold_mail, 0); + } - if (session_flags & SESSION_WAZOO) - request = create_freqlist(remote); + if (session_flags & SESSION_WAZOO) + request = create_freqlist(remote); - /* - * Send only file requests during first batch if remote supports - * "RH1" flag. - */ + /* + * Send only file requests during first batch if remote supports + * "RH1" flag. + */ + if (emsi_remote_lcodes & LCODE_RH1) { + rc = hydra_batch(role, request); + } else { + if (request != NULL) { + tmpfl = tosend; + tosend = request; + for (; request->next; request = request->next); + request->next = tmpfl; + + request = NULL; + } + + rc = hydra_batch(role, tosend); + } + + Syslog('+', "Hydra: start second batch"); + + if (rc == 0) { + if ((emsi_local_opts & OPT_NRQ) == 0) + respond = respond_wazoo(); + if (emsi_remote_lcodes & LCODE_RH1) { - rc = hydra_batch(role, request); + for (tmpfl = tosend; tmpfl->next; tmpfl = tmpfl->next); + tmpfl->next = respond; + + rc = hydra_batch(role, tosend); + tmpfl->next = NULL; /* split filelist into tosend and respond again */ } else { - if (request != NULL) { - tmpfl = tosend; - tosend = request; - for (; request->next; request = request->next); - request->next = tmpfl; - - request = NULL; - } - - rc = hydra_batch(role, tosend); + rc = hydra_batch(role, respond); } + } - Syslog('+', "Hydra: start second batch"); + tidy_filelist(request, (rc == 0)); + tidy_filelist(tosend, (rc == 0)); + tidy_filelist(respond, 0); - if (rc == 0) { - if ((emsi_local_opts & OPT_NRQ) == 0) - respond = respond_wazoo(); + Syslog('+', "Hydra: end transfer"); - if (emsi_remote_lcodes & LCODE_RH1) { - for (tmpfl = tosend; tmpfl->next; tmpfl = tmpfl->next); - tmpfl->next = respond; - - rc = hydra_batch(role, tosend); - tmpfl->next = NULL; /* split filelist into tosend - and respond again */ - } else { - rc = hydra_batch(role, respond); - } - } - - tidy_filelist(request, (rc == 0)); - tidy_filelist(tosend, (rc == 0)); - tidy_filelist(respond, 0); - - Syslog('+', "Hydra: end transfer"); - - return rc; + return rc; } diff --git a/mbcico/hydra.h b/mbcico/hydra.h index 156aef6f..37ab0cbf 100644 --- a/mbcico/hydra.h +++ b/mbcico/hydra.h @@ -1,8 +1,14 @@ -/* As this file has been derived from the HydraCom source, here is the +/* $Id$ */ +/* + * As this file has been derived from the HydraCom source, here is the * original copyright information: * * Note that you can find the file LICENSE.DOC from HydraCom in * misc/HYDRACOM-LICENSE + * + * Some changes are made in this file to customize for use with MBSE BBS. + * There are also some extensions not in the original Hydra code for zlib + * packet compression of data packets. */ /*============================================================================= @@ -147,10 +153,24 @@ enum HyPktTypes HPKT_IDLE = 'L', /* Idle - just saying I'm alive */ HPKT_DEVDATA = 'M', /* Data to specified device */ HPKT_DEVDACK = 'N', /* Response to DEVDATA pkt */ +#ifdef HAVE_ZLIB_H + HPKT_ZIPDATA = 'O', /* Zlib compressed file data packet */ - HPKT_HIGHEST = 'N' /* Highest known pkttype in this imp */ + HPKT_HIGHEST = 'O' /* Highest known pkttype in this imp */ +#else + HPKT_HIGHEST = 'N' /* Highest known pkttype in this imp */ +#endif }; +/* HYDRA compression types ------------------------------------------------- */ +enum HyCompStates +{ + HCMP_NONE, /* No compression, default */ + HCMP_GZ, /* Gzip compression */ + HCMP_BZ2, /* Bzip2 compression */ +}; + + /* HYDRA Internal Pseudo Packet Types -------------------------------------- */ #define H_NOPKT 0 /* No packet (yet) */ #define H_CANCEL (-1) /* Received cancel sequence 5*Ctrl-X */ @@ -182,17 +202,33 @@ enum HyPktFormats #define HOPT_CRC32 (0x00000100L) /* Packets with CRC-32 allowed */ #define HOPT_DEVICE (0x00000200L) /* DEVICE packets allowed */ #define HOPT_FPT (0x00000400L) /* Can handle filenames with paths */ +#ifdef HAVE_ZLIB_H +#define HOPT_CANPLZ (0x00000800L) /* Can handle zlib packet compress */ +#endif /* What we can do */ +#ifdef HAVE_ZLIB_H +#define HCAN_OPTIONS (HOPT_XONXOFF | HOPT_TELENET | HOPT_CTLCHRS | HOPT_HIGHCTL | HOPT_HIGHBIT | HOPT_CRC32 | HOPT_CANPLZ) +#else #define HCAN_OPTIONS (HOPT_XONXOFF | HOPT_TELENET | HOPT_CTLCHRS | HOPT_HIGHCTL | HOPT_HIGHBIT | HOPT_CRC32) +#endif + /* Vital options if we ask for any; abort if other side doesn't support them */ #define HNEC_OPTIONS (HOPT_XONXOFF | HOPT_TELENET | HOPT_CTLCHRS | HOPT_HIGHCTL | HOPT_HIGHBIT | HOPT_CANBRK) + /* Non-vital options; nice if other side supports them, but doesn't matter */ +#ifdef HAVE_ZLIB_H +#define HUNN_OPTIONS (HOPT_CANASC | HOPT_CANUUE | HOPT_CRC32 | HOPT_CANPLZ) +#else #define HUNN_OPTIONS (HOPT_CANASC | HOPT_CANUUE | HOPT_CRC32) +#endif + /* Default options */ #define HDEF_OPTIONS (HOPT_CRC32) + /* rxoptions during init (needs to handle ANY link yet unknown at that point */ #define HRXI_OPTIONS (HOPT_XONXOFF | HOPT_TELENET | HOPT_CTLCHRS | HOPT_HIGHCTL | HOPT_HIGHBIT) + /* ditto, but this time txoptions */ #define HTXI_OPTIONS (HOPT_XONXOFF | HOPT_TELENET | HOPT_CTLCHRS | HOPT_HIGHCTL | HOPT_HIGHBIT) diff --git a/mbsebbs/bye.c b/mbsebbs/bye.c index bbb74dca..2cea913f 100644 --- a/mbsebbs/bye.c +++ b/mbsebbs/bye.c @@ -62,10 +62,13 @@ void Good_Bye(int onsig) if (onsig != SIGHUP) DisplayFile((char *)"goodbye"); + Syslog('b', "goodbye displayed"); + if (do_mailout) CreateSema((char *)"mailout"); SaveLastCallers(); + Syslog('b', "Lastcallers written"); /* * Update the users database record. diff --git a/mbsebbs/chat.c b/mbsebbs/chat.c index 5e4eb04f..3947f425 100644 --- a/mbsebbs/chat.c +++ b/mbsebbs/chat.c @@ -175,7 +175,7 @@ void Chat(char *username, char *channel) char sbuf[81], resp[128], *cnt, *msg; static char buf[200]; - WhosDoingWhat(SYSOPCHAT); + WhosDoingWhat(SYSOPCHAT, NULL); clear(); rsize = exitinfo.iScreenLen - 5; diff --git a/mbsebbs/door.c b/mbsebbs/door.c index 971e66b3..b8d16fcc 100644 --- a/mbsebbs/door.c +++ b/mbsebbs/door.c @@ -97,17 +97,54 @@ char *Rdate(char *ind, int Y2K) /* * Function will run a external program or door */ -void ExtDoor(char *Program, int NoDoorsys, int Y2Kdoorsys, int Comport, int NoSuid, int NoPrompt) +void ExtDoor(char *Program, int NoDoorsys, int Y2Kdoorsys, int Comport, int NoSuid, int NoPrompt, int SingleUser, char *What) { char *String, *String1; - int i, rc; - char *temp1; + int i, rc, Start; + char *temp1, buf[128]; FILE *fp; temp1 = calloc(PATH_MAX, sizeof(char)); String = calloc(81, sizeof(char)); - WhosDoingWhat(DOOR); + Start = TRUE; + if (SingleUser && What) { + /* + * Check if the door is in use + */ + while (TRUE) { + if (Start) + sprintf(buf, "GMON:1,1;"); + else + sprintf(buf, "GMON:1,0;"); + Start = FALSE; + if (socket_send(buf) == 0) { + strcpy(buf, socket_receive()); + if (strncmp(buf, "100:0;", 6) == 0) + break; /* No more data */ + if (strstr(buf, "mbsebbs")) { + strtok(buf, ","); /* Nr of parameters */ + strtok(NULL, ","); /* Pid */ + strtok(NULL, ","); /* tty */ + strtok(NULL, ","); /* username */ + strtok(NULL, ","); /* program name */ + strtok(NULL, ","); /* location */ + if (strcmp(strtok(NULL, ","), menus.DoorName) == 0) { + Syslog('+', "User tried single user door %s, but door is in use", menus.DoorName); + colour(LIGHTRED, BLACK); + /* The door is in use by another user, try again later */ + printf("\n%s\n\n", (char *) Language(20)); + Pause(); + free(temp1); + free(String); + return; + } + } + } + } + } + + WhosDoingWhat(DOOR, What); if ((strstr(Program, "/N")) != NULL) { sprintf(temp1, "%d", iNode); diff --git a/mbsebbs/door.h b/mbsebbs/door.h index c844d7f0..5814ba7e 100644 --- a/mbsebbs/door.h +++ b/mbsebbs/door.h @@ -3,7 +3,7 @@ #ifndef _DOOR_H #define _DOOR_H -void ExtDoor(char *, int, int, int, int, int); /* Run external door */ +void ExtDoor(char *, int, int, int, int, int, int, char *); /* Run external door */ int exec_nosuid(char *); /* Execute as real user */ #endif diff --git a/mbsebbs/email.c b/mbsebbs/email.c index a8185aa7..ad810579 100644 --- a/mbsebbs/email.c +++ b/mbsebbs/email.c @@ -178,7 +178,7 @@ int Export_a_Email(unsigned long Num) LastNum = Num; iLineCount = 7; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); Syslog('+', "Export email %d in area %s", Num, sMailbox); /* @@ -374,7 +374,7 @@ int Read_a_Email(unsigned long Num) LastNum = Num; iLineCount = 7; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); /* * The area data is already set, so we can do the next things @@ -519,7 +519,7 @@ int EmailPanel(void) { int input; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); colour(15, 4); /* (A)gain, (N)ext, (L)ast, (R)eply, (E)nter, (D)elete, (Q)uit, e(X)port */ @@ -681,7 +681,7 @@ void Reply_Email(int IsReply) x = 0; Line = 1; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); clear(); colour(1,7); printf(" %-71s", sMailbox); @@ -817,7 +817,7 @@ void Write_Email(void) orgbox = xstrcpy(sMailbox); SetEmailArea((char *)"mailbox"); - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); clear(); for (i = 0; i < (TEXTBUFSIZE + 1); i++) @@ -907,7 +907,7 @@ void QuickScan_Email(void) long i; iLineCount = 2; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); if (EmailBase.Total == 0) { Enter(1); diff --git a/mbsebbs/file.c b/mbsebbs/file.c index 67a35e61..6d1d4fd9 100644 --- a/mbsebbs/file.c +++ b/mbsebbs/file.c @@ -99,7 +99,7 @@ void File_List() _Tag T; iLineCount = 0; - WhosDoingWhat(FILELIST); + WhosDoingWhat(FILELIST, NULL); Syslog('+', "Listing File Area # %d", iAreaNumber); @@ -184,7 +184,7 @@ void Download(void) Enter(2); OldArea = iAreaNumber; - WhosDoingWhat(DOWNLOAD); + WhosDoingWhat(DOWNLOAD, NULL); system("rm -f ./tag/*"); if ((tf = fopen("taglist", "r+")) == NULL) { @@ -1005,7 +1005,7 @@ int Upload() char *arc; - WhosDoingWhat(UPLOAD); + WhosDoingWhat(UPLOAD, NULL); /* * Select default protocol if users hasn't any. @@ -1278,7 +1278,7 @@ int DownloadDirect(char *Name, int Wait) return FALSE; } - WhosDoingWhat(DOWNLOAD); + WhosDoingWhat(DOWNLOAD, NULL); ReadExitinfo(); clear(); @@ -1524,7 +1524,7 @@ int Download_Home() File = calloc(PATH_MAX, sizeof(char)); temp = calloc(PATH_MAX, sizeof(char)); - WhosDoingWhat(DOWNLOAD); + WhosDoingWhat(DOWNLOAD, NULL); colour(14,0); /* Please enter filename: */ @@ -1589,7 +1589,7 @@ int Upload_Home() int err; struct stat statfile; - WhosDoingWhat(UPLOAD); + WhosDoingWhat(UPLOAD, NULL); if (!ForceProtocol()) return 0; diff --git a/mbsebbs/mail.c b/mbsebbs/mail.c index 3dcbd397..c89d74e9 100644 --- a/mbsebbs/mail.c +++ b/mbsebbs/mail.c @@ -402,7 +402,7 @@ void Post_Msg() unsigned short point; Line = 1; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); SetMsgArea(iMsgAreaNumber); clear(); @@ -811,7 +811,7 @@ int Export_a_Msg(unsigned long Num) LastNum = Num; iLineCount = 7; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); /* * The sysop has a choice to export to the rules directory. @@ -960,7 +960,7 @@ int Read_a_Msg(unsigned long Num, int UpdateLR) LastNum = Num; iLineCount = 7; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); /* * The area data is already set, so we can do the next things @@ -1172,7 +1172,7 @@ int ReadPanel() { int input; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); colour(WHITE, RED); /* @@ -1310,7 +1310,7 @@ void Reply_Msg(int IsReply) strncpy(msgid, Msg.Msgid, 80); x = 0; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); clear(); colour(BLUE, LIGHTGRAY); printf(" %-71s", sMsgAreaDesc); @@ -1486,7 +1486,7 @@ void QuickScan_Msgs() long i; iLineCount = 2; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); if (MsgBase.Total == 0) { Enter(1); @@ -1552,7 +1552,7 @@ void Delete_Msg() char *temp; unsigned long Msgnum = 0L; - WhosDoingWhat(READ_POST); + WhosDoingWhat(READ_POST, NULL); /* * The area data is already set, so we can do the next things @@ -2524,7 +2524,7 @@ int Ext_Edit() } fclose(fd); stat( tmpname, &st1 ); - ExtDoor(CFG.externaleditor,FALSE,TRUE,TRUE,FALSE,TRUE); + ExtDoor(CFG.externaleditor,FALSE,TRUE,TRUE,FALSE,TRUE, FALSE, (char *)"Write message"); stat( tmpname, &st2 ); } diff --git a/mbsebbs/menu.c b/mbsebbs/menu.c index a4e78339..b3c9bc97 100644 --- a/mbsebbs/menu.c +++ b/mbsebbs/menu.c @@ -104,7 +104,7 @@ void menu() */ while (TRUE) { - WhosDoingWhat(BROWSING); + WhosDoingWhat(BROWSING, NULL); /* * Open menufile, first users language menu, if it fails @@ -333,7 +333,15 @@ void DoMenu(int Type) case 7: /* Run external program */ - ExtDoor(menus.OptionalData, menus.NoDoorsys, menus.Y2Kdoorsys, menus.Comport, menus.NoSuid, menus.NoPrompt); + if (strlen(menus.DoorName) && !menus.HideDoor) { + memset(temp, 0, sizeof(temp)); + strcpy(temp, menus.DoorName); + ExtDoor(menus.OptionalData, menus.NoDoorsys, menus.Y2Kdoorsys, menus.Comport, + menus.NoSuid, menus.NoPrompt, menus.SingleUser, temp); + } else { + ExtDoor(menus.OptionalData, menus.NoDoorsys, menus.Y2Kdoorsys, menus.Comport, + menus.NoSuid, menus.NoPrompt, menus.SingleUser, NULL); + } break; case 8: diff --git a/mbsebbs/offline.c b/mbsebbs/offline.c index e6f525cf..61a9d6ef 100644 --- a/mbsebbs/offline.c +++ b/mbsebbs/offline.c @@ -232,7 +232,7 @@ void OLR_TagArea() long total, Offset, Area; int lines, input, ignore = FALSE, maxlines; - WhosDoingWhat(OLR); + WhosDoingWhat(OLR, NULL); Msgname = calloc(PATH_MAX, sizeof(char)); Tagname = calloc(PATH_MAX, sizeof(char)); @@ -375,7 +375,7 @@ void OLR_UntagArea() long total, Offset, Area; int lines, input, ignore = FALSE, maxlines; - WhosDoingWhat(OLR); + WhosDoingWhat(OLR, NULL); Msgname = calloc(PATH_MAX, sizeof(char)); Tagname = calloc(PATH_MAX, sizeof(char)); @@ -719,7 +719,7 @@ void OLR_ViewTags() long total, Area = 0; int lines, input, ignore = FALSE, maxlines; - WhosDoingWhat(OLR); + WhosDoingWhat(OLR, NULL); Tagname = calloc(PATH_MAX, sizeof(char)); Msgname = calloc(PATH_MAX, sizeof(char)); @@ -813,7 +813,7 @@ int OLR_Prescan() FILE *mf, *tf; int x; - WhosDoingWhat(OLR); + WhosDoingWhat(OLR, NULL); clear(); colour(LIGHTMAGENTA, BLACK); /* Offline Reader Download */ @@ -939,7 +939,7 @@ void DrawBar(char *Pktname) void OLR_RestrictDate() { - WhosDoingWhat(OLR); + WhosDoingWhat(OLR, NULL); printf("Not Yet Implemented\n"); Pause(); @@ -1022,7 +1022,7 @@ void OLR_Upload(void) return; } - WhosDoingWhat(OLR); + WhosDoingWhat(OLR, NULL); clear(); colour(LIGHTMAGENTA, BLACK); /* Offline Reader Upload */ diff --git a/mbsebbs/whoson.c b/mbsebbs/whoson.c index 4f88e2bb..7e685a10 100644 --- a/mbsebbs/whoson.c +++ b/mbsebbs/whoson.c @@ -62,7 +62,7 @@ void WhosOn(char *OpData) Underline = calloc(81, sizeof(char)); Heading = calloc(81, sizeof(char)); - WhosDoingWhat(WHOSON); + WhosDoingWhat(WHOSON, NULL); clear(); Enter(1); @@ -174,9 +174,15 @@ void WhosOn(char *OpData) else if (strstr(isdoing, "Offline")) /* Offline Reader */ printf("%-15s", (char *) Language(429)); - else - /* Browsing */ /* This is default when nothing matches */ - printf("%-15s", (char *) Language(418)); + else { + /* + * This is default when nothing matches, with doors this + * will show the name of the door. + */ + if (strlen(isdoing) > 15) + isdoing[15] = '\0'; + printf("%-15s", isdoing); + } colour(LIGHTRED, BLACK); printf("%-25s\n", location); @@ -200,7 +206,7 @@ void WhosOn(char *OpData) /* * Function will update users file and and update exitinfo.iStatus */ -void WhosDoingWhat(int iStatus) +void WhosDoingWhat(int iStatus, char *what) { char *temp; @@ -226,7 +232,10 @@ void WhosDoingWhat(int iStatus) LC_Read = TRUE; break; - case DOOR: strcpy(temp, "External Door"); + case DOOR: if (what) + strcpy(temp, what); + else + strcpy(temp, "External Door"); LC_Door = TRUE; break; diff --git a/mbsebbs/whoson.h b/mbsebbs/whoson.h index 629c6aa1..df7f006d 100644 --- a/mbsebbs/whoson.h +++ b/mbsebbs/whoson.h @@ -4,7 +4,7 @@ #define _WHOSON_H void WhosOn(char *); /* What users are currently online */ -void WhosDoingWhat(int); /* Update what user is doing */ +void WhosDoingWhat(int, char *); /* Update what user is doing */ void SendOnlineMsg(char *); /* Send On-Line Message to User */ #endif diff --git a/mbsetup/m_menu.c b/mbsetup/m_menu.c index 9688ff5c..b1445e6b 100644 --- a/mbsetup/m_menu.c +++ b/mbsetup/m_menu.c @@ -108,16 +108,18 @@ void Show_A_Menu(void) mvprintw(11, 2, "4. Display"); mvprintw(12, 2, "5. Security"); mvprintw(13, 2, "6. Min. age"); - mvprintw(14, 2, "7. Password"); - mvprintw(15, 2, "8. Lo-colors"); - mvprintw(16, 2, "9. Hi-colors"); - mvprintw(17, 2, "10. Autoexec"); + mvprintw(14, 2, "7. Lo-colors"); + mvprintw(15, 2, "8. Hi-colors"); + mvprintw(16, 2, "9. Autoexec"); if (le_int(menus.MenuType) == 7) { - mvprintw(13,42, "11. No door.sys"); - mvprintw(14,42, "12. Y2K style"); - mvprintw(15,42, "13. Use Comport"); - mvprintw(16,42, "14. Run nosuid"); - mvprintw(17,42, "15. No Prompt"); + mvprintw(17, 2, "10. Door Name"); + mvprintw(18, 2, "11. Y2K style"); + mvprintw(13,42, "12. No door.sys"); + mvprintw(14,42, "13. Use COMport"); + mvprintw(15,42, "14. Run nosuid"); + mvprintw(16,42, "15. No Prompt"); + mvprintw(17,42, "16. Single User"); + mvprintw(18,42, "17. Hidden door"); } set_color(WHITE, BLACK); @@ -128,20 +130,19 @@ void Show_A_Menu(void) show_str(11,16,64, menus.Display); show_sec(12,16, menus.MenuSecurity); show_int(13,16, le_int(menus.Age)); - if (strlen(menus.Password)) - show_str(14,16,14, (char *)"**************"); - else - show_str(14,16,14, (char *)""); - S_COL(15,16, "Normal display color", le_int(menus.ForeGnd), le_int(menus.BackGnd)) - S_COL(16,16, "Bright display color", le_int(menus.HiForeGnd), le_int(menus.HiBackGnd)) + S_COL(14,16, "Normal display color", le_int(menus.ForeGnd), le_int(menus.BackGnd)) + S_COL(15,16, "Bright display color", le_int(menus.HiForeGnd), le_int(menus.HiBackGnd)) set_color(WHITE, BLACK); - show_bool(17,16, menus.AutoExec); + show_bool(16,16, menus.AutoExec); if (le_int(menus.MenuType) == 7) { + show_str(17,16,14, menus.DoorName); + show_bool(18,16, menus.Y2Kdoorsys); show_bool(13,58, menus.NoDoorsys); - show_bool(14,58, menus.Y2Kdoorsys); - show_bool(15,58, menus.Comport); - show_bool(16,58, menus.NoSuid); - show_bool(17,58, menus.NoPrompt); + show_bool(14,58, menus.Comport); + show_bool(15,58, menus.NoSuid); + show_bool(16,58, menus.NoPrompt); + show_bool(17,58, menus.SingleUser); + show_bool(18,58, menus.HideDoor); } } @@ -214,7 +215,7 @@ void Edit_A_Menu(void) Show_A_Menu(); for (;;) { - switch(select_menu(15)) { + switch(select_menu(17)) { case 0: return; break; case 1: E_UPS( 7,16, 1, menus.MenuKey, "The ^key^ to select this menu item") @@ -238,41 +239,76 @@ void Edit_A_Menu(void) temp = edit_int(13,16, temp, (char *)"The minimum ^Age^ to select this menu, 0 is don't care"); menus.Age = le_int(temp); break; - case 7: E_STR(14,16,14, menus.Password, "The ^password^ to access this menu item") - case 8: fg = le_int(menus.ForeGnd); + case 7: fg = le_int(menus.ForeGnd); bg = le_int(menus.BackGnd); - edit_color(&fg, &bg, (char *)"8.3.8 EDIT COLOR", (char *)"normal"); + edit_color(&fg, &bg, (char *)"8.3.7 EDIT COLOR", (char *)"normal"); menus.ForeGnd = le_int(fg); menus.BackGnd = le_int(bg); Show_A_Menu(); break; - case 9: fg = le_int(menus.HiForeGnd); + case 8: fg = le_int(menus.HiForeGnd); bg = le_int(menus.HiBackGnd); - edit_color(&fg, &bg, (char *)"8.3.9 EDIT COLOR", (char *)"bright"); + edit_color(&fg, &bg, (char *)"8.3.8 EDIT COLOR", (char *)"bright"); menus.HiForeGnd = le_int(fg); menus.HiBackGnd = le_int(bg); Show_A_Menu(); break; - case 10:menus.AutoExec = edit_bool(17,16, menus.AutoExec, (char *)"Is this an ^Autoexecute^ menu item"); + case 9: menus.AutoExec = edit_bool(16,16, menus.AutoExec, (char *)"Is this an ^Autoexecute^ menu item"); + break; + case 10:if (le_int(menus.MenuType) == 7) { + E_STR(17,16,14, menus.DoorName, (char *)"The ^name^ of the door to show to the users") + } else { + working(2, 0, 0); + working(0, 0, 0); + } break; case 11:if (le_int(menus.MenuType) == 7) { - menus.NoDoorsys = edit_bool(13,58, menus.NoDoorsys, (char *)"Suppress writing ^door.sys^ dropfile"); + menus.Y2Kdoorsys = edit_bool(18,16, menus.Y2Kdoorsys, (char *)"Create ^door.sys^ with 4 digit yearnumbers"); + } else { + working(2, 0, 0); + working(0, 0, 0); } break; case 12:if (le_int(menus.MenuType) == 7) { - menus.Y2Kdoorsys = edit_bool(14,58, menus.Y2Kdoorsys, (char *)"Create ^door.sys^ with 4 digit yearnumbers"); + menus.NoDoorsys = edit_bool(13,58, menus.NoDoorsys, (char *)"Suppress writing ^door.sys^ dropfile"); + } else { + working(2, 0, 0); + working(0, 0, 0); } break; case 13:if (le_int(menus.MenuType) == 7) { - menus.Comport = edit_bool(15,58, menus.Comport, (char *)"Write real ^COM port^ in door.sys for Vmodem patch"); + menus.Comport = edit_bool(14,58, menus.Comport, (char *)"Write real ^COM port^ in door.sys for Vmodem patch"); + } else { + working(2, 0, 0); + working(0, 0, 0); } break; case 14:if (le_int(menus.MenuType) == 7) { - menus.NoSuid = edit_bool(16,58, menus.NoSuid, (char *)"Run the door as ^real user (nosuid)^"); + menus.NoSuid = edit_bool(15,58, menus.NoSuid, (char *)"Run the door as ^real user (nosuid)^"); + } else { + working(2, 0, 0); + working(0, 0, 0); } break; case 15:if (le_int(menus.MenuType) == 7) { - menus.NoPrompt = edit_bool(17,58, menus.NoPrompt, (char *)"^Don't display prompt^ when door is finished"); + menus.NoPrompt = edit_bool(16,58, menus.NoPrompt, (char *)"^Don't display prompt^ when door is finished"); + } else { + working(2, 0, 0); + working(0, 0, 0); + } + break; + case 16:if (le_int(menus.MenuType) == 7) { + menus.SingleUser = edit_bool(17,58, menus.SingleUser, (char *)"Set if door is for ^single user^ only"); + } else { + working(2, 0, 0); + working(0, 0, 0); + } + break; + case 17:if (le_int(menus.MenuType) == 7) { + menus.HideDoor = edit_bool(18,58, menus.HideDoor, (char *)"^Hide door^ from user display lists"); + } else { + working(2, 0, 0); + working(0, 0, 0); } break; } @@ -596,17 +632,19 @@ int bbs_menu_doc(FILE *fp, FILE *toc, int page) fprintf(fp, " Display %s\n", menus.Display); fprintf(fp, " Security %s\n", get_secstr(menus.MenuSecurity)); fprintf(fp, " Minimum age %d\n", menus.Age); - fprintf(fp, " Password %s\n", menus.Password); fprintf(fp, " Lo-colors %s on %s\n", get_color(le_int(menus.ForeGnd)), get_color(le_int(menus.BackGnd))); fprintf(fp, " Hi-colors %s on %s\n", get_color(le_int(menus.HiForeGnd)), get_color(le_int(menus.HiBackGnd))); if (le_int(menus.MenuType) == 7) { - fprintf(fp, " No door.sys %s\n", getboolean(menus.NoDoorsys)); - fprintf(fp, " Y2K door.sys %s\n", getboolean(menus.Y2Kdoorsys)); + fprintf(fp, " Door Name %s\n", menus.DoorName); + fprintf(fp, " No door.sys %s", getboolean(menus.NoDoorsys)); + fprintf(fp, " Y2K door.sys %s", getboolean(menus.Y2Kdoorsys)); fprintf(fp, " Use COM port %s\n", getboolean(menus.Comport)); - fprintf(fp, " No setuid %s\n", getboolean(menus.NoSuid)); - fprintf(fp, " No Prompt %s\n", getboolean(menus.NoPrompt)); + fprintf(fp, " Run nosuid %s", getboolean(menus.NoSuid)); + fprintf(fp, " No Prompt %s", getboolean(menus.NoPrompt)); + fprintf(fp, " Single user %s\n", getboolean(menus.SingleUser)); + fprintf(fp, " Hidden door %s\n", getboolean(menus.HideDoor)); } fprintf(fp, "\n\n"); j++;