diff options
Diffstat (limited to 'gnu/libexec/uucp/common_sources')
20 files changed, 10160 insertions, 0 deletions
diff --git a/gnu/libexec/uucp/common_sources/chat.c b/gnu/libexec/uucp/common_sources/chat.c new file mode 100644 index 000000000000..8544ed2e2027 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/chat.c @@ -0,0 +1,1429 @@ +/* chat.c + Chat routine for the UUCP package. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char chat_rcsid[] = "$Id: chat.c,v 1.1 1993/08/05 18:22:30 conklin Exp $"; +#endif + +#include <ctype.h> +#include <errno.h> + +#include "uudefs.h" +#include "uuconf.h" +#include "conn.h" +#include "prot.h" +#include "system.h" + +/* Local functions. */ + +static int icexpect P((struct sconnection *qconn, int cstrings, + char **azstrings, size_t *aclens, + int ctimeout, boolean fstrip)); +static boolean fcsend P((struct sconnection *qconn, pointer puuconf, + const char *zsend, + const struct uuconf_system *qsys, + const struct uuconf_dialer *qdial, + const char *zphone, + boolean ftranslate, boolean fstrip)); +static boolean fcecho_send_strip P((struct sconnection *qconn, + const char *z, size_t clen)); +static boolean fcecho_send_nostrip P((struct sconnection *qconn, + const char *z, size_t clen)); +static boolean fcecho_send P((struct sconnection *qconn, const char *z, + size_t clen, boolean fstrip)); +static boolean fcphone P((struct sconnection *qconn, + pointer puuconf, + const struct uuconf_dialer *qdial, + const char *zphone, + boolean (*pfwrite) P((struct sconnection *qc, + const char *zwrite, + size_t cwrite)), + boolean ftranslate, boolean *pfquote)); +static boolean fctranslate P((pointer puuconf, const char *zphone, + const char **pzprefix, + const char **pzsuffix)); +static boolean fcprogram P((struct sconnection *qconn, pointer puuconf, + char **pzprogram, + const struct uuconf_system *qsys, + const struct uuconf_dialer *qdial, + const char *zphone, const char *zport, + long ibaud)); + +/* Run a chat script with the other system. The chat script is a + series of expect send pairs. We wait for the expect string to show + up, and then we send the send string. The chat string for a system + holds the expect and send strings separated by a single space. */ + +boolean +fchat (qconn, puuconf, qchat, qsys, qdial, zphone, ftranslate, zport, ibaud) + struct sconnection *qconn; + pointer puuconf; + const struct uuconf_chat *qchat; + const struct uuconf_system *qsys; + const struct uuconf_dialer *qdial; + const char *zphone; + boolean ftranslate; + const char *zport; + long ibaud; +{ + int cstrings; + char **azstrings; + size_t *aclens; + char **pzchat; + char *zbuf; + size_t cbuflen; + boolean fret; + int i; + + /* First run the program, if any. */ + if (qchat->uuconf_pzprogram != NULL) + { + if (! fcprogram (qconn, puuconf, qchat->uuconf_pzprogram, qsys, qdial, + zphone, zport, ibaud)) + return FALSE; + } + + /* If there's no chat script, we're done. */ + if (qchat->uuconf_pzchat == NULL) + return TRUE; + + if (qchat->uuconf_pzfail == NULL) + { + cstrings = 1; + azstrings = (char **) xmalloc (sizeof (char *)); + aclens = (size_t *) xmalloc (sizeof (size_t)); + } + else + { + char **pz; + + /* We leave string number 0 for the chat script. */ + cstrings = 1; + for (pz = qchat->uuconf_pzfail; *pz != NULL; pz++) + ++cstrings; + + azstrings = (char **) xmalloc (cstrings * sizeof (char *)); + aclens = (size_t *) xmalloc (cstrings * sizeof (size_t)); + + /* Get the strings into the array, and handle all the escape + characters. */ + for (cstrings = 1, pz = qchat->uuconf_pzfail; + *pz != NULL; + cstrings++, pz++) + { + azstrings[cstrings] = zbufcpy (*pz); + aclens[cstrings] = cescape (azstrings[cstrings]); + } + } + + cbuflen = 0; + zbuf = NULL; + fret = TRUE; + + pzchat = qchat->uuconf_pzchat; + + while (*pzchat != NULL) + { + size_t clen; + + /* Loop over subexpects and subsends. */ + while (TRUE) + { + /* Copy the expect string into the buffer so that we can + modify it in cescape. */ + clen = strlen (*pzchat); + if (clen >= cbuflen) + { + ubuffree (zbuf); + zbuf = zbufalc (clen + 1); + cbuflen = clen; + } + memcpy (zbuf, *pzchat, clen + 1); + + azstrings[0] = zbuf; + if (azstrings[0][0] == '-') + ++azstrings[0]; + aclens[0] = cescape (azstrings[0]); + + if (aclens[0] == 0 + || (aclens[0] == 2 + && strcmp (azstrings[0], "\"\"") == 0)) + { + /* There is no subexpect sequence. If there is a + subsend sequence we move on to it. Otherwise we let + this expect succeed. This is somewhat inconsistent, + but it seems to be the traditional approach. */ + if (pzchat[1] == NULL || pzchat[1][0] != '-') + break; + } + else + { + int istr; + + istr = icexpect (qconn, cstrings, azstrings, aclens, + qchat->uuconf_ctimeout, + qchat->uuconf_fstrip); + + /* If we found the string, break out of the + subexpect/subsend loop. */ + if (istr == 0) + break; + + /* If we got an error, return FALSE. */ + if (istr < -1) + { + fret = FALSE; + break; + } + + /* If we found a failure string, log it and get out. */ + if (istr > 0) + { + ulog (LOG_ERROR, "Chat script failed: Got \"%s\"", + qchat->uuconf_pzfail[istr - 1]); + fret = FALSE; + break; + } + + /* We timed out; look for a send subsequence. If none, + the chat script has failed. */ + if (pzchat[1] == NULL || pzchat[1][0] != '-') + { + ulog (LOG_ERROR, "Timed out in chat script"); + fret = FALSE; + break; + } + } + + /* Send the send subsequence without the leading '-'. A + \"\" will send nothing. An empty string will send a + carriage return. */ + ++pzchat; + if (! fcsend (qconn, puuconf, *pzchat + 1, qsys, qdial, zphone, + ftranslate, qchat->uuconf_fstrip)) + { + fret = FALSE; + break; + } + + /* If there is no expect subsequence, we are done. */ + if (pzchat[1] == NULL || pzchat[1][0] != '-') + break; + + /* Move on to next expect subsequence. */ + ++pzchat; + } + + if (! fret) + break; + + /* Move on to the send string. If there is none, we have + succeeded. */ + do + { + ++pzchat; + } + while (*pzchat != NULL && (*pzchat)[0] == '-'); + + if (*pzchat == NULL) + break; + + if (**pzchat != '\0') + { + if (! fcsend (qconn, puuconf, *pzchat, qsys, qdial, zphone, + ftranslate, qchat->uuconf_fstrip)) + { + fret = FALSE; + break; + } + } + + ++pzchat; + } + + ubuffree (zbuf); + for (i = 1; i < cstrings; i++) + ubuffree (azstrings[i]); + xfree ((pointer) azstrings); + xfree ((pointer) aclens); + + return fret; +} + +/* Read characters and wait for one of a set of memory strings to come + in. This returns the index into the array of the string that + arrives, or -1 on timeout, or -2 on error. */ + +static int +icexpect (qconn, cstrings, azstrings, aclens, ctimeout, fstrip) + struct sconnection *qconn; + int cstrings; + char **azstrings; + size_t *aclens; + int ctimeout; + boolean fstrip; +{ + int i; + size_t cmax; + char *zhave; + size_t chave; + long iendtime; +#if DEBUG > 1 + int cchars; + int iolddebug; +#endif + + cmax = aclens[0]; + for (i = 1; i < cstrings; i++) + if (cmax < aclens[i]) + cmax = aclens[i]; + + zhave = zbufalc (cmax); + chave = 0; + + iendtime = ixsysdep_time ((long *) NULL) + ctimeout; + +#if DEBUG > 1 + cchars = 0; + iolddebug = iDebug; + if (FDEBUGGING (DEBUG_CHAT)) + { + udebug_buffer ("icexpect: Looking for", azstrings[0], + aclens[0]); + ulog (LOG_DEBUG_START, "icexpect: Got \""); + iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT); + } +#endif + + while (TRUE) + { + int bchar; + + /* If we have no more time, get out. */ + if (ctimeout <= 0) + { +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_CHAT)) + { + ulog (LOG_DEBUG_END, "\" (timed out)"); + iDebug = iolddebug; + } +#endif + ubuffree (zhave); + return -1; + } + + /* Read one character at a time. We could use a more complex + algorithm to read in larger batches, but it's probably not + worth it. If the buffer is full, shift it left; we already + know that no string matches, and the buffer holds the largest + string, so this can't lose a match. */ + if (chave >= cmax) + { + size_t imove; + + for (imove = 0; imove < cmax - 1; imove++) + zhave[imove] = zhave[imove + 1]; + --chave; + } + + /* The timeout/error return values from breceive_char are the + same as for this function. */ + bchar = breceive_char (qconn, ctimeout, TRUE); + if (bchar < 0) + { +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_CHAT)) + { + /* If there was an error, it will probably be logged in + the middle of our string, but this is only debugging + so it's not a big deal. */ + ulog (LOG_DEBUG_END, "\" (%s)", + bchar == -1 ? "timed out" : "error"); + iDebug = iolddebug; + } +#endif + ubuffree (zhave); + return bchar; + } + + /* Strip the parity bit if desired. */ + if (fstrip) + bchar &= 0x7f; + + zhave[chave] = (char) bchar; + ++chave; + +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_CHAT)) + { + char ab[5]; + + ++cchars; + if (cchars > 60) + { + ulog (LOG_DEBUG_END, "\""); + ulog (LOG_DEBUG_START, "icexpect: Got \""); + cchars = 0; + } + (void) cdebug_char (ab, bchar); + ulog (LOG_DEBUG_CONTINUE, "%s", ab); + } +#endif + + /* See if any of the strings can be found in the buffer. Since + we read one character at a time, the string can only be found + at the end of the buffer. */ + for (i = 0; i < cstrings; i++) + { + if (aclens[i] <= chave + && memcmp (zhave + chave - aclens[i], azstrings[i], + aclens[i]) == 0) + { +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_CHAT)) + { + if (i == 0) + ulog (LOG_DEBUG_END, "\" (found it)"); + else + { + ulog (LOG_DEBUG_END, "\""); + udebug_buffer ("icexpect: Found", azstrings[i], + aclens[i]); + } + iDebug = iolddebug; + } +#endif + ubuffree (zhave); + return i; + } + } + + ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL)); + } +} + +#if DEBUG > 1 + +/* Debugging function for fcsend. This takes the fquote variable, the + length of the string (0 if this an informational string which can + be printed directly) and the string itself. It returns the new + value for fquote. The fquote variable is TRUE if the debugging + output is in the middle of a quoted string. */ + +static size_t cCsend_chars; +static int iColddebug; + +static boolean fcsend_debug P((boolean, size_t, const char *)); + +static boolean +fcsend_debug (fquote, clen, zbuf) + boolean fquote; + size_t clen; + const char *zbuf; +{ + size_t cwas; + + if (! FDEBUGGING (DEBUG_CHAT)) + return TRUE; + + cwas = cCsend_chars; + if (clen > 0) + cCsend_chars += clen; + else + cCsend_chars += strlen (zbuf); + if (cCsend_chars > 60 && cwas > 10) + { + ulog (LOG_DEBUG_END, "%s", fquote ? "\"" : ""); + fquote = FALSE; + ulog (LOG_DEBUG_START, "fcsend: Writing"); + cCsend_chars = 0; + } + + if (clen == 0) + { + ulog (LOG_DEBUG_CONTINUE, "%s %s", fquote ? "\"" : "", zbuf); + return FALSE; + } + else + { + int i; + + if (! fquote) + ulog (LOG_DEBUG_CONTINUE, " \""); + for (i = 0; i < clen; i++) + { + char ab[5]; + + (void) cdebug_char (ab, zbuf[i]); + ulog (LOG_DEBUG_CONTINUE, "%s", ab); + } + + return TRUE; + } +} + +/* Finish up the debugging information for fcsend. */ + +static void ucsend_debug_end P((boolean, boolean)); + +static void +ucsend_debug_end (fquote, ferr) + boolean fquote; + boolean ferr; +{ + if (! FDEBUGGING (DEBUG_CHAT)) + return; + + if (fquote) + ulog (LOG_DEBUG_CONTINUE, "\""); + + if (ferr) + ulog (LOG_DEBUG_CONTINUE, " (error)"); + + ulog (LOG_DEBUG_END, "%s", ""); + + iDebug = iColddebug; +} + +#else /* DEBUG <= 1 */ + +/* Use macro definitions to make fcsend look neater. */ + +#define fcsend_debug(fquote, clen, zbuf) TRUE + +#define ucsend_debug_end(fquote, ferror) + +#endif /* DEBUG <= 1 */ + +/* Send a string out. This has to parse escape sequences as it goes. + Note that it handles the dialer escape sequences (\e, \E, \D, \T) + although they make no sense for chatting with a system. */ + +static boolean +fcsend (qconn, puuconf, z, qsys, qdial, zphone, ftranslate, fstrip) + struct sconnection *qconn; + pointer puuconf; + const char *z; + const struct uuconf_system *qsys; + const struct uuconf_dialer *qdial; + const char *zphone; + boolean ftranslate; + boolean fstrip; +{ + boolean fnocr; + boolean (*pfwrite) P((struct sconnection *, const char *, size_t)); + char *zcallout_login; + char *zcallout_pass; + boolean fquote; + + if (strcmp (z, "\"\"") == 0) + return TRUE; + + fnocr = FALSE; + pfwrite = fconn_write; + zcallout_login = NULL; + zcallout_pass = NULL; + +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_CHAT)) + { + ulog (LOG_DEBUG_START, "fcsend: Writing"); + fquote = FALSE; + cCsend_chars = 0; + iColddebug = iDebug; + iDebug &=~ (DEBUG_OUTGOING | DEBUG_PORT); + } +#endif + + while (*z != '\0') + { + const char *zlook; + boolean fsend; + char bsend; + + zlook = z + strcspn ((char *) z, "\\BE"); + + if (zlook > z) + { + size_t c; + + c = zlook - z; + fquote = fcsend_debug (fquote, c, z); + if (! (*pfwrite) (qconn, z, c)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + } + + if (*zlook == '\0') + break; + + z = zlook; + + fsend = FALSE; + switch (*z) + { + case 'B': + if (strncmp (z, "BREAK", 5) == 0) + { + fquote = fcsend_debug (fquote, (size_t) 0, "break"); + if (! fconn_break (qconn)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + fnocr = TRUE; + z += 5; + } + else + { + fsend = TRUE; + bsend = 'B'; + ++z; + } + break; + case 'E': + if (strncmp (z, "EOT", 3) == 0) + { + fsend = TRUE; + bsend = '\004'; + fnocr = TRUE; + z += 3; + } + else + { + fsend = TRUE; + bsend = 'E'; + ++z; + } + break; + case '\\': + ++z; + switch (*z) + { + case '-': + fsend = TRUE; + bsend = '-'; + break; + case 'b': + fsend = TRUE; + bsend = '\b'; + break; + case 'c': + fnocr = TRUE; + break; + case 'd': + fquote = fcsend_debug (fquote, (size_t) 0, "sleep"); + usysdep_sleep (2); + break; + case 'e': + fquote = fcsend_debug (fquote, (size_t) 0, "echo-check-off"); + pfwrite = fconn_write; + break; + case 'E': + fquote = fcsend_debug (fquote, (size_t) 0, "echo-check-on"); + if (fstrip) + pfwrite = fcecho_send_strip; + else + pfwrite = fcecho_send_nostrip; + break; + case 'K': + fquote = fcsend_debug (fquote, (size_t) 0, "break"); + if (! fconn_break (qconn)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + break; + case 'n': + fsend = TRUE; + bsend = '\n'; + break; + case 'N': + fsend = TRUE; + bsend = '\0'; + break; + case 'p': + fquote = fcsend_debug (fquote, (size_t) 0, "pause"); + usysdep_pause (); + break; + case 'r': + fsend = TRUE; + bsend = '\r'; + break; + case 's': + fsend = TRUE; + bsend = ' '; + break; + case 't': + fsend = TRUE; + bsend = '\t'; + break; + case '\0': + --z; + /* Fall through. */ + case '\\': + fsend = TRUE; + bsend = '\\'; + break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + fsend = TRUE; + bsend = *z - '0'; + if (z[1] >= '0' && z[1] <= '7') + bsend = (char) (8 * bsend + *++z - '0'); + if (z[1] >= '0' && z[1] <= '7') + bsend = (char) (8 * bsend + *++z - '0'); + break; + case 'x': + fsend = TRUE; + bsend = 0; + while (isxdigit (BUCHAR (z[1]))) + { + if (isdigit (BUCHAR (z[1]))) + bsend = (char) (16 * bsend + *++z - '0'); + else if (isupper (BUCHAR (z[1]))) + bsend = (char) (16 * bsend + *++z - 'A'); + else + bsend = (char) (16 * bsend + *++z - 'a'); + } + break; + case 'L': + { + const char *zlog; + + if (qsys == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "Illegal use of \\L"); + return FALSE; + } + zlog = qsys->uuconf_zcall_login; + if (zlog == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "No login defined"); + return FALSE; + } + if (zlog[0] == '*' && zlog[1] == '\0') + { + if (zcallout_login == NULL) + { + int iuuconf; + + iuuconf = uuconf_callout (puuconf, qsys, + &zcallout_login, + &zcallout_pass); + if (iuuconf == UUCONF_NOT_FOUND + || zcallout_login == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "No login defined"); + return FALSE; + } + else if (iuuconf != UUCONF_SUCCESS) + { + ucsend_debug_end (fquote, TRUE); + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + return FALSE; + } + } + zlog = zcallout_login; + } + fquote = fcsend_debug (fquote, (size_t) 0, "login"); + fquote = fcsend_debug (fquote, strlen (zlog), zlog); + if (! (*pfwrite) (qconn, zlog, strlen (zlog))) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + } + break; + case 'P': + { + const char *zpass; + + if (qsys == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "Illegal use of \\P"); + return FALSE; + } + zpass = qsys->uuconf_zcall_password; + if (zpass == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "No password defined"); + return FALSE; + } + if (zpass[0] == '*' && zpass[1] == '\0') + { + if (zcallout_pass == NULL) + { + int iuuconf; + + iuuconf = uuconf_callout (puuconf, qsys, + &zcallout_login, + &zcallout_pass); + if (iuuconf == UUCONF_NOT_FOUND + || zcallout_pass == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "No password defined"); + return FALSE; + } + else if (iuuconf != UUCONF_SUCCESS) + { + ucsend_debug_end (fquote, TRUE); + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + return FALSE; + } + } + zpass = zcallout_pass; + } + fquote = fcsend_debug (fquote, (size_t) 0, "password"); + fquote = fcsend_debug (fquote, strlen (zpass), zpass); + if (! (*pfwrite) (qconn, zpass, strlen (zpass))) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + } + break; + case 'D': + if (qdial == NULL || zphone == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "Illegal use of \\D"); + return FALSE; + } + fquote = fcsend_debug (fquote, (size_t) 0, "\\D"); + if (! fcphone (qconn, puuconf, qdial, zphone, pfwrite, + ftranslate, &fquote)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + break; + case 'T': + if (qdial == NULL || zphone == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "Illegal use of \\T"); + return FALSE; + } + fquote = fcsend_debug (fquote, (size_t) 0, "\\T"); + if (! fcphone (qconn, puuconf, qdial, zphone, pfwrite, TRUE, + &fquote)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + break; + case 'M': + if (qdial == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "Illegal use of \\M"); + return FALSE; + } + fquote = fcsend_debug (fquote, (size_t) 0, "ignore-carrier"); + if (! fconn_carrier (qconn, FALSE)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + break; + case 'm': + if (qdial == NULL) + { + ucsend_debug_end (fquote, TRUE); + ulog (LOG_ERROR, "Illegal use of \\m"); + return FALSE; + } + if (qdial->uuconf_fcarrier) + { + fquote = fcsend_debug (fquote, (size_t) 0, "need-carrier"); + if (! fconn_carrier (qconn, TRUE)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + } + break; + default: + /* This error message will screw up any debugging + information, but it's easily avoidable. */ + ulog (LOG_ERROR, + "Unrecognized escape sequence \\%c in send string", + *z); + fsend = TRUE; + bsend = *z; + break; + } + ++z; + break; +#if DEBUG > 0 + default: + ulog (LOG_FATAL, "fcsend: Can't happen"); + break; +#endif + } + + if (fsend) + { + fquote = fcsend_debug (fquote, (size_t) 1, &bsend); + if (! (*pfwrite) (qconn, &bsend, (size_t) 1)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + } + } + + xfree ((pointer) zcallout_login); + xfree ((pointer) zcallout_pass); + + /* Output a final carriage return, unless there was a \c. Don't + bother to check for an echo. */ + if (! fnocr) + { + char b; + + b = '\r'; + fquote = fcsend_debug (fquote, (size_t) 1, &b); + if (! fconn_write (qconn, &b, (size_t) 1)) + { + ucsend_debug_end (fquote, TRUE); + return FALSE; + } + } + + ucsend_debug_end (fquote, FALSE); + + return TRUE; +} + +/* Write out a phone number with optional dialcode translation. The + pfquote argument is only used for debugging. */ + +static boolean +fcphone (qconn, puuconf, qdial, zphone, pfwrite, ftranslate, pfquote) + struct sconnection *qconn; + pointer puuconf; + const struct uuconf_dialer *qdial; + const char *zphone; + boolean (*pfwrite) P((struct sconnection *qc, const char *zwrite, + size_t cwrite)); + boolean ftranslate; + boolean *pfquote; +{ + const char *zprefix, *zsuffix; + + if (ftranslate) + { + if (! fctranslate (puuconf, zphone, &zprefix, &zsuffix)) + return FALSE; + } + else + { + zprefix = zphone; + zsuffix = NULL; + } + + while (zprefix != NULL) + { + while (TRUE) + { + const char *z; + const char *zstr; + + z = zprefix + strcspn ((char *) zprefix, "=-"); + if (z > zprefix) + { + size_t clen; + + clen = z - zprefix; + *pfquote = fcsend_debug (*pfquote, clen, zprefix); + if (! (*pfwrite) (qconn, zprefix, clen)) + return FALSE; + } + + if (*z == '=') + zstr = qdial->uuconf_zdialtone; + else if (*z == '-') + zstr = qdial->uuconf_zpause; + else /* *z == '\0' */ + break; + + if (zstr != NULL) + { + *pfquote = fcsend_debug (*pfquote, strlen (zstr), zstr); + if (! (*pfwrite) (qconn, zstr, strlen (zstr))) + return FALSE; + } + + zprefix = z + 1; + } + + zprefix = zsuffix; + zsuffix = NULL; + } + + return TRUE; +} + +/* Given a phone number, run it through dial code translation + returning two strings. */ + +static boolean +fctranslate (puuconf, zphone, pzprefix, pzsuffix) + pointer puuconf; + const char *zphone; + const char **pzprefix; + const char **pzsuffix; +{ + int iuuconf; + char *zdialcode, *zto; + const char *zfrom; + char *ztrans; + + *pzprefix = zphone; + *pzsuffix = NULL; + + zdialcode = zbufalc (strlen (zphone) + 1); + zfrom = zphone; + zto = zdialcode; + while (*zfrom != '\0' && isalpha (BUCHAR (*zfrom))) + *zto++ = *zfrom++; + *zto = '\0'; + + if (*zdialcode == '\0') + { + ubuffree (zdialcode); + return TRUE; + } + + iuuconf = uuconf_dialcode (puuconf, zdialcode, &ztrans); + + ubuffree (zdialcode); + + if (iuuconf == UUCONF_NOT_FOUND) + return TRUE; + else if (iuuconf != UUCONF_SUCCESS) + { + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + return FALSE; + } + else + { + /* We really should figure out a way to free up ztrans here. */ + *pzprefix = ztrans; + *pzsuffix = zfrom; + return TRUE; + } +} + +/* Write out a string making sure the each character is echoed back. + There are two versions of this function, one which strips the + parity bit from the characters and one which does not. This is so + that I can use a single function pointer in fcsend, and to avoid + using any static variables so that I can put chat scripts in a + library some day. */ + +static boolean +fcecho_send_strip (qconn, zwrite, cwrite) + struct sconnection *qconn; + const char *zwrite; + size_t cwrite; +{ + return fcecho_send (qconn, zwrite, cwrite, TRUE); +} + +static boolean +fcecho_send_nostrip (qconn, zwrite, cwrite) + struct sconnection *qconn; + const char *zwrite; + size_t cwrite; +{ + return fcecho_send (qconn, zwrite, cwrite, FALSE); +} + +static boolean +fcecho_send (qconn, zwrite, cwrite, fstrip) + struct sconnection *qconn; + const char *zwrite; + size_t cwrite; + boolean fstrip; +{ + const char *zend; + + zend = zwrite + cwrite; + + for (; zwrite < zend; zwrite++) + { + int b; + char bwrite; + + bwrite = *zwrite; + if (! fconn_write (qconn, &bwrite, (size_t) 1)) + return FALSE; + if (fstrip) + bwrite &= 0x7f; + do + { + /* We arbitrarily wait five seconds for the echo. */ + b = breceive_char (qconn, 5, TRUE); + /* Now b == -1 on timeout, -2 on error. */ + if (b < 0) + { + if (b == -1) + ulog (LOG_ERROR, "Character not echoed"); + return FALSE; + } + if (fstrip) + b &= 0x7f; + } + while (b != BUCHAR (bwrite)); + } + + return TRUE; +} + +/* Run a chat program. Expand any escape sequences and call a system + dependent program to run it. */ + +static boolean +fcprogram (qconn, puuconf, pzprogram, qsys, qdial, zphone, zport, ibaud) + struct sconnection *qconn; + pointer puuconf; + char **pzprogram; + const struct uuconf_system *qsys; + const struct uuconf_dialer *qdial; + const char *zphone; + const char *zport; + long ibaud; +{ + size_t cargs; + char **pzpass, **pzarg; + char **pz; + char *zcallout_login; + char *zcallout_pass; + boolean fret; + + cargs = 1; + for (pz = pzprogram; *pz != NULL; pz++) + ++cargs; + + pzpass = (char **) xmalloc (cargs * sizeof (char *)); + + zcallout_login = NULL; + zcallout_pass = NULL; + fret = TRUE; + + /* Copy the string into memory expanding escape sequences. */ + for (pz = pzprogram, pzarg = pzpass; *pz != NULL; pz++, pzarg++) + { + const char *zfrom; + size_t calc, clen; + char *zto; + + if (strchr (*pz, '\\') == NULL) + { + *pzarg = zbufcpy (*pz); + continue; + } + + *pzarg = NULL; + zto = NULL; + calc = 0; + clen = 0; + + for (zfrom = *pz; *zfrom != '\0'; zfrom++) + { + const char *zadd = NULL; + size_t cadd; + char abadd[15]; + + if (*zfrom != '\\') + { + if (clen + 2 > calc) + { + char *znew; + + calc = clen + 50; + znew = zbufalc (calc); + memcpy (znew, *pzarg, clen); + ubuffree (*pzarg); + *pzarg = znew; + zto = znew + clen; + } + *zto++ = *zfrom; + ++clen; + continue; + } + + ++zfrom; + switch (*zfrom) + { + case '\0': + --zfrom; + /* Fall through. */ + case '\\': + zadd = "\\"; + break; + case 'L': + { + const char *zlog; + + if (qsys == NULL) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\L"); + fret = FALSE; + break; + } + zlog = qsys->uuconf_zcall_login; + if (zlog == NULL) + { + ulog (LOG_ERROR, "chat-program: No login defined"); + fret = FALSE; + break; + } + if (zlog[0] == '*' && zlog[1] == '\0') + { + if (zcallout_login == NULL) + { + int iuuconf; + + iuuconf = uuconf_callout (puuconf, qsys, + &zcallout_login, + &zcallout_pass); + if (iuuconf == UUCONF_NOT_FOUND + || zcallout_login == NULL) + { + ulog (LOG_ERROR, + "chat-program: No login defined"); + fret = FALSE; + break; + } + else if (iuuconf != UUCONF_SUCCESS) + { + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + fret = FALSE; + break; + } + } + zlog = zcallout_login; + } + zadd = zlog; + } + break; + case 'P': + { + const char *zpass; + + if (qsys == NULL) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\P"); + fret = FALSE; + break; + } + zpass = qsys->uuconf_zcall_password; + if (zpass == NULL) + { + ulog (LOG_ERROR, "chat-program: No password defined"); + fret = FALSE; + break; + } + if (zpass[0] == '*' && zpass[1] == '\0') + { + if (zcallout_pass == NULL) + { + int iuuconf; + + iuuconf = uuconf_callout (puuconf, qsys, + &zcallout_login, + &zcallout_pass); + if (iuuconf == UUCONF_NOT_FOUND + || zcallout_pass == NULL) + { + ulog (LOG_ERROR, + "chat-program: No password defined"); + fret = FALSE; + break; + } + else if (iuuconf != UUCONF_SUCCESS) + { + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + fret = FALSE; + break; + } + } + zpass = zcallout_pass; + } + zadd = zpass; + } + break; + case 'D': + if (qdial == NULL || zphone == NULL) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\D"); + fret = FALSE; + break; + } + zadd = zphone; + break; + case 'T': + { + const char *zprefix, *zsuffix; + + if (qdial == NULL || zphone == NULL) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\T"); + fret = FALSE; + break; + } + + if (! fctranslate (puuconf, zphone, &zprefix, &zsuffix)) + { + fret = FALSE; + break; + } + + if (zsuffix == NULL) + zadd = zprefix; + else + { + size_t cprefix; + + cprefix = strlen (zprefix); + if (clen + cprefix + 1 > calc) + { + char *znew; + + calc = clen + cprefix + 20; + znew = zbufalc (calc); + memcpy (znew, *pzarg, clen); + ubuffree (*pzarg); + *pzarg = znew; + zto = znew + clen; + } + memcpy (zto, zprefix, cprefix); + zto += cprefix; + clen += cprefix; + zadd = zsuffix; + } + } + break; + case 'Y': + if (zLdevice == NULL && zport == NULL) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\Y"); + fret = FALSE; + break; + } + /* zLdevice will generally make more sense than zport, but + it might not be set yet. */ + zadd = zLdevice; + if (zadd == NULL) + zadd = zport; + break; + case 'Z': + if (qsys == NULL) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\Z"); + fret = FALSE; + break; + } + zadd = qsys->uuconf_zname; + break; + case 'S': + { + if (ibaud == 0) + { + ulog (LOG_ERROR, "chat-program: Illegal use of \\S"); + fret = FALSE; + break; + } + sprintf (abadd, "%ld", ibaud); + zadd = abadd; + } + break; + default: + { + ulog (LOG_ERROR, + "chat-program: Unrecognized escape sequence \\%c", + *zfrom); + abadd[0] = *zfrom; + abadd[1] = '\0'; + zadd = abadd; + } + break; + } + + if (! fret) + break; + + cadd = strlen (zadd); + if (clen + cadd + 1 > calc) + { + char *znew; + + calc = clen + cadd + 20; + znew = zbufalc (calc); + memcpy (znew, *pzarg, clen); + ubuffree (*pzarg); + *pzarg = znew; + zto = znew + clen; + } + memcpy (zto, zadd, cadd + 1); + zto += cadd; + clen += cadd; + } + + if (! fret) + break; + + *zto++ = '\0'; + ++clen; + } + + *pzarg = NULL; + + if (fret) + fret = fconn_run_chat (qconn, pzpass); + + for (pz = pzpass; *pz != NULL; pz++) + ubuffree (*pz); + xfree ((pointer) pzpass); + xfree ((pointer) zcallout_login); + xfree ((pointer) zcallout_pass); + + return fret; +} diff --git a/gnu/libexec/uucp/common_sources/conf.h b/gnu/libexec/uucp/common_sources/conf.h new file mode 100644 index 000000000000..9053c4423e0a --- /dev/null +++ b/gnu/libexec/uucp/common_sources/conf.h @@ -0,0 +1,444 @@ +/* conf.h. Generated automatically by configure. */ +/* Configuration header file for Taylor UUCP. -*- C -*- */ + +/* Set MAIL_PROGRAM to a program which takes a mail address as an + argument and accepts a mail message to send to that address on + stdin (e.g. "/bin/mail"). */ +#define MAIL_PROGRAM "/usr/bin/mail" + +/* Set ECHO_PROGRAM to a program which echoes its arguments; if echo + is a shell builtin you can just use "echo". */ +#define ECHO_PROGRAM "echo" + +/* The following macros indicate what header files you have. Set the + macro to 1 if you have the corresponding header file, or 0 if you + do not. */ +#define HAVE_STDDEF_H 1 /* <stddef.h> */ +#define HAVE_STRING_H 1 /* <string.h> */ +#define HAVE_STRINGS_H 1 /* <strings.h> */ +#define HAVE_UNISTD_H 1 /* <unistd.h> */ +#define HAVE_STDLIB_H 1 /* <stdlib.h> */ +#define HAVE_LIMITS_H 1 /* <limits.h> */ +#define HAVE_TIME_H 1 /* <time.h> */ +#define HAVE_SYS_WAIT_H 1 /* <sys/wait.h> */ +#define HAVE_SYS_IOCTL_H 1 /* <sys/ioctl.h> */ +#define HAVE_DIRENT_H 1 /* <dirent.h> */ +#define HAVE_MEMORY_H 1 /* <memory.h> */ +#define HAVE_SYS_PARAM_H 1 /* <sys/param.h> */ +#define HAVE_UTIME_H 1 /* <utime.h> */ +#define HAVE_FCNTL_H 1 /* <fcntl.h> */ +#define HAVE_SYS_FILE_H 1 /* <sys/file.h> */ +#define HAVE_SYS_TIMES_H 1 /* <sys/times.h> */ +#define HAVE_LIBC_H 0 /* <libc.h> */ +#define HAVE_SYSEXITS_H 1 /* <sysexits.h> */ +#define HAVE_POLL_H 0 /* <poll.h> */ +#define HAVE_TIUSER_H 0 /* <tiuser.h> */ +#define HAVE_XTI_H 0 /* <xti.h> */ +#define HAVE_SYS_TLI_H 0 /* <sys/tli.h> */ +#define HAVE_STROPTS_H 0 /* <stropts.h> */ +#define HAVE_FTW_H 0 /* <ftw.h> */ +#define HAVE_GLOB_H 1 /* <glob.h> */ +#define HAVE_SYS_SELECT_H 0 /* <sys/select.h> */ +#define HAVE_SYS_TYPES_TCP_H 0 /* <sys/types.tcp.h> */ + +/* If major and minor are not defined in <sys/types.h>, but are in + <sys/mkdev.h>, set MAJOR_IN_MKDEV to 1. If they are in + <sys/sysmacros.h>, set MAJOR_IN_SYSMACROS to 1. */ +#define MAJOR_IN_MKDEV 0 +#define MAJOR_IN_SYSMACROS 0 + +/* If the macro offsetof is not defined in <stddef.h>, you may give it + a definition here. If you do not, the code will use a definition + (in uucp.h) that should be fairly portable. */ +/* #define offsetof */ + +/* Set RETSIGTYPE to the return type of a signal handler. On newer + systems this will be void; some older systems use int. */ +#define RETSIGTYPE void + +/* Set HAVE_SYS_TIME_AND_TIME_H to 1 if <time.h> and <sys/time.h> can both + be included in a single source file; if you don't have either or both of + them, it doesn't matter what you set this to. */ +#define HAVE_SYS_TIME_AND_TIME_H 1 + +/* Set HAVE_TERMIOS_AND_SYS_IOCTL_H to 1 if <termios.h> and <sys/ioctl.h> + can both be included in a single source file; if you don't have either + or both of them, it doesn't matter what you set this to. */ +#define HAVE_TERMIOS_AND_SYS_IOCTL_H 1 + +/* If you are configuring by hand, you should set one of the terminal + driver options in policy.h. If you are autoconfiguring, the script + will check whether your system defines CBREAK, which is a terminal + setting; if your system supports CBREAK, and you don't set a terminal + driver in policy.h, the code will assume that you have a BSD style + terminal driver. */ +#define HAVE_CBREAK 1 + +/* The package needs several standard types. If you are using the + configure script, it will look in standard places for these types, + and give default definitions for them here if it doesn't find them. + The default definitions should work on most systems, but you may + want to check them. If you are configuring by hand, you will have + to figure out whether the types are defined on your system, and + what they should be defined to. + + Any type that is not defined on your system should get a macro + definition. The definition should be of the name of the type in + all capital letters. For example, #define PID_T int. If the type + is defined in a standard header file, the macro name should not be + defined. */ + +/* The type pid_t is used to hold a process ID number. It is normally + defined in <sys/types.h>. This is the type returned by the + functions fork or getpid. Usually int will work fine. */ +#undef PID_T + +/* The type uid_t is used to hold a user ID number. It is normally + defined in <sys/types.h>. This is the type returned by the getuid + function. Usually int will work fine. */ +#undef UID_T + +/* The type gid_t is used to hold a group ID number. It is sometimes + defined in <sys/types.h>. This is the type returned by the getgid + function. Usually int will work fine. */ +#undef GID_T + +/* The type off_t is used to hold an offset in a file. It is sometimes + defined in <sys/types.h>. This is the type of the second argument to + the lseek function. Usually long will work fine. */ +#undef OFF_T + +/* Set HAVE_SIG_ATOMIC_T_IN_SIGNAL_H if the type sig_atomic_t is defined + in <signal.h> as required by ANSI C. */ +#define HAVE_SIG_ATOMIC_T_IN_SIGNAL_H 0 + +/* Set HAVE_SIG_ATOMIC_T_IN_TYPES_H if the type sig_atomic_t is defined + in <sys/types.h>. This is ignored if HAVE_SIG_ATOMIC_T_IN_SIGNAL_H is + set to 1. */ +#define HAVE_SIG_ATOMIC_T_IN_TYPES_H 0 + +/* The type sig_atomic_t is used to hold a value which may be + referenced in a single atomic operation. If it is not defined in + either <signal.h> or <sys/types.h>, you may want to give it a + definition here. If you don't, the code will use char. If your + compiler does not support sig_atomic_t, there is no type which is + really correct; fortunately, for this package it does not really + matter very much. */ +#undef SIG_ATOMIC_T + +/* Set HAVE_SIZE_T_IN_STDDEF_H to 1 if the type size_t is defined in + <stddef.h> as required by ANSI C. */ +#define HAVE_SIZE_T_IN_STDDEF_H 1 + +/* Set HAVE_SIZE_T_IN_TYPES_H to 1 if the type size_t is defined in + <sys/types.h>. This is ignored if HAVE_SIZE_T_IN_STDDEF_H is set + to 1. */ +#define HAVE_SIZE_T_IN_TYPES_H 1 + +/* The type size_t is used to hold the size of an object. In + particular, an argument of this type is passed as the size argument + to the malloc and realloc functions. If size_t is not defined in + either <stddef.h> or <sys/types.h>, you may want to give it a + definition here. If you don't, the code will use unsigned. */ +#undef SIZE_T + +/* Set HAVE_TIME_T_IN_TIME_H to 1 if the type time_t is defined in + <time.h>, as required by the ANSI C standard. */ +#define HAVE_TIME_T_IN_TIME_H 1 + +/* Set HAVE_TIME_T_IN_TYPES_H to 1 if the type time_t is defined in + <sys/types.h>. This is ignored if HAVE_TIME_T_IN_TIME_H is set to + 1. */ +#define HAVE_TIME_T_IN_TYPES_H 1 + +/* When Taylor UUCP is talking to another instance of itself, it will + tell the other side the size of a file before it is transferred. + If the package can determine how much disk space is available, it + will use this information to avoid filling up the disk. Define one + of the following macros to tell the code how to determine the + amount of available disk space. It is possible that none of these + are appropriate; it will do no harm to use none of them, but, of + course, nothing will then prevent the package from filling up the + disk. Note that this space check is only useful when talking to + another instance of Taylor UUCP. + + STAT_STATVFS statvfs function + STAT_STATFS2_BSIZE two argument statfs function with f_bsize field + STAT_STATFS2_FSIZE two argument statfs function with f_fsize field + STAT_STATFS2_FS_DATA two argument statfs function with fd_req field + STAT_STATFS4 four argument statfs function + STAT_USTAT the ustat function with 512 byte blocks. */ +#define STAT_STATVFS 0 +#define STAT_STATFS2_BSIZE 0 +#define STAT_STATFS2_FSIZE 1 +#define STAT_STATFS2_FS_DATA 0 +#define STAT_STATFS4 0 +#define STAT_USTAT 0 + +/* Set HAVE_VOID to 1 if the compiler supports declaring functions with + a return type of void and casting values to void. */ +#define HAVE_VOID 1 + +/* Set HAVE_UNSIGNED_CHAR to 1 if the compiler supports the type unsigned + char. */ +#define HAVE_UNSIGNED_CHAR 1 + +/* Set HAVE_ERRNO_DECLARATION to 1 if errno is declared in <errno.h>. */ +#define HAVE_ERRNO_DECLARATION 1 + +/* There are now a number of functions to check for. For each of + these, the macro HAVE_FUNC should be set to 1 if your system has + FUNC. For example, HAVE_VFPRINTF should be set to 1 if your system + has vfprintf, 0 otherwise. */ + +/* Taylor UUCP will take advantage of the following functions if they + are available, but knows how to deal with their absence. */ +#define HAVE_VFPRINTF 1 +#define HAVE_FTRUNCATE 1 +#define HAVE_LTRUNC 0 +#define HAVE_WAITPID 1 +#define HAVE_WAIT4 1 +#define HAVE_GLOB 1 +#define HAVE_SETREUID 1 + +/* There are several functions which are replaced in the subdirectory + lib. If they are missing, the configure script will automatically + add them to lib/Makefile to force them to be recompiled. If you + are configuring by hand, you will have to do this yourself. The + string @LIBOBJS@ in lib/Makefile.in should be replaced by a list of + object files in lib/Makefile. The following comments tell you + which object file names to add (they are generally fairly obvious, + given that the file names have no more than six characters before + the period). */ + +/* For each of these functions, if it does not exist, the indicated + object file should be added to lib/Makefile. */ +#define HAVE_BSEARCH 1 /* bsrch.o */ +#define HAVE_GETLINE 0 /* getlin.o */ +#define HAVE_MEMCHR 1 /* memchr.o */ +#define HAVE_STRDUP 1 /* strdup.o */ +#define HAVE_STRSTR 1 /* strstr.o */ +#define HAVE_STRTOL 1 /* strtol.o */ + +/* If neither of these functions exists, you should add bzero.o to + lib/Makefile. */ +#define HAVE_BZERO 1 +#define HAVE_MEMSET 1 + +/* If neither of these functions exists, you should add memcmp.o to + lib/Makefile. */ +#define HAVE_MEMCMP 1 +#define HAVE_BCMP 1 + +/* If neither of these functions exists, you should add memcpy.o to + lib/Makefile. */ +#define HAVE_MEMCPY 1 +#define HAVE_BCOPY 1 + +/* If neither of these functions exists, you should add strcas.o to + lib/Makefile. */ +#define HAVE_STRCASECMP 1 +#define HAVE_STRICMP 0 + +/* If neither of these functions exists, you should add strncs.o to + lib/Makefile. */ +#define HAVE_STRNCASECMP 1 +#define HAVE_STRNICMP 0 + +/* If neither of these functions exists, you should add strchr.o to + lib/Makefile. */ +#define HAVE_STRCHR 1 +#define HAVE_INDEX 1 + +/* If neither of these functions exists, you should add strrch.o to + lib/Makefile. */ +#define HAVE_STRRCHR 1 +#define HAVE_RINDEX 1 + +/* There are also Unix specific functions which are replaced in the + subdirectory unix. If they are missing, the configure script will + automatically add them to unix/Makefile to force them to be + recompiled. If you are configuring by hand, you will have to do + this yourself. The string @UNIXOBJS@ in unix/Makefile.in should be + replaced by a list of object files in unix/Makefile. The following + comments tell you which object file names to add. */ + +/* For each of these functions, if it does not exist, the indicated + object file should be added to unix/Makefile. */ +#define HAVE_OPENDIR 1 /* dirent.o */ +#define HAVE_DUP2 1 /* dup2.o */ +#define HAVE_FTW 0 /* ftw.o */ +#define HAVE_REMOVE 1 /* remove.o */ +#define HAVE_RENAME 1 /* rename.o */ +#define HAVE_STRERROR 1 /* strerr.o */ + +/* The code needs to know how to create directories. If you have the + mkdir function, set HAVE_MKDIR to 1 and replace @UUDIR@ in + Makefile.in with '# ' (the configure script will set @UUDIR@ + according to the variable UUDIR). Otherwise, set HAVE_MKDIR to 0, + remove @UUDIR@ from Makefile.in, set MKDIR_PROGRAM to the name of + the program which will create a directory named on the command line + (e.g., "/bin/mkdir"), and add mkdir.o to the @UNIXOBJS@ string in + unix/Makefile.in. */ +#define HAVE_MKDIR 1 +#define MKDIR_PROGRAM unused + +/* The code also needs to know how to remove directories. If you have + the rmdir function, set HAVE_RMDIR to 1. Otherwise, set + RMDIR_PROGRAM to the name of the program which will remove a + directory named on the command line (e.g., "/bin/rmdir") and add + rmdir.o to the @UNIXOBJS@ string in unix/Makefile.in. */ +#define HAVE_RMDIR 1 +#define RMDIR_PROGRAM unused + +/* The code needs to know to how to get the name of the current + directory. If getcwd is available it will be used, otherwise if + getwd is available it will be used. Otherwise, set PWD_PROGRAM to + the name of the program which will print the name of the current + working directory (e.g., "/bin/pwd") and add getcwd.o to the + @UNIXOBJS@ string in unix/Makefile.in. */ +#define HAVE_GETCWD 1 +#define HAVE_GETWD 1 +#define PWD_PROGRAM unused + +/* If you have either sigsetjmp or setret, it will be used instead of + setjmp. These functions will only be used if your system restarts + system calls after interrupts (see HAVE_RESTARTABLE_SYSCALLS, + below). */ +#define HAVE_SIGSETJMP 0 +#define HAVE_SETRET 0 + +/* The code needs to know what function to use to set a signal + handler. If will try to use each of the following functions in + turn. If none are available, it will use signal, which is assumed + to always exist. */ +#define HAVE_SIGACTION 1 +#define HAVE_SIGVEC 1 +#define HAVE_SIGSET 0 + +/* If the code is going to use sigvec (HAVE_SIGACTION is 0 and + HAVE_SIGVEC is 1), then HAVE_SIGVEC_SV_FLAGS must be set to 1 if + the sigvec structure contains the sv_flags field, or 0 if the + sigvec structure contains the sv_onstack field. If the code is not + going to use sigvec, it doesn't matter what this is set to. */ +#define HAVE_SIGVEC_SV_FLAGS 1 + +/* The code will try to use each of the following functions in turn + when blocking signals from delivery. If none are available, a + relatively unimportant race condition will exist. */ +#define HAVE_SIGPROCMASK 1 +#define HAVE_SIGBLOCK 1 +#define HAVE_SIGHOLD 0 + +/* If you have either of the following functions, it will be used to + determine the number of file descriptors which may be open. + Otherwise, the code will use OPEN_MAX if defined, then NOFILE if + defined, then 20. */ +#define HAVE_GETDTABLESIZE 1 +#define HAVE_SYSCONF 0 + +/* The code will use one of the following functions when detaching + from a terminal. One of these must exist. */ +#define HAVE_SETPGRP 0 +#define HAVE_SETSID 1 + +/* If you do not specify the local node name in the main configuration + file, Taylor UUCP will try to use each of the following functions + in turn. If neither is available, you must specify the local node + name in the configuration file. */ +#define HAVE_GETHOSTNAME 1 +#define HAVE_UNAME 0 + +/* The code will try to use each of the following functions in turn to + determine the current time. If none are available, it will use + time, which is assumed to always exist. */ +#define HAVE_GETTIMEOFDAY 1 +#define HAVE_FTIME 0 + +/* If neither gettimeofday nor ftime is available, the code will use + times (if available) to measure a span of time. See also the + discussion of TIMES_TICK in policy.h. */ +#define HAVE_TIMES 1 + +/* When a chat script requests a pause of less than a second with \p, + Taylor UUCP will try to use each of the following functions in + turn. If none are available, it will sleep for a full second. + Also, the (non-portable) tstuu program requires either select or + poll. */ +#define HAVE_NAPMS 0 +#define HAVE_NAP 0 +#define HAVE_USLEEP 1 +#define HAVE_POLL 0 +#define HAVE_SELECT 1 + +/* If the getgrent function is available, it will be used to determine + all the groups a user belongs to when checking file access + permissions. */ +#define HAVE_GETGRENT 1 + +/* If the socket function is available, TCP support code will be + compiled in. */ +#define HAVE_SOCKET 1 + +/* If the t_open function is available, TLI support code will be + compiled in. This may require adding a library, such as -lnsl or + -lxti, to the Makefile variables LIBS. */ +#define HAVE_T_OPEN 0 + +/* That's the end of the list of the functions. Now there are a few + last miscellaneous items. */ + +/* On some systems the following functions are declared in such a way + that the code cannot make a simple extern. On other systems, these + functions are not declared at all, and the extern is required. If + a declaration of the function, as shown, compiles on your system, + set the value to 1. Not all functions declared externally are + listed here, only the ones with which I have had trouble. */ +/* extern long times (); */ +#define TIMES_DECLARATION_OK 0 +/* extern struct passwd *getpwnam (); */ +#define GETPWNAM_DECLARATION_OK 1 +/* extern struct passwd *getpwuid (); */ +#define GETPWUID_DECLARATION_OK 0 +/* extern struct group *getgrent (); */ +#define GETGRENT_DECLARATION_OK 1 + +/* Set HAVE_BSD_PGRP to 1 if your getpgrp call takes 1 argument and + your setpgrp calls takes 2 arguments (on System V they generally + take no arguments). You can safely set this to 1 on System V, + provided the call will compile without any errors. */ +#define HAVE_BSD_PGRP 0 + +/* Set HAVE_UNION_WAIT to 1 if union wait is defined in the header + file <sys/wait.h>. */ +#define HAVE_UNION_WAIT 1 + +/* Set HAVE_LONG_FILE_NAMES to 1 if the system supports file names + longer than 14 characters. */ +#define HAVE_LONG_FILE_NAMES 1 + +/* If slow system calls are restarted after interrupts, set + HAVE_RESTARTABLE_SYSCALLS to 1. This is ignored if HAVE_SIGACTION + is 1 or if HAVE_SIGVEC is 1 and HAVE_SIGVEC_SV_FLAGS is 1 and + SV_INTERRUPT is defined in <signal.h>. In both of these cases + system calls can be prevented from restarting. */ +#define HAVE_RESTARTABLE_SYSCALLS 1 + +/* Some systems supposedly need the following macros to be defined. + These are handled by the configure script (it will turn #undef into + #define when appropriate, which is why the peculiar #ifndef #undef + construction is used). If you are configuring by hand, you may add + appropriate definitions here, or just add them to CFLAGS when + running make. */ +#ifndef _ALL_SOURCE +#undef _ALL_SOURCE +#endif +#ifndef _POSIX_SOURCE +#undef _POSIX_SOURCE +#endif +#ifndef _MINIX +#undef _MINIX +#endif +#ifndef _POSIX_1_SOURCE +#undef _POSIX_1_SOURCE +#endif diff --git a/gnu/libexec/uucp/common_sources/conn.c b/gnu/libexec/uucp/common_sources/conn.c new file mode 100644 index 000000000000..8db53516a685 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/conn.c @@ -0,0 +1,552 @@ +/* conn.c + Connection routines for the Taylor UUCP package. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char conn_rcsid[] = "$Id: conn.c,v 1.1 1993/08/05 18:22:35 conklin Exp $"; +#endif + +#include <ctype.h> + +#include "uudefs.h" +#include "uuconf.h" +#include "conn.h" + +static boolean fcdo_dial P((struct sconnection *qconn, pointer puuconf, + struct uuconf_dialer *qdialer, + const char *zphone, boolean ftranslate)); + +/* Create a new connection. This relies on system dependent functions + to set the qcmds and psysdep fields. If qport is NULL, it opens a + standard input port. */ + +boolean +fconn_init (qport, qconn) + struct uuconf_port *qport; + struct sconnection *qconn; +{ + qconn->qport = qport; + switch (qport == NULL ? UUCONF_PORTTYPE_STDIN : qport->uuconf_ttype) + { + case UUCONF_PORTTYPE_STDIN: + return fsysdep_stdin_init (qconn); + case UUCONF_PORTTYPE_MODEM: + return fsysdep_modem_init (qconn); + case UUCONF_PORTTYPE_DIRECT: + return fsysdep_direct_init (qconn); +#if HAVE_TCP + case UUCONF_PORTTYPE_TCP: + return fsysdep_tcp_init (qconn); +#endif +#if HAVE_TLI + case UUCONF_PORTTYPE_TLI: + return fsysdep_tli_init (qconn); +#endif + default: + ulog (LOG_ERROR, "Unknown port type"); + return FALSE; + } +} + +/* Connection dispatch routines. */ + +/* Free a connection. */ + +void +uconn_free (qconn) + struct sconnection *qconn; +{ + (*qconn->qcmds->pufree) (qconn); +} + +/* Lock a connection. */ + +boolean +fconn_lock (qconn, fin) + struct sconnection *qconn; + boolean fin; +{ + boolean (*pflock) P((struct sconnection *, boolean)); + + pflock = qconn->qcmds->pflock; + if (pflock == NULL) + return TRUE; + return (*pflock) (qconn, fin); +} + +/* Unlock a connection. */ + +boolean +fconn_unlock (qconn) + struct sconnection *qconn; +{ + boolean (*pfunlock) P((struct sconnection *)); + + pfunlock = qconn->qcmds->pfunlock; + if (pfunlock == NULL) + return TRUE; + return (*pfunlock) (qconn); +} + +/* Open a connection. */ + +boolean +fconn_open (qconn, ibaud, ihighbaud, fwait) + struct sconnection *qconn; + long ibaud; + long ihighbaud; + boolean fwait; +{ + boolean fret; + +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_PORT)) + { + char abspeed[20]; + + if (ibaud == (long) 0) + strcpy (abspeed, "default speed"); + else + sprintf (abspeed, "speed %ld", ibaud); + + if (qconn->qport == NULL) + ulog (LOG_DEBUG, "fconn_open: Opening stdin port (%s)", + abspeed); + else if (qconn->qport->uuconf_zname == NULL) + ulog (LOG_DEBUG, "fconn_open: Opening unnamed port (%s)", + abspeed); + else + ulog (LOG_DEBUG, "fconn_open: Opening port %s (%s)", + qconn->qport->uuconf_zname, abspeed); + } +#endif + + /* If the system provides a range of baud rates, we select the + highest baud rate supported by the port. */ + if (ihighbaud != 0 && qconn->qport != NULL) + { + struct uuconf_port *qport; + + qport = qconn->qport; + ibaud = ihighbaud; + if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM) + { + if (qport->uuconf_u.uuconf_smodem.uuconf_ilowbaud != 0) + { + if (qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud < ibaud) + ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ihighbaud; + } + else if (qport->uuconf_u.uuconf_smodem.uuconf_ibaud != 0) + ibaud = qport->uuconf_u.uuconf_smodem.uuconf_ibaud; + } + else if (qport->uuconf_ttype == UUCONF_PORTTYPE_DIRECT) + { + if (qport->uuconf_u.uuconf_sdirect.uuconf_ibaud != 0) + ibaud = qport->uuconf_u.uuconf_sdirect.uuconf_ibaud; + } + } + + /* This will normally be overridden by the port specific open + routine. */ + if (qconn->qport == NULL) + ulog_device ("stdin"); + else + ulog_device (qconn->qport->uuconf_zname); + + fret = (*qconn->qcmds->pfopen) (qconn, ibaud, fwait); + + if (! fret) + ulog_device ((const char *) NULL); + + return fret; +} + +/* Close a connection. */ + +boolean +fconn_close (qconn, puuconf, qdialer, fsuccess) + struct sconnection *qconn; + pointer puuconf; + struct uuconf_dialer *qdialer; + boolean fsuccess; +{ + boolean fret; + + DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_close: Closing connection"); + + /* Don't report hangup signals while we're closing. */ + fLog_sighup = FALSE; + + fret = (*qconn->qcmds->pfclose) (qconn, puuconf, qdialer, fsuccess); + + /* Make sure any signal reporting has been done before we set + fLog_sighup back to TRUE. */ + ulog (LOG_ERROR, (const char *) NULL); + fLog_sighup = TRUE; + + ulog_device ((const char *) NULL); + + return fret; +} + +/* Reset the connection. */ + +boolean +fconn_reset (qconn) + struct sconnection *qconn; +{ + DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_reset: Resetting connection"); + + return (*qconn->qcmds->pfreset) (qconn); +} + +/* Dial out on the connection. */ + +boolean +fconn_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) + struct sconnection *qconn; + pointer puuconf; + const struct uuconf_system *qsys; + const char *zphone; + struct uuconf_dialer *qdialer; + enum tdialerfound *ptdialerfound; +{ + struct uuconf_dialer sdialer; + enum tdialerfound tfound; + boolean (*pfdial) P((struct sconnection *, pointer, + const struct uuconf_system *, const char *, + struct uuconf_dialer *, enum tdialerfound *)); + + if (qdialer == NULL) + qdialer = &sdialer; + if (ptdialerfound == NULL) + ptdialerfound = &tfound; + + qdialer->uuconf_zname = NULL; + *ptdialerfound = DIALERFOUND_FALSE; + + pfdial = qconn->qcmds->pfdial; + if (pfdial == NULL) + return TRUE; + return (*pfdial) (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound); +} + +/* Read data from the connection. */ + +boolean +fconn_read (qconn, zbuf, pclen, cmin, ctimeout, freport) + struct sconnection *qconn; + char *zbuf; + size_t *pclen; + size_t cmin; + int ctimeout; + boolean freport; +{ + boolean fret; + + fret = (*qconn->qcmds->pfread) (qconn, zbuf, pclen, cmin, ctimeout, + freport); + +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_INCOMING)) + udebug_buffer ("fconn_read: Read", zbuf, *pclen); + else if (FDEBUGGING (DEBUG_PORT)) + ulog (LOG_DEBUG, "fconn_read: Read %lu", (unsigned long) *pclen); +#endif + + return fret; +} + +/* Write data to the connection. */ + +boolean +fconn_write (qconn, zbuf, clen) + struct sconnection *qconn; + const char *zbuf; + size_t clen; +{ +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_OUTGOING)) + udebug_buffer ("fconn_write: Writing", zbuf, clen); + else if (FDEBUGGING (DEBUG_PORT)) + ulog (LOG_DEBUG, "fconn_write: Writing %lu", (unsigned long) clen); +#endif + + return (*qconn->qcmds->pfwrite) (qconn, zbuf, clen); +} + +/* Read and write data. */ + +boolean +fconn_io (qconn, zwrite, pcwrite, zread, pcread) + struct sconnection *qconn; + const char *zwrite; + size_t *pcwrite; + char *zread; + size_t *pcread; +{ + boolean fret; +#if DEBUG > 1 + size_t cwrite = *pcwrite; + size_t cread = *pcread; + + if (cread == 0 || cwrite == 0) + ulog (LOG_FATAL, "fconn_io: cread %lu; cwrite %lu", + (unsigned long) cread, (unsigned long) cwrite); +#endif + +#if DEBUG > 1 + if (FDEBUGGING (DEBUG_OUTGOING)) + udebug_buffer ("fconn_io: Writing", zwrite, cwrite); +#endif + + fret = (*qconn->qcmds->pfio) (qconn, zwrite, pcwrite, zread, pcread); + + DEBUG_MESSAGE4 (DEBUG_PORT, + "fconn_io: Wrote %lu of %lu, read %lu of %lu", + (unsigned long) *pcwrite, (unsigned long) cwrite, + (unsigned long) *pcread, (unsigned long) cread); + +#if DEBUG > 1 + if (*pcread > 0 && FDEBUGGING (DEBUG_INCOMING)) + udebug_buffer ("fconn_io: Read", zread, *pcread); +#endif + + return fret; +} + +/* Send a break character to a connection. Some port types may not + support break characters, in which case we just return TRUE. */ + +boolean +fconn_break (qconn) + struct sconnection *qconn; +{ + boolean (*pfbreak) P((struct sconnection *)); + + pfbreak = *qconn->qcmds->pfbreak; + if (pfbreak == NULL) + return TRUE; + + DEBUG_MESSAGE0 (DEBUG_PORT, "fconn_break: Sending break character"); + + return (*pfbreak) (qconn); +} + +/* Change the setting of a connection. Some port types may not + support this, in which case we just return TRUE. */ + +boolean +fconn_set (qconn, tparity, tstrip, txonxoff) + struct sconnection *qconn; + enum tparitysetting tparity; + enum tstripsetting tstrip; + enum txonxoffsetting txonxoff; +{ + boolean (*pfset) P((struct sconnection *, enum tparitysetting, + enum tstripsetting, enum txonxoffsetting)); + + pfset = qconn->qcmds->pfset; + if (pfset == NULL) + return TRUE; + + DEBUG_MESSAGE3 (DEBUG_PORT, + "fconn_set: Changing setting to %d, %d, %d", + (int) tparity, (int) tstrip, (int) txonxoff); + + return (*pfset) (qconn, tparity, tstrip, txonxoff); +} + +/* Require or ignore carrier on a connection. */ + +boolean +fconn_carrier (qconn, fcarrier) + struct sconnection *qconn; + boolean fcarrier; +{ + boolean (*pfcarrier) P((struct sconnection *, boolean)); + + pfcarrier = qconn->qcmds->pfcarrier; + if (pfcarrier == NULL) + return TRUE; + return (*pfcarrier) (qconn, fcarrier); +} + +/* Run a chat program on a connection. */ + +boolean +fconn_run_chat (qconn, pzprog) + struct sconnection *qconn; + char **pzprog; +{ + return (*qconn->qcmds->pfchat) (qconn, pzprog); +} + +/* Get the baud rate of a connection. */ + +long +iconn_baud (qconn) + struct sconnection *qconn; +{ + long (*pibaud) P((struct sconnection *)); + + pibaud = qconn->qcmds->pibaud; + if (pibaud == NULL) + return 0; + return (*pibaud) (qconn); +} + +/* Modem dialing routines. */ + +/*ARGSUSED*/ +boolean +fmodem_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) + struct sconnection *qconn; + pointer puuconf; + const struct uuconf_system *qsys; + const char *zphone; + struct uuconf_dialer *qdialer; + enum tdialerfound *ptdialerfound; +{ + *ptdialerfound = DIALERFOUND_FALSE; + + if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL) + { + char **pz; + boolean ffirst; + + /* The pzdialer field is a sequence of dialer/token pairs. The + dialer portion names a dialer to use. The token portion is + what \D and \T in the chat script expand to. If there is no + token for the last dialer, the phone number for the system is + used. */ + ffirst = TRUE; + pz = qconn->qport->uuconf_u.uuconf_smodem.uuconf_pzdialer; + while (*pz != NULL) + { + int iuuconf; + struct uuconf_dialer *q; + struct uuconf_dialer s; + const char *ztoken; + boolean ftranslate; + + if (! ffirst) + q = &s; + else + q = qdialer; + + iuuconf = uuconf_dialer_info (puuconf, *pz, q); + if (iuuconf == UUCONF_NOT_FOUND) + { + ulog (LOG_ERROR, "%s: Dialer not found", *pz); + return FALSE; + } + else if (iuuconf != UUCONF_SUCCESS) + { + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + return FALSE; + } + + ++pz; + ztoken = *pz; + + ftranslate = FALSE; + if (ztoken == NULL + || strcmp (ztoken, "\\D") == 0) + ztoken = zphone; + else if (strcmp (ztoken, "\\T") == 0) + { + ztoken = zphone; + ftranslate = TRUE; + } + + if (! fcdo_dial (qconn, puuconf, q, ztoken, ftranslate)) + { + (void) uuconf_dialer_free (puuconf, q); + if (! ffirst) + (void) uuconf_dialer_free (puuconf, qdialer); + return FALSE; + } + + if (ffirst) + { + *ptdialerfound = DIALERFOUND_FREE; + ffirst = FALSE; + } + else + (void) uuconf_dialer_free (puuconf, q); + + if (*pz != NULL) + ++pz; + } + + return TRUE; + } + else if (qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer != NULL) + { + struct uuconf_dialer *q; + + q = qconn->qport->uuconf_u.uuconf_smodem.uuconf_qdialer; + *qdialer = *q; + *ptdialerfound = DIALERFOUND_TRUE; + return fcdo_dial (qconn, puuconf, q, zphone, FALSE); + } + else + { + ulog (LOG_ERROR, "No dialer information"); + return FALSE; + } +} + +/* Actually use a dialer. We set up the modem (which may include + opening the dialer device), run the chat script, and finish dealing + with the modem. */ + +static boolean +fcdo_dial (qconn, puuconf, qdial, zphone, ftranslate) + struct sconnection *qconn; + pointer puuconf; + struct uuconf_dialer *qdial; + const char *zphone; + boolean ftranslate; +{ + const char *zname; + + if (! fsysdep_modem_begin_dial (qconn, qdial)) + return FALSE; + + if (qconn->qport == NULL) + zname = NULL; + else + zname = qconn->qport->uuconf_zname; + + if (! fchat (qconn, puuconf, &qdial->uuconf_schat, + (const struct uuconf_system *) NULL, qdial, + zphone, ftranslate, zname, iconn_baud (qconn))) + return FALSE; + + return fsysdep_modem_end_dial (qconn, qdial); +} diff --git a/gnu/libexec/uucp/common_sources/conn.h b/gnu/libexec/uucp/common_sources/conn.h new file mode 100644 index 000000000000..59d4881b07ff --- /dev/null +++ b/gnu/libexec/uucp/common_sources/conn.h @@ -0,0 +1,312 @@ +/* conn.h + Header file for routines which manipulate connections. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#ifndef CONN_H + +#define CONN_H + +#if ANSI_C +/* These structures are used in prototypes but are not defined in this + header file. */ +struct uuconf_system; +struct uuconf_dialer; +struct uuconf_chat; +#endif + +/* This structure represents a connection. */ + +struct sconnection +{ + /* Pointer to command table for this type of connection. */ + const struct sconncmds *qcmds; + /* Pointer to system dependent information. */ + pointer psysdep; + /* Pointer to system independent information. */ + struct uuconf_port *qport; +}; + +/* Whether fconn_dial got a dialer. */ + +enum tdialerfound +{ + /* Did not find a dialer. */ + DIALERFOUND_FALSE, + /* Found a dialer which does not need to be freed. */ + DIALERFOUND_TRUE, + /* Found a dialer which does need to be freed. */ + DIALERFOUND_FREE +}; + +/* Parity settings to pass to fconn_set. */ + +enum tparitysetting +{ + /* Do not change output parity generation. */ + PARITYSETTING_DEFAULT, + /* No parity (all eight output bits used). */ + PARITYSETTING_NONE, + /* Even parity. */ + PARITYSETTING_EVEN, + /* Odd parity. */ + PARITYSETTING_ODD, + /* Mark parity. */ + PARITYSETTING_MARK, + /* Space parity. */ + PARITYSETTING_SPACE +}; + +/* Type of strip control argument to fconn_set. */ + +enum tstripsetting +{ + /* Do not change the stripping of input characters. */ + STRIPSETTING_DEFAULT, + /* Do not strip input characters to seven bits. */ + STRIPSETTING_EIGHTBITS, + /* Strip input characters to seven bits. */ + STRIPSETTING_SEVENBITS +}; + +/* Type of XON/XOFF control argument to fconn_set. */ + +enum txonxoffsetting +{ + /* Do not change XON/XOFF handshake setting. */ + XONXOFF_DEFAULT, + /* Do not do XON/XOFF handshaking. */ + XONXOFF_OFF, + /* Do XON/XOFF handshaking. */ + XONXOFF_ON +}; + +/* A command table holds the functions which implement actions for + each different kind of connection. */ + +struct sconncmds +{ + /* Free up a connection. */ + void (*pufree) P((struct sconnection *qconn)); + /* Lock the connection. The fin argument is TRUE if the connection + is to be used for an incoming call. May be NULL. */ + boolean (*pflock) P((struct sconnection *qconn, boolean fin)); + /* Unlock the connection. May be NULL. */ + boolean (*pfunlock) P((struct sconnection *qconn)); + /* Open the connection. */ + boolean (*pfopen) P((struct sconnection *qconn, long ibaud, + boolean fwait)); + /* Close the connection. */ + boolean (*pfclose) P((struct sconnection *qconn, + pointer puuconf, + struct uuconf_dialer *qdialer, + boolean fsuccess)); + /* Reset the connection so that another call may be accepted. */ + boolean (*pfreset) P((struct sconnection *qconn)); + /* Dial a number on a connection. This set *qdialer to the dialer + used, if any, and sets *ptdialerfound appropriately. The qsys + and zphone arguments are for the chat script. This field may be + NULL. */ + boolean (*pfdial) P((struct sconnection *qconn, pointer puuconf, + const struct uuconf_system *qsys, + const char *zphone, + struct uuconf_dialer *qdialer, + enum tdialerfound *ptdialerfound)); + /* Read data from a connection, with a timeout in seconds. When + called *pclen is the length of the buffer; on successful return + *pclen is the number of bytes read into the buffer. The cmin + argument is the minimum number of bytes to read before returning + ahead of a timeout. */ + boolean (*pfread) P((struct sconnection *qconn, char *zbuf, size_t *pclen, + size_t cmin, int ctimeout, boolean freport)); + /* Write data to the connection. */ + boolean (*pfwrite) P((struct sconnection *qconn, const char *zbuf, + size_t clen)); + /* Read and write data to the connection. This reads and writes + data until either all passed in data has been written or the read + buffer has been filled. When called *pcread is the size of the + read buffer and *pcwrite is the number of bytes to write; on + successful return *pcread is the number of bytes read and + *pcwrite is the number of bytes written. */ + boolean (*pfio) P((struct sconnection *qconn, const char *zwrite, + size_t *pcwrite, char *zread, size_t *pcread)); + /* Send a break character. This field may be NULL. */ + boolean (*pfbreak) P((struct sconnection *qconn)); + /* Change the connection setting. This field may be NULL. */ + boolean (*pfset) P((struct sconnection *qconn, + enum tparitysetting tparity, + enum tstripsetting tstrip, + enum txonxoffsetting txonxoff)); + /* Require or ignore carrer. This field may be NULL. */ + boolean (*pfcarrier) P((struct sconnection *qconn, + boolean fcarrier)); + /* Run a chat program on a connection. */ + boolean (*pfchat) P((struct sconnection *qconn, char **pzprog)); + /* Get the baud rate of a connection. This field may be NULL. */ + long (*pibaud) P((struct sconnection *qconn)); +}; + +/* Connection functions. */ + +/* Initialize a connection. This must be called before any of the + other connection functions are called. It initializes the fields + of qconn. It returns FALSE on error. */ +extern boolean fconn_init P((struct uuconf_port *qport, + struct sconnection *qconn)); + +/* Free up connection data. */ +extern void uconn_free P((struct sconnection *qconn)); + +/* Lock a connection. The fin argument is TRUE if the port is to be + used for an incoming call; certains type of Unix locking need this + information because they need to open the port. */ +extern boolean fconn_lock P((struct sconnection *qconn, boolean fin)); + +/* Unlock a connection. */ +extern boolean fconn_unlock P((struct sconnection *qconn)); + +/* Open a connection. If ibaud is 0, the natural baud rate of the + port is used. If ihighbaud is not 0, fconn_open chooses the + highest supported baud rate between ibaud and ihighbaud. If fwait + is TRUE, this should wait for an incoming call. */ +extern boolean fconn_open P((struct sconnection *qconn, long ibaud, + long ihighbaud, boolean fwait)); + +/* Close a connection. The fsuccess argument is TRUE if the + conversation completed normally, FALSE if it is being aborted. */ +extern boolean fconn_close P((struct sconnection *qconn, + pointer puuconf, + struct uuconf_dialer *qdialer, + boolean fsuccess)); + +/* Reset a connection such that another call may be accepted. */ +extern boolean fconn_reset P((struct sconnection *q)); + +/* Dial out on a connection. The qsys and zphone arguments are for + the chat scripts; zphone is the phone number to dial. If qdialer + is not NULL, *qdialer will be set to the dialer information used if + any; *ptdialerfound will be set appropriately. */ +extern boolean fconn_dial P((struct sconnection *q, pointer puuconf, + const struct uuconf_system *qsys, + const char *zphone, + struct uuconf_dialer *qdialer, + enum tdialerfound *ptdialerfound)); + +/* Read from a connection. + zbuf -- buffer to read bytes into + *pclen on call -- length of zbuf + *pclen on successful return -- number of bytes read + cmin -- minimum number of bytes to read before returning ahead of timeout + ctimeout -- timeout in seconds, 0 if none + freport -- whether to report errors. */ +extern boolean fconn_read P((struct sconnection *qconn, char *zbuf, + size_t *pclen, size_t cmin, + int ctimeout, boolean freport)); + +/* Write to a connection. */ +extern boolean fconn_write P((struct sconnection *qconn, const char *zbuf, + size_t cbytes)); + +/* Read and write to a connection. This reads and writes data until + either all passed-in data has been written or the read buffer is + full. + zwrite -- buffer to write bytes from + *pcwrite on call -- number of bytes to write + *pcwrite on successful return -- number of bytes written + zread -- buffer to read bytes into + *pcread on call -- size of read buffer + *pcread on successful return -- number of bytes read. */ +extern boolean fconn_io P((struct sconnection *qconn, const char *zwrite, + size_t *pcwrite, char *zread, size_t *pcread)); + +/* Send a break character to a connection. */ +extern boolean fconn_break P((struct sconnection *qconn)); + +/* Change the settings of a connection. This allows independent + control over the parity of output characters, whether to strip + input characters, and whether to do XON/XOFF handshaking. There is + no explicit control over parity checking of input characters. This + function returns FALSE on error. Attempts to set values not + supported by the hardware are silently ignored. */ +extern boolean fconn_set P((struct sconnection *qconn, + enum tparitysetting tparity, + enum tstripsetting tstrip, + enum txonxoffsetting txonxoff)); + +/* Get the baud rate of a connection. */ +extern long iconn_baud P((struct sconnection *qconn)); + +/* Do a chat script with a system. */ +extern boolean fchat P((struct sconnection *qconn, pointer puuconf, + const struct uuconf_chat *qchat, + const struct uuconf_system *qsys, + const struct uuconf_dialer *qdialer, + const char *zphone, boolean ftranslate, + const char *zport, long ibaud)); + +/* Tell the connection to either require or ignore carrier as fcarrier + is TRUE or FALSE respectively. This is called with fcarrier TRUE + when \m is encountered in a chat script, and with fcarrier FALSE + when \M is encountered. */ +extern boolean fconn_carrier P((struct sconnection *qconn, + boolean fcarrier)); + +/* Run a chat program on a connection. */ +extern boolean fconn_run_chat P((struct sconnection *qconn, + char **pzprog)); + +/* Dialing out on a modem is partially system independent. This is + the modem dialing routine. */ +extern boolean fmodem_dial P((struct sconnection *qconn, pointer puuconf, + const struct uuconf_system *qsys, + const char *zphone, + struct uuconf_dialer *qdialer, + enum tdialerfound *ptdialerfound)); + +/* Begin dialing out. This should open the dialer device if there is + one, toggle DTR if requested and possible, and tell the port to + ignore carrier. It should return FALSE on error. */ +extern boolean fsysdep_modem_begin_dial P((struct sconnection *qconn, + struct uuconf_dialer *qdial)); + +/* Finish dialing out on a modem. This should close the dialer device + if there is one. If the dialer and the port both support carrier, + the connection should be told to pay attention to carrier. If it + is possible to wait for carrier to come on, and the dialer and the + port both the port support carrier, it should wait until carrier + comes on. */ +extern boolean fsysdep_modem_end_dial P((struct sconnection *qconn, + struct uuconf_dialer *qdial)); + +/* System dependent initialization routines. */ +extern boolean fsysdep_stdin_init P((struct sconnection *qconn)); +extern boolean fsysdep_modem_init P((struct sconnection *qconn)); +extern boolean fsysdep_direct_init P((struct sconnection *qconn)); +#if HAVE_TCP +extern boolean fsysdep_tcp_init P((struct sconnection *qconn)); +#endif +#if HAVE_TLI +extern boolean fsysdep_tli_init P((struct sconnection *qconn)); +#endif + +#endif /* ! defined (CONN_H) */ diff --git a/gnu/libexec/uucp/common_sources/copy.c b/gnu/libexec/uucp/common_sources/copy.c new file mode 100644 index 000000000000..0d1a5bb2c270 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/copy.c @@ -0,0 +1,202 @@ +/* copy.c + Copy one file to another for the UUCP package. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char copy_rcsid[] = "$Id: copy.c,v 1.1 1993/08/05 18:22:37 conklin Exp $"; +#endif + +#include "uudefs.h" +#include "system.h" +#include "sysdep.h" + +#include <stdio.h> +#include <errno.h> + +/* Copy one file to another. */ + +#if USE_STDIO + +boolean +fcopy_file (zfrom, zto, fpublic, fmkdirs) + const char *zfrom; + const char *zto; + boolean fpublic; + boolean fmkdirs; +{ + FILE *efrom; + boolean fret; + + efrom = fopen (zfrom, BINREAD); + if (efrom == NULL) + { + ulog (LOG_ERROR, "fopen (%s): %s", zfrom, strerror (errno)); + return FALSE; + } + + fret = fcopy_open_file (efrom, zto, fpublic, fmkdirs); + (void) fclose (efrom); + return fret; +} + +boolean +fcopy_open_file (efrom, zto, fpublic, fmkdirs) + FILE *efrom; + const char *zto; + boolean fpublic; + boolean fmkdirs; +{ + FILE *eto; + char ab[8192]; + int c; + + eto = esysdep_fopen (zto, fpublic, FALSE, fmkdirs); + if (eto == NULL) + return FALSE; + + while ((c = fread (ab, sizeof (char), sizeof ab, efrom)) != 0) + { + if (fwrite (ab, sizeof (char), (size_t) c, eto) != c) + { + ulog (LOG_ERROR, "fwrite: %s", strerror (errno)); + (void) fclose (eto); + (void) remove (zto); + return FALSE; + } + } + + if (fclose (eto) != 0) + { + ulog (LOG_ERROR, "fclose: %s", strerror (errno)); + (void) remove (zto); + return FALSE; + } + + return TRUE; +} + +#else /* ! USE_STDIO */ + +#if HAVE_FCNTL_H +#include <fcntl.h> +#else +#if HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#endif + +#ifndef O_RDONLY +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#endif + +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + +boolean +fcopy_file (zfrom, zto, fpublic, fmkdirs) + const char *zfrom; + const char *zto; + boolean fpublic; + boolean fmkdirs; +{ + int ofrom; + boolean fret; + + ofrom = open (zfrom, O_RDONLY | O_NOCTTY, 0); + if (ofrom < 0) + { + ulog (LOG_ERROR, "open (%s): %s", zfrom, strerror (errno)); + return FALSE; + } + + fret = fcopy_open_file (ofrom, zto, fpublic, fmkdirs); + (void) close (ofrom); + return fret; +} + +boolean +fcopy_open_file (ofrom, zto, fpublic, fmkdirs) + int ofrom; + const char *zto; + boolean fpublic; + boolean fmkdirs; +{ + int oto; + char ab[8192]; + int c; + + /* These file mode arguments are from the UNIX version of sysdep.h; + each system dependent header file will need their own + definitions. */ + oto = creat (zto, fpublic ? IPUBLIC_FILE_MODE : IPRIVATE_FILE_MODE); + if (oto < 0) + { + if (errno == ENOENT && fmkdirs) + { + if (! fsysdep_make_dirs (zto, fpublic)) + return FALSE; + oto = creat (zto, + fpublic ? IPUBLIC_FILE_MODE : IPRIVATE_FILE_MODE); + } + if (oto < 0) + { + ulog (LOG_ERROR, "open (%s): %s", zto, strerror (errno)); + return FALSE; + } + } + + while ((c = read (ofrom, ab, sizeof ab)) > 0) + { + if (write (oto, ab, (size_t) c) != c) + { + ulog (LOG_ERROR, "write: %s", strerror (errno)); + (void) close (oto); + (void) remove (zto); + return FALSE; + } + } + + if (close (oto) < 0) + { + ulog (LOG_ERROR, "close: %s", strerror (errno)); + (void) remove (zto); + return FALSE; + } + + if (c < 0) + { + ulog (LOG_ERROR, "read: %s", strerror (errno)); + (void) remove (zto); + return FALSE; + } + + return TRUE; +} + +#endif /* ! USE_STDIO */ diff --git a/gnu/libexec/uucp/common_sources/cu.h b/gnu/libexec/uucp/common_sources/cu.h new file mode 100644 index 000000000000..5a514ee3bfe7 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/cu.h @@ -0,0 +1,80 @@ +/* cu.h + Header file for cu. + + Copyright (C) 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +/* The user settable variables supported by cu. */ + +/* The escape character used to introduce a special command. The + escape character is the first character of this string. */ +extern const char *zCuvar_escape; + +/* Whether to delay for a second before printing the host name after + seeing an escape character. */ +extern boolean fCuvar_delay; + +/* The input characters which finish a line. The escape character is + only recognized following one of these characters. */ +extern const char *zCuvar_eol; + +/* Whether to transfer binary data (nonprintable characters other than + newline and tab) when sending a file. If this is FALSE, then + newline is changed to carriage return. */ +extern boolean fCuvar_binary; + +/* A prefix string to use before sending a binary character from a + file; this is only used if fCuvar_binary is TRUE. */ +extern const char *zCuvar_binary_prefix; + +/* Whether to check for echoes of characters sent when sending a file. + This is ignored if fCuvar_binary is TRUE. */ +extern boolean fCuvar_echocheck; + +/* A character to look for after each newline is sent when sending a + file. The character is the first character in this string, except + that a '\0' means that no echo check is done. */ +extern const char *zCuvar_echonl; + +/* The timeout to use when looking for an character. */ +extern int cCuvar_timeout; + +/* The character to use to kill a line if an echo check fails. The + first character in this string is sent. */ +extern const char *zCuvar_kill; + +/* The number of times to try resending a line if the echo check keeps + failing. */ +extern int cCuvar_resend; + +/* The string to send at the end of a file sent with ~>. */ +extern const char *zCuvar_eofwrite; + +/* The string to look for to finish a file received with ~<. For tip + this is a collection of single characters, but I don't want to do + that because it means that there are characters which cannot be + received. */ +extern const char *zCuvar_eofread; + +/* Whether to provide verbose information when sending or receiving a + file. */ +extern boolean fCuvar_verbose; diff --git a/gnu/libexec/uucp/common_sources/getopt.h b/gnu/libexec/uucp/common_sources/getopt.h new file mode 100644 index 000000000000..1a70e027714e --- /dev/null +++ b/gnu/libexec/uucp/common_sources/getopt.h @@ -0,0 +1,120 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + + This file was modified slightly by Ian Lance Taylor, November 1992, + for Taylor UUCP. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Ian Lance Taylor <ian@airs.com> added the following defines for + Taylor UUCP. This avoids reported conflicts with system getopt + definitions. */ +#define getopt gnu_getopt +#define optarg gnu_optarg +#define optind gnu_optind +#define opterr gnu_opterr + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +enum _argtype +{ + no_argument, + required_argument, + optional_argument +}; + +extern int getopt P((int argc, char *const *argv, const char *shortopts)); +extern int getopt_long P((int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind)); +extern int getopt_long_only P((int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind)); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal P((int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only)); + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/gnu/libexec/uucp/common_sources/log.c b/gnu/libexec/uucp/common_sources/log.c new file mode 100644 index 000000000000..9528baf5ca39 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/log.c @@ -0,0 +1,699 @@ +/* log.c + Routines to add entries to the log files. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char log_rcsid[] = "$Id: log.c,v 1.1 1993/08/05 18:22:39 conklin Exp $"; +#endif + +#include <errno.h> + +#if ANSI_C +#include <stdarg.h> +#endif + +#if HAVE_TIME_H +#include <time.h> +#endif + +#include "uudefs.h" +#include "uuconf.h" +#include "system.h" + +/* Local functions. */ + +static const char *zldate_and_time P((void)); + +/* Log file name. */ +static const char *zLogfile; + +/* The function to call when a LOG_FATAL error occurs. */ +static void (*pfLfatal) P((void)); + +/* Whether to go to a file. */ +static boolean fLfile; + +/* ID number. */ +static int iLid; + +/* The current user name. */ +static char *zLuser; + +/* The current system name. */ +static char *zLsystem; + +/* The current device name. */ +char *zLdevice; + +/* The open log file. */ +static FILE *eLlog; + +/* Whether we have tried to open the log file. We need this because + we don't want to keep trying to open the log file if we failed the + first time. It can't be static because under HAVE_HDB_LOGGING we + may have to write to various different log files. */ +static boolean fLlog_tried; + +#if DEBUG > 1 +/* Debugging file name. */ +static const char *zLdebugfile; + +/* The open debugging file. */ +static FILE *eLdebug; + +/* Whether we've tried to open the debugging file. */ +static boolean fLdebug_tried; + +/* Whether we've written out any debugging information. */ +static boolean fLdebugging; +#endif + +/* Statistics file name. */ +static const char *zLstatsfile; + +/* The open statistics file. */ +static FILE *eLstats; + +/* Whether we've tried to open the statistics file. */ +static boolean fLstats_tried; + +/* The array of signals. The elements are only set to TRUE by the + default signal handler. They are only set to FALSE if we don't + care whether we got the signal or not. */ +volatile sig_atomic_t afSignal[INDEXSIG_COUNT]; + +/* The array of signals to log. The elements are only set to TRUE by + the default signal handler. They are set to FALSE when the signal + is logged in ulog. This means that if a signal comes in at just + the right time we won't log it (or, rather, we'll log it once + instead of twice), but that is not a catatrophe. */ +volatile sig_atomic_t afLog_signal[INDEXSIG_COUNT]; + +/* Flag that indicates SIGHUP is worth logging. */ +boolean fLog_sighup = TRUE; + +/* Signal names to use when logging signals. */ +static const char * const azSignal_names[INDEXSIG_COUNT] = INDEXSIG_NAMES; + +/* If not NULL, ulog calls this function before outputting anything. + This is used to support cu. */ +void (*pfLstart) P((void)); + +/* If not NULL, ulog calls this function after outputting everything. + This is used to support cu. */ +void (*pfLend) P((void)); + +/* Set the function to call on a LOG_FATAL error. */ + +void +ulog_fatal_fn (pfn) + void (*pfn) P((void)); +{ + pfLfatal = pfn; +} + +/* Decide whether to send log message to the file or not. */ + +void +ulog_to_file (puuconf, ffile) + pointer puuconf; + boolean ffile; +{ + int iuuconf; + + iuuconf = uuconf_logfile (puuconf, &zLogfile); + if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + +#if DEBUG > 1 + iuuconf = uuconf_debugfile (puuconf, &zLdebugfile); + if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); +#endif + + iuuconf = uuconf_statsfile (puuconf, &zLstatsfile); + if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + + fLfile = ffile; +} + +/* Set the ID number. This will be called by the usysdep_initialize + if there is something sensible to set it to. */ + +void +ulog_id (i) + int i; +{ + iLid = i; +} + +/* Set the user we are making log entries for. The arguments will be + copied into memory. */ + +void +ulog_user (zuser) + const char *zuser; +{ + ubuffree (zLuser); + zLuser = zbufcpy (zuser); +} + +/* Set the system name we are making log entries for. The name is copied + into memory. */ + +void +ulog_system (zsystem) + const char *zsystem; +{ + if (zsystem == NULL + || zLsystem == NULL + || strcmp (zsystem, zLsystem) != 0) + { + ubuffree (zLsystem); + zLsystem = zbufcpy (zsystem); +#if HAVE_HDB_LOGGING + /* Under HDB logging we now must write to a different log file. */ + ulog_close (); +#endif /* HAVE_HDB_LOGGING */ + } +} + +/* Set the device name. This is copied into memory. */ + +void +ulog_device (zdevice) + const char *zdevice; +{ + ubuffree (zLdevice); + zLdevice = zbufcpy (zdevice); +} + +/* Make a log entry. We make a token concession to non ANSI_C systems, + but it clearly won't always work. */ + +#if ! ANSI_C +#undef HAVE_VFPRINTF +#endif + +/*VARARGS2*/ +#if HAVE_VFPRINTF +void +ulog (enum tlog ttype, const char *zmsg, ...) +#else +void +ulog (ttype, zmsg, a, b, c, d, f, g, h, i, j) + enum tlog ttype; + const char *zmsg; +#endif +{ +#if HAVE_VFPRINTF + va_list parg; +#endif + FILE *e, *edebug; + boolean fstart, fend; + const char *zhdr, *zstr; + + /* Log any received signal. We do it this way to avoid calling ulog + from the signal handler. A few routines call ulog to get this + message out with zmsg == NULL. */ + { + static boolean fdoing_sigs; + + if (! fdoing_sigs) + { + int isig; + + fdoing_sigs = TRUE; + for (isig = 0; isig < INDEXSIG_COUNT; isig++) + { + if (afLog_signal[isig]) + { + afLog_signal[isig] = FALSE; + + /* Apparently SunOS sends SIGINT rather than SIGHUP + when hanging up, so we don't log either signal if + fLog_sighup is FALSE. */ + if ((isig != INDEXSIG_SIGHUP && isig != INDEXSIG_SIGINT) + || fLog_sighup) + ulog (LOG_ERROR, "Got %s signal", azSignal_names[isig]); + } + } + fdoing_sigs = FALSE; + } + } + + if (zmsg == NULL) + return; + +#if DEBUG > 1 + /* If we've had a debugging file open in the past, then we want to + write all log file entries to the debugging file even if it's + currently closed. */ + if (fLfile + && eLdebug == NULL + && ! fLdebug_tried + && (fLdebugging || (int) ttype >= (int) LOG_DEBUG)) + { + fLdebug_tried = TRUE; + eLdebug = esysdep_fopen (zLdebugfile, FALSE, TRUE, TRUE); + fLdebugging = TRUE; + } +#endif /* DEBUG > 1 */ + + if (! fLfile) + e = stderr; +#if DEBUG > 1 + else if ((int) ttype >= (int) LOG_DEBUG) + { + e = eLdebug; + + /* If we can't open the debugging file, don't output any + debugging messages. */ + if (e == NULL) + return; + } +#endif /* DEBUG > 1 */ + else + { + if (eLlog == NULL && ! fLlog_tried) + { + fLlog_tried = TRUE; +#if ! HAVE_HDB_LOGGING + eLlog = esysdep_fopen (zLogfile, TRUE, TRUE, TRUE); +#else /* HAVE_HDB_LOGGING */ + { + const char *zsys; + char *zfile; + + /* We want to write to .Log/program/system, e.g. + .Log/uucico/uunet. The system name may not be set. */ + if (zLsystem == NULL) + zsys = "ANY"; + else + zsys = zLsystem; + + zfile = zbufalc (strlen (zLogfile) + + strlen (abProgram) + + strlen (zsys) + + 1); + sprintf (zfile, zLogfile, abProgram, zsys); + eLlog = esysdep_fopen (zfile, TRUE, TRUE, TRUE); + ubuffree (zfile); + } +#endif /* HAVE_HDB_LOGGING */ + + if (eLlog == NULL) + { + /* We can't open the log file. We don't even have a + safe way to report this problem, since we may not be + able to write to stderr (it may, for example, be + attached to the incoming call). */ + if (pfLfatal != NULL) + (*pfLfatal) (); + usysdep_exit (FALSE); + } + } + + e = eLlog; + + /* eLlog might be NULL here because we might try to open the log + file recursively via esysdep_fopen. */ + if (e == NULL) + return; + } + + if (pfLstart != NULL) + (*pfLstart) (); + + edebug = NULL; +#if DEBUG > 1 + if ((int) ttype < (int) LOG_DEBUG) + edebug = eLdebug; +#endif + + fstart = TRUE; + fend = TRUE; + + switch (ttype) + { + case LOG_NORMAL: + zhdr = ""; + break; + case LOG_ERROR: + zhdr = "ERROR: "; + break; + case LOG_FATAL: + zhdr = "FATAL: "; + break; +#if DEBUG > 1 + case LOG_DEBUG: + zhdr = "DEBUG: "; + break; + case LOG_DEBUG_START: + zhdr = "DEBUG: "; + fend = FALSE; + break; + case LOG_DEBUG_CONTINUE: + zhdr = NULL; + fstart = FALSE; + fend = FALSE; + break; + case LOG_DEBUG_END: + zhdr = NULL; + fstart = FALSE; + break; +#endif + default: + zhdr = "???: "; + break; + } + + if (fstart) + { + if (! fLfile) + { + fprintf (e, "%s: ", abProgram); + if (edebug != NULL) + fprintf (edebug, "%s: ", abProgram); + } + else + { +#if HAVE_TAYLOR_LOGGING + fprintf (e, "%s ", abProgram); + if (edebug != NULL) + fprintf (edebug, "%s ", abProgram); +#else /* ! HAVE_TAYLOR_LOGGING */ + fprintf (e, "%s ", zLuser == NULL ? "uucp" : zLuser); + if (edebug != NULL) + fprintf (edebug, "%s ", zLuser == NULL ? "uucp" : zLuser); +#endif /* HAVE_TAYLOR_LOGGING */ + + fprintf (e, "%s ", zLsystem == NULL ? "-" : zLsystem); + if (edebug != NULL) + fprintf (edebug, "%s ", zLsystem == NULL ? "-" : zLsystem); + +#if HAVE_TAYLOR_LOGGING + fprintf (e, "%s ", zLuser == NULL ? "-" : zLuser); + if (edebug != NULL) + fprintf (edebug, "%s ", zLuser == NULL ? "-" : zLuser); +#endif /* HAVE_TAYLOR_LOGGING */ + + zstr = zldate_and_time (); + fprintf (e, "(%s", zstr); + if (edebug != NULL) + fprintf (edebug, "(%s", zstr); + + if (iLid != 0) + { +#if ! HAVE_HDB_LOGGING +#if HAVE_TAYLOR_LOGGING + fprintf (e, " %d", iLid); + if (edebug != NULL) + fprintf (edebug, " %d", iLid); +#else /* ! HAVE_TAYLOR_LOGGING */ + fprintf (e, "-%d", iLid); + if (edebug != NULL) + fprintf (edebug, "-%d", iLid); +#endif /* ! HAVE_TAYLOR_LOGGING */ +#else /* HAVE_HDB_LOGGING */ + + /* I assume that the second number here is meant to be + some sort of file sequence number, and that it should + correspond to the sequence number in the statistics + file. I don't have any really convenient way to do + this, so I won't unless somebody thinks it's very + important. */ + fprintf (e, ",%d,%d", iLid, 0); + if (edebug != NULL) + fprintf (edebug, ",%d,%d", iLid, 0); +#endif /* HAVE_HDB_LOGGING */ + } + + fprintf (e, ") "); + if (edebug != NULL) + fprintf (edebug, ") "); + + fprintf (e, "%s", zhdr); + if (edebug != NULL) + fprintf (edebug, "%s", zhdr); + } + } + +#if HAVE_VFPRINTF + va_start (parg, zmsg); + vfprintf (e, zmsg, parg); + va_end (parg); + if (edebug != NULL) + { + va_start (parg, zmsg); + vfprintf (edebug, zmsg, parg); + va_end (parg); + } +#else /* ! HAVE_VFPRINTF */ + fprintf (e, zmsg, a, b, c, d, f, g, h, i, j); + if (edebug != NULL) + fprintf (edebug, zmsg, a, b, c, d, f, g, h, i, j); +#endif /* ! HAVE_VFPRINTF */ + + if (fend) + { + fprintf (e, "\n"); + if (edebug != NULL) + fprintf (edebug, "\n"); + } + + (void) fflush (e); + if (edebug != NULL) + (void) fflush (edebug); + + if (pfLend != NULL) + (*pfLend) (); + + if (ttype == LOG_FATAL) + { + if (pfLfatal != NULL) + (*pfLfatal) (); + usysdep_exit (FALSE); + } + +#if CLOSE_LOGFILES + ulog_close (); +#endif +} + +/* Log a uuconf error. */ + +void +ulog_uuconf (ttype, puuconf, iuuconf) + enum tlog ttype; + pointer puuconf; + int iuuconf; +{ + char ab[512]; + + (void) uuconf_error_string (puuconf, iuuconf, ab, sizeof ab); + ulog (ttype, "%s", ab); +} + +/* Close the log file. There's nothing useful we can do with errors, + so we don't check for them. */ + +void +ulog_close () +{ + /* Make sure we logged any signal we received. */ + ulog (LOG_ERROR, (const char *) NULL); + + if (eLlog != NULL) + { + (void) fclose (eLlog); + eLlog = NULL; + fLlog_tried = FALSE; + } + +#if DEBUG > 1 + if (eLdebug != NULL) + { + (void) fclose (eLdebug); + eLdebug = NULL; + fLdebug_tried = FALSE; + } +#endif +} + +/* Add an entry to the statistics file. We may eventually want to put + failed file transfers in here, but we currently do not. */ + +/*ARGSUSED*/ +void +ustats (fsucceeded, zuser, zsystem, fsent, cbytes, csecs, cmicros, fmaster) + boolean fsucceeded; + const char *zuser; + const char *zsystem; + boolean fsent; + long cbytes; + long csecs; + long cmicros; + boolean fmaster; +{ + long cbps; + + /* The seconds and microseconds are now counted independently, so + they may be out of synch. */ + if (cmicros < 0) + { + csecs -= ((- cmicros) / 1000000L) + 1; + cmicros = 1000000L - ((- cmicros) % 1000000L); + } + if (cmicros >= 1000000L) + { + csecs += cmicros / 10000000L; + cmicros = cmicros % 1000000L; + } + + /* On a system which can determine microseconds we might very well + have both csecs == 0 and cmicros == 0. */ + if (csecs == 0 && cmicros < 1000) + cbps = 0; + else + { + long cmillis; + + /* This computation will not overflow provided csecs < 2147483 + and cbytes and cbps both fit in a long. */ + cmillis = csecs * 1000 + cmicros / 1000; + cbps = ((cbytes / cmillis) * 1000 + + ((cbytes % cmillis) * 1000) / cmillis); + } + + if (eLstats == NULL) + { + if (fLstats_tried) + return; + fLstats_tried = TRUE; + eLstats = esysdep_fopen (zLstatsfile, TRUE, TRUE, TRUE); + if (eLstats == NULL) + return; + } + +#if HAVE_TAYLOR_LOGGING + fprintf (eLstats, + "%s %s (%s) %s%s %ld bytes in %ld.%03ld seconds (%ld bytes/sec)\n", + zuser, zsystem, zldate_and_time (), + fsucceeded ? "" : "failed after ", + fsent ? "sent" : "received", + cbytes, csecs, cmicros / 1000, cbps); +#endif /* HAVE_TAYLOR_LOGGING */ +#if HAVE_V2_LOGGING + fprintf (eLstats, + "%s %s (%s) (%ld) %s %s %ld bytes %ld seconds\n", + zuser, zsystem, zldate_and_time (), + (long) time ((time_t *) NULL), + fsent ? "sent" : "received", + fsucceeded ? "data" : "failed after", + cbytes, csecs + cmicros / 500000); +#endif /* HAVE_V2_LOGGING */ +#if HAVE_HDB_LOGGING + { + static int iseq; + + /* I don't know what the 'C' means. The sequence number should + probably correspond to the sequence number in the log file, but + that is currently always 0; using this fake sequence number + will still at least reveal which transfers are from different + calls. We don't report a failed data transfer with this + format. */ + if (! fsucceeded) + return; + ++iseq; + fprintf (eLstats, + "%s!%s %c (%s) (C,%d,%d) [%s] %s %ld / %ld.%03ld secs, %ld %s\n", + zsystem, zuser, fmaster ? 'M' : 'S', zldate_and_time (), + iLid, iseq, zLdevice == NULL ? "unknown" : zLdevice, + fsent ? "->" : "<-", + cbytes, csecs, cmicros / 1000, cbps, + "bytes/sec"); + } +#endif /* HAVE_HDB_LOGGING */ + + (void) fflush (eLstats); + +#if CLOSE_LOGFILES + ustats_close (); +#endif +} + +/* Close the statistics file. */ + +void +ustats_close () +{ + if (eLstats != NULL) + { + if (fclose (eLstats) != 0) + ulog (LOG_ERROR, "fclose: %s", strerror (errno)); + eLstats = NULL; + fLstats_tried = FALSE; + } +} + +/* Return the date and time in a form used for a log entry. */ + +static const char * +zldate_and_time () +{ + long isecs, imicros; + struct tm s; +#if HAVE_TAYLOR_LOGGING + static char ab[sizeof "1991-12-31 12:00:00.00"]; +#endif +#if HAVE_V2_LOGGING + static char ab[sizeof "12/31-12:00"]; +#endif +#if HAVE_HDB_LOGGING + static char ab[sizeof "12/31-12:00:00"]; +#endif + + isecs = ixsysdep_time (&imicros); + usysdep_localtime (isecs, &s); + +#if HAVE_TAYLOR_LOGGING + sprintf (ab, "%04d-%02d-%02d %02d:%02d:%02d.%02d", + s.tm_year + 1900, s.tm_mon + 1, s.tm_mday, s.tm_hour, + s.tm_min, s.tm_sec, (int) (imicros / 10000)); +#endif +#if HAVE_V2_LOGGING + sprintf (ab, "%d/%d-%02d:%02d", s.tm_mon + 1, s.tm_mday, + s.tm_hour, s.tm_min); +#endif +#if HAVE_HDB_LOGGING + sprintf (ab, "%d/%d-%02d:%02d:%02d", s.tm_mon + 1, s.tm_mday, + s.tm_hour, s.tm_min, s.tm_sec); +#endif + + return ab; +} diff --git a/gnu/libexec/uucp/common_sources/policy.h b/gnu/libexec/uucp/common_sources/policy.h new file mode 100644 index 000000000000..4c829bf42d8e --- /dev/null +++ b/gnu/libexec/uucp/common_sources/policy.h @@ -0,0 +1,521 @@ +/* policy.h + Configuration file for policy decisions. To be edited on site. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +/* This header file contains macro definitions which must be set by + each site before compilation. The first few are system + characteristics that can not be easily discovered by the + configuration script. Most are configuration decisions that must + be made by the local administrator. */ + +/* System characteristics. */ + +/* This code tries to use several ANSI C features, including + prototypes, stdarg.h, the const qualifier and the types void + (including void * pointers) and unsigned char. By default it will + use these features if the compiler defines __STDC__. If your + compiler supports these features but does not define __STDC__, you + should set ANSI_C to 1. If your compiler does not support these + features but defines __STDC__ (no compiler should do this, in my + opinion), you should set ANSI_C to 0. In most cases (or if you're + not sure) just leave the line below commented out. */ +/* #define ANSI_C 1 */ + +/* Set USE_STDIO to 1 if data files should be read using the stdio + routines (fopen, fread, etc.) rather than the UNIX unbuffered I/O + calls (open, read, etc.). Unless you know your stdio is really + rotten, you should leave this as 1. */ +#define USE_STDIO 1 + +/* Exactly one of the following macros must be set to 1. Many modern + systems support more than one of these choices through some form of + compilation environment, in which case the setting will depend on + the compilation environment you use. If you have a reasonable + choice between options, I suspect that TERMIO or TERMIOS will be + more efficient than TTY, but I have not done any head to head + comparisons. + + If you don't set any of these macros, the code below will guess. + It will doubtless be wrong on some systems. + + HAVE_BSD_TTY -- Use the 4.2BSD tty routines + HAVE_SYSV_TERMIO -- Use the System V termio routines + HAVE_POSIX_TERMIOS -- Use the POSIX termios routines + */ +#define HAVE_BSD_TTY 0 +#define HAVE_SYSV_TERMIO 0 +#define HAVE_POSIX_TERMIOS 1 + +/* This code tries to guess which terminal driver to use if you did + not make a choice above. It is in this file to make it easy to + figure out what's happening if something goes wrong. */ + +#if HAVE_BSD_TTY + HAVE_SYSV_TERMIO + HAVE_POSIX_TERMIOS == 0 +#if HAVE_CBREAK +#undef HAVE_BSD_TTY +#define HAVE_BSD_TTY 1 +#else +#undef HAVE_SYSV_TERMIO +#define HAVE_SYSV_TERMIO 1 +#endif +#endif + +/* On some systems a write to a serial port will block even if the + file descriptor has been set to not block. File transfer can be + more efficient if the package knows that a write to the serial port + will not block; however, if the write does block unexpectedly then + data loss is possible at high speeds. + + If writes to a serial port always block even when requested not to, + you should set HAVE_UNBLOCKED_WRITES to 0; otherwise you should set + it to 1. In general on System V releases without STREAMS-based + ttys (e.g., before SVR4) HAVE_UNBLOCKED_WRITES should be 0 and on + BSD or SVR4 it should be 1. + + If HAVE_UNBLOCKED_WRITES is set to 1 when it should be 0 you may + see an unexpectedly large number of transmission errors, or, if you + have hardware handshaking, transfer times may be lower than + expected (but then, they always are). If HAVE_UNBLOCKED_WRITES is + set to 0 when it should be 1, file transfer will use more CPU time + than necessary. If you are unsure, setting HAVE_UNBLOCKED_WRITES + to 0 should always be safe. */ +#define HAVE_UNBLOCKED_WRITES 1 + +/* When the code does do a blocking write, it wants to write the + largest amount of data which the kernel will accept as a single + unit. On BSD this is typically the value of OBUFSIZ in + <sys/tty.h>, usually 100. On System V before SVR4 this is + typically the size of a clist, CLSIZE in <sys/tty.h>, which is + usually 64. On SVR4, which uses STREAMS-based ttys, 2048 is + reasonable. Define SINGLE_WRITE to the correct value for your + system. If SINGLE_WRITE is too large, data loss may occur. If + SINGLE_WRITE is too small, file transfer will use more CPU time + than necessary. If you have no idea, 64 should work on most modern + systems. */ +#define SINGLE_WRITE 100 + +/* Some tty drivers, such as those from SCO and AT&T's Unix PC, have a + bug in the implementation of ioctl() that causes CLOCAL to be + ineffective until the port is opened a second time. If + HAVE_CLOCAL_BUG is set to 1, code will be added to do this second + open on the port. Set this if you are getting messages that say + "Line disconnected" while in the dial chat script after only + writing the first few characters to the port. This bug causes the + resetting of CLOCAL to have no effect, so the "\m" (require + carrier) escape sequence won't function properly in dialer chat + scripts. */ +#define HAVE_CLOCAL_BUG 0 + +/* On some systems, such as SCO Xenix, resetting DTR on a port + apparently prevents getty from working on the port, and thus + prevents anybody from dialing in. If HAVE_RESET_BUG is set to 1, + DTR will not be reset when a serial port is closed. */ +#define HAVE_RESET_BUG 0 + +/* The Sony NEWS reportedly handles no parity by clearing both the odd + and even parity bits in the sgtty structure, unlike most BSD based + systems in which no parity is indicated by setting both the odd and + even parity bits. Setting HAVE_PARITY_BUG to 1 will handle this + correctly. */ +#define HAVE_PARITY_BUG 0 + +#if HAVE_BSD_TTY +#ifdef sony +#undef HAVE_PARITY_BUG +#define HAVE_PARITY_BUG 1 +#endif +#endif + +/* On Ultrix 4.0, at least, setting CBREAK causes input characters to + be stripped, regardless of the setting of LPASS8 and LLITOUT. This + can be worked around by using the termio call to reset ISTRIP. + This probably does not apply to any other operating system. + Setting HAVE_STRIP_BUG to 1 will use this workaround. */ +#define HAVE_STRIP_BUG 0 + +#if HAVE_BSD_TTY +#ifdef ultrix +#undef HAVE_STRIP_BUG +#define HAVE_STRIP_BUG 1 +#endif +#endif + +/* TIMES_TICK is the fraction of a second which times(2) returns (for + example, if times returns 100ths of a second TIMES_TICK should be + set to 100). On a true POSIX system (one which has the sysconf + function and also has _SC_CLK_TCK defined in <unistd.h>) TIMES_TICK + may simply be left as 0. On some systems the environment variable + HZ is what you want for TIMES_TICK, but on some other systems HZ + has the wrong value; check the man page. If you leave this set to + 0, the code will try to guess; it will doubtless be wrong on some + non-POSIX systems. If TIMES_TICK is wrong the code may report + incorrect file transfer times in the statistics file, but on many + systems times(2) will actually not be used and this value will not + matter at all. */ +#define TIMES_TICK 0 + +/* If your system does not support saved set user ID, set + HAVE_SAVED_SETUID to 0. However, this is ignored if your system + has the setreuid function. Most modern Unixes have one or the + other. If your system has the setreuid function, don't worry about + this define, or about the following discussion. + + If you set HAVE_SAVED_SETUID to 0, you will not be able to use uucp + to transfer files that the uucp user can not read. Basically, you + will only be able to use uucp on world-readable files. If you set + HAVE_SAVED_SETUID to 1, but your system does not have saved set + user ID, uucp will fail with an error message whenever anybody + other than the uucp user uses it. */ +#define HAVE_SAVED_SETUID 1 + +/* On some systems, such as the DG Aviion and, possibly, the RS/6000, + the setreuid function is broken. It should be possible to use + setreuid to swap the real and effective user ID's, but on some + systems it will not change the real user ID (I believe this is due + to a misreading of the POSIX standard). On such a system you must + set HAVE_BROKEN_SETREUID to 1; if you do not, you will get error + messages from setreuid. Systems on which setreuid exists but is + broken pretty much always have saved setuid. */ +#define HAVE_BROKEN_SETREUID 0 + +/* On the 3B2, and possibly other systems, nap takes an argument in + hundredths of a second rather than milliseconds. I don't know of + any way to test for this. Set HAVE_HUNDREDTHS_NAP to 1 if this is + true on your system. This does not matter if your system does not + have the nap function. */ +#define HAVE_HUNDREDTHS_NAP 0 + +/* Set PS_PROGRAM to the program to run to get a process status, + including the arguments to pass it. This is used by ``uustat -p''. + Set HAVE_PS_MULTIPLE to 1 if a comma separated list of process + numbers may be appended (e.g. ``ps -flp1,10,100''). Otherwise ps + will be invoked several times, with a single process number append + each time. The default definitions should work on most systems, + although some (such as the NeXT) will complain about the 'p' + option; for those, use the second set of definitions. The third + set of definitions are appropriate for System V. To use the second + or third set of definitions, change the ``#if 1'' to ``#if 0'' and + change the appropriate ``#if 0'' to ``#if 1''. */ +#if 1 +#define PS_PROGRAM "/bin/ps -lp" +#define HAVE_PS_MULTIPLE 0 +#endif +#if 0 +#define PS_PROGRAM "/bin/ps -l" +#define HAVE_PS_MULTIPLE 0 +#endif +#if 0 +#define PS_PROGRAM "/bin/ps -flp" +#define HAVE_PS_MULTIPLE 1 +#endif + +/* If you use other programs that also lock devices, such as cu or + uugetty, the other programs and UUCP must agree on whether a device + is locked. This is typically done by creating a lock file in a + specific directory; the lock files are generally named + LCK..something or LK.something. If the LOCKDIR macro is defined, + these lock files will be placed in the named directory; otherwise + they will be placed in the default spool directory. On some HDB + systems the lock files are placed in /etc/locks. On some they are + placed in /usr/spool/locks. On the NeXT they are placed in + /usr/spool/uucp/LCK. */ +/* #define LOCKDIR "/usr/spool/uucp" */ +/* #define LOCKDIR "/etc/locks" */ +/* #define LOCKDIR "/usr/spool/locks" */ +/* #define LOCKDIR "/usr/spool/uucp/LCK" */ +#define LOCKDIR "/var/spool/lock" + +/* You must also specify the format of the lock files by setting + exactly one of the following macros to 1. Check an existing lock + file to decide which of these choices is more appropriate. + + The HDB style is to write the locking process ID in ASCII, passed + to ten characters, followed by a newline. + + The V2 style is to write the locking process ID as four binary + bytes in the host byte order. Many BSD derived systems use this + type of lock file, including the NeXT. + + SCO lock files are similar to HDB lock files, but always lock the + lowercase version of the tty (i.e., LCK..tty2a is created if you + are locking tty2A). They are appropriate if you are using Taylor + UUCP on an SCO Unix, SCO Xenix, or SCO Open Desktop system. + + SVR4 lock files are also similar to HDB lock files, but they use a + different naming convention. The filenames are LK.xxx.yyy.zzz, + where xxx is the major device number of the device holding the + special device file, yyy is the major device number of the port + device itself, and zzz is the minor device number of the port + device. + + Coherent use a completely different method of terminal locking. + See unix/cohtty for details. For locks other than for terminals, + HDB type lock files are used. */ +#define HAVE_V2_LOCKFILES 0 +#define HAVE_HDB_LOCKFILES 1 +#define HAVE_SCO_LOCKFILES 0 +#define HAVE_SVR4_LOCKFILES 0 +#define HAVE_COHERENT_LOCKFILES 0 + +/* If your system supports Internet mail addresses (which look like + user@host.domain rather than system!user), HAVE_INTERNET_MAIL + should be set to 1. This is checked by uuxqt when sending error + (or success, if requested) notifications to the person who + submitted the job. */ +#define HAVE_INTERNET_MAIL 1 + +/* Adminstrative decisions. */ + +/* Set USE_RCS_ID to 1 if you want the RCS ID strings compiled into + the executable. Leaving them out will decrease the executable + size. Leaving them in will make it easier to determine which + version you are running. */ +#define USE_RCS_ID 1 + +/* DEBUG controls how much debugging information is compiled into the + code. If DEBUG is defined as 0, no sanity checks will be done and + no debugging messages will be compiled in. If DEBUG is defined as + 1 sanity checks will be done but there will still be no debugging + messages. If DEBUG is 2 than debugging messages will be compiled + in. When initially testing, DEBUG should be 2, and you should + probably leave it at 2 unless a small reduction in the executable + file size will be very helpful. */ +#define DEBUG 2 + +/* Set the default grade to use for a uucp command if the -g option is + not used. The grades, from highest to lowest, are 0 to 9, A to Z, + a to z. */ +#define BDEFAULT_UUCP_GRADE ('N') + +/* Set the default grade to use for a uux command if the -g option is + not used. */ +#define BDEFAULT_UUX_GRADE ('N') + +/* To compile in use of the new style of configuration files described + in the documentation, set HAVE_TAYLOR_CONFIG to 1. */ +#define HAVE_TAYLOR_CONFIG 1 + +/* To compile in use of V2 style configuration files (L.sys, L-devices + and so on), set HAVE_V2_CONFIG to 1. To compile in use of HDB + style configuration files (Systems, Devices and so on) set + HAVE_HDB_CONFIG to 1. The files will be looked up in the + oldconfigdir directory as defined in the Makefile. + + You may set any or all of HAVE_TAYLOR_CONFIG, HAVE_V2_CONFIG and + HAVE_HDB_CONFIG to 1 (you must set at least one of the macros). + When looking something up (a system, a port, etc.) the new style + configuration files will be read first, followed by the V2 + configuration files, followed by the HDB configuration files. */ +#define HAVE_V2_CONFIG 1 +#define HAVE_HDB_CONFIG 1 + +/* Exactly one of the following macros must be set to 1. The exact + format of the spool directories is explained in unix/spool.c. + + SPOOLDIR_V2 -- Use a Version 2 (original UUCP) style spool directory + SPOOLDIR_BSD42 -- Use a BSD 4.2 style spool directory + SPOOLDIR_BSD43 -- Use a BSD 4.3 style spool directory + SPOOLDIR_HDB -- Use a HDB (BNU) style spool directory + SPOOLDIR_ULTRIX -- Use an Ultrix style spool directory + SPOOLDIR_SVR4 -- Use a System V Release 4 spool directory + SPOOLDIR_TAYLOR -- Use a new style spool directory + + If you are not worried about compatibility with a currently running + UUCP, use SPOOLDIR_TAYLOR. */ +#define SPOOLDIR_V2 0 +#define SPOOLDIR_BSD42 0 +#define SPOOLDIR_BSD43 0 +#define SPOOLDIR_HDB 0 +#define SPOOLDIR_ULTRIX 0 +#define SPOOLDIR_SVR4 0 +#define SPOOLDIR_TAYLOR 1 + +/* You must select which type of logging you want by setting exactly + one of the following to 1. These control output to the log file + and to the statistics file. + + If you define HAVE_TAYLOR_LOGGING, each line in the log file will + look something like this: + + uucico uunet uucp (1991-12-10 09:04:34.45 16390) Receiving uunet/D./D.uunetSwJ72 + + and each line in the statistics file will look something like this: + + uucp uunet (1991-12-10 09:04:40.20) received 2371 bytes in 5 seconds (474 bytes/sec) + + If you define HAVE_V2_LOGGING, each line in the log file will look + something like this: + + uucico uunet uucp (12/10-09:04 16390) Receiving uunet/D./D.uunetSwJ72 + + and each line in the statistics file will look something like this: + + uucp uunet (12/10-09:04 16390) (692373862) received data 2371 bytes 5 seconds + + If you define HAVE_HDB_LOGGING, each program will by default use a + separate log file. For uucico talking to uunet, for example, it + will be /usr/spool/uucp/.Log/uucico/uunet. Each line will look + something like this: + + uucp uunet (12/10-09:04:22,16390,1) Receiving uunet/D./D.uunetSwJ72 + + and each line in the statistics file will look something like this: + + uunet!uucp M (12/10-09:04:22) (C,16390,1) [ttyXX] <- 2371 / 5.000 secs, 474 bytes/sec + + The main reason to prefer one format over another is that you may + have shell scripts which expect the files to have a particular + format. If you have none, choose whichever format you find more + appealing. */ +#define HAVE_TAYLOR_LOGGING 1 +#define HAVE_V2_LOGGING 0 +#define HAVE_HDB_LOGGING 0 + +/* If you would like the log, debugging and statistics files to be + closed after each message, set CLOSE_LOGFILES to 1. This will + permit the log files to be easily moved. If a log file does not + exist when a new message is written out, it will be created. + Setting CLOSE_LOGFILES to 1 will obviously require slightly more + processing time. */ +#define CLOSE_LOGFILES 0 + +/* The name of the default spool directory. If HAVE_TAYLOR_CONFIG is + set to 1, this may be overridden by the ``spool'' command in the + configuration file. */ +#define SPOOLDIR "/var/spool/uucp" + +/* The name of the default public directory. If HAVE_TAYLOR_CONFIG is + set to 1, this may be overridden by the ``pubdir'' command in the + configuration file. Also, a particular system may be given a + specific public directory by using the ``pubdir'' command in the + system file. */ +#define PUBDIR "/var/spool/uucppublic" + +/* The default command path. This is a space separated list of + directories. Remote command executions requested by uux are looked + up using this path. If you are using HAVE_TAYLOR_CONFIG, the + command path may be overridden for a particular system. For most + systems, you should just make sure that the programs rmail and + rnews can be found using this path. */ +#define CMDPATH "/bin /usr/bin /usr/local/bin" + +/* The default amount of free space to require for systems that do not + specify an amount with the ``free-space'' command. This is only + used when talking to another instance of Taylor UUCP; if accepting + a file would not leave at least this many bytes free on the disk, + it will be refused. */ +#define DEFAULT_FREE_SPACE (50000) + +/* While a file is being received, Taylor UUCP will periodically check + to see if there is enough free space remaining on the disk. If + there is not enough space available on the disk (as determined by + DEFAULT_FREE_SPACE, above, or the ``free-space'' command for the + system) the communication will be aborted. The disk will be + checked each time FREE_SPACE_DELTA bytes are received. Lower + values of FREE_SPACE_DELTA are less likely to fill up the disk, but + will also waste more time checking the amount of free space. To + avoid checking the disk while the file is being received, set + FREE_SPACE_DELTA to 0. */ +#define FREE_SPACE_DELTA (10240) + +/* It is possible for an execute job to request to be executed using + sh(1), rather than execve(2). This is such a security risk, it is + being disabled by default; to allow such jobs, set the following + macro to 1. */ +#define ALLOW_SH_EXECUTION 0 + +/* If a command executed on behalf of a remote system takes a filename + as an argument, a security breach may be possible (note that on my + system neither of the default commands, rmail and rnews, take + filename arguments). If you set ALLOW_FILENAME_ARGUMENTS to 0, all + arguments to a command will be checked; if any argument + 1) starts with ../ + 2) contains the string /../ + 3) begins with a / but does not name a file that may be sent or + received (according to the specified ``remote-send'' and + ``remote-receive'') + the command will be rejected. By default, any argument is + permitted. */ +#define ALLOW_FILENAME_ARGUMENTS 1 + +#if HAVE_TAYLOR_LOGGING + +/* The default log file when using HAVE_TAYLOR_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``logfile'' + command in the configuration file. */ +#define LOGFILE "/var/spool/uucp/Log" + +/* The default statistics file when using HAVE_TAYLOR_LOGGING. When + using HAVE_TAYLOR_CONFIG, this may be overridden by the + ``statfile'' command in the configuration file. */ +#define STATFILE "/var/spool/uucp/Stats" + +/* The default debugging file when using HAVE_TAYLOR_LOGGING. When + using HAVE_TAYLOR_CONFIG, this may be overridden by the + ``debugfile'' command in the configuration file. */ +#define DEBUGFILE "/var/spool/uucp/Debug" + +#endif /* HAVE_TAYLOR_LOGGING */ + +#if HAVE_V2_LOGGING + +/* The default log file when using HAVE_V2_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``logfile'' + command in the configuration file. */ +#define LOGFILE "/var/spool/uucp/LOGFILE" + +/* The default statistics file when using HAVE_V2_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``statfile'' + command in the configuration file. */ +#define STATFILE "/var/spool/uucp/SYSLOG" + +/* The default debugging file when using HAVE_V2_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``debugfile'' + command in the configuration file. */ +#define DEBUGFILE "/var/spool/uucp/DEBUG" + +#endif /* HAVE_V2_LOGGING */ + +#if HAVE_HDB_LOGGING + +/* The default log file when using HAVE_HDB_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``logfile'' + command in the configuration file. The first %s in the string will + be replaced by the program name (e.g. uucico); the second %s will + be replaced by the system name (if there is no appropriate system, + "ANY" will be used). No other '%' character may appear in the + string. */ +#define LOGFILE "/var/spool/uucp/.Log/%s/%s" + +/* The default statistics file when using HAVE_HDB_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``statfile'' + command in the configuration file. */ +#define STATFILE "/var/spool/uucp/.Admin/xferstats" + +/* The default debugging file when using HAVE_HDB_LOGGING. When using + HAVE_TAYLOR_CONFIG, this may be overridden by the ``debugfile'' + command in the configuration file. */ +#define DEBUGFILE "/var/spool/uucp/.Admin/audit.local" + +#endif /* HAVE_HDB_LOGGING */ diff --git a/gnu/libexec/uucp/common_sources/prot.c b/gnu/libexec/uucp/common_sources/prot.c new file mode 100644 index 000000000000..433bf2766829 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/prot.c @@ -0,0 +1,237 @@ +/* prot.c + Protocol support routines to move commands and data around. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char prot_rcsid[] = "$Id: prot.c,v 1.1 1993/08/05 18:22:41 conklin Exp $"; +#endif + +#include <errno.h> + +#include "uudefs.h" +#include "system.h" +#include "conn.h" +#include "prot.h" + +/* Variables visible to the protocol-specific routines. */ + +/* Buffer to hold received data. */ +char abPrecbuf[CRECBUFLEN]; + +/* Index of start of data in abPrecbuf. */ +int iPrecstart; + +/* Index of end of data (first byte not included in data) in abPrecbuf. */ +int iPrecend; + +/* We want to output and input at the same time, if supported on this + machine. If we have something to send, we send it all while + accepting a large amount of data. Once we have sent everything we + look at whatever we have received. If data comes in faster than we + can send it, we may run out of buffer space. */ + +boolean +fsend_data (qconn, zsend, csend, fdoread) + struct sconnection *qconn; + const char *zsend; + size_t csend; + boolean fdoread; +{ + if (! fdoread) + return fconn_write (qconn, zsend, csend); + + while (csend > 0) + { + size_t crec, csent; + + if (iPrecend < iPrecstart) + crec = iPrecstart - iPrecend - 1; + else + { + crec = CRECBUFLEN - iPrecend; + if (iPrecstart == 0) + --crec; + } + + csent = csend; + + if (! fconn_io (qconn, zsend, &csent, abPrecbuf + iPrecend, &crec)) + return FALSE; + + csend -= csent; + zsend += csent; + + iPrecend = (iPrecend + crec) % CRECBUFLEN; + } + + return TRUE; +} + +/* Read data from the other system when we have nothing to send. The + argument cneed is the amount of data the caller wants, and ctimeout + is the timeout in seconds. The function sets *pcrec to the amount + of data which was actually received, which may be less than cneed + if there isn't enough room in the receive buffer. If no data is + received before the timeout expires, *pcrec will be returned as 0. + If an error occurs, the function returns FALSE. If the freport + argument is FALSE, no error should be reported. */ + +boolean +freceive_data (qconn, cneed, pcrec, ctimeout, freport) + struct sconnection *qconn; + size_t cneed; + size_t *pcrec; + int ctimeout; + boolean freport; +{ + /* Set *pcrec to the maximum amount of data we can read. fconn_read + expects *pcrec to be the buffer size, and sets it to the amount + actually received. */ + if (iPrecend < iPrecstart) + *pcrec = iPrecstart - iPrecend - 1; + else + { + *pcrec = CRECBUFLEN - iPrecend; + if (iPrecstart == 0) + --(*pcrec); + } + +#if DEBUG > 0 + /* If we have no room in the buffer, we're in trouble. The + protocols must be written to ensure that this can't happen. */ + if (*pcrec == 0) + ulog (LOG_FATAL, "freceive_data: No room in buffer"); +#endif + + /* If we don't have room for all the data the caller wants, we + simply have to expect less. We'll get the rest later. */ + if (*pcrec < cneed) + cneed = *pcrec; + + if (! fconn_read (qconn, abPrecbuf + iPrecend, pcrec, cneed, ctimeout, + freport)) + return FALSE; + + iPrecend = (iPrecend + *pcrec) % CRECBUFLEN; + + return TRUE; +} + +/* Read a single character. Get it out of the receive buffer if it's + there, otherwise ask freceive_data for at least one character. + This is used because as a protocol is shutting down freceive_data + may read ahead and eat characters that should be read outside the + protocol routines. We call freceive_data rather than fconn_read + with an argument of 1 so that we can get all the available data in + a single system call. The ctimeout argument is the timeout in + seconds; the freport argument is FALSE if no error should be + reported. This returns a character, or -1 on timeout or -2 on + error. */ + +int +breceive_char (qconn, ctimeout, freport) + struct sconnection *qconn; + int ctimeout; + boolean freport; +{ + char b; + + if (iPrecstart == iPrecend) + { + size_t crec; + + if (! freceive_data (qconn, sizeof (char), &crec, ctimeout, freport)) + return -2; + if (crec == 0) + return -1; + } + + b = abPrecbuf[iPrecstart]; + iPrecstart = (iPrecstart + 1) % CRECBUFLEN; + return BUCHAR (b); +} + +/* Send mail about a file transfer. We send to the given mailing + address if there is one, otherwise to the user. */ + +boolean +fmail_transfer (fsuccess, zuser, zmail, zwhy, zfromfile, zfromsys, + ztofile, ztosys, zsaved) + boolean fsuccess; + const char *zuser; + const char *zmail; + const char *zwhy; + const char *zfromfile; + const char *zfromsys; + const char *ztofile; + const char *ztosys; + const char *zsaved; +{ + const char *zsendto; + const char *az[20]; + int i; + + if (zmail != NULL && *zmail != '\0') + zsendto = zmail; + else + zsendto = zuser; + + i = 0; + az[i++] = "The file\n\t"; + if (zfromsys != NULL) + { + az[i++] = zfromsys; + az[i++] = "!"; + } + az[i++] = zfromfile; + if (fsuccess) + az[i++] = "\nwas successfully transferred to\n\t"; + else + az[i++] = "\ncould not be transferred to\n\t"; + if (ztosys != NULL) + { + az[i++] = ztosys; + az[i++] = "!"; + } + az[i++] = ztofile; + az[i++] = "\nas requested by\n\t"; + az[i++] = zuser; + if (! fsuccess) + { + az[i++] = "\nfor the following reason:\n\t"; + az[i++] = zwhy; + az[i++] = "\n"; + } + if (zsaved != NULL) + { + az[i++] = zsaved; + az[i++] = "\n"; + } + + return fsysdep_mail (zsendto, + fsuccess ? "UUCP succeeded" : "UUCP failed", + i, az); +} diff --git a/gnu/libexec/uucp/common_sources/prot.h b/gnu/libexec/uucp/common_sources/prot.h new file mode 100644 index 000000000000..4e2bb584d842 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/prot.h @@ -0,0 +1,250 @@ +/* prot.h + Protocol header file. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +/* We need the definition of uuconf_cmdtab to declare the protocol + parameter arrays. */ +#ifndef UUCONF_H +#include "uuconf.h" +#endif + +#if ANSI_C +/* These structures are used in prototypes but are not defined in this + header file. */ +struct sdaemon; +struct sconnection; +struct stransfer; +#endif + +/* The sprotocol structure holds information and functions for a specific + protocol (e.g. the 'g' protocol). */ + +struct sprotocol +{ + /* The name of the protocol (e.g. 'g'). */ + char bname; + /* Reliability requirements, an or of UUCONF_RELIABLE_xxx defines + from uuconf.h. */ + int ireliable; + /* The maximum number of channels this protocol can support. */ + int cchans; + /* Protocol parameter commands. */ + struct uuconf_cmdtab *qcmds; + /* A routine to start the protocol. If *pzlog is set to be + non-NULL, it is an informative message to be logged; it should + then be passed to ubuffree. */ + boolean (*pfstart) P((struct sdaemon *qdaemon, char **pzlog)); + /* Shutdown the protocol. */ + boolean (*pfshutdown) P((struct sdaemon *qdaemon)); + /* Send a command to the other side. */ + boolean (*pfsendcmd) P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); + /* Get buffer to space to fill with data. This should set *pcdata + to the amount of data desired. */ + char *(*pzgetspace) P((struct sdaemon *qdaemon, size_t *pcdata)); + /* Send data to the other side. The argument z must be a return + value of pzgetspace. The ipos argument is the file position, and + is ignored by most protocols. */ + boolean (*pfsenddata) P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); + /* Wait for data to come in and call fgot_data with it until + fgot_data sets *pfexit. */ + boolean (*pfwait) P((struct sdaemon *qdaemon)); + /* Handle any file level actions that need to be taken. If a file + transfer is starting rather than ending, fstart is TRUE. If the + file is being sent rather than received, fsend is TRUE. If + fstart and fsend are both TRUE, cbytes holds the size of the + file. If *pfhandled is set to TRUE, then the protocol routine + has taken care of queueing up qtrans for the next action. */ + boolean (*pffile) P((struct sdaemon *qdaemon, struct stransfer *qtrans, + boolean fstart, boolean fsend, long cbytes, + boolean *pfhandled)); +}; + +/* Send data to the other system. If the fread argument is TRUE, this + will also receive data into the receive buffer abPrecbuf; fread is + passed as TRUE if the protocol expects data to be coming back, to + make sure the input buffer does not fill up. Returns FALSE on + error. */ +extern boolean fsend_data P((struct sconnection *qconn, + const char *zsend, size_t csend, + boolean fdoread)); + +/* Receive data from the other system when there is no data to send. + The cneed argument is the amount of data desired and the ctimeout + argument is the timeout in seconds. This will set *pcrec to the + amount of data received. It will return FALSE on error. If a + timeout occurs, it will return TRUE with *pcrec set to zero. */ +extern boolean freceive_data P((struct sconnection *qconn, size_t cneed, + size_t *pcrec, int ctimeout, + boolean freport)); + +/* Get one character from the remote system, going through the + procotol buffering. The ctimeout argument is the timeout in + seconds, and the freport argument is TRUE if errors should be + reported (when closing a connection it is pointless to report + errors). This returns a character or -1 on a timeout or -2 on an + error. */ +extern int breceive_char P((struct sconnection *qconn, + int ctimeout, boolean freport)); + +/* Compute a 32 bit CRC of a data buffer, given an initial CRC. */ +extern unsigned long icrc P((const char *z, size_t c, unsigned long ick)); + +/* The initial CRC value to use for a new buffer. */ +#if ANSI_C +#define ICRCINIT (0xffffffffUL) +#else +#define ICRCINIT ((unsigned long) 0xffffffffL) +#endif + +/* The size of the receive buffer. */ +#define CRECBUFLEN (16384) + +/* Buffer to hold received data. */ +extern char abPrecbuf[CRECBUFLEN]; + +/* Index of start of data in abPrecbuf. */ +extern int iPrecstart; + +/* Index of end of data (first byte not included in data) in abPrecbuf. */ +extern int iPrecend; + +/* There are a couple of variables and functions that are shared by + the 'i' and 'j' protocols (the 'j' protocol is just a wrapper + around the 'i' protocol). These belong in a separate header file, + protij.h, but I don't want to create one for just a couple of + things. */ + +/* An escape sequence of characters for the 'j' protocol to avoid + (protocol parameter ``avoid''). */ +extern const char *zJavoid_parameter; + +/* Timeout to use when sending the 'i' protocol SYNC packet (protocol + parameter ``sync-timeout''). */ +extern int cIsync_timeout; + +/* Shared startup routine for the 'i' and 'j' protocols. */ +extern boolean fijstart P((struct sdaemon *qdaemon, char **pzlog, + int imaxpacksize, + boolean (*pfsend) P((struct sconnection *qconn, + const char *zsend, + size_t csend, + boolean fdoread)), + boolean (*pfreceive) P((struct sconnection *qconn, + size_t cneed, + size_t *pcrec, + int ctimeout, + boolean freport)))); + +/* Prototypes for 'g' protocol functions. */ + +extern struct uuconf_cmdtab asGproto_params[]; +extern boolean fgstart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean fbiggstart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean fgshutdown P((struct sdaemon *qdaemon)); +extern boolean fgsendcmd P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); +extern char *zggetspace P((struct sdaemon *qdaemon, size_t *pcdata)); +extern boolean fgsenddata P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); +extern boolean fgwait P((struct sdaemon *qdaemon)); + +/* Prototypes for 'f' protocol functions. */ + +extern struct uuconf_cmdtab asFproto_params[]; +extern boolean ffstart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean ffshutdown P((struct sdaemon *qdaemon)); +extern boolean ffsendcmd P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); +extern char *zfgetspace P((struct sdaemon *qdaemon, size_t *pcdata)); +extern boolean ffsenddata P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); +extern boolean ffwait P((struct sdaemon *qdaemon)); +extern boolean fffile P((struct sdaemon *qdaemon, struct stransfer *qtrans, + boolean fstart, boolean fsend, long cbytes, + boolean *pfhandled)); + +/* Prototypes for 't' protocol functions. */ + +extern struct uuconf_cmdtab asTproto_params[]; +extern boolean ftstart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean ftshutdown P((struct sdaemon *qdaemon)); +extern boolean ftsendcmd P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); +extern char *ztgetspace P((struct sdaemon *qdaemon, size_t *pcdata)); +extern boolean ftsenddata P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); +extern boolean ftwait P((struct sdaemon *qdaemon)); +extern boolean ftfile P((struct sdaemon *qdaemon, struct stransfer *qtrans, + boolean fstart, boolean fsend, long cbytes, + boolean *pfhandled)); + +/* Prototypes for 'e' protocol functions. */ + +extern struct uuconf_cmdtab asEproto_params[]; +extern boolean festart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean feshutdown P((struct sdaemon *qdaemon)); +extern boolean fesendcmd P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); +extern char *zegetspace P((struct sdaemon *qdaemon, size_t *pcdata)); +extern boolean fesenddata P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); +extern boolean fewait P((struct sdaemon *qdaemon)); +extern boolean fefile P((struct sdaemon *qdaemon, struct stransfer *qtrans, + boolean fstart, boolean fsend, long cbytes, + boolean *pfhandled)); + +/* Prototypes for 'i' protocol functions. */ + +extern struct uuconf_cmdtab asIproto_params[]; +extern boolean fistart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean fishutdown P((struct sdaemon *qdaemon)); +extern boolean fisendcmd P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); +extern char *zigetspace P((struct sdaemon *qdaemon, size_t *pcdata)); +extern boolean fisenddata P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); +extern boolean fiwait P((struct sdaemon *qdaemon)); + +/* Prototypes for 'j' protocol functions. The 'j' protocol mostly + uses the 'i' protocol functions, but it has a couple of functions + of its own. */ +extern boolean fjstart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean fjshutdown P((struct sdaemon *qdaemon)); + +/* Prototypes for 'a' protocol functions (these use 'z' as the second + character because 'a' is a modified Zmodem protocol). */ +extern struct uuconf_cmdtab asZproto_params[]; +extern boolean fzstart P((struct sdaemon *qdaemon, char **pzlog)); +extern boolean fzshutdown P((struct sdaemon *qdaemon)); +extern boolean fzsendcmd P((struct sdaemon *qdaemon, const char *z, + int ilocal, int iremote)); +extern char *zzgetspace P((struct sdaemon *qdaemon, size_t *pcdata)); +extern boolean fzsenddata P((struct sdaemon *qdaemon, char *z, size_t c, + int ilocal, int iremote, long ipos)); +extern boolean fzwait P((struct sdaemon *qdaemon)); +extern boolean fzfile P((struct sdaemon *qdaemon, struct stransfer *qtrans, + boolean fstart, boolean fsend, long cbytes, + boolean *pfhandled)); diff --git a/gnu/libexec/uucp/common_sources/sysdep.h b/gnu/libexec/uucp/common_sources/sysdep.h new file mode 100644 index 000000000000..47675ac2385d --- /dev/null +++ b/gnu/libexec/uucp/common_sources/sysdep.h @@ -0,0 +1,530 @@ +/* sysh.unx -*- C -*- + The header file for the UNIX system dependent routines. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#ifndef SYSH_UNX_H + +#define SYSH_UNX_H + +#if ANSI_C +/* These structures are used in prototypes but are not defined in this + header file. */ +struct uuconf_system; +struct sconnection; +#endif + +/* Make sure the defines do not conflict. These are in this file + because they are Unix dependent. */ +#if HAVE_V2_LOCKFILES + HAVE_HDB_LOCKFILES + HAVE_SCO_LOCKFILES + HAVE_SVR4_LOCKFILES + HAVE_COHERENT_LOCKFILES != 1 + #error LOCKFILES define not set or duplicated +#endif + +/* SCO and SVR4 lockfiles are basically just like HDB lockfiles. */ +#if HAVE_SCO_LOCKFILES || HAVE_SVR4_LOCKFILES +#undef HAVE_HDB_LOCKFILES +#define HAVE_HDB_LOCKFILES 1 +#endif + +#if HAVE_BSD_TTY + HAVE_SYSV_TERMIO + HAVE_POSIX_TERMIOS != 1 + #error Terminal driver define not set or duplicated +#endif + +#if SPOOLDIR_V2 + SPOOLDIR_BSD42 + SPOOLDIR_BSD43 + SPOOLDIR_HDB + SPOOLDIR_ULTRIX + SPOOLDIR_SVR4 + SPOOLDIR_TAYLOR != 1 + #error Spool directory define not set or duplicated +#endif + +/* If setreuid is broken, don't use it. */ +#if HAVE_BROKEN_SETREUID +#undef HAVE_SETREUID +#define HAVE_SETREUID 0 +#endif + +/* Get some standard types from the configuration header file. */ +#ifdef PID_T +typedef PID_T pid_t; +#endif + +#ifdef UID_T +typedef UID_T uid_t; +#endif + +#ifdef GID_T +typedef GID_T gid_t; +#endif + +#ifdef OFF_T +typedef OFF_T off_t; +#endif + +/* On Unix, binary files are the same as text files. */ +#define BINREAD "r" +#define BINWRITE "w" + +/* If we have sigaction, we can force system calls to not be + restarted. */ +#if HAVE_SIGACTION +#undef HAVE_RESTARTABLE_SYSCALLS +#define HAVE_RESTARTABLE_SYSCALLS 0 +#endif + +/* If we have sigvec, and we have HAVE_SIGVEC_SV_FLAGS, and + SV_INTERRUPT is defined, we can force system calls to not be + restarted (signal.h is included by uucp.h before this point, so + SV_INTERRUPT will be defined by now if it it ever is). */ +#if HAVE_SIGVEC && HAVE_SIGVEC_SV_FLAGS +#ifdef SV_INTERRUPT +#undef HAVE_RESTARTABLE_SYSCALLS +#define HAVE_RESTARTABLE_SYSCALLS 0 +#endif +#endif + +/* If we were cross-configured, we will have a value of -1 for + HAVE_RESTARTABLE_SYSCALLS. In this case, we try to guess what the + correct value should be. Yuck. If we have sigvec, but neither of + the above cases applied (which we know because they would have + changed HAVE_RESTARTABLE_SYSCALLS) then we are probably on 4.2BSD + and system calls are automatically restarted. Otherwise, assume + that they are not. */ +#if HAVE_RESTARTABLE_SYSCALLS == -1 +#undef HAVE_RESTARTABLE_SYSCALLS +#if HAVE_SIGVEC +#define HAVE_RESTARTABLE_SYSCALLS 1 +#else +#define HAVE_RESTARTABLE_SYSCALLS 0 +#endif +#endif /* HAVE_RESTARTABLE_SYSCALLS == -1 */ + +/* We don't handle sigset in combination with restartable system + calls, so we check for it although this combination will never + happen. */ +#if ! HAVE_SIGACTION && ! HAVE_SIGVEC && HAVE_SIGSET +#if HAVE_RESTARTABLE_SYSCALLS +#undef HAVE_SIGSET +#define HAVE_SIGSET 0 +#endif +#endif + +/* If we don't have restartable system calls, we can ignore + fsysdep_catch, usysdep_start_catch and usysdep_end_catch. + Otherwise fsysdep_catch has to do a setjmp. */ + +#if ! HAVE_RESTARTABLE_SYSCALLS + +#define fsysdep_catch() (TRUE) +#define usysdep_start_catch() +#define usysdep_end_catch() +#define CATCH_PROTECT + +#else /* HAVE_RESTARTABLE_SYSCALLS */ + +#if HAVE_SETRET && ! HAVE_SIGSETJMP +#include <setret.h> +#define setjmp setret +#define longjmp longret +#define jmp_buf ret_buf +#else /* ! HAVE_SETRET || HAVE_SIGSETJMP */ +#include <setjmp.h> +#if HAVE_SIGSETJMP +#undef setjmp +#undef longjmp +#undef jmp_buf +#define setjmp(s) sigsetjmp ((s), TRUE) +#define longjmp siglongjmp +#define jmp_buf sigjmp_buf +#endif /* HAVE_SIGSETJMP */ +#endif /* ! HAVE_SETRET || HAVE_SIGSETJMP */ + +extern volatile sig_atomic_t fSjmp; +extern volatile jmp_buf sSjmp_buf; + +#define fsysdep_catch() (setjmp (sSjmp_buf) == 0) + +#define usysdep_start_catch() (fSjmp = TRUE) + +#define usysdep_end_catch() (fSjmp = FALSE) + +#define CATCH_PROTECT volatile + +#endif /* HAVE_RESTARTABLE_SYSCALLS */ + +/* Get definitions for the terminal driver. */ + +#if HAVE_BSD_TTY +#include <sgtty.h> +struct sbsd_terminal +{ + struct sgttyb stty; + struct tchars stchars; + struct ltchars sltchars; +}; +typedef struct sbsd_terminal sterminal; +#define fgetterminfo(o, q) \ + (ioctl ((o), TIOCGETP, &(q)->stty) == 0 \ + && ioctl ((o), TIOCGETC, &(q)->stchars) == 0 \ + && ioctl ((o), TIOCGLTC, &(q)->sltchars) == 0) +#define fsetterminfo(o, q) \ + (ioctl ((o), TIOCSETN, &(q)->stty) == 0 \ + && ioctl ((o), TIOCSETC, &(q)->stchars) == 0 \ + && ioctl ((o), TIOCSLTC, &(q)->sltchars) == 0) +#define fsetterminfodrain(o, q) \ + (ioctl ((o), TIOCSETP, &(q)->stty) == 0 \ + && ioctl ((o), TIOCSETC, &(q)->stchars) == 0 \ + && ioctl ((o), TIOCSLTC, &(q)->sltchars) == 0) +#endif /* HAVE_BSD_TTY */ + +#if HAVE_SYSV_TERMIO +#include <termio.h> +typedef struct termio sterminal; +#define fgetterminfo(o, q) (ioctl ((o), TCGETA, (q)) == 0) +#define fsetterminfo(o, q) (ioctl ((o), TCSETA, (q)) == 0) +#define fsetterminfodrain(o, q) (ioctl ((o), TCSETAW, (q)) == 0) +#endif /* HAVE_SYSV_TERMIO */ + +#if HAVE_POSIX_TERMIOS +#include <termios.h> +typedef struct termios sterminal; +#define fgetterminfo(o, q) (tcgetattr ((o), (q)) == 0) +#define fsetterminfo(o, q) (tcsetattr ((o), TCSANOW, (q)) == 0) +#define fsetterminfodrain(o, q) (tcsetattr ((o), TCSADRAIN, (q)) == 0) + +/* On some systems it is not possible to include both <sys/ioctl.h> + and <termios.h> in the same source files; I don't really know why. + On such systems, we pretend that we don't have <sys/ioctl.h>. */ +#if ! HAVE_TERMIOS_AND_SYS_IOCTL_H +#undef HAVE_SYS_IOCTL_H +#define HAVE_SYS_IOCTL_H 0 +#endif + +#endif /* HAVE_POSIX_TERMIOS */ + +/* The root directory (this is needed by the system independent stuff + as the default for local-send). */ +#define ZROOTDIR "/" + +/* The name of the execution directory within the spool directory + (this is need by the system independent uuxqt.c). */ +#define XQTDIR ".Xqtdir" + +/* The name of the directory in which we preserve file transfers that + failed. */ +#define PRESERVEDIR ".Preserve" + +/* The length of the sequence number used in a file name. */ +#define CSEQLEN (4) + +/* Get some standard definitions. Avoid including the files more than + once--some might have been included by uucp.h. */ +#if USE_STDIO && HAVE_UNISTD_H +#include <unistd.h> +#endif +#if ! USE_TYPES_H +#include <sys/types.h> +#endif +#include <sys/stat.h> + +/* Get definitions for the file permission bits. */ + +#ifndef S_IRWXU +#define S_IRWXU 0700 +#endif +#ifndef S_IRUSR +#define S_IRUSR 0400 +#endif +#ifndef S_IWUSR +#define S_IWUSR 0200 +#endif +#ifndef S_IXUSR +#define S_IXUSR 0100 +#endif + +#ifndef S_IRWXG +#define S_IRWXG 0070 +#endif +#ifndef S_IRGRP +#define S_IRGRP 0040 +#endif +#ifndef S_IWGRP +#define S_IWGRP 0020 +#endif +#ifndef S_IXGRP +#define S_IXGRP 0010 +#endif + +#ifndef S_IRWXO +#define S_IRWXO 0007 +#endif +#ifndef S_IROTH +#define S_IROTH 0004 +#endif +#ifndef S_IWOTH +#define S_IWOTH 0002 +#endif +#ifndef S_IXOTH +#define S_IXOTH 0001 +#endif + +#ifndef S_ISDIR +#ifdef S_IFDIR +#define S_ISDIR(i) (((i) & S_IFMT) == S_IFDIR) +#else /* ! defined (S_IFDIR) */ +#define S_ISDIR(i) (((i) & 0170000) == 040000) +#endif /* ! defined (S_IFDIR) */ +#endif /* ! defined (S_ISDIR) */ + +/* We need the access macros. */ +#ifndef R_OK +#define R_OK 4 +#define W_OK 2 +#define X_OK 1 +#define F_OK 0 +#endif /* ! defined (R_OK) */ + +/* We create files with these modes (should this be configurable?). */ +#define IPRIVATE_FILE_MODE (S_IRUSR | S_IWUSR) +#define IPUBLIC_FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) + +/* We create directories with this mode (should this be configurable?). */ +#define IDIRECTORY_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#define IPUBLIC_DIRECTORY_MODE (S_IRWXU | S_IRWXG | S_IRWXO) + +#if ! HAVE_OPENDIR + +/* Define some structures to use if we don't have opendir, etc. These + will only work if we have the old Unix filesystem, with a 2 byte + inode and a 14 byte filename. */ + +#include <sys/dir.h> + +struct dirent +{ + char d_name[DIRSIZ + 1]; +}; + +typedef struct +{ + int o; + struct dirent s; +} DIR; + +extern DIR *opendir P((const char *zdir)); +extern struct dirent *readdir P((DIR *)); +extern int closedir P((DIR *)); + +#endif /* ! HAVE_OPENDIR */ + +#if ! HAVE_FTW_H + +/* If there is no <ftw.h>, define the ftw constants. */ + +#define FTW_F (0) +#define FTW_D (1) +#define FTW_DNR (2) +#define FTW_NS (3) + +#endif /* ! HAVE_FTW_H */ + +/* This structure holds the system dependent information we keep for a + connection. This is used by the TCP and TLI code. */ + +struct ssysdep_conn +{ + /* File descriptor. */ + int o; + /* Device name. */ + char *zdevice; + /* File status flags. */ + int iflags; + /* File status flags for descriptor 1 (-1 if not standard input). */ + int istdout_flags; + /* Hold the real descriptor when using a dialer device. */ + int ohold; + /* TRUE if this is a terminal and the remaining fields are valid. */ + boolean fterminal; + /* TRUE if this is a TLI descriptor. */ + boolean ftli; + /* Baud rate. */ + long ibaud; + /* Original terminal settings. */ + sterminal sorig; + /* Current terminal settings. */ + sterminal snew; +#if HAVE_COHERENT_LOCKFILES + /* On Coherent we need to hold on to the real port name which will + be used to enable the port. Ick. */ + char *zenable; +#endif +}; + +/* These functions do I/O and chat scripts to a port. They are called + by the TCP and TLI routines. */ +extern boolean fsysdep_conn_read P((struct sconnection *qconn, + char *zbuf, size_t *pclen, + size_t cmin, int ctimeout, + boolean freport)); +extern boolean fsysdep_conn_write P((struct sconnection *qconn, + const char *zbuf, size_t clen)); +extern boolean fsysdep_conn_io P((struct sconnection *qconn, + const char *zwrite, size_t *pcwrite, + char *zread, size_t *pcread)); +extern boolean fsysdep_conn_chat P((struct sconnection *qconn, + char **pzprog)); + +/* Set a signal handler. */ +extern void usset_signal P((int isig, RETSIGTYPE (*pfn) P((int)), + boolean fforce, boolean *pfignored)); + +/* Default signal handler. This sets the appropriate element of the + afSignal array. If system calls are automatically restarted, it + may do a longjmp to an fsysdep_catch. */ +extern RETSIGTYPE ussignal P((int isig)); + +/* Try to fork, repeating several times. */ +extern pid_t ixsfork P((void)); + +/* Spawn a job. Returns the process ID of the spawned job or -1 on + error. The following macros may be passed in aidescs. */ + +/* Set descriptor to /dev/null. */ +#define SPAWN_NULL (-1) +/* Set element of aidescs to a pipe for caller to read from. */ +#define SPAWN_READ_PIPE (-2) +/* Set element of aidescs to a pipe for caller to write to. */ +#define SPAWN_WRITE_PIPE (-3) + +extern pid_t ixsspawn P((const char **pazargs, int *aidescs, + boolean fkeepuid, boolean fkeepenv, + const char *zchdir, boolean fnosigs, + boolean fshell, const char *zpath, + const char *zuu_machine, + const char *zuu_user)); + +/* Do a form of popen using ixsspawn. */ +extern FILE *espopen P((const char **pazargs, boolean frd, + pid_t *pipid)); + +/* Wait for a particular process to finish, returning the exit status. + The process ID should be pid_t, but we can't put that in a + prototype. */ +extern int ixswait P((unsigned long ipid, const char *zreport)); + +/* Find a spool file in the spool directory. For a local file, the + bgrade argument is the grade of the file. This is needed for + SPOOLDIR_SVR4. */ +extern char *zsfind_file P((const char *zsimple, const char *zsystem, + int bgrade)); + +/* Return the grade given a sequence number. */ +extern char bsgrade P((pointer pseq)); + +/* Lock a string. */ +extern boolean fsdo_lock P((const char *, boolean fspooldir, + boolean *pferr)); + +/* Unlock a string. */ +extern boolean fsdo_unlock P((const char *, boolean fspooldir)); + +/* Check access for a particular user name, or NULL to check access + for any user. */ +extern boolean fsuser_access P((const struct stat *, int imode, + const char *zuser)); + +/* Stick two directories and a file name together. */ +extern char *zsappend3 P((const char *zdir1, const char *zdir2, + const char *zfile)); + +/* Stick three directories and a file name together. */ +extern char *zsappend4 P((const char *zdir1, const char *zdir2, + const char *zdir3, const char *zfile)); + +/* Get a temporary file name. */ +extern char *zstemp_file P((const struct uuconf_system *qsys)); + +/* Get a command file name. */ +extern char *zscmd_file P((const struct uuconf_system *qsys, int bgrade)); + +/* Get a jobid from a system, a file name, and a grade. */ +extern char *zsfile_to_jobid P((const struct uuconf_system *qsys, + const char *zfile, + int bgrade)); + +/* Get a file name from a jobid. This also returns the associated system + in *pzsystem and the grade in *pbgrade. */ +extern char *zsjobid_to_file P((const char *zid, char **pzsystem, + char *pbgrade)); + +/* See whether there is a spool directory for a system when using + SPOOLDIR_ULTRIX. */ +extern boolean fsultrix_has_spool P((const char *zsystem)); + +#if HAVE_COHERENT_LOCKFILES +/* Lock a coherent tty. */ +extern boolean lockttyexist P((const char *z)); +extern boolean fscoherent_disable_tty P((const char *zdevice, + char **pzenable)); +#endif + +/* Some replacements for standard Unix functions. */ + +#if ! HAVE_DUP2 +extern int dup2 P((int oold, int onew)); +#endif + +#if ! HAVE_FTW +extern int ftw P((const char *zdir, + int (*pfn) P((const char *zfile, + const struct stat *qstat, + int iflag)), + int cdescriptors)); +#endif + +#if ! HAVE_GETCWD && ! HAVE_GETWD +extern char *getcwd P((char *zbuf, size_t cbuf)); +#endif + +#if ! HAVE_MKDIR +extern int mkdir P((const char *zdir, int imode)); +#endif + +#if ! HAVE_RENAME +extern int rename P((const char *zold, const char *znew)); +#endif + +#if ! HAVE_RMDIR +extern int rmdir P((const char *zdir)); +#endif + +/* The working directory from which the program was run (this is set + by usysdep_initialize if called with INIT_GETCWD). */ +extern char *zScwd; + +/* The spool directory name. */ +extern const char *zSspooldir; + +/* The lock directory name. */ +extern const char *zSlockdir; + +/* The local UUCP name (needed for some spool directory stuff). */ +extern const char *zSlocalname; + +#endif /* ! defined (SYSH_UNX_H) */ diff --git a/gnu/libexec/uucp/common_sources/system.h b/gnu/libexec/uucp/common_sources/system.h new file mode 100644 index 000000000000..aa9d2a41a45a --- /dev/null +++ b/gnu/libexec/uucp/common_sources/system.h @@ -0,0 +1,950 @@ +/* system.h + Header file for system dependent stuff in the Taylor UUCP package. + This file is not itself system dependent. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#ifndef SYSTEM_H + +#define SYSTEM_H + +#if ANSI_C +/* These structures are used in prototypes but are not defined in this + header file. */ +struct tm; +struct uuconf_system; +struct uuconf_port; +struct sconnection; +struct sstatus; +struct scmd; +#endif + +/* Any function which returns an error should also report an error + message, unless otherwise indicated. + + Any function that returns a char *, rather than a const char *, is + returning a pointer to a buffer allocated by zbufalc which must be + freed using ubuffree, unless otherwise indicated. */ + +/* The maximum length of a remote system name. */ +extern size_t cSysdep_max_name_len; + +/* Initialize. If something goes wrong, this routine should just + exit. The flag argument is 0, or a combination of any of the + following flags. */ + +/* This program needs to know the current working directory. This is + used because on Unix it can be expensive to determine the current + working directory (some versions of getcwd fork a process), but in + most cases we don't need to know it. However, we are going to + chdir to the spool directory (unless INIT_CHDIR is set), so we have + to get the cwd now if we are ever going to get it. Both uucp and + uux use the function fsysdep_needs_cwd to determine whether they + will need the current working directory, and pass the argument to + usysdep_initialize appropriately. There's probably a cleaner way + to handle this, but this will suffice for now. */ +#define INIT_GETCWD (01) + +/* This program should not chdir to the spool directory. This may + only make sense on Unix. It is set by cu. */ +#define INIT_NOCHDIR (02) + +/* This program needs special access to the spool directories. That + means, on Unix, this program is normally installed setuid. */ +#define INIT_SUID (04) + +extern void usysdep_initialize P((pointer puuconf, int iflags)); + +/* Exit the program. The fsuccess argument indicates whether to + return an indication of success or failure to the outer + environment. This routine should not return. */ +extern void usysdep_exit P((boolean fsuccess)); + +/* Called when a non-standard configuration file is being used, to + avoid handing out privileged access. If it returns FALSE, default + configuration file will be used. This is called before the + usysdep_initialize function is called. */ +extern boolean fsysdep_other_config P((const char *)); + +/* Detach from the controlling terminal. This probably only makes + sense on Unix. It is called by uucico to try to get the modem port + as a controlling terminal. It is also called by uucico before it + starts up uuxqt, so that uuxqt will be a complete daemon. */ +extern void usysdep_detach P((void)); + +/* Get the local node name if it is not specified in the configuration + files. Returns NULL on error; otherwise the return value should + point to a static buffer. */ +extern const char *zsysdep_localname P((void)); + +/* Get the login name. This is used when uucico is started up with no + arguments in slave mode, which causes it to assume that somebody + has logged in. It also used by uucp and uux for recording the user + name. This may not return NULL. The return value should point to + a static buffer. */ +extern const char *zsysdep_login_name P((void)); + +/* Set a signal handler for a signal. If the signal occurs, the + appropriate element of afSignal should be set to the signal number + (see the declaration of afSignal in uucp.h). This routine might be + able to just use signal, but Unix requires more complex handling. + This is called before usysdep_initialize. */ +extern void usysdep_signal P((int isig)); + +/* Catch a signal. This is actually defined as a macro in the system + dependent header file, and the prototype here just indicates how it + should be called. It is called before a routine which must exit if + a signal occurs, and is expected to set do a setjmp (which is why + it must be a macro). It is actually only called in one place in + the system independent code, before the call to read stdin in uux. + This is needed to handle 4.2 BSD restartable system calls, which + require a longjmp. On systems which don't need to do + setjmp/longjmp around system calls, this can be redefined in + sysdep.h to TRUE. It should return TRUE if the routine should + proceed, or FALSE if a signal occurred. After having this return + TRUE, usysdep_start_catch should be used to start catching the + signal; this basically tells the signal handler that it's OK to do + the longjmp, if fsysdep_catch did not already do so. */ +#ifndef fsysdep_catch +extern boolean fsysdep_catch P((void)); +#endif + +/* Start catching a signal. This is called after fsysdep_catch to + tell the signal handler to go ahead and do the longjmp. This may + be implemented as a macro in sysdep.h. */ +#ifndef usysdep_start_catch +extern void usysdep_start_catch P((void)); +#endif + +/* Stop catching a signal. This is called when it is no longer + necessary for fsysdep_catch to handle signals. This may be + implemented as a macro in sysdep.h. */ +#ifndef usysdep_end_catch +extern void usysdep_end_catch P((void)); +#endif + +/* Link two files. On Unix this should attempt the link. If it + succeeds it should return TRUE with *pfworked set to TRUE. If the + link fails because it must go across a device, it should return + TRUE with *pfworked set to FALSE. If the link fails for some other + reason, it should log an error message and return FALSE. On a + system which does not support links to files, this should just + return TRUE with *pfworked set to FALSE. */ +extern boolean fsysdep_link P((const char *zfrom, const char *zto, + boolean *pfworked)); + +/* Get the port name. This is used when uucico is started up in slave + mode to figure out which port was used to call in so that it can + determine any appropriate protocol parameters. This may return + NULL if the port cannot be determined, which will just mean that no + protocol parameters are applied. The name returned should be the + sort of name that would appear in the port file. This should set + *pftcp_port to TRUE if it can determine that the port is a TCP + connection rather than a normal serial port. The return value (if + not NULL) should point to a static buffer. */ +extern const char *zsysdep_port_name P((boolean *pftcp_port)); + +/* Expand a file name on the local system. On Unix, if the zfile + argument begins with ~user/ it goes in that users home directory, + and if it begins with ~/ it goes in the public directory (the + public directory is passed to this routine, since each system may + have its own public directory). Similar conventions may be + desirable on other systems. This should always return an absolute + path name, probably in the public directory. It should return NULL + on error; otherwise the return value should be allocated using + zbufcpy or zbufalc. */ +extern char *zsysdep_local_file P((const char *zname, + const char *zpubdir)); + +/* Return whether a file name is in a directory, and check for read or + write access. This should check whether zfile is within zdir (or + is zdir itself). If it is not, it should return FALSE. If zfile + is in zdir, then fcheck indicates whether further checking should + be done. If fcheck is FALSE, no further checking is done. + Otherwise, if freadable is TRUE the user zuser should have search + access to all directories from zdir down to zfile and should have + read access on zfile itself (if zfile does not exist, or is not a + regular file, this function may return FALSE but does not have to). + If freadable is FALSE, the user zuser should have search access to + all directories from zdir down to zfile and should have write + access on zfile (which may be a directory, or may not actually + exist, which is acceptable). The zuser argument may be NULL, in + which case the check should be made for any user, not just zuser. + There is no way for this function to return error. */ +extern boolean fsysdep_in_directory P((const char *zfile, + const char *zdir, + boolean fcheck, + boolean freadable, + const char *zuser)); + +/* Return TRUE if a file exists, FALSE otherwise. There is no way to + return error. */ +extern boolean fsysdep_file_exists P((const char *zfile)); + +/* Start up a program. The code expects fsysdep_run to return after + doing a fork, but at least for now everything will work fine if it + does not (on a system which does not support forking). The three + string arguments may be catenated together to form the program to + execute; I did it this way to make it easy to call execl(2), and + because I never needed more than two arguments. The program will + always be "uucico" or "uuxqt". The return value will be passed + directly to usysdep_exit, and should be TRUE on success, FALSE on + error. */ +extern boolean fsysdep_run P((const char *zprogram, const char *zarg1, + const char *zarg2)); + +/* Send a mail message. This function will be passed an array of + strings. All necessary newlines are already included; the strings + should simply be concatenated together to form the mail message. + It should return FALSE on error, although the return value is often + ignored. */ +extern boolean fsysdep_mail P((const char *zto, const char *zsubject, + int cstrs, const char **paz)); + +/* Get the time in seconds since some epoch. The actual epoch is + unimportant, so long as the time values are consistent across + program executions and the value is never negative. If the + pimicros argument is not NULL, it should be set to the number of + microseconds (if this is not available, *pimicros should be set to + zero). */ +extern long ixsysdep_time P((long *pimicros)); + +/* Get the time in seconds and microseconds (millionths of a second) + since some epoch. The actual epoch is not important, and it may + change in between program invocations; this is provided because on + Unix the times function may be used. If microseconds can not be + determined, *pimicros can just be set to zero. */ +extern long ixsysdep_process_time P((long *pimicros)); + +/* Parse the value returned by ixsysdep_time into a struct tm. I + assume that this structure is defined in <time.h>. This is + basically just localtime, except that the ANSI function takes a + time_t which may not be what is returned by ixsysdep_time. */ +extern void usysdep_localtime P((long itime, struct tm *q)); + +/* Sleep for a number of seconds. */ +extern void usysdep_sleep P((int cseconds)); + +/* Pause for half a second, or 1 second if subsecond sleeps are not + possible. */ +extern void usysdep_pause P((void)); + +/* Lock a remote system. This should return FALSE if the system is + already locked (no error should be reported). */ +extern boolean fsysdep_lock_system P((const struct uuconf_system *qsys)); + +/* Unlock a remote system. This should return FALSE on error + (although the return value is generally ignored). */ +extern boolean fsysdep_unlock_system P((const struct uuconf_system *qsys)); + +/* Get the conversation sequence number for a remote system, and + increment it for next time. This should return -1 on error. */ +extern long ixsysdep_get_sequence P((const struct uuconf_system *qsys)); + +/* Get the status of a remote system. This should return FALSE on + error. Otherwise it should set *qret to the status. If no status + information is available, this should set *qret to sensible values + and return TRUE. If pfnone is not NULL, then it should be set to + TRUE if no status information was available or FALSE otherwise. */ +extern boolean fsysdep_get_status P((const struct uuconf_system *qsys, + struct sstatus *qret, + boolean *pfnone)); + +/* Set the status of a remote system. This should return FALSE on + error. The system will be locked before this call is made. */ +extern boolean fsysdep_set_status P((const struct uuconf_system *qsys, + const struct sstatus *qset)); + +/* See whether a remote system is permitted to log in. This is just + to support the remote.unknown shell script for HDB. The zscript + argument is the script name, as return by uuconf_remote_unknown. + The zsystem argument is the name given by the remote system. If + the system is not permitted to log in, this function should log an + error and return FALSE. */ +extern boolean fsysdep_unknown_caller P((const char *zscript, + const char *zsystem)); + +/* Check whether there is work for a remote system. It should return + TRUE if there is work, FALSE otherwise; there is no way to indicate + an error. */ +extern boolean fsysdep_has_work P((const struct uuconf_system *qsys)); + +/* Initialize the work scan. This will be called before + fsysdep_get_work. The bgrade argument is the minimum grade of + execution files that should be considered (e.g. a bgrade of 'd' + will allow all grades from 'A' to 'Z' and 'a' to 'd'). This + function should return FALSE on error. */ +extern boolean fsysdep_get_work_init P((const struct uuconf_system *qsys, + int bgrade)); + +/* Get the next command to be executed for a remote system. The + bgrade argument will be the same as for fsysdep_get_work_init; + probably only one of these functions will use it, namely the + function for which it is more convenient. This should return FALSE + on error. The structure pointed to by qcmd should be filled in. + The strings may point into a static buffer; they will be copied out + if necessary. If there is no more work, this should set qcmd->bcmd + to 'H' and return TRUE. This should set qcmd->pseq to something + which can be passed to fsysdep_did_work to remove the job from the + queue when it has been completed. This may set qcmd->bcmd to 'P' + to represent a poll file; the main code will just pass the pseq + element of such a structure to fsysdep_did_work if the system is + called. */ +extern boolean fsysdep_get_work P((const struct uuconf_system *qsys, + int bgrade, struct scmd *qcmd)); + +/* Remove a job from the work queue. This must also remove the + temporary file used for a send command, if there is one. It should + return FALSE on error. */ +extern boolean fsysdep_did_work P((pointer pseq)); + +/* Save the temporary file for a send command. This function should + return a string that will be put into a mail message. On success + this string should say something like ``The file has been saved as + ...''. On failure it could say something like ``The file could not + be saved because ...''. If there is no temporary file, or for some + reason it's not appropriate to include a message, this function + should just return NULL. This function is used when a file send + fails for some reason, to make sure that we don't completely lost + the file. */ +extern const char *zsysdep_save_temp_file P((pointer pseq)); + +/* Cleanup anything left over by fsysdep_get_work_init and + fsysdep_get_work. This may be called even though + fsysdep_get_work_init has not been. */ +extern void usysdep_get_work_free P((const struct uuconf_system *qsys)); + +/* Add a base name to a file if it is a directory. If zfile names a + directory, then return a string naming a file within the directory + with the base file name of zname. This should return NULL on + error. */ +extern char *zsysdep_add_base P((const char *zfile, + const char *zname)); + +/* Get a file name from the spool directory. This should return NULL + on error. The pseq argument is TRUE if the file was found from + searching the work directory; this is, unfortunately, needed to + support SVR4 spool directories. */ +extern char *zsysdep_spool_file_name P((const struct uuconf_system *qsys, + const char *zfile, + pointer pseq)); + +/* Make necessary directories. This should create all non-existent + directories for a file. If the fpublic argument is TRUE, anybody + should be permitted to create and remove files in the directory; + otherwise anybody can list the directory, but only the UUCP system + can create and remove files. It should return FALSE on error. */ +extern boolean fsysdep_make_dirs P((const char *zfile, boolean fpublic)); + +/* Create a stdio file, setting appropriate protection. If the + fpublic argument is TRUE, the file is made publically accessible; + otherwise it is treated as a private data file. If the fappend + argument is TRUE, the file is opened in append mode; otherwise any + previously existing file of the same name is removed. If the + fmkdirs argument is TRUE, then any necessary directories should + also be created. On a system in which file protections are + unimportant and the necessary directories exist, this may be + implemented as + + fopen (zfile, fappend ? "a" : "w"); + + */ +extern FILE *esysdep_fopen P((const char *zfile, boolean fpublic, + boolean fappend, boolean fmkdirs)); + +/* Open a file, using the access permission of the user who invoked + the program. The frd argument is TRUE if the file should be opened + for reading, and the fbinary argument is TRUE if the file should be + opened as a binary file (this is ignored on Unix, since there all + files are binary files). This returns an openfile_t, not a FILE *. + This is supposed to be able to open a file even if it can not be + read by the uucp user. This is not possible on some older Unix + systems. */ +extern openfile_t esysdep_user_fopen P((const char *zfile, + boolean frd, boolean fbinary)); + +/* Open a file to send to another system; the qsys argument is the + system the file is being sent to. If fcheck is TRUE, it should + make sure that the file is readable by zuser (if zuser is NULL the + file must be readable by anybody). This is to eliminate a window + between fsysdep_in_directory and esysdep_open_send. If an error + occurs, it should return EFILECLOSED. */ +extern openfile_t esysdep_open_send P((const struct uuconf_system *qsys, + const char *zname, + boolean fcheck, + const char *zuser)); + +/* Return a temporary file name to receive into. This file will be + opened by esysdep_open_receive. The qsys argument is the system + the file is coming from, the zto argument is the name the file will + have after it has been fully received, and the ztemp argument, if + it is not NULL, is from the command sent by the remote system. The + return value must be freed using ubuffree. The function should + return NULL on error. */ +extern char *zsysdep_receive_temp P((const struct uuconf_system *qsys, + const char *zfile, + const char *ztemp)); + +/* Open a file to receive from another system. The zreceive argument + is the return value of zsysdep_receive_temp with the same qsys, + zfile and ztemp arguments. If the function can determine that this + file has already been partially received, it should set *pcrestart + to the number of bytes that have been received. If the file has + not been partially received, *pcrestart should be set to -1. The + function should return EFILECLOSED on error. After the file is + written, fsysdep_move_file will be called to move the file to its + final destination, and to set the correct file mode. */ +extern openfile_t esysdep_open_receive P((const struct uuconf_system *qsys, + const char *zto, + const char *ztemp, + const char *zreceive, + long *pcrestart)); + +/* Move a file. This is used to move a received file to its final + location. The zto argument is the file to create. The zorig + argument is the name of the file to move. If fmkdirs is TRUE, then + any necessary directories are created; fpublic indicates whether + they should be publically writeable or not. If fcheck is TRUE, + this should make sure the directory is writeable by the user zuser + (if zuser is NULL, then it must be writeable by any user); this is + to avoid a window of vulnerability between fsysdep_in_directory and + fsysdep_move_file. This function should return FALSE on error; the + zorig file should be removed even if an error occurs. */ +extern boolean fsysdep_move_file P((const char *zorig, const char *zto, + boolean fmkdirs, boolean fpublic, + boolean fcheck, const char *zuser)); + +/* Change the mode of a file. The imode argument is a Unix mode. + This should return FALSE on error. */ +extern boolean fsysdep_change_mode P((const char *zfile, + unsigned int imode)); + +/* Truncate a file which we are receiving into. This may be done by + closing the original file, removing it and reopening it. This + should return FALSE on error. */ +extern openfile_t esysdep_truncate P((openfile_t e, const char *zname)); + +/* It is possible for the acknowledgement of a received file to be + lost. The sending system will then now know that the file was + correctly received, and will send it again. This can be a problem + particularly with protocols which support channels, since they may + send several small files in a single window, all of which may be + received correctly although the sending system never sees the + acknowledgement. If these files involve an execution, the + execution will happen twice, which will be bad. + + This function is called when a file is completely received. It is + supposed to try and remember the reception, in case the connection + is lost. It is passed the system, the file name to receive to, and + the temporary file name from the sending system. It should return + FALSE on error. */ +extern boolean fsysdep_remember_reception P((const struct uuconf_system *qsys, + const char *zto, + const char *ztemp)); + +/* This function is called to see if a file has already been received + successfully. It gets the same arguments as + fsysdep_remember_reception. It should return TRUE if the file was + already received, FALSE otherwise. There is no way to report + error. */ +extern boolean fsysdep_already_received P((const struct uuconf_system *qsys, + const char *zto, + const char *ztemp)); + +/* This function is called when it is no longer necessary to remember + that a file has been received. This will be called when the + protocol knows that the receive message has been acknowledged. It + gets the same arguments as fsysdep_remember_reception. it should + return FALSE on error. */ +extern boolean fsysdep_forget_reception P((const struct uuconf_system *qsys, + const char *zto, + const char *ztemp)); + +/* Start expanding a wildcarded file name. This should return FALSE + on error; otherwise subsequent calls to zsysdep_wildcard should + return file names. */ +extern boolean fsysdep_wildcard_start P((const char *zfile)); + +/* Get the next wildcard name. This should return NULL when there are + no more names to return. The return value should be freed using + ubuffree. The argument should be the same as that to + fsysdep_wildcard_start. There is no way to return error. */ +extern char *zsysdep_wildcard P((const char *zfile)); + +/* Finish getting wildcard names. This may be called before or after + zsysdep_wildcard has returned NULL. It should return FALSE on + error. */ +extern boolean fsysdep_wildcard_end P((void)); + +/* Prepare to execute a bunch of file transfer requests. This should + make an entry in the spool directory so that the next time uucico + is started up it will transfer these files. The bgrade argument + specifies the grade of the commands. The commands themselves are + in the pascmds array, which has ccmds entries. The function should + return NULL on error, or the jobid on success. The jobid is a + string that may be printed or passed to fsysdep_kill_job and + related functions, but is otherwise uninterpreted. */ +extern char *zsysdep_spool_commands P((const struct uuconf_system *qsys, + int bgrade, int ccmds, + const struct scmd *pascmds)); + +/* Get a file name to use for a data file to be copied to another + system. The ztname, zdname and zxname arguments will all either be + NULL or point to an array of CFILE_NAME_LEN characters in length. + The ztname array should be set to a temporary file name that could + be passed to zsysdep_spool_file_name to retrieve the return value + of this function; this will be appropriate for the temporary name + in a send request. The zdname array should be set to a data file + name that is appropriate for the spool directory of the other + system; this will be appropriate for the name of the destination + file in a send request of a data file for an execution of some + sort. The zxname array should be set to an execute file name that + is appropriate for the other system. The zlocalname argument is + the name of the local system as seen by the remote system, the + bgrade argument is the grade, and fxqt is TRUE if this file is + going to become an execution file. This should return NULL on + error. */ +#define CFILE_NAME_LEN (15) + +extern char *zsysdep_data_file_name P((const struct uuconf_system *qsys, + const char *zlocalname, + int bgrade, boolean fxqt, + char *ztname, char *zdname, + char *zxname)); + +/* Get a name for a local execute file. This is used by uux for a + local command with remote files. Returns NULL on error. */ +extern char *zsysdep_xqt_file_name P((void)); + +/* Beginning getting execute files. To get a list of execute files, + first fsysdep_get_xqt_init is called, then zsysdep_get_xqt is + called several times until it returns NULL, then finally + usysdep_get_xqt_free is called. */ +extern boolean fsysdep_get_xqt_init P((void)); + +/* Get the next execute file. This should return NULL when finished + (with *pferr set to FALSE). On an error this should return NULL + with *pferr set to TRUE. This should set *pzsystem to the name of + the system for which the execute file was created. Both the return + value and *pzsystem should be freed using ubuffree. */ +extern char *zsysdep_get_xqt P((char **pzsystem, + boolean *pferr)); + +/* Clean up after getting execute files. */ +extern void usysdep_get_xqt_free P((void)); + +/* Get the absolute pathname of a command to execute. This is given + the legal list of commands (which may be the special case "ALL") + and the path. It must return an absolute pathname to the command. + If it gets an error it should set *pferr to TRUE and return NULL; + if the command is not found it should set *pferr to FALSE and + return NULL. */ +extern char *zsysdep_find_command P((const char *zcmd, char **pzcmds, + char **pzpath, boolean *pferr)); + +/* Expand file names for uuxqt. This exists because uuxqt on Unix has + to expand file names which begin with a ~. It does not want to + expand any other type of file name, and it turns a double ~ into a + single one without expanding. If this returns NULL, the file does + not need to be changed; otherwise it returns a zbufalc'ed string. + There is no way to report error. */ +extern char *zsysdep_xqt_local_file P((const struct uuconf_system *qsys, + const char *zfile)); + +#if ! ALLOW_FILENAME_ARGUMENTS +/* Check an argument to an execution command to make sure that it + doesn't refer to a file name that may not be accessed. This should + check the argument to see if it is a filename. If it is, it should + either reject it out of hand or it should call fin_directory_list + on the file with both qsys->zremote_receive and qsys->zremote_send. + If the file is rejected, it should log an error and return FALSE. + Otherwise it should return TRUE. */ +extern boolean fsysdep_xqt_check_file P((const struct uuconf_system *qsys, + const char *zfile)); +#endif /* ! ALLOW_FILENAME_ARGUMENTS */ + +/* Run an execute file. The arguments are: + + qsys -- system for which execute file was created + zuser -- user who requested execution + pazargs -- list of arguments to command (element 0 is command) + zfullcmd -- command and arguments stuck together in one string + zinput -- file name for standard input (may be NULL) + zoutput -- file name for standard output (may be NULL) + fshell -- if TRUE, use /bin/sh to execute file + ilock -- return value of ixsysdep_lock_uuxqt + pzerror -- set to name of standard error file + pftemp -- set to TRUE if error is temporary, FALSE otherwise + + If fshell is TRUE, the command should be executed with /bin/sh + (obviously, this can only really be done on Unix systems). If an + error occurs this should return FALSE and set *pftemp + appropriately. *pzerror should be freed using ubuffree. */ +extern boolean fsysdep_execute P((const struct uuconf_system *qsys, + const char *zuser, + const char **pazargs, + const char *zfullcmd, + const char *zinput, + const char *zoutput, + boolean fshell, + int ilock, + char **pzerror, + boolean *pftemp)); + +/* Lock for uuxqt execution. If the cmaxuuxqts argument is not zero, + this should make sure that no more than cmaxuuxqts uuxqt processes + are running at once. Also, only one uuxqt may execute a particular + command (specified by the -c option) at a time. If zcmd is not + NULL, it is a command that must be locked. This should return a + nonnegative number which will be passed to other routines, + including fsysdep_unlock_uuxqt, or -1 on error. */ +extern int ixsysdep_lock_uuxqt P((const char *zcmd, + int cmaxuuxqts)); + +/* Unlock a uuxqt process. This is passed the return value of + ixsysdep_lock_uuxqt, as well as the arguments passed to + ixsysdep_lock_uuxqt. It may return FALSE on error, but at present + the return value is ignored. */ +extern boolean fsysdep_unlock_uuxqt P((int iseq, const char *zcmd, + int cmaxuuxqts)); + +/* See whether a particular uuxqt command is locked. This should + return TRUE if the command is locked (because ixsysdep_lock_uuxqt + was called with it as an argument), FALSE otherwise. There is no + way to return error. */ +extern boolean fsysdep_uuxqt_locked P((const char *zcmd)); + +/* Lock an execute file in order to execute it. This should return + FALSE if the execute file is already locked. There is no way to + return error. */ +extern boolean fsysdep_lock_uuxqt_file P((const char *zfile)); + +/* Unlock an execute file. This should return FALSE on error. */ +extern boolean fsysdep_unlock_uuxqt_file P((const char *zfile)); + +/* Lock the execution directory. The ilock argument is the return + value of ixsysdep_lock_uuxqt. This should return FALSE if the + directory is already locked. There is no way to return error. */ +extern boolean fsysdep_lock_uuxqt_dir P((int ilock)); + +/* Remove all files in the execution directory, and unlock it. This + should return FALSE on error. */ +extern boolean fsysdep_unlock_uuxqt_dir P((int ilock)); + +/* Move files into or out of the execution directory. The code will + already have checked that all the files exist. The elements in the + pzfrom array will be complete filenames, and the elements in the + pzto array will be either NULL (in which case the file should not + be moved) or simple base names. If fto is TRUE, the files in + pzfrom should be moved to pzto; otherwise, the files in pzto should + be moved to pzfrom (this is used if a temporary failure occurs, in + which case the execution will be retried later). If pzinput and + *pzinput are not NULL, then it is the name of the standard input + file; if it is the same as any element of pzfrom, then *pzinput + should be set to the zbufcpy of the corresponding pzto value, if + any. */ +extern boolean fsysdep_move_uuxqt_files P((int cfiles, + const char *const *pzfrom, + const char *const *pzto, + boolean fto, int ilock, + char **pzinput)); + +/* Expand a file name on the local system, defaulting to the current + directory. This is just like zsysdep_local_file, except that + relative files are placed in the working directory the program + started in rather than in the public directory. This should return + NULL on error. */ +extern char *zsysdep_local_file_cwd P((const char *zname, + const char *zpubdir)); + +/* Add the working directory to a file name. The named file is + actually on a remote system. If the file already has a directory, + it should not be changed. This should return NULL on error. */ +extern char *zsysdep_add_cwd P((const char *zfile)); + +/* See whether a file name will need the current working directory + when zsysdep_local_file_cwd or zsysdep_add_cwd is called on it. + This will be called before usysdep_initialize. It should just + check whether the argument is an absolute path. See the comment + above usysdep_initialize in this file for an explanation of why + things are done this way. */ +extern boolean fsysdep_needs_cwd P((const char *zfile)); + +/* Get the base name of a file. The file will be a local file name, + and this function should return the base file name, ideally in a + form which will make sense on most systems; it will be used if the + destination of a uucp is a directory. */ +extern char *zsysdep_base_name P((const char *zfile)); + +/* Return a filename within a directory. */ +extern char *zsysdep_in_dir P((const char *zdir, const char *zfile)); + +/* Get the mode of a file. This should return a Unix style file mode. + It should return 0 on error. */ +extern unsigned int ixsysdep_file_mode P((const char *zfile)); + +/* See whether the user has access to a file. This is called by uucp + and uux to prevent copying of a file which uucp can read but the + user cannot. If access is denied, this should log an error message + and return FALSE. */ +extern boolean fsysdep_access P((const char *zfile)); + +/* See whether the daemon has access to a file. This is called by + uucp and uux when a file is queued up for transfer without being + copied into the spool directory. It is merely an early error + check, as the daemon would of course discover the error itself when + it tried the transfer. If access would be denied, this should log + an error message and return FALSE. */ +extern boolean fsysdep_daemon_access P((const char *zfile)); + +/* Translate a destination from system!user to a place in the public + directory where uupick will get the file. On Unix this produces + system!~/receive/user/localname, and that's probably what it has to + produce on any other system as well. Returns NULL on a usage + error, or otherwise returns string allocated by zbufcpy. */ +extern char *zsysdep_uuto P((const char *zdest, + const char *zlocalname)); + +/* Return TRUE if a pathname exists and is a directory. */ +extern boolean fsysdep_directory P((const char *zpath)); + +/* Walk a directory tree. The zdir argument is the directory to walk. + The pufn argument is a function to call on each regular file in the + tree. The first argument to pufn should be the full filename; the + second argument to pufn should be the filename relative to zdir; + the third argument to pufn should be the pinfo argument to + usysdep_walk_tree. The usysdep_walk_tree function should return + FALSE on error. */ +extern boolean usysdep_walk_tree P((const char *zdir, + void (*pufn) P((const char *zfull, + const char *zrelative, + pointer pinfo)), + pointer pinfo)); + +/* Return the jobid of a work file, given the sequence value. On + error this should log an error and return NULL. The jobid is a + string which may be printed out and read in and passed to + fsysdep_kill_job, etc., but is not otherwise interpreted. */ +extern char *zsysdep_jobid P((const struct uuconf_system *qsys, + pointer pseq)); + +/* See whether the current user is permitted to kill jobs submitted by + another user. This should return TRUE if permission is granted, + FALSE otherwise. */ +extern boolean fsysdep_privileged P((void)); + +/* Kill a job, given the jobid. This should remove all associated + files and in general eliminate the job completely. On error it + should log an error message and return FALSE. */ +extern boolean fsysdep_kill_job P((pointer puuconf, + const char *zjobid)); + +/* Rejuvenate a job, given the jobid. If possible, this should update + the time associated with the job such that it will not be + eliminated by uustat -K or similar programs that check the creation + time. This should affect the return value of ixsysdep_work_time. + On error it should log an error message and return FALSE. */ +extern boolean fsysdep_rejuvenate_job P((pointer puuconf, + const char *zjobid)); + +/* Get the time a job was queued, given the sequence number. There is + no way to indicate error. The return value must use the same epoch + as ixsysdep_time. */ +extern long ixsysdep_work_time P((const struct uuconf_system *qsys, + pointer pseq)); + +/* Get the time a file was created. This is called by uustat on + execution files. There is no way to indicate error. The return + value must use the same epoch as ixsysdep_time. */ +extern long ixsysdep_file_time P((const char *zfile)); + +/* Get the size in bytes of a file. If this file does not exist, this + should not give an error message, but should return -1. If some + other error occurs, this should return -2. */ +extern long csysdep_size P((const char *zfile)); + +/* Return the amount of free space on the containing the given file + name (the file may or may not exist). If the amount of free space + cannot be determined, the function should return -1. */ +extern long csysdep_bytes_free P((const char *zfile)); + +/* Start getting status information for all systems with available + status information. There may be status information for unknown + systems, which is why this series of functions is used. The phold + argument is used to pass information around, to possibly avoid the + use of static variables. On error this should log an error and + return FALSE. */ +extern boolean fsysdep_all_status_init P((pointer *phold)); + +/* Get status information for the next system. This should return the + system name and fill in the qstat argument. The phold argument + will be that set by fsysdep_all_status_init. On error this should + log an error, set *pferr to TRUE, and return NULL. */ +extern char *zsysdep_all_status P((pointer phold, boolean *pferr, + struct sstatus *qstat)); + +/* Free up anything allocated by fsysdep_all_status_init and + zsysdep_all_status. The phold argument is that set by + fsysdep_all_status_init. */ +extern void usysdep_all_status_free P((pointer phold)); + +/* Display the process status of all processes holding lock files. + This is uustat -p. The return value is passed to usysdep_exit. */ +extern boolean fsysdep_lock_status P((void)); + +/* Return TRUE if the user has legitimate access to the port. This is + used by cu to control whether the user can open a port directly, + rather than merely being able to dial out on it. Opening a port + directly allows the modem to be reprogrammed. */ +extern boolean fsysdep_port_access P((struct uuconf_port *qport)); + +/* Return whether the given port could be named by the given line. On + Unix, the line argument would be something like "ttyd0", and this + function should return TRUE if the named port is "/dev/ttyd0". */ +extern boolean fsysdep_port_is_line P((struct uuconf_port *qport, + const char *zline)); + +/* Set the terminal into raw mode. In this mode no input characters + should be treated specially, and characters should be made + available as they are typed. The original terminal mode should be + saved, so that it can be restored by fsysdep_terminal_restore. If + flocalecho is TRUE, then local echoing should still be done; + otherwise echoing should be disabled. This function returns FALSE + on error. */ +extern boolean fsysdep_terminal_raw P((boolean flocalecho)); + +/* Restore the terminal back to the original setting, before + fsysdep_terminal_raw was called. Returns FALSE on error. */ +extern boolean fsysdep_terminal_restore P((void)); + +/* Read a line from the terminal. The fsysdep_terminal_raw function + will have been called. This should print the zprompt argument + (unless it is NULL) and return the line, allocated by zbufcpy, or + NULL on error. */ +extern char *zsysdep_terminal_line P((const char *zprompt)); + +/* Write a line to the terminal, ending with a newline. This is + basically just puts (zline, stdout), except that the terminal will + be in raw mode, so on ASCII Unix systems the line needs to end with + \r\n. */ +extern boolean fsysdep_terminal_puts P((const char *zline)); + +/* If faccept is TRUE, permit the user to generate signals from the + terminal. If faccept is FALSE, turn signals off again. After + fsysdep_terminal_raw is called, signals should be off. Return + FALSE on error. */ +extern boolean fsysdep_terminal_signals P((boolean faccept)); + +/* The cu program expects the system dependent code to handle the + details of copying data from the communications port to the + terminal. This should be set up by fsysdep_cu_init, and done while + fsysdep_cu is called. It is permissible to do it on a continual + basis (on Unix a subprocess handles it) so long as the copying can + be stopped by the fsysdep_cu_copy function. + + The fsysdep_cu_init function does any system dependent + initialization needed for this. */ +extern boolean fsysdep_cu_init P((struct sconnection *qconn)); + +/* Copy all data from the communications port to the terminal, and all + data from the terminal to the communications port. Keep this up + until the escape character *zCuvar_escape is seen. Set *pbcmd to + the character following the escape character; after the escape + character, zlocalname should be printed, possibly after a delay. + If two escape characters are entered in sequence, this function + should send a single escape character to the port, and not return. + Returns FALSE on error. */ +extern boolean fsysdep_cu P((struct sconnection *qconn, + char *pbcmd, + const char *zlocalname)); + +/* If fcopy is TRUE, start copying data from the communications port + to the terminal. If fcopy is FALSE, stop copying data. This + function may be called several times during a cu session. It + should return FALSE on error. */ +extern boolean fsysdep_cu_copy P((boolean fcopy)); + +/* Stop copying data from the communications port to the terminal, and + generally clean up after fsysdep_cu_init and fsysdep_cu. Returns + FALSE on error. */ +extern boolean fsysdep_cu_finish P((void)); + +/* Run a shell command. If zcmd is NULL, or *zcmd == '\0', just + start up a shell. The second argument is one of the following + values. This should return FALSE on error. */ +enum tshell_cmd +{ + /* Attach stdin and stdout to the terminal. */ + SHELL_NORMAL, + /* Attach stdout to the communications port, stdin to the terminal. */ + SHELL_STDOUT_TO_PORT, + /* Attach stdin to the communications port, stdout to the terminal. */ + SHELL_STDIN_FROM_PORT, + /* Attach both stdin and stdout to the communications port. */ + SHELL_STDIO_ON_PORT +}; + +extern boolean fsysdep_shell P((struct sconnection *qconn, + const char *zcmd, + enum tshell_cmd tcmd)); + +/* Change directory. If zdir is NULL, or *zdir == '\0', change to the + user's home directory. Return FALSE on error. */ +extern boolean fsysdep_chdir P((const char *zdir)); + +/* Suspend the current process. This is only expected to work on Unix + versions that support SIGTSTP. In general, people can just shell + out. */ +extern boolean fsysdep_suspend P((void)); + +/* Start getting files for uupick. The zsystem argument may be NULL + to get files from all systems, or it may specify a particular + system. The zpubdir argument is the public directory to use. This + returns FALSE on error. */ +extern boolean fsysdep_uupick_init P((const char *zsystem, + const char *zpubdir)); + +/* Get the next file for uupick. This returns the basic file name. + It sets *pzfull to the full name, and *pzfrom to the name of the + system which sent this file over; both should be freed using + ubuffree. *pzfull should be passed to ubuffree after it is no + longer needed. The zsystem and zpubdir arguments should be the + same as the arguments to fsysdep_uupick_init. This returns NULL + when all files been returned. */ +extern char *zsysdep_uupick P((const char *zsystem, const char *zpubdir, + char **pzfrom, char **pzfull)); + +/* Clean up after getting files for uupick. */ +extern boolean fsysdep_uupick_free P((const char *zsystem, + const char *zpubdir)); + +/* Translate a local file name for uupick. On Unix this is just like + zsysdep_local_file_cwd except that a file beginning with ~/ is + placed in the user's home directory rather than in the public + directory. */ +extern char *zsysdep_uupick_local_file P((const char *zfile)); + +/* Remove a directory and all the files in it. */ +extern boolean fsysdep_rmdir P((const char *zdir)); + +#endif /* ! defined (SYSTEM_H) */ diff --git a/gnu/libexec/uucp/common_sources/tcp.c b/gnu/libexec/uucp/common_sources/tcp.c new file mode 100644 index 000000000000..543e9f0d8205 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/tcp.c @@ -0,0 +1,470 @@ +/* tcp.c + Code to handle TCP connections. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char tcp_rcsid[] = "$Id: tcp.c,v 1.1 1993/08/05 18:22:46 conklin Exp $"; +#endif + +#if HAVE_TCP + +#include "uudefs.h" +#include "uuconf.h" +#include "sysdep.h" +#include "conn.h" +#include "system.h" + +#include <errno.h> + +#if HAVE_SYS_TYPES_TCP_H +#include <sys/types.tcp.h> +#endif +#include <sys/socket.h> +#include <netdb.h> +#include <netinet/in.h> + +#if HAVE_FCNTL_H +#include <fcntl.h> +#else +#if HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#endif + +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +/* This code handles TCP connections. It assumes a Berkeley socket + interface. */ + +/* The normal "uucp" port number. */ +#define IUUCP_PORT (540) + +/* Local functions. */ +static void utcp_free P((struct sconnection *qconn)); +static boolean ftcp_open P((struct sconnection *qconn, long ibaud, + boolean fwait)); +static boolean ftcp_close P((struct sconnection *qconn, + pointer puuconf, + struct uuconf_dialer *qdialer, + boolean fsuccess)); +static boolean ftcp_reset P((struct sconnection *qconn)); +static boolean ftcp_dial P((struct sconnection *qconn, pointer puuconf, + const struct uuconf_system *qsys, + const char *zphone, + struct uuconf_dialer *qdialer, + enum tdialerfound *ptdialer)); +static int itcp_port_number P((const char *zport)); + +/* The command table for a TCP connection. */ +static const struct sconncmds stcpcmds = +{ + utcp_free, + NULL, /* pflock */ + NULL, /* pfunlock */ + ftcp_open, + ftcp_close, + ftcp_reset, + ftcp_dial, + fsysdep_conn_read, + fsysdep_conn_write, + fsysdep_conn_io, + NULL, /* pfbreak */ + NULL, /* pfset */ + NULL, /* pfcarrier */ + fsysdep_conn_chat, + NULL /* pibaud */ +}; + +/* Initialize a TCP connection. */ + +boolean +fsysdep_tcp_init (qconn) + struct sconnection *qconn; +{ + struct ssysdep_conn *q; + + q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn)); + q->o = -1; + q->zdevice = NULL; + q->iflags = -1; + q->istdout_flags = -1; + q->fterminal = FALSE; + q->ftli = FALSE; + q->ibaud = 0; + + qconn->psysdep = (pointer) q; + qconn->qcmds = &stcpcmds; + return TRUE; +} + +/* Free a TCP connection. */ + +static void +utcp_free (qconn) + struct sconnection *qconn; +{ + xfree (qconn->psysdep); +} + +/* Open a TCP connection. If the fwait argument is TRUE, we are + running as a server. Otherwise we are just trying to reach another + system. */ + +static boolean +ftcp_open (qconn, ibaud, fwait) + struct sconnection *qconn; + long ibaud; + boolean fwait; +{ + struct ssysdep_conn *qsysdep; + struct sockaddr_in s; + const char *zport; + uid_t iuid, ieuid; + + ulog_device ("TCP"); + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + + qsysdep->o = socket (AF_INET, SOCK_STREAM, 0); + if (qsysdep->o < 0) + { + ulog (LOG_ERROR, "socket: %s", strerror (errno)); + return FALSE; + } + + if (fcntl (qsysdep->o, F_SETFD, + fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0) + { + ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } + + qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0); + if (qsysdep->iflags < 0) + { + ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } + + /* If we aren't waiting for a connection, we're done. */ + if (! fwait) + return TRUE; + + /* Run as a server and wait for a new connection. The code in + uucico.c has already detached us from our controlling terminal. + From this point on if the server gets an error we exit; we only + return if we have received a connection. It would be more robust + to respawn the server if it fails; someday. */ + bzero ((pointer) &s, sizeof s); + s.sin_family = AF_INET; + zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport; + s.sin_port = itcp_port_number (zport); + s.sin_addr.s_addr = htonl (INADDR_ANY); + + /* Swap to our real user ID when doing the bind call. This will + permit the server to use privileged TCP ports when invoked by + root. We only swap if our effective user ID is not root, so that + the program can also be made suid root in order to get privileged + ports when invoked by anybody. */ + iuid = getuid (); + ieuid = geteuid (); + if (ieuid != 0) + { +#if HAVE_SETREUID + /* Swap the effective user id and the real user id. We can then + swap them back again when we want to return to the uucp + user's permissions. */ + if (setreuid (ieuid, iuid) < 0) + { + ulog (LOG_ERROR, "setreuid (%ld, %ld): %s", + (long) ieuid, (long) iuid, strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } +#else /* ! HAVE_SETREUID */ +#if HAVE_SAVED_SETUID + /* Set the effective user id to the real user id. Since the + effective user id is the saved setuid we will able to set + back to it later. If the real user id is root we will not be + able to switch back and forth, but that doesn't matter since + we only want to switch once. */ + if (setuid (iuid) < 0) + { + ulog (LOG_ERROR, "setuid (%ld): %s", (long) iuid, + strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } +#else /* ! HAVE_SAVED_SETUID */ + /* There's no way to switch between real permissions and + effective permissions. Just try the bind with the uucp + permissions. */ +#endif /* ! HAVE_SAVED_SETUID */ +#endif /* ! HAVE_SETREUID */ + } + + if (bind (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0) + ulog (LOG_FATAL, "bind: %s", strerror (errno)); + + /* Now swap back to the uucp user ID. */ + if (ieuid != 0) + { +#if HAVE_SETREUID + if (setreuid (iuid, ieuid) < 0) + { + ulog (LOG_ERROR, "setreuid (%ld, %ld): %s", + (long) iuid, (long) ieuid, strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } +#else /* ! HAVE_SETREUID */ +#if HAVE_SAVED_SETUID + /* Set ourselves back to our original effective user id. */ + if (setuid ((uid_t) ieuid) < 0) + { + ulog (LOG_ERROR, "setuid (%ld): %s", (long) ieuid, + strerror (errno)); + (void) close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } +#else /* ! HAVE_SAVED_SETUID */ + /* We didn't switch, no need to switch back. */ +#endif /* ! HAVE_SAVED_SETUID */ +#endif /* ! HAVE_SETREUID */ + } + + if (listen (qsysdep->o, 5) < 0) + ulog (LOG_FATAL, "listen: %s", strerror (errno)); + + while (! FGOT_SIGNAL ()) + { + size_t clen; + int onew; + pid_t ipid; + + DEBUG_MESSAGE0 (DEBUG_PORT, + "ftcp_open: Waiting for connections"); + + clen = sizeof s; + onew = accept (qsysdep->o, (struct sockaddr *) &s, &clen); + if (onew < 0) + ulog (LOG_FATAL, "accept: %s", strerror (errno)); + + DEBUG_MESSAGE0 (DEBUG_PORT, + "ftcp_open: Got connection; forking"); + + ipid = ixsfork (); + if (ipid < 0) + ulog (LOG_FATAL, "fork: %s", strerror (errno)); + if (ipid == 0) + { + (void) close (qsysdep->o); + qsysdep->o = onew; + + /* Now we fork and let our parent die, so that we become + a child of init. This lets the main server code wait + for its child and then continue without accumulating + zombie children. */ + ipid = ixsfork (); + if (ipid < 0) + { + ulog (LOG_ERROR, "fork: %s", strerror (errno)); + _exit (EXIT_FAILURE); + } + + if (ipid != 0) + _exit (EXIT_SUCCESS); + + ulog_id (getpid ()); + + return TRUE; + } + + (void) close (onew); + + /* Now wait for the child. */ + (void) ixswait ((unsigned long) ipid, (const char *) NULL); + } + + /* We got a signal. */ + usysdep_exit (FALSE); + + /* Avoid compiler warnings. */ + return FALSE; +} + +/* Close the port. */ + +/*ARGSUSED*/ +static boolean +ftcp_close (qconn, puuconf, qdialer, fsuccess) + struct sconnection *qconn; + pointer puuconf; + struct uuconf_dialer *qdialer; + boolean fsuccess; +{ + struct ssysdep_conn *qsysdep; + boolean fret; + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + fret = TRUE; + if (qsysdep->o >= 0 && close (qsysdep->o) < 0) + { + ulog (LOG_ERROR, "close: %s", strerror (errno)); + fret = FALSE; + } + qsysdep->o = -1; + return fret; +} + +/* Reset the port. This will be called by a child which was forked + off in ftcp_open, above. We don't want uucico to continue looping + and giving login prompts, so we pretend that we received a SIGINT + signal. This should probably be handled more cleanly. The signal + will not be recorded in the log file because we don't set + afLog_signal[INDEXSIG_SIGINT]. */ + +/*ARGSUSED*/ +static boolean +ftcp_reset (qconn) + struct sconnection *qconn; +{ + afSignal[INDEXSIG_SIGINT] = TRUE; + return TRUE; +} + +/* Dial out on a TCP port, so to speak: connect to a remote computer. */ + +/*ARGSUSED*/ +static boolean +ftcp_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialer) + struct sconnection *qconn; + pointer puuconf; + const struct uuconf_system *qsys; + const char *zphone; + struct uuconf_dialer *qdialer; + enum tdialerfound *ptdialer; +{ + struct ssysdep_conn *qsysdep; + const char *zhost; + struct hostent *q; + struct sockaddr_in s; + const char *zport; + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + + *ptdialer = DIALERFOUND_FALSE; + + zhost = zphone; + if (zhost == NULL) + { + if (qsys == NULL) + { + ulog (LOG_ERROR, "No address for TCP connection"); + return FALSE; + } + zhost = qsys->uuconf_zname; + } + + errno = 0; + q = gethostbyname ((char *) zhost); + if (q == NULL) + { + if (errno == 0) + ulog (LOG_ERROR, "%s: unknown host name", zhost); + else + ulog (LOG_ERROR, "gethostbyname (%s): %s", zhost, strerror (errno)); + return FALSE; + } + + s.sin_family = q->h_addrtype; + zport = qconn->qport->uuconf_u.uuconf_stcp.uuconf_zport; + s.sin_port = itcp_port_number (zport); + memcpy (&s.sin_addr.s_addr, q->h_addr, (size_t) q->h_length); + + if (connect (qsysdep->o, (struct sockaddr *) &s, sizeof s) < 0) + { + ulog (LOG_ERROR, "connect: %s", strerror (errno)); + return FALSE; + } + + return TRUE; +} + +/* Get the port number given a name. The argument will almost always + be "uucp" so we cache that value. The return value is always in + network byte order. This returns -1 on error. */ + +static int +itcp_port_number (zname) + const char *zname; +{ + boolean fuucp; + static int iuucp; + int i; + char *zend; + struct servent *q; + + fuucp = strcmp (zname, "uucp") == 0; + if (fuucp && iuucp != 0) + return iuucp; + + /* Try it as a number first. */ + i = strtol ((char *) zname, &zend, 10); + if (i != 0 && *zend == '\0') + return htons (i); + + q = getservbyname ((char *) zname, (char *) "tcp"); + if (q == NULL) + { + /* We know that the "uucp" service should be 540, even if isn't + in /etc/services. */ + if (fuucp) + { + iuucp = htons (IUUCP_PORT); + return iuucp; + } + ulog (LOG_ERROR, "getservbyname (%s): %s", zname, strerror (errno)); + return -1; + } + + if (fuucp) + iuucp = q->s_port; + + return q->s_port; +} + +#endif /* HAVE_TCP */ diff --git a/gnu/libexec/uucp/common_sources/tli.c b/gnu/libexec/uucp/common_sources/tli.c new file mode 100644 index 000000000000..9fffdcdfebd1 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/tli.c @@ -0,0 +1,644 @@ +/* tli.c + Code to handle TLI connections. + + Copyright (C) 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char tli_rcsid[] = "$Id: tli.c,v 1.1 1993/08/05 18:22:46 conklin Exp $"; +#endif + +#if HAVE_TLI + +#include "sysdep.h" +#include "uudefs.h" +#include "uuconf.h" +#include "conn.h" +#include "system.h" + +#include <errno.h> + +#if HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#if HAVE_TIUSER_H +#include <tiuser.h> +#else +#if HAVE_XTI_H +#include <xti.h> +#else +#if HAVE_SYS_TLI_H +#include <sys/tli.h> +#endif +#endif +#endif + +#if HAVE_STROPTS_H +#include <stropts.h> +#endif + +#if HAVE_FCNTL_H +#include <fcntl.h> +#else +#if HAVE_SYS_FILE_H +#include <sys/file.h> +#endif +#endif + +#ifndef O_RDONLY +#define O_RDONLY 0 +#define O_WRONLY 1 +#define O_RDWR 2 +#endif + +#ifndef FD_CLOEXEC +#define FD_CLOEXEC 1 +#endif + +/* The arguments to t_alloca have two different names. I want the + SVID ones, not the XPG3 ones. */ +#ifndef T_BIND +#define T_BIND T_BIND_STR +#endif +#ifndef T_CALL +#define T_CALL T_CALL_STR +#endif + +/* Hopefully these externs will not cause any trouble. This is how + they are shown in the SVID. */ +extern int t_errno; +extern char *t_errlist[]; +extern int t_nerr; + +#ifndef t_alloc +extern pointer t_alloc (); +#endif + +/* This code handles TLI connections. It's Unix specific. It's + largely based on code from Unix Network Programming, by W. Richard + Stevens. */ + +/* Local functions. */ +static const char *ztlierror P((void)); +static void utli_free P((struct sconnection *qconn)); +static boolean ftli_push P((struct sconnection *qconn)); +static boolean ftli_open P((struct sconnection *qconn, long ibaud, + boolean fwait)); +static boolean ftli_close P((struct sconnection *qconn, + pointer puuconf, + struct uuconf_dialer *qdialer, + boolean fsuccess)); +static boolean ftli_reset P((struct sconnection *qconn)); +static boolean ftli_dial P((struct sconnection *qconn, pointer puuconf, + const struct uuconf_system *qsys, + const char *zphone, + struct uuconf_dialer *qdialer, + enum tdialerfound *ptdialer)); + +/* The command table for a TLI connection. */ +static const struct sconncmds stlicmds = +{ + utli_free, + NULL, /* pflock */ + NULL, /* pfunlock */ + ftli_open, + ftli_close, + ftli_reset, + ftli_dial, + fsysdep_conn_read, + fsysdep_conn_write, + fsysdep_conn_io, + NULL, /* pfbreak */ + NULL, /* pfset */ + NULL, /* pfcarrier */ + fsysdep_conn_chat, + NULL /* pibaud */ +}; + +/* Get a TLI error string. */ + +static const char * +ztlierror () +{ + if (t_errno == TSYSERR) + return strerror (errno); + if (t_errno < 0 || t_errno >= t_nerr) + return "Unknown TLI error"; + return t_errlist[t_errno]; +} + +/* Initialize a TLI connection. */ + +boolean +fsysdep_tli_init (qconn) + struct sconnection *qconn; +{ + struct ssysdep_conn *q; + + q = (struct ssysdep_conn *) xmalloc (sizeof (struct ssysdep_conn)); + q->o = -1; + q->zdevice = NULL; + q->iflags = -1; + q->istdout_flags = -1; + q->fterminal = FALSE; + q->ftli = TRUE; + q->ibaud = 0; + + qconn->psysdep = (pointer) q; + qconn->qcmds = &stlicmds; + return TRUE; +} + +/* Free a TLI connection. */ + +static void +utli_free (qconn) + struct sconnection *qconn; +{ + xfree (qconn->psysdep); +} + +/* Push all desired modules onto a TLI stream. If the user requests a + STREAMS connection without giving a list of modules, we just push + tirdwr. If the I_PUSH ioctl is not defined on this system, we just + ignore any list of modules. */ + +static boolean +ftli_push (qconn) + struct sconnection *qconn; +{ +#ifdef I_PUSH + + struct ssysdep_conn *qsysdep; + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + + if (qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush != NULL) + { + char **pz; + + for (pz = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzpush; + *pz != NULL; + pz++) + { + if (ioctl (qsysdep->o, I_PUSH, *pz) < 0) + { + ulog (LOG_ERROR, "ioctl (I_PUSH, %s): %s", *pz, + strerror (errno)); + return FALSE; + } + } + } + else if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream) + { + if (ioctl (qsysdep->o, I_PUSH, "tirdwr") < 0) + { + ulog (LOG_ERROR, "ioctl (I_PUSH, tirdwr): %s", + strerror (errno)); + return FALSE; + } + } + + /* If we have just put the connection into stream mode, we must turn + off the TLI flag to avoid using TLI calls on it. */ + if (qconn->qport->uuconf_u.uuconf_stli.uuconf_fstream) + qsysdep->ftli = FALSE; + +#endif /* defined (I_PUSH) */ + + return TRUE; +} + +/* Open a TLI connection. If the fwait argument is TRUE, we are + running as a server. Otherwise we are just trying to reach another + system. */ + +static boolean +ftli_open (qconn, ibaud, fwait) + struct sconnection *qconn; + long ibaud; + boolean fwait; +{ + struct ssysdep_conn *qsysdep; + const char *zdevice; + char *zfreedev; + const char *zservaddr; + char *zfreeaddr; + struct t_bind *qtbind; + struct t_call *qtcall; + + /* Unlike most other device types, we don't bother to call + ulog_device here, because fconn_open calls it with the name of + the port anyhow. */ + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + + zdevice = qconn->qport->uuconf_u.uuconf_stli.uuconf_zdevice; + if (zdevice == NULL) + zdevice = qconn->qport->uuconf_zname; + + zfreedev = NULL; + if (*zdevice != '/') + { + zfreedev = zbufalc (sizeof "/dev/" + strlen (zdevice)); + sprintf (zfreedev, "/dev/%s", zdevice); + zdevice = zfreedev; + } + + qsysdep->o = t_open (zdevice, O_RDWR, (struct t_info *) NULL); + if (qsysdep->o < 0) + { + ulog (LOG_ERROR, "t_open (%s): %s", zdevice, ztlierror ()); + ubuffree (zfreedev); + return FALSE; + } + + if (fcntl (qsysdep->o, F_SETFD, + fcntl (qsysdep->o, F_GETFD, 0) | FD_CLOEXEC) < 0) + { + ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); + ubuffree (zfreedev); + (void) t_close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } + + qsysdep->iflags = fcntl (qsysdep->o, F_GETFL, 0); + if (qsysdep->iflags < 0) + { + ulog (LOG_ERROR, "fcntl: %s", strerror (errno)); + ubuffree (zfreedev); + (void) t_close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } + + /* If we aren't waiting for a connection, we can bind to any local + address, and then we're finished. */ + if (! fwait) + { + ubuffree (zfreedev); + if (t_bind (qsysdep->o, (struct t_bind *) NULL, + (struct t_bind *) NULL) < 0) + { + ulog (LOG_ERROR, "t_bind: %s", ztlierror ()); + (void) t_close (qsysdep->o); + qsysdep->o = -1; + return FALSE; + } + return TRUE; + } + + /* Run as a server and wait for a new connection. The code in + uucico.c has already detached us from our controlling terminal. + From this point on if the server gets an error we exit; we only + return if we have received a connection. It would be more robust + to respawn the server if it fails; someday. */ + qtbind = (struct t_bind *) t_alloc (qsysdep->o, T_BIND, T_ALL); + if (qtbind == NULL) + ulog (LOG_FATAL, "t_alloc (T_BIND): %s", ztlierror ()); + + zservaddr = qconn->qport->uuconf_u.uuconf_stli.uuconf_zservaddr; + if (zservaddr == NULL) + ulog (LOG_FATAL, "Can't run as TLI server; no server address"); + + zfreeaddr = zbufcpy (zservaddr); + qtbind->addr.len = cescape (zfreeaddr); + if (qtbind->addr.len > qtbind->addr.maxlen) + ulog (LOG_FATAL, "%s: TLI server address too long (max %d)", + zservaddr, qtbind->addr.maxlen); + memcpy (qtbind->addr.buf, zfreeaddr, qtbind->addr.len); + ubuffree (zfreeaddr); + + qtbind->qlen = 5; + + if (t_bind (qsysdep->o, qtbind, (struct t_bind *) NULL) < 0) + ulog (LOG_FATAL, "t_bind (%s): %s", zservaddr, ztlierror ()); + + (void) t_free ((pointer) qtbind, T_BIND); + + qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ALL); + if (qtcall == NULL) + ulog (LOG_FATAL, "t_alloc (T_CALL): %s", ztlierror ()); + + while (! FGOT_SIGNAL ()) + { + int onew; + pid_t ipid; + + DEBUG_MESSAGE0 (DEBUG_PORT, + "ftli_open: Waiting for connections"); + + if (t_listen (qsysdep->o, qtcall) < 0) + ulog (LOG_FATAL, "t_listen: %s", ztlierror ()); + + onew = t_open (zdevice, O_RDWR, (struct t_info *) NULL); + if (onew < 0) + ulog (LOG_FATAL, "t_open (%s): %s", zdevice, ztlierror ()); + + if (fcntl (onew, F_SETFD, + fcntl (onew, F_GETFD, 0) | FD_CLOEXEC) < 0) + ulog (LOG_FATAL, "fcntl (FD_CLOEXEC): %s", strerror (errno)); + + if (t_bind (onew, (struct t_bind *) NULL, (struct t_bind *) NULL) < 0) + ulog (LOG_FATAL, "t_bind: %s", ztlierror ()); + + if (t_accept (qsysdep->o, onew, qtcall) < 0) + { + /* We may have received a disconnect. */ + if (t_errno != TLOOK) + ulog (LOG_FATAL, "t_accept: %s", ztlierror ()); + if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0) + ulog (LOG_FATAL, "t_rcvdis: %s", ztlierror ()); + (void) t_close (onew); + continue; + } + + DEBUG_MESSAGE0 (DEBUG_PORT, + "ftli_open: Got connection; forking"); + + ipid = ixsfork (); + if (ipid < 0) + ulog (LOG_FATAL, "fork: %s", strerror (errno)); + if (ipid == 0) + { + ulog_close (); + + (void) t_close (qsysdep->o); + qsysdep->o = onew; + + /* Push any desired modules. */ + if (! ftli_push (qconn)) + _exit (EXIT_FAILURE); + + /* Now we fork and let our parent die, so that we become + a child of init. This lets the main server code wait + for its child and then continue without accumulating + zombie children. */ + ipid = ixsfork (); + if (ipid < 0) + { + ulog (LOG_ERROR, "fork: %s", strerror (errno)); + _exit (EXIT_FAILURE); + } + + if (ipid != 0) + _exit (EXIT_SUCCESS); + + ulog_id (getpid ()); + + return TRUE; + } + + (void) t_close (onew); + + /* Now wait for the child. */ + (void) ixswait ((unsigned long) ipid, (const char *) NULL); + } + + /* We got a signal. */ + usysdep_exit (FALSE); + + /* Avoid compiler warnings. */ + return FALSE; +} + +/* Close the port. */ + +/*ARGSUSED*/ +static boolean +ftli_close (qconn, puuconf, qdialer, fsuccess) + struct sconnection *qconn; + pointer puuconf; + struct uuconf_dialer *qdialer; + boolean fsuccess; +{ + struct ssysdep_conn *qsysdep; + boolean fret; + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + + fret = TRUE; + if (qsysdep->o >= 0) + { + if (qsysdep->ftli) + { + if (t_close (qsysdep->o) < 0) + { + ulog (LOG_ERROR, "t_close: %s", ztlierror ()); + fret = FALSE; + } + } + else + { + if (close (qsysdep->o) < 0) + { + ulog (LOG_ERROR, "close: %s", strerror (errno)); + fret = FALSE; + } + } + + qsysdep->o = -1; + } + + return fret; +} + +/* Reset the port. This will be called by a child which was forked + off in ftli_open, above. We don't want uucico to continue looping + and giving login prompts, so we pretend that we received a SIGINT + signal. This should probably be handled more cleanly. The signal + will not be recorded in the log file because we don't set + afLog_signal[INDEXSIG_SIGINT]. */ + +/*ARGSUSED*/ +static boolean +ftli_reset (qconn) + struct sconnection *qconn; +{ + afSignal[INDEXSIG_SIGINT] = TRUE; + return TRUE; +} + +/* Dial out on a TLI port, so to speak: connect to a remote computer. */ + +/*ARGSUSED*/ +static boolean +ftli_dial (qconn, puuconf, qsys, zphone, qdialer, ptdialerfound) + struct sconnection *qconn; + pointer puuconf; + const struct uuconf_system *qsys; + const char *zphone; + struct uuconf_dialer *qdialer; + enum tdialerfound *ptdialerfound; +{ + struct ssysdep_conn *qsysdep; + char **pzdialer; + const char *zaddr; + struct t_call *qtcall; + char *zescape; + + qsysdep = (struct ssysdep_conn *) qconn->psysdep; + + *ptdialerfound = DIALERFOUND_FALSE; + + pzdialer = qconn->qport->uuconf_u.uuconf_stli.uuconf_pzdialer; + if (*pzdialer == NULL) + pzdialer = NULL; + + /* If the first dialer is "TLI" or "TLIS", we use the first token + (pzdialer[1]) as the address to connect to. */ + zaddr = zphone; + if (pzdialer != NULL + && (strcmp (pzdialer[0], "TLI") == 0 + || strcmp (pzdialer[0], "TLIS") == 0)) + { + if (pzdialer[1] == NULL) + ++pzdialer; + else + { + if (strcmp (pzdialer[1], "\\D") != 0 + && strcmp (pzdialer[1], "\\T") != 0) + zaddr = pzdialer[1]; + pzdialer += 2; + } + } + + if (zaddr == NULL) + { + ulog (LOG_ERROR, "No address for TLI connection"); + return FALSE; + } + + qtcall = (struct t_call *) t_alloc (qsysdep->o, T_CALL, T_ADDR); + if (qtcall == NULL) + { + ulog (LOG_ERROR, "t_alloc (T_CALL): %s", ztlierror ()); + return FALSE; + } + + zescape = zbufcpy (zaddr); + qtcall->addr.len = cescape (zescape); + if (qtcall->addr.len > qtcall->addr.maxlen) + { + ulog (LOG_ERROR, "%s: TLI address too long (max %d)", zaddr, + qtcall->addr.maxlen); + ubuffree (zescape); + return FALSE; + } + memcpy (qtcall->addr.buf, zescape, qtcall->addr.len); + ubuffree (zescape); + + if (t_connect (qsysdep->o, qtcall, (struct t_call *) NULL) < 0) + { + if (t_errno != TLOOK) + ulog (LOG_ERROR, "t_connect: %s", ztlierror ()); + else + { + if (t_rcvdis (qsysdep->o, (struct t_discon *) NULL) < 0) + ulog (LOG_ERROR, "t_rcvdis: %s", ztlierror ()); + else + ulog (LOG_ERROR, "Connection refused"); + } + return FALSE; + } + + /* We've connected to the remote. Push any desired modules. */ + if (! ftli_push (qconn)) + return FALSE; + + /* Handle the rest of the dialer sequence. This is similar to + fmodem_dial, and they should, perhaps, be combined somehow. */ + if (pzdialer != NULL) + { + boolean ffirst; + + ffirst = TRUE; + while (*pzdialer != NULL) + { + int iuuconf; + struct uuconf_dialer *q; + struct uuconf_dialer s; + const char *ztoken; + boolean ftranslate; + + if (! ffirst) + q = &s; + else + q = qdialer; + + iuuconf = uuconf_dialer_info (puuconf, *pzdialer, q); + if (iuuconf == UUCONF_NOT_FOUND) + { + ulog (LOG_ERROR, "%s: Dialer not found", *pzdialer); + return FALSE; + } + else if (iuuconf != UUCONF_SUCCESS) + { + ulog_uuconf (LOG_ERROR, puuconf, iuuconf); + return FALSE; + } + + ++pzdialer; + ztoken = *pzdialer; + + ftranslate = FALSE; + if (ztoken == NULL + || strcmp (ztoken, "\\D") == 0) + ztoken = zphone; + else if (strcmp (ztoken, "\\T") == 0) + { + ztoken = zphone; + ftranslate = TRUE; + } + + if (! fchat (qconn, puuconf, &q->uuconf_schat, + (const struct uuconf_system *) NULL, q, + zphone, ftranslate, qconn->qport->uuconf_zname, + (long) 0)) + { + (void) uuconf_dialer_free (puuconf, q); + if (! ffirst) + (void) uuconf_dialer_free (puuconf, qdialer); + return FALSE; + } + + if (ffirst) + { + *ptdialerfound = DIALERFOUND_FREE; + ffirst = FALSE; + } + else + (void) uuconf_dialer_free (puuconf, q); + + if (*pzdialer != NULL) + ++pzdialer; + } + } + + return TRUE; +} + +#endif /* HAVE_TLI */ diff --git a/gnu/libexec/uucp/common_sources/trans.h b/gnu/libexec/uucp/common_sources/trans.h new file mode 100644 index 000000000000..79c380ea48d8 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/trans.h @@ -0,0 +1,268 @@ +/* trans.h + Header file for file and command transfer routines. + + Copyright (C) 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +/* The maximum possible number of channels. */ +#define IMAX_CHAN (16) + +/* The ifeatures field of the sdaemon structure is an or of the + following values. These values are sent during the uucico + handshake, and MUST NOT CHANGE. */ + +/* File size negotiation. */ +#define FEATURE_SIZES (01) + +/* File transfer restart. */ +#define FEATURE_RESTART (02) + +/* The E (execute) command. */ +#define FEATURE_EXEC (04) + +/* Version 1.03: requires decimal size in S and R command. Needless + to say, this should not be used by any new programs. */ +#define FEATURE_V103 (010) + +/* SVR4 UUCP: expects dummy string between notify field and size field + in send command. There is probably some meaning to this string, + but I don't know what it is. If I ever find out, this flag will + still be used to indicate it. */ +#define FEATURE_SVR4 (020) + +/* This structure is used to hold information concerning the + communication link established with the remote system. */ + +struct sdaemon +{ + /* Global uuconf pointer. */ + pointer puuconf; + /* Remote system information. */ + const struct uuconf_system *qsys; + /* Local name being used. */ + const char *zlocalname; + /* Connection structure. */ + struct sconnection *qconn; + /* Protocol being used. */ + const struct sprotocol *qproto; + /* The largest file size permitted for a local request. */ + long clocal_size; + /* The largest file size permitted for a remote request. */ + long cremote_size; + /* The largest file size that may ever be transferred. */ + long cmax_ever; + /* The remote system ulimit. */ + long cmax_receive; + /* Features supported by the remote side. */ + int ifeatures; + /* TRUE if we should request the remote side to hang up. */ + boolean frequest_hangup; + /* TRUE if the remote side requested a hangup. */ + boolean fhangup_requested; + /* TRUE if we are hanging up. */ + boolean fhangup; + /* TRUE if the local system is currently the master. */ + boolean fmaster; + /* TRUE if the local system placed the call. */ + boolean fcaller; + /* UUCONF_RELIABLE_* flags for the connection. */ + int ireliable; + /* If fcaller is FALSE, the lowest grade which may be transferred + during this call. */ + char bgrade; +}; + +/* This structure is used to hold a file or command transfer which is + in progress. */ + +struct stransfer +{ + /* Next file transfer in queue. */ + struct stransfer *qnext; + /* Previous file transfer in queue. */ + struct stransfer *qprev; + /* Points to the queue this structure is on. */ + struct stransfer **pqqueue; + /* The function to call to send some data. */ + boolean (*psendfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon)); + /* The function to call when data is received. */ + boolean (*precfn) P((struct stransfer *qtrans, struct sdaemon *qdaemon, + const char *zdata, size_t cdata)); + /* Type specific information. */ + pointer pinfo; + /* TRUE if we are sending the file e (this is used to avoid a call + to psendfn). */ + boolean fsendfile; + /* TRUE if we are receiving the file e (this is used to avoid a call + to precfn). */ + boolean frecfile; + /* The file to read or write. */ + openfile_t e; + /* The position we are at in the file. */ + long ipos; + /* TRUE if we are waiting for a command string. */ + boolean fcmd; + /* The command string we have so far. */ + char *zcmd; + /* The length of the command string we have so far. */ + size_t ccmd; + /* Local destination number. */ + int ilocal; + /* Remote destination number. */ + int iremote; + /* The command. */ + struct scmd s; + /* A message to log when work starts. */ + char *zlog; + /* The process time; imicros can be negative. */ + long isecs; + long imicros; + /* Number of bytes sent or received. */ + long cbytes; +}; + +/* Reasons that a file transfer might fail. */ + +enum tfailure +{ + /* No failure. */ + FAILURE_NONE, + /* No permission for operation. */ + FAILURE_PERM, + /* Can't open necessary file. */ + FAILURE_OPEN, + /* Not enough space to receive file. */ + FAILURE_SIZE, + /* File was received in a previous conversation. */ + FAILURE_RECEIVED +}; + +/* The main loop which talks to the remote system, passing transfer + requests and file back and forth. */ +extern boolean floop P((struct sdaemon *qdaemon)); + +/* Allocate a new transfer structure. */ +extern struct stransfer *qtransalc P((struct scmd *qcmd)); + +/* Free a transfer structure. */ +extern void utransfree P((struct stransfer *qtrans)); + +/* Queue up local requests. If pfany is not NULL, this sets *pfany to + TRUE if there are, in fact, any local requests which can be done at + this point. */ +extern boolean fqueue P((struct sdaemon *qdaemon, boolean *pfany)); + +/* Clear away any queued requests. This may be called more than once + at the end of a call. */ +extern void uclear_queue P((struct sdaemon *qdaemon)); + +/* Queue a new transfer request made by the local system. */ +extern boolean fqueue_local P((struct sdaemon *qdaemon, + struct stransfer *qtrans)); + +/* Queue a new transfer request made by the remote system. */ +extern boolean fqueue_remote P((struct sdaemon *qdaemon, + struct stransfer *qtrans)); + +/* Queue a transfer request which wants to send something. */ +extern boolean fqueue_send P((struct sdaemon *qdaemon, + struct stransfer *qtrans)); + +/* Queue a transfer request which wants to receiving something. */ +extern boolean fqueue_receive P((struct sdaemon *qdaemon, + struct stransfer *qtrans)); + +/* Prepare to send a file by local or remote request. */ +extern boolean flocal_send_file_init P((struct sdaemon *qdaemon, + struct scmd *qcmd)); +extern boolean fremote_send_file_init P((struct sdaemon *qdaemon, + struct scmd *qcmd, + int iremote)); + +/* Prepare to receive a file by local or remote request. */ +extern boolean flocal_rec_file_init P((struct sdaemon *qdaemon, + struct scmd *qcmd)); +extern boolean fremote_rec_file_init P((struct sdaemon *qdaemon, + struct scmd *qcmd, + int iremote)); + +/* Prepare to request work by local or remote request. */ +extern boolean flocal_xcmd_init P((struct sdaemon *qdaemon, + struct scmd *qcmd)); +extern boolean fremote_xcmd_init P((struct sdaemon *qdaemon, + struct scmd *qcmd, + int iremote)); + +/* We have lost the connection; record any in progress file transfers + in the statistics file and discard any temporary files. */ +extern void ufailed P((struct sdaemon *qdaemon)); + +/* Check that there is enough disk space for a file receive. Return + FALSE if there is not. */ +extern boolean frec_check_free P((struct stransfer *qtrans, + long cfree_space)); + +/* Discard the temporary file being used to receive a file, if + appropriate. */ +extern boolean frec_discard_temp P((struct sdaemon *qdaemon, + struct stransfer *qtrans)); + +/* Handle data received by a protocol. This is called by the protocol + specific routines as data comes in. The data is passed as two + buffers because that is convenient for packet based protocols, but + normally csecond will be 0. The ilocal argument is the local + channel number, and the iremote argument is the remote channel + number. Either may be -1, if the protocol does not have channels. + The ipos argument is the position in the file, if the protocol + knows it; for most protocols, this will be -1. The fallacked + argument should be set to TRUE if the remote has acknowledged all + outstanding data; see uwindow_acked, below, for details. This will + set *pfexit to TRUE if there is something for the main loop to do. + A file is complete is when a zero length buffer is passed (cfirst + == 0). A command is complete when data containing a null byte is + passed. This will return FALSE on error. If the protocol pfwait + entry point should exit and let the top level loop continue, + *pfexit will be set to TRUE (if pfexit is not NULL). This will not + set *pfexit to FALSE, so the caller must do that. */ +extern boolean fgot_data P((struct sdaemon *qdaemon, + const char *zfirst, size_t cfirst, + const char *zsecond, size_t csecond, + int ilocal, int iremote, + long ipos, boolean fallacked, + boolean *pfexit)); + +/* This routine is called when an ack is sent for a file receive. */ +extern void usent_receive_ack P((struct sdaemon *qdaemon, + struct stransfer *qtrans)); + +/* A protocol may call this routine to indicate the packets have been + acknowledged by the remote system. If the fallacked argument is + TRUE, then all outstanding packets have been acknowledged; for + convenience, this may also be indicated by passing fallacked as + TRUE to fgot_data, above. Otherwise this routine should be called + each time a complete window is acked by the remote system. The + transfer code uses this information to keep track of when an + acknowledgement of a file receive has been seen by the other side, + so that file receives may be handled cleanly if the connection is + lost. */ +extern void uwindow_acked P((struct sdaemon *qdaemon, + boolean fallacked)); diff --git a/gnu/libexec/uucp/common_sources/util.c b/gnu/libexec/uucp/common_sources/util.c new file mode 100644 index 000000000000..89b3caf1d446 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/util.c @@ -0,0 +1,144 @@ +/* util.c + A couple of UUCP utility functions. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#include "uucp.h" + +#if USE_RCS_ID +const char util_rcsid[] = "$Id: util.c,v 1.1 1993/08/05 18:22:48 conklin Exp $"; +#endif + +#include <ctype.h> + +#include "uudefs.h" +#include "uuconf.h" +#include "system.h" + +/* Get information for an unknown system. This will leave the name + allocated on the heap. We could fix this by breaking the + abstraction and adding the name to qsys->palloc. It makes sure the + name is not too long, but takes no other useful action. */ + +boolean +funknown_system (puuconf, zsystem, qsys) + pointer puuconf; + const char *zsystem; + struct uuconf_system *qsys; +{ + char *z; + int iuuconf; + + if (strlen (zsystem) <= cSysdep_max_name_len) + z = zbufcpy (zsystem); + else + { + char **pznames, **pz; + boolean ffound; + + z = zbufalc (cSysdep_max_name_len + 1); + memcpy (z, zsystem, cSysdep_max_name_len); + z[cSysdep_max_name_len] = '\0'; + + iuuconf = uuconf_system_names (puuconf, &pznames, TRUE); + if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + + ffound = FALSE; + for (pz = pznames; *pz != NULL; pz++) + { + if (strcmp (*pz, z) == 0) + ffound = TRUE; + xfree ((pointer) *pz); + } + xfree ((pointer) pznames); + + if (ffound) + { + ubuffree (z); + return FALSE; + } + } + + iuuconf = uuconf_system_unknown (puuconf, qsys); + if (iuuconf == UUCONF_NOT_FOUND) + { + ubuffree (z); + return FALSE; + } + else if (iuuconf != UUCONF_SUCCESS) + ulog_uuconf (LOG_FATAL, puuconf, iuuconf); + + for (; qsys != NULL; qsys = qsys->uuconf_qalternate) + qsys->uuconf_zname = z; + + return TRUE; +} + +/* See whether a file is in a directory list, and make sure the user + has appropriate access. */ + +boolean +fin_directory_list (zfile, pzdirs, zpubdir, fcheck, freadable, zuser) + const char *zfile; + char **pzdirs; + const char *zpubdir; + boolean fcheck; + boolean freadable; + const char *zuser; +{ + boolean fmatch; + char **pz; + + fmatch = FALSE; + + for (pz = pzdirs; *pz != NULL; pz++) + { + char *zuse; + + if (pz[0][0] == '!') + { + zuse = zsysdep_local_file (*pz + 1, zpubdir); + if (zuse == NULL) + return FALSE; + + if (fsysdep_in_directory (zfile, zuse, FALSE, + FALSE, (const char *) NULL)) + fmatch = FALSE; + } + else + { + zuse = zsysdep_local_file (*pz, zpubdir); + if (zuse == NULL) + return FALSE; + + if (fsysdep_in_directory (zfile, zuse, fcheck, + freadable, zuser)) + fmatch = TRUE; + } + + ubuffree (zuse); + } + + return fmatch; +} diff --git a/gnu/libexec/uucp/common_sources/uuconf.h b/gnu/libexec/uucp/common_sources/uuconf.h new file mode 100644 index 000000000000..4bf6bccbf3f2 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/uuconf.h @@ -0,0 +1,1496 @@ +/* uuconf.h + Header file for UUCP configuration routines. + + Copyright (C) 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP uuconf library. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License + as published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The use of an object file which uses material from this header + file, and from no other portion of the uuconf library, is + unrestricted, as described in paragraph 4 of section 5 of version 2 + of the GNU Library General Public License (this sentence is merely + informative, and does not modify the License in any way). + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#ifndef UUCONF_H + +#define UUCONF_H + +#include <stdio.h> + +/* The macro UUCONF_ANSI_C may be used to override __STDC__. */ +#ifndef UUCONF_ANSI_C +#ifdef __STDC__ +#define UUCONF_ANSI_C 1 +#else /* ! defined (__STDC__) */ +#define UUCONF_ANSI_C 0 +#endif /* ! defined (__STDC__) */ +#endif /* ! defined (UUCONF_ANSI_C) */ + +#if UUCONF_ANSI_C +#define UUCONF_CONST const +typedef void *UUCONF_POINTER; +#include <stddef.h> +typedef size_t UUCONF_SIZE_T; +#else +#define UUCONF_CONST +typedef char *UUCONF_POINTER; +typedef unsigned int UUCONF_SIZE_T; +#endif + +/* The field names of each of the following structures begin with + "uuconf_". This is to avoid any conflicts with user defined + macros. The first character following the "uuconf_" string + indicates the type of the field. + + z -- a string (char *) + c -- a count (normally int) + i -- an integer value (normally int) + f -- a boolean value (normally int) + b -- a single character value (char or int) + t -- an enum (enum XX) + s -- a structure (struct XX) + u -- a union (union XX) + q -- a pointer to a structure (struct XX *) + p -- a pointer to something other than a string + */ + +/* The information which is kept for a chat script. */ + +struct uuconf_chat +{ + /* The script itself. This is a NULL terminated list of expect/send + pairs. The first string is an expect string. A string starting + with a '-' indicates subsend string; the following strings which + start with '-' are subexpect/subsend strings. This field may be + NULL, in which case there is no chat script (but pzprogram may + hold a program to run). */ + char **uuconf_pzchat; + /* The chat program to run. This is a NULL terminated list of + arguments; element 0 if the program. May be NULL, in which case + there is no program. */ + char **uuconf_pzprogram; + /* The timeout in seconds to use for expect strings in the chat + script. */ + int uuconf_ctimeout; + /* The NULL terminated list of failure strings. If any of these + strings appear, the chat script is aborted. May be NULL, in + which case there are no failure strings. */ + char **uuconf_pzfail; + /* Non-zero if incoming characters should be stripped to seven bits + (by anding with 0x7f). */ + int uuconf_fstrip; +}; + +/* The information which is kept for a time specification. This is a + linked list of structures. Each element of the list represents a + span of time, giving a starting time and an ending time. The time + only depends on the day of the week, not on the day of the month or + of the year. The time is only specified down to the minute, not + down to the second or below. The list is sorted by starting time. + + The starting and ending time are expressed in minutes since the + beginning of the week, which is considered to be 12 midnight on + Sunday. Thus 60 is 1 am on Sunday, 1440 (== 60 * 24) is 12 + midnight on Monday, and the largest possible value is 10080 (== 60 + * 24 * 7) which is 12 midnight on the following Sunday. + + Each span of time has a value associated with it. This is the + lowest grade or the largest file size that may be transferred + during that time, depending on the source of the time span. When + time specifications overlap, the value used for the overlap is the + higher grade or the smaller file size. Thus specifying + ``call-timegrade z Any'' and ``call-timegrade Z Mo'' means that + only grade Z or higher may be sent on Monday, since Z is the higer + grade of the overlapping spans. The final array wil have no + overlaps. + + Each span also has a retry time associated with it. This permits + different retry times to be used at different times of day. The + retry time is only relevant if the span came from a ``time'' or + ``timegrade'' command for a system. */ + +struct uuconf_timespan +{ + /* Next element in list. */ + struct uuconf_timespan *uuconf_qnext; + /* Starting minute (-1 at the end of the array). */ + int uuconf_istart; + /* Ending minute. */ + int uuconf_iend; + /* Value for this span (lowest grade or largest file that may be + transferred at this time). */ + long uuconf_ival; + /* Retry time. */ + int uuconf_cretry; +}; + +/* The information which is kept for protocol parameters. Protocol + parameter information is stored as an array of the following + structures. */ + +struct uuconf_proto_param +{ + /* The name of the protocol to which this entry applies. This is + '\0' for the last element of the array. */ + int uuconf_bproto; + /* Specific entries for this protocol. This points to an array + ending in an element with a uuconf_cargs field of 0. */ + struct uuconf_proto_param_entry *uuconf_qentries; +}; + +/* Each particular protocol parameter entry is one of the following + structures. */ + +struct uuconf_proto_param_entry +{ + /* The number of arguments to the ``protocol-parameter'' command + (not counting ``protocol-parameter'' itself). This is 0 for the + last element of the array. */ + int uuconf_cargs; + /* The actual arguments to the ``protocol-parameter'' command; this + is an array with cargs entries. */ + char **uuconf_pzargs; +}; + +/* The information which is kept for a system. The zname and zalias + fields will be the same for all alternates. Every other fields is + specific to the particular alternate in which it appears (although + most will be the same for all alternates). */ + +struct uuconf_system +{ + /* The name of the system. */ + char *uuconf_zname; + /* A list of aliases for the system. This is a NULL terminated list + of strings. May be NULL, in which case there are no aliases. */ + char **uuconf_pzalias; + /* A linked list of alternate call in or call out information. Each + alternative way to call this system occupies an element of this + list. May be NULL, in which case there are no alternates. */ + struct uuconf_system *uuconf_qalternate; + /* The name for this particular alternate. May be NULL, in which + case this alternate does not have a name. */ + char *uuconf_zalternate; + /* If non-zero, this alternate may be used for calling out. */ + int uuconf_fcall; + /* If non-zero, this alternate may be used for accepting a call. */ + int uuconf_fcalled; + /* The times at which this system may be called. The ival field of + each uuconf_timespan structure is the lowest grade which may be + transferred at that time. The cretry field is the number of + minutes to wait before retrying the call, or 0 if it was not + specified. May be NULL, in which case the system may never be + called. */ + struct uuconf_timespan *uuconf_qtimegrade; + /* The times at which to request a particular grade of the system + when calling it, and the grades to request. The ival field of + each uuconf_timespan structure is the lowest grade which the + other system should transfer at that time. May be NULL, in which + case there are no grade restrictions. */ + struct uuconf_timespan *uuconf_qcalltimegrade; + /* The maximum number of times to retry calling this system. If + this is 0, there is no limit. */ + int uuconf_cmax_retries; + /* The number of minutes to wait between successful calls to a + system. */ + int uuconf_csuccess_wait; + /* The size restrictions by time for local requests during a locally + placed call. The ival field of each uuconf_timespan structure is + the size in bytes of the largest file which may be transferred at + that time. May be NULL, in which case there are no size + restrictions. */ + struct uuconf_timespan *uuconf_qcall_local_size; + /* The size restrictions by time for remote requests during a + locally placed call. May be NULL. */ + struct uuconf_timespan *uuconf_qcall_remote_size; + /* The size restrictions by time for local requests during a + remotely placed call. May be NULL. */ + struct uuconf_timespan *uuconf_qcalled_local_size; + /* The size restrictions by time for remote requests during a + remotely placed call. May be NULL. */ + struct uuconf_timespan *uuconf_qcalled_remote_size; + /* Baud rate, or speed. Zero means any baud rate. If ihighbaud is + non-zero, this is the low baud rate of a range. */ + long uuconf_ibaud; + /* If non-zero, ibaud is the low baud rate of a range and ihighbaud + is the high baud rate. */ + long uuconf_ihighbaud; + /* Port name to use. May be NULL. If an HDB configuration file + contains a modem class (alphabetic characters preceeding the baud + rate), the class is appended to the port name. */ + char *uuconf_zport; + /* Specific port information, if the system entry includes port + information. May be NULL. */ + struct uuconf_port *uuconf_qport; + /* Phone number to call, or address to use for a TCP connection. + May be NULL, in which case a dialer script may not use \D or \T + for this system, and a TCP port will use the system name. */ + char *uuconf_zphone; + /* Chat script to use when logging in to the system. */ + struct uuconf_chat uuconf_schat; + /* Login name to use for \L in the login chat script. This should + normally be accessed via uuconf_callout. If it is "*", + uuconf_callout will look it up in the call out file. This may be + NULL, in which case the login script may not use \L. */ + char *uuconf_zcall_login; + /* Password to use for \P in the login chat script. This should + normally be accessed via uuconf_callout. If it is "*", + uuconf_callout will look it up in the call out file. This may be + NULL, in which case the login script may not use \P. */ + char *uuconf_zcall_password; + /* The login name this system must use when calling in. This may be + different for different alternates. This should only be examined + if uuconf_fcalled is TRUE. If this is NULL or "ANY" then + uuconf_validate must be called to make sure that whatever login + name was used is permitted for this machine. */ + char *uuconf_zcalled_login; + /* If non-zero, then when this system calls in the call should not + be allowed to proceed and the system should be called back. */ + int uuconf_fcallback; + /* If non-zero, then conversation sequence numbers should be used + with this system. */ + int uuconf_fsequence; + /* A list of protocols to use with this system. Each protocol has a + single character name. May be NULL, in which case any known + protocol may be used. */ + char *uuconf_zprotocols; + /* Array of protocol parameters. Ends in an entry with a + uuconf_bproto field of '\0'. May be NULL. */ + struct uuconf_proto_param *uuconf_qproto_params; + /* Chat script to run when called by this system. */ + struct uuconf_chat uuconf_scalled_chat; + /* Debugging level to set during a conversation. May be NULL. */ + char *uuconf_zdebug; + /* Maximum remote debugging level this system may request. May be + NULL. */ + char *uuconf_zmax_remote_debug; + /* Non-zero if the remote system may request us to send files from + the local system to the remote. */ + int uuconf_fsend_request; + /* Non-zero if the remote system may request us to receive files + from the remote system to the local. */ + int uuconf_frec_request; + /* Non-zero if local requests are permitted when calling this + system. */ + int uuconf_fcall_transfer; + /* Non-zero if local requests are permitted when this system calls + in. */ + int uuconf_fcalled_transfer; + /* NULL terminated list of directories from which files may be sent + by local request. */ + char **uuconf_pzlocal_send; + /* NULL terminated list of directories from which files may be sent + by remote request. */ + char **uuconf_pzremote_send; + /* NULL terminated list of directories into which files may be + received by local request. */ + char **uuconf_pzlocal_receive; + /* NULL terminated list of directories into which files may be + received by remote request. */ + char **uuconf_pzremote_receive; + /* Path to use for command execution. This is a NULL terminated + list of directories. */ + char **uuconf_pzpath; + /* NULL terminated List of commands that may be executed. */ + char **uuconf_pzcmds; + /* Amount of free space to leave when accepting a file from this + system, in bytes. */ + long uuconf_cfree_space; + /* NULL terminated list of systems that this system may forward + from. May be NULL if there are no systems from which files may + be forwarded. The list may include "ANY". */ + char **uuconf_pzforward_from; + /* NULL terminated list of systems that this system may forward to. + May be NULL if there are no systems to which files may be + forwarded. The list may include "ANY". */ + char **uuconf_pzforward_to; + /* The public directory to use for this sytem. */ + const char *uuconf_zpubdir; + /* The local name to use for this remote system. May be NULL if the + usual local name should be used. */ + char *uuconf_zlocalname; + /* Memory allocation block for the system. */ + UUCONF_POINTER uuconf_palloc; +}; + +/* Types of ports. */ + +enum uuconf_porttype +{ + /* Unknown port type. A port of this type should never be returned + by the uuconf functions. */ + UUCONF_PORTTYPE_UNKNOWN, + /* Read from standard input and write to standard output. Not + normally used. */ + UUCONF_PORTTYPE_STDIN, + /* A modem port. */ + UUCONF_PORTTYPE_MODEM, + /* A direct connect port. */ + UUCONF_PORTTYPE_DIRECT, + /* A TCP port. Not supported on all systems. */ + UUCONF_PORTTYPE_TCP, + /* A TLI port. Not supported on all systems. */ + UUCONF_PORTTYPE_TLI +}; + +/* Additional information for a stdin port (there is none). */ + +struct uuconf_stdin_port +{ + int uuconf_idummy; +}; + +/* Additional information for a modem port. */ + +struct uuconf_modem_port +{ + /* The device name. May be NULL, in which case the port name is + used instead. */ + char *uuconf_zdevice; + /* The device name to send the dialer chat script to. May be NULL, + in which case the chat script is sent to the usual device. */ + char *uuconf_zdial_device; + /* The default baud rate (speed). If zero, there is no default. */ + long uuconf_ibaud; + /* The low baud rate, if a range is used. If zero, a range is not + used and ihighbaud should be ignored. */ + long uuconf_ilowbaud; + /* The high baud rate, if ilowbaud is non-zero. */ + long uuconf_ihighbaud; + /* Non-zero if the port supports carrier detect. */ + int uuconf_fcarrier; + /* A NULL terminated sequence of dialer/token pairs (element 0 is a + dialer name, element 1 is a token, etc.) May be NULL, in which + case qdialer should not be NULL. */ + char **uuconf_pzdialer; + /* Specific dialer information. Only used if pzdialer is NULL. */ + struct uuconf_dialer *uuconf_qdialer; +}; + +/* Additional information for a direct connect port. */ + +struct uuconf_direct_port +{ + /* The device name. May be NULL, in which case the port name is + used instead. */ + char *uuconf_zdevice; + /* The baud rate (speed). */ + long uuconf_ibaud; +}; + +/* Additional information for a TCP port. */ + +struct uuconf_tcp_port +{ + /* The TCP port number to use. May be a name or a number. May be + NULL, in which case "uucp" is looked up using getservbyname. */ + char *uuconf_zport; +}; + +/* Additional information for a TLI port. */ + +struct uuconf_tli_port +{ + /* Device name to open. May be NULL, in which case the port name is + used. */ + char *uuconf_zdevice; + /* Whether this port should be turned into a stream, permitting the + read and write calls instead of the t_rcv and t_send calls. */ + int uuconf_fstream; + /* A NULL terminated list of modules to push after making the + connection. May be NULL, in which case if fstream is non-zero, + then "tirdwr" is pushed onto the stream, and otherwise nothing is + pushed. */ + char **uuconf_pzpush; + /* A NULL terminated sequence of dialer/token pairs (element 0 is a + dialer name, element 1 is a token, etc.) May be NULL. If + element 0 is TLI or TLIS, element 1 is used as the address to + connect to; otherwise uuconf_zphone from the system information + is used. */ + char **uuconf_pzdialer; + /* Address to use when operating as a server. This may contain + escape sequences. */ + char *uuconf_zservaddr; +}; + +/* Information kept for a port. */ + +struct uuconf_port +{ + /* The name of the port. */ + char *uuconf_zname; + /* The type of the port. */ + enum uuconf_porttype uuconf_ttype; + /* The list of protocols supported by the port. The name of each + protocol is a single character. May be NULL, in which case any + protocol is permitted. */ + char *uuconf_zprotocols; + /* Array of protocol parameters. Ends in an entry with a + uuconf_bproto field of '\0'. May be NULL. */ + struct uuconf_proto_param *uuconf_qproto_params; + /* The set of reliability bits. */ + int uuconf_ireliable; + /* The lock file name to use. */ + char *uuconf_zlockname; + /* Memory allocation block for the port. */ + UUCONF_POINTER uuconf_palloc; + /* The type specific information. */ + union + { + struct uuconf_stdin_port uuconf_sstdin; + struct uuconf_modem_port uuconf_smodem; + struct uuconf_direct_port uuconf_sdirect; + struct uuconf_tcp_port uuconf_stcp; + struct uuconf_tli_port uuconf_stli; + } uuconf_u; +}; + +/* Information kept about a dialer. */ + +struct uuconf_dialer +{ + /* The name of the dialer. */ + char *uuconf_zname; + /* The chat script to use when dialing out. */ + struct uuconf_chat uuconf_schat; + /* The string to send when a `=' appears in the phone number. */ + char *uuconf_zdialtone; + /* The string to send when a `-' appears in the phone number. */ + char *uuconf_zpause; + /* Non-zero if the dialer supports carrier detect. */ + int uuconf_fcarrier; + /* The number of seconds to wait for carrier after the chat script + is complete. Only used if fcarrier is non-zero. Only supported + on some systems. */ + int uuconf_ccarrier_wait; + /* If non-zero, DTR should be toggled before dialing. Only + supported on some systems. */ + int uuconf_fdtr_toggle; + /* If non-zero, sleep for 1 second after toggling DTR. Ignored if + fdtr_toggle is zero. */ + int uuconf_fdtr_toggle_wait; + /* The chat script to use when a call is complete. */ + struct uuconf_chat uuconf_scomplete; + /* The chat script to use when a call is aborted. */ + struct uuconf_chat uuconf_sabort; + /* Array of protocol parameters. Ends in an entry with a + uuconf_bproto field of '\0'. May be NULL. */ + struct uuconf_proto_param *uuconf_qproto_params; + /* The set of reliability bits. */ + int uuconf_ireliable; + /* Memory allocation block for the dialer. */ + UUCONF_POINTER uuconf_palloc; +}; + +/* Reliability bits for the ireliable field of ports and dialers. + These bits are used to decide which protocol to run. A given + protocol will have a set of these bits, and each of them must be + turned on for the port before we will permit that protocol to be + used. This will be overridden by the zprotocols field. */ + +/* Whether a set of reliability bits is given. If this bit is not + set, then there is no reliability information. */ +#define UUCONF_RELIABLE_SPECIFIED (01) + +/* Set if the connection is eight bit transparent. */ +#define UUCONF_RELIABLE_EIGHT (02) + +/* Set if the connection is error-free. */ +#define UUCONF_RELIABLE_RELIABLE (04) + +/* Set if the connection is end-to-end reliable (e.g. TCP). */ +#define UUCONF_RELIABLE_ENDTOEND (010) + +/* Set if the connection is full-duplex; that is, no time consuming + line turnaround is required before sending data in the reverse + direction. If the connection is truly half-duplex, in the sense + that communication can only flow in one direction, UUCP can not be + used. */ +#define UUCONF_RELIABLE_FULLDUPLEX (020) + +/* UUCP grades range from 0 to 9, A to Z, a to z in order from highest + to lowest (work of higher grades is done before work of lower + grades). */ + +/* The highest grade. */ +#define UUCONF_GRADE_HIGH ('0') + +/* The lowest grade. */ +#define UUCONF_GRADE_LOW ('z') + +/* Whether a character is a legal grade (requires <ctype.h>). */ +#define UUCONF_GRADE_LEGAL(b) (isalnum ((unsigned) (b))) + +/* Return < 0 if the first grade should be done before the second + grade, == 0 if they are the same, or > 0 if the first grade should + be done after the second grade. On an ASCII system, this can just + be b1 - b2. */ +#define UUCONF_GRADE_CMP(b1, b2) (uuconf_grade_cmp ((b1), (b2))) + +/* Most of the uuconf functions returns an error code. A value of + zero (UUCONF_SUCCESS) indicates success. */ + +/* If this bit is set in the returned error code, then the + uuconf_errno function may be used to obtain the errno value as set + by the function which caused the failure. */ +#define UUCONF_ERROR_ERRNO (0x100) + +/* If this bit is set in the returned error code, then the + uuconf_filename function may be used to get the name of a file + associated with the error. */ +#define UUCONF_ERROR_FILENAME (0x200) + +/* If this bit is set in the returned error code, then the + uuconf_lineno function may be used to get a line number associated + with the error; normally if this is set UUCONF_ERROR_FILENAME will + also be set. */ +#define UUCONF_ERROR_LINENO (0x400) + +/* There are two UUCONF_CMDTABRET bits that may be set in the return + value of uuconf_cmd_line or uuconf_cmd_args, described below. They + do not indicate an error, but instead give instructions to the + calling function, often uuconf_cmd_file. They may also be set in + the return value of a user function listed in a uuconf_cmdtab + table, in which case they will be honored by uuconf_cmd_file. */ + +/* This bit means that the memory occupied by the arguments passed to + the function should be preserved, and not overwritten or freed. It + refers only to the contents of the arguments; the contents of the + argv array itself may always be destroyed. If this bit is set in + the return value of uuconf_cmd_line or uuconf_cmd_args, it must be + honored. It will be honored by uuconf_cmd_file. This may be + combined with an error code or with UUCONF_CMDTABRET_EXIT, although + neither uuconf_cmd_file or uuconf_cmd_line will do so. */ +#define UUCONF_CMDTABRET_KEEP (0x800) + +/* This bit means that uuconf_cmd_file should exit, rather than go on + to read and process the next line. If uuconf_cmd_line or + uuconf_cmd_args encounter an error, the return value will have this + bit set along with the error code. A user function may set this + bit with or without an error; the return value of the user function + will be returned by uuconf_cmd_file, except that the + UUCONF_CMDTABRET_KEEP and UUCONF_CMDTABRET_EXIT bits will be + cleared. */ +#define UUCONF_CMDTABRET_EXIT (0x1000) + +/* This macro may be used to extract the specific error value. */ +#define UUCONF_ERROR_VALUE(i) ((i) & 0xff) + +/* UUCONF_ERROR_VALUE will return one of the following values. */ + +/* Function succeeded. */ +#define UUCONF_SUCCESS (0) +/* Named item not found. */ +#define UUCONF_NOT_FOUND (1) +/* A call to fopen failed. */ +#define UUCONF_FOPEN_FAILED (2) +/* A call to fseek failed. */ +#define UUCONF_FSEEK_FAILED (3) +/* A call to malloc or realloc failed. */ +#define UUCONF_MALLOC_FAILED (4) +/* Syntax error in file. */ +#define UUCONF_SYNTAX_ERROR (5) +/* Unknown command. */ +#define UUCONF_UNKNOWN_COMMAND (6) + +#if UUCONF_ANSI_C + +/* For each type of configuration file (Taylor, V2, HDB), there are + separate routines to read various sorts of information. There are + also generic routines, which call on the appropriate type specific + routines. The library can be compiled to read any desired + combination of the configuration file types. This affects only the + generic routines, as it determines which type specific routines + they call. Thus, on a system which, for example, does not have any + V2 configuration files, there is no need to include the overhead of + the code to parse the files and the time to look for them. + However, a program which specifically wants to be able to parse + them can call the V2 specific routines. + + The uuconf functions all take as an argument a pointer to uuconf + global information. This must be initialized by any the + initialization routines (the generic one and the three file type + specific ones) before any of the other uuconf functions may be + called. */ + +/* Initialize the configuration file reading routines. The ppglobal + argument should point to a generic pointer (a void *, or, on older + compilers, a char *) which will be initialized and may then be + passed to the other uuconf routines. The zprogram argument is the + name of the program for which files should be read. A NULL is + taken as "uucp", and reads the standard UUCP configuration files. + The only other common argument is "cu", but any string is + permitted. The zname argument is the name of the Taylor UUCP + config file; if it is NULL, the default config file will be read. + If not reading Taylor UUCP configuration information, the argument + is ignored. This function must be called before any of the other + uuconf functions. + + Note that if the zname argument is obtained from the user running + the program, the program should be careful to revoke any special + privileges it may have (e.g. on Unix call setuid (getuid ()) and + setgid (getgid ())). Otherwise various sorts of spoofing become + possible. */ +extern int uuconf_init (void **uuconf_ppglobal, + const char *uuconf_zprogram, + const char *uuconf_zname); + +/* Adjust the configuration file global pointer for a new thread. The + library is fully reentrant (with the exception of the function + uuconf_error_string, which calls strerror, which on some systems is + not reentrant), provided that each new thread that wishes to call + the library calls this function and uses the new global pointer + value. The ppglobal argument should be set to the address of the + global pointer set by any of the init functions; it will be + modified to become a new global pointer. */ +extern int uuconf_init_thread (void **uuconf_ppglobal); + +/* Get the names of all known systems. This sets sets *ppzsystems to + point to an array of system names. The list of names is NULL + terminated. The array is allocated using malloc, as is each + element of the array, and they may all be passed to free when they + are no longer needed. If the falias argument is 0, the list will + not include any aliases; otherwise, it will. */ +extern int uuconf_system_names (void *uuconf_pglobal, + char ***uuconf_ppzsystems, + int uuconf_falias); + +/* Get the information for the system zsystem. This sets the fields + in *qsys. This will work whether zsystem is the official name of + the system or merely an alias. */ +extern int uuconf_system_info (void *uuconf_pglobal, + const char *uuconf_zsystem, + struct uuconf_system *uuconf_qsys); + +/* Get information for an unknown (anonymous) system. The + uuconf_zname field of the returned system information will be NULL. + If no information is available for unknown systems, this will + return UUCONF_NOT_FOUND. This does not run the HDB remote.unknown + shell script. */ +extern int uuconf_system_unknown (void *uuconf_pglobal, + struct uuconf_system *uuconf_qsys); + +/* Get information for the local system. Normally the local system + name should first be looked up using uuconf_system_info. If that + returns UUCONF_NOT_FOUND, this function may be used to get an + appropriate set of defaults. The uuconf_zname field of the + returned system information may be NULL. */ +extern int uuconf_system_local (void *uuconf_pglobal, + struct uuconf_system *uuconf_qsys); + +/* Free the memory occupied by system information returned by + uuconf_system_info, uuconf_system_unknown, uuconf_system_local, or + any of the configuration file type specific routines described + below. After this is called, the contents of the structure shall + not be referred to. */ +extern int uuconf_system_free (void *uuconf_pglobal, + struct uuconf_system *uuconf_qsys); + +#ifdef __OPTIMIZE__ +#define uuconf_system_free(qglob, q) \ + (uuconf_free_block ((q)->uuconf_palloc), UUCONF_SUCCESS) +#endif + +/* Find a matching port. This will consider each port in turn. + + If the zname argument is not NULL, the port's uuconf_zname field + must match it. + + If the ibaud argument is not zero and the ihighbaud argument is + zero, the port's baud rate, if defined, must be the same (if the + port has a range of baud rates, ibaud must be within the range). + If ibaud and ihighbaud are both not zero, the port's baud rate, if + defined, must be between ibaud and ihighbaud inclusive (if the port + has a range of baud rates, the ranges must intersect). If the port + has no baud rate, either because it is a type of port for which + baud rate is not defined (e.g. a TCP port) or because the + uuconf_ibaud field is 0, the ibaud and ihighbaud arguments are + ignored. + + If the pifn argument is not NULL, the port is passed to pifn, along + with the pinfo argument (which is otherwise ignored). If pifn + returns UUCONF_SUCCESS, the port matches. If pifn returns + UUCONF_NOT_FOUND, a new port is sought. Otherwise the return value + of pifn is returned from uuconf_find_port. The pifn function may + be used to further restrict the port, such as by modem class or + device name. It may also be used to lock the port, if appropriate; + in this case, if the lock fails, pifn may return UUCONF_NOT_FOUND + to force uuconf_find_port to continue searching for a port. + + If the port matches, the information is set into uuconf_qport, and + uuconf_find_port returns UUCONF_SUCCESS. */ +extern int uuconf_find_port (void *uuconf_pglobal, + const char *uuconf_zname, + long uuconf_ibaud, + long uuconf_ihighbaud, + int (*uuconf_pifn) (struct uuconf_port *, + void *uuconf_pinfo), + void *uuconf_pinfo, + struct uuconf_port *uuconf_qport); + +/* Free the memory occupied by system information returned by + uuconf_find_port (or any of the configuration file specific + routines described below). After this is called, the contents of + the structure shall not be referred to. */ +extern int uuconf_port_free (void *uuconf_pglobal, + struct uuconf_port *uuconf_qport); + +#ifdef __OPTIMIZE__ +#define uuconf_port_free(qglob, q) \ + (uuconf_free_block ((q)->uuconf_palloc), UUCONF_SUCCESS) +#endif + +/* Get the names of all known dialers. This sets sets *ppzdialers to + point to an array of dialer names. The list of names is NULL + terminated. The array is allocated using malloc, as is each + element of the array, and they may all be passed to free when they + are no longer needed. */ +extern int uuconf_dialer_names (void *uuconf_pglobal, + char ***uuconf_ppzdialers); + +/* Get the information for the dialer zdialer. This sets the fields + in *qdialer. */ +extern int uuconf_dialer_info (void *uuconf_pglobal, + const char *uuconf_zdialer, + struct uuconf_dialer *uuconf_qdialer); + +/* Free the memory occupied by system information returned by + uuconf_dialer_info (or any of the configuration file specific + routines described below). After this is called, the contents of + the structure shall not be referred to. */ +extern int uuconf_dialer_free (void *uuconf_pglobal, + struct uuconf_dialer *uuconf_qsys); + +#ifdef __OPTIMIZE__ +#define uuconf_dialer_free(qglob, q) \ + (uuconf_free_block ((q)->uuconf_palloc), UUCONF_SUCCESS) +#endif + +/* Get the local node name. If the node name is not specified + (because no ``nodename'' command appeared in the config file) this + will return UUCONF_NOT_FOUND, and some system dependent function + must be used to determine the node name. Otherwise it will return + a pointer to a constant string, which should not be freed. */ +extern int uuconf_localname (void *uuconf_pglobal, + const char **pzname); + +/* Get the local node name that should be used, given a login name. + This function will check for any special local name that may be + associated with the login name zlogin (as set by the ``myname'' + command in a Taylor configuration file, or the MYNAME field in a + Permissions entry). This will set *pzname to the node name. If no + node name can be determined, *pzname will be set to NULL and the + function will return UUCONF_NOT_FOUND; in this case some system + dependent function must be used to determine the node name. If the + function returns UUCONF_SUCCESS, *pzname will be point to an + malloced buffer. */ +extern int uuconf_login_localname (void *uuconf_pglobal, + const char *uuconf_zlogin, + char **pzname); + +/* Get the name of the UUCP spool directory. This will set *pzspool + to a constant string, which should not be freed. */ +extern int uuconf_spooldir (void *uuconf_pglobal, + const char **uuconf_pzspool); + +/* Get the name of the default UUCP public directory. This will set + *pzpub to a constant string, which should not be freed. Note that + particular systems may use a different public directory. */ +extern int uuconf_pubdir (void *uuconf_pglobal, + const char **uuconf_pzpub); + +/* Get the name of the UUCP lock directory. This will set *pzlock to + a constant string, which should not be freed. */ +extern int uuconf_lockdir (void *uuconf_pglobal, + const char **uuconf_pzlock); + +/* Get the name of the UUCP log file. This will set *pzlog to a + constant string, which should not be freed. */ +extern int uuconf_logfile (void *uuconf_pglobal, + const char **uuconf_pzlog); + +/* Get the name of the UUCP statistics file. This will set *pzstats + to a constant string, which should not be freed. */ +extern int uuconf_statsfile (void *uuconf_pglobal, + const char **uuconf_pzstats); + +/* Get the name of the UUCP debugging file. This will set *pzdebug to + a constant string, which should not be freed. */ +extern int uuconf_debugfile (void *uuconf_pglobal, + const char **uuconf_pzdebug); + +/* Get the default debugging level to use. This basically gets the + argument of the ``debug'' command from the Taylor UUCP config file. + It will set *pzdebug to a constant string, which should not be + freed. */ +extern int uuconf_debuglevel (void *uuconf_pglobal, + const char **uuconf_pzdebug); + +/* Get the maximum number of simultaneous uuxqt executions. This will + set *pcmaxuuxqt to the number. Zero indicates no maximum. */ +extern int uuconf_maxuuxqts (void *uuconf_pglobal, + int *uuconf_pcmaxuuxqt); + +/* Check a login name and password. This checks the Taylor UUCP + password file (not /etc/passwd). It will work even if + uuconf_taylor_init was not called. If the login name exists and + the password is correct, this returns UUCONF_SUCCESS. If the login + does not exist, or the password is wrong, this returns + UUCONF_NOT_FOUND. Other errors are also possible. */ +extern int uuconf_callin (void *uuconf_pglobal, + const char *uuconf_zlogin, + const char *uuconf_zpassword); + +/* Get the callout login name and password for a system. This will + set both *pzlog and *pzpass to a string allocated by malloc, or to + NULL if the value is not found. If neither value is found, the + function will return UUCONF_NOT_FOUND. */ +extern int uuconf_callout (void *uuconf_pglobal, + const struct uuconf_system *uuconf_qsys, + char **uuconf_pzlog, + char **uuconf_pzpass); + +/* See if a login name is permitted for a system. This will return + UUCONF_SUCCESS if it is permitted or UUCONF_NOT_FOUND if it is + invalid. This simply calls uuconf_taylor_validate or returns + UUCONF_SUCCESS, depending on the value of HAVE_TAYLOR_CONFIG. */ +extern int uuconf_validate (void *uuconf_pglobal, + const struct uuconf_system *uuconf_qsys, + const char *uuconf_zlogin); + +/* Get the name of the HDB remote.unknown shell script, if using + HAVE_HDB_CONFIG. This does not actually run the shell script. If + the function returns UUCONF_SUCCESS, the name will be in *pzname, + which will point to an malloced buffer. If it returns + UUCONF_NOT_FOUND, then there is no script to run. */ +extern int uuconf_remote_unknown (void *uuconf_pglobal, + char **pzname); + +/* Translate a dial code. This sets *pznum to an malloced string. + This will look up the entire zdial string in the dialcode file, so + for normal use the alphabetic prefix should be separated. */ +extern int uuconf_dialcode (void *uuconf_pglobal, + const char *uuconf_zdial, + char **uuconf_pznum); + +/* Compare two grades, returning < 0 if b1 should be executed before + b2, == 0 if they are the same, or > 0 if b1 should be executed + after b2. This can not fail, and does not return a standard uuconf + error code; it is normally called via the macro UUCONF_GRADE_CMP, + defined above. */ +extern int uuconf_grade_cmp (int uuconf_b1, int uuconf_b2); + +#else /* ! UUCONF_ANSI_C */ + +extern int uuconf_init (); +extern int uuconf_init_thread (); +extern int uuconf_system_names (); +extern int uuconf_system_info (); +extern int uuconf_system_unknown (); +extern int uuconf_system_local (); +extern int uuconf_system_free (); +extern int uuconf_find_port (); +extern int uuconf_port_free (); +extern int uuconf_dialer_names (); +extern int uuconf_dialer_info (); +extern int uuconf_dialer_free (); +extern int uuconf_localname (); +extern int uuconf_login_localname (); +extern int uuconf_spooldir (); +extern int uuconf_lockdir (); +extern int uuconf_pubdir (); +extern int uuconf_logfile (); +extern int uuconf_statsfile (); +extern int uuconf_debugfile (); +extern int uuconf_debuglevel (); +extern int uuconf_maxuuxqts (); +extern int uuconf_callin (); +extern int uuconf_callout (); +extern int uuconf_remote_unknown (); +extern int uuconf_validate (); +extern int uuconf_grade_cmp (); + +#ifdef __OPTIMIZE__ +#define uuconf_system_free(qglob, q) \ + (uuconf_free_block ((q)->uuconf_palloc), UUCONF_SUCCESS) +#define uuconf_port_free(qglob, q) \ + (uuconf_free_block ((q)->uuconf_palloc), UUCONF_SUCCESS) +#define uuconf_dialer_free(qglob, q) \ + (uuconf_free_block ((q)->uuconf_palloc), UUCONF_SUCCESS) +#endif + +#endif /* ! UUCONF_ANSI_C */ + +#if UUCONF_ANSI_C + +/* Initialize the Taylor UUCP configuration file reading routines. + This must be called before calling any of the Taylor UUCP + configuration file specific routines. The ppglobal argument should + point to a generic pointer. Moreover, before calling this function + the pointer either must be set to NULL, or must have been passed to + one of the other uuconf init routines. The zprogram argument is + the name of the program for which files should be read. If NULL, + it is taken as "uucp", which means to read the standard UUCP files. + The zname argument is the name of the config file. If it is NULL, + the default config file will be used. + + Note that if the zname argument is obtained from the user running + the program, the program should be careful to revoke any special + privileges it may have (e.g. on Unix call setuid (getuid ()) and + setgid (getgid ())). Otherwise various sorts of spoofing become + possible. */ +extern int uuconf_taylor_init (void **uuconf_pglobal, + const char *uuconf_zprogram, + const char *uuconf_zname); + +/* Get the names of all systems listed in the Taylor UUCP + configuration files. This sets *ppzsystems to point to an array of + system names. The list of names is NULL terminated. The array is + allocated using malloc, as is each element of the array. If the + falias argument is 0, the list will not include any aliases; + otherwise, it will. */ +extern int uuconf_taylor_system_names (void *uuconf_pglobal, + char ***uuconf_ppzsystems, + int uuconf_falias); + +/* Get the information for system zsystem from the Taylor UUCP + configuration files. This will set *qsys. */ +extern int uuconf_taylor_system_info (void *uuconf_pglobal, + const char *uuconf_zsystem, + struct uuconf_system *uuconf_qsys); + +/* Get information for an unknown (anonymous) system. This returns + the values set by the ``unknown'' command in the main configuration + file. If the ``unknown'' command was not used, this will return + UUCONF_NOT_FOUND. */ +extern int uuconf_taylor_system_unknown (void *uuconf_pglobal, + struct uuconf_system *uuconf_qsys); + +/* Find a port from the Taylor UUCP configuration files. The + arguments and return values are identical to those of + uuconf_find_port. */ +extern int uuconf_taylor_find_port (void *uuconf_pglobal, + const char *uuconf_zname, + long uuconf_ibaud, + long uuconf_ihighbaud, + int (*uuconf_pifn) (struct uuconf_port *, + void *uuconf_pinfo), + void *uuconf_pinfo, + struct uuconf_port *uuconf_qport); + +/* Get the names of all dialers listed in the Taylor UUCP + configuration files. This sets *ppzdialers to point to an array of + dialer names. The list of names is NULL terminated. The array is + allocated using malloc, as is each element of the array. */ +extern int uuconf_taylor_dialer_names (void *uuconf_pglobal, + char ***uuconf_ppzdialers); + +/* Get the information for the dialer zdialer from the Taylor UUCP + configuration files. This sets the fields in *qdialer. */ +extern int uuconf_taylor_dialer_info (void *uuconf_pglobal, + const char *uuconf_zdialer, + struct uuconf_dialer *uuconf_qdialer); + +/* Get the local node name that should be used, given a login name, + considering only the ``myname'' command in the Taylor UUCP + configuration files. If the function returns UUCONF_SUCCESS, + *pzname will point to an malloced buffer. */ +extern int uuconf_taylor_login_localname (void *uuconf_pglobal, + const char *uuconf_zlogin, + char **pzname); + +/* Get the callout login name and password for a system from the + Taylor UUCP configuration files. This will set both *pzlog and + *pzpass to a string allocated by malloc, or to NULL if the value is + not found. If neither value is found, the function will return + UUCONF_NOT_FOUND. */ +extern int uuconf_taylor_callout (void *uuconf_pglobal, + const struct uuconf_system *uuconf_qsys, + char **uuconf_pzlog, + char **uuconf_pzpass); + +/* See if a login name is permitted for a system. This will return + UUCONF_SUCCESS if it is permitted or UUCONF_NOT_FOUND if it is + invalid. This checks whether the login name appears in a + called-login command with a list of system which does not include + the system qsys. */ +extern int uuconf_taylor_validate (void *uuconf_pglobal, + const struct uuconf_system *uuconf_qsys, + const char *uuconf_zlogin); + +#else /* ! UUCONF_ANSI_C */ + +extern int uuconf_taylor_init (); +extern int uuconf_taylor_system_names (); +extern int uuconf_taylor_system_info (); +extern int uuconf_taylor_system_unknown (); +extern int uuconf_taylor_find_port (); +extern int uuconf_taylor_dialer_names (); +extern int uuconf_taylor_dialer_info (); +extern int uuconf_taylor_login_localname (); +extern int uuconf_taylor_callout (); +extern int uuconf_taylor_validate (); + +#endif /* ! UUCONF_ANSI_C */ + +#if UUCONF_ANSI_C + +/* Initialize the V2 configuration file reading routines. This must + be called before any of the other V2 routines are called. The + ppglobal argument should point to a generic pointer. Moreover, + before calling this function the pointer either must be set to + NULL, or must have been passed to one of the other uuconf init + routines. */ +extern int uuconf_v2_init (void **uuconf_ppglobal); + +/* Get the names of all systems listed in the V2 configuration files. + This sets *ppzsystems to point to an array of system names. The + list of names is NULL terminated. The array is allocated using + malloc, as is each element of the array. If the falias argument is + 0, the list will not include any aliases; otherwise, it will. */ +extern int uuconf_v2_system_names (void *uuconf_pglobal, + char ***uuconf_ppzsystems, + int uuconf_falias); + +/* Get the information for system zsystem from the V2 configuration + files. This will set *qsys. */ +extern int uuconf_v2_system_info (void *uuconf_pglobal, + const char *uuconf_zsystem, + struct uuconf_system *uuconf_qsys); + +/* Find a port from the V2 configuration files. The arguments and + return values are identical to those of uuconf_find_port. */ +extern int uuconf_v2_find_port (void *uuconf_pglobal, + const char *uuconf_zname, + long uuconf_ibaud, + long uuconf_ihighbaud, + int (*uuconf_pifn) (struct uuconf_port *, + void *uuconf_pinfo), + void *uuconf_pinfo, + struct uuconf_port *uuconf_qport); + +#else /* ! UUCONF_ANSI_C */ + +extern int uuconf_v2_init (); +extern int uuconf_v2_system_names (); +extern int uuconf_v2_system_info (); +extern int uuconf_v2_find_port (); + +#endif /* ! UUCONF_ANSI_C */ + +#if UUCONF_ANSI_C + +/* Initialize the HDB configuration file reading routines. This + should be called before any of the other HDB routines are called. + The ppglobal argument should point to a generic pointer. Moreover, + before calling this function the pointer either must be set to + NULL, or must have been passed to one of the other uuconf init + routines. The zprogram argument is used to match against a + "services" string in Sysfiles. A NULL or "uucp" argument is taken + as "uucico". */ +extern int uuconf_hdb_init (void **uuconf_ppglobal, + const char *uuconf_zprogram); + +/* Get the names of all systems listed in the HDB configuration files. + This sets *ppzsystems to point to an array of system names. The + list of names is NULL terminated. The array is allocated using + malloc, as is each element of the array. If the falias argument is + 0, the list will not include any aliases; otherwise, it will (an + alias is created by using the ALIAS= keyword in the Permissions + file). */ +extern int uuconf_hdb_system_names (void *uuconf_pglobal, + char ***uuconf_ppzsystems, + int uuconf_falias); + +/* Get the information for system zsystem from the HDB configuration + files. This will set *qsys. */ +extern int uuconf_hdb_system_info (void *uuconf_pglobal, + const char *uuconf_zsystem, + struct uuconf_system *uuconf_qsys); + + +/* Get information for an unknown (anonymous) system. If no + information is available for unknown systems, this will return + UUCONF_NOT_FOUND. This does not run the remote.unknown shell + script. */ +extern int uuconf_hdb_system_unknown (void *uuconf_pglobal, + struct uuconf_system *uuconf_qsys); + +/* Find a port from the HDB configuration files. The arguments and + return values are identical to those of uuconf_find_port. */ +extern int uuconf_hdb_find_port (void *uuconf_pglobal, + const char *uuconf_zname, + long uuconf_ibaud, + long uuconf_ihighbaud, + int (*uuconf_pifn) (struct uuconf_port *, + void *uuconf_pinfo), + void *uuconf_pinfo, + struct uuconf_port *uuconf_qport); + +/* Get the names of all dialers listed in the HDB configuration files. + This sets *ppzdialers to point to an array of dialer names. The + list of names is NULL terminated. The array is allocated using + malloc, as is each element of the array. */ +extern int uuconf_hdb_dialer_names (void *uuconf_pglobal, + char ***uuconf_ppzdialers); + +/* Get the information for the dialer zdialer from the HDB + configuration files. This sets the fields in *qdialer. */ +extern int uuconf_hdb_dialer_info (void *uuconf_pglobal, + const char *uuconf_zdialer, + struct uuconf_dialer *uuconf_qdialer); + +/* Get the local node name that should be used, given a login name, + considering only the MYNAME field in the HDB Permissions file. If + the function returns UUCONF_SUCCESS, *pzname will point to an + malloced buffer. */ +extern int uuconf_hdb_login_localname (void *uuconf_pglobal, + const char *uuconf_zlogin, + char **pzname); + +/* Get the name of the HDB remote.unknown shell script. This does not + actually run the shell script. If the function returns + UUCONF_SUCCESS, the name will be in *pzname, which will point to an + malloced buffer. */ +extern int uuconf_hdb_remote_unknown (void *uuconf_pglobal, + char **pzname); + +#else /* ! UUCONF_ANSI_C */ + +extern int uuconf_hdb_init (); +extern int uuconf_hdb_system_names (); +extern int uuconf_hdb_system_info (); +extern int uuconf_hdb_system_unknown (); +extern int uuconf_hdb_find_port (); +extern int uuconf_hdb_dialer_names (); +extern int uuconf_hdb_dialer_info (); +extern int uuconf_hdb_localname (); +extern int uuconf_hdb_remote_unknown (); + +#endif /* ! UUCONF_ANSI_C */ + +#if UUCONF_ANSI_C + +/* This function will set an appropriate error message into the buffer + zbuf, given a uuconf error code. The buffer will always be null + terminated, and will never be accessed beyond the length cbuf. + This function will return the number of characters needed for the + complete message, including the null byte. If this is less than + the cbytes argument, the buffer holds a truncated string. */ +extern int uuconf_error_string (void *uuconf_pglobal, int ierror, + char *zbuf, UUCONF_SIZE_T cbuf); + +/* If UUCONF_ERROR_ERRNO is set in a return value, this function may + be used to retrieve the errno value. This will be the value of + errno as set by the system function which failed. However, some + system functions, notably some stdio routines, may not set errno, + in which case the value will be meaningless. This function does + not return a uuconf error code, and it cannot fail. */ +extern int uuconf_error_errno (void *uuconf_pglobal); + +/* If UUCONF_ERROR_FILENAME is set in a return value, this function + may be used to retrieve the file name. This function does not + return a uuconf error code, and it cannot fail. The string that it + returns a pointer to is not guaranteed to remain allocated across + the next call to a uuconf function (other than one of the three + error retrieving functions). */ +extern const char *uuconf_error_filename (void *uuconf_pglobal); + +/* If UUCONF_ERROR_LINENO is set in a return value, this function may + be used to retrieve the line number. This function does not return + a uuconf error code, and it cannot fail. */ +extern int uuconf_error_lineno (void *uuconf_pglobal); + +#else /* ! UUCONF_ANSI_C */ + +extern int uuconf_error_string (); +extern int uuconf_error_errno (); +extern UUCONF_CONST char *uuconf_error_filename (); +extern int uuconf_error_lineno (); + +#endif /* ! UUCONF_ANSI_C */ + +/* The uuconf package also provides a few functions which can accept + commands and parcel them out according to a table. These are + publically visible, partially in the hopes that they will be + useful, but mostly because the rest of the Taylor UUCP package uses + them. */ + +/* The types of entries allowed in a command table (struct + uuconf_cmdtab). Each type defines how a particular command is + interpreted. Each type will either assign a value to a variable or + call a function. In all cases, a line of input is parsed into + separate fields, separated by whitespace; comments beginning with + '#' are discarded, except that a '#' preceeded by a backslash is + retained. The first field is taken as the command to execute, and + the remaining fields are its arguments. */ + +/* A boolean value. Used for a command which accepts a single + argument, which must begin with 'y', 'Y', 't', or 'T' for true (1) + or 'n', 'N', 'f', or 'F' for false (0). The corresponding variable + must be an int. */ +#define UUCONF_CMDTABTYPE_BOOLEAN (0x12) + +/* An integer value. Used for a command which accepts a single + argument, which must be an integer. The corresponding variable + must be an int. */ +#define UUCONF_CMDTABTYPE_INT (0x22) + +/* A long value. Used for a command which accepts a single value, + which must be an integer. The corresponding variable must be a + long. */ +#define UUCONF_CMDTABTYPE_LONG (0x32) + +/* A string value. Used for a command which accepts a string + argument. If there is no argument, the variable will be set to + point to a zero byte. Otherwise the variable will be set to point + to the string. The corresponding variable must be a char *. The + memory pointed to by the variable after it is set must not be + modified. */ +#define UUCONF_CMDTABTYPE_STRING (0x40) + +/* A full string value. Used for a command which accepts a series of + string arguments separated by whitespace. The corresponding + variable must be a char **. It will be set to an NULL terminated + array of the arguments. The memory occupied by the array itself, + and by the strings within it, must not be modified. */ +#define UUCONF_CMDTABTYPE_FULLSTRING (0x50) + +/* A function. If this command is encountered, the command and its + arguments are passed to the corresponding function. They are + passed as an array of strings, in which the first string is the + command itself, along with a count of strings. This value may be + or'red with a specific number of required arguments; + UUCONF_CMDTABTYPE_FN | 1 accepts no additional arguments besides + the command itself, UUCONF_CMDTABTYPE_FN | 2 accepts 1 argument, + etc. UUCONF_CMDTABTYPE_FN | 0, accepts any number of additional + arguments. */ +#define UUCONF_CMDTABTYPE_FN (0x60) + +/* A prefix function. The string in the table is a prefix; if a + command is encountered with the same prefix, the corresponding + function will be called as for UUCONF_CMDTABTYPE_FN. The number of + arguments may be or'red in as with UUCONF_CMDTABTYPE_FN. */ +#define UUCONF_CMDTABTYPE_PREFIX (0x70) + +/* This macro will return the particular type of a CMDTABTYPE. */ +#define UUCONF_TTYPE_CMDTABTYPE(i) ((i) & 0x70) + +/* This macro will return the required number of arguments of a + CMDTABTYPE. If it is zero, there is no restriction. */ +#define UUCONF_CARGS_CMDTABTYPE(i) ((i) & 0x0f) + +/* When a function is called via UUCONF_CMDTABTYPE_FN or + UUCONF_CMDTABTYPE_PREFIX, it may return any uuconf error code (see + above). However, it will normally return one of the following: + + UUCONF_CMDTABRET_CONTINUE: Take no special action. In particular, + the arguments passed to the function may be overwritten or freed. + + UUCONF_CMDTABRET_KEEP: The memory occupied by the arguments passed + to the function must be preserved. Continue processing commands. + + UUCONF_CMDTABRET_EXIT: If reading commands from a file, stop + processing. The arguments passed to the function may be + overwritten or freed. + + UUCONF_CMDTABRET_KEEP_AND_EXIT: Stop processing any file. The + memory occupied by the arguments passed to the function must be + preserved. + + These values are interpreted by uuconf_cmd_file. The + uuconf_cmd_line and uuconf_cmd_args functions may return + UUCONF_CMDTABRET_KEEP. It they get an error, they will return an + error code with UUCONF_CMDTABRET_EXIT set. Also, of course, they + may return any value that is returned by one of the user functions + in the uuconf_cmdtab table. */ + +/* UUCONF_CMDTABRET_KEEP and UUCONF_CMDTABRET_EXIT are defined above, + with the error codes. */ + +#define UUCONF_CMDTABRET_CONTINUE UUCONF_SUCCESS +#define UUCONF_CMDTABRET_KEEP_AND_EXIT \ + (UUCONF_CMDTABRET_KEEP | UUCONF_CMDTABRET_EXIT) + +/* When a function is called via CMDTABTYPE_FN or CMDTABTYPE_PREFIX, + it is passed five arguments. This is the type of a pointer to such + a function. The uuconf global information structure is passed in + for convenience in calling another uuconf function. The arguments + to the command are passed in (the command itself is the first + argument) along with a count and the value of the pvar field from + the uuconf_cmdtab structure in which the function pointer was + found. The pinfo argument to the function is taken from the + argument to uuconf_cmd_*. */ + +#if UUCONF_ANSI_C +typedef int (*uuconf_cmdtabfn) (void *uuconf_pglobal, + int uuconf_argc, + char **uuconf_argv, + void *uuconf_pvar, + void *uuconf_pinfo); +#else +typedef int (*uuconf_cmdtabfn) (); +#endif + +/* A table of commands is an array of the following structures. The + final element of the table should have uuconf_zcmd == NULL. */ + +struct uuconf_cmdtab +{ + /* Command name. */ + UUCONF_CONST char *uuconf_zcmd; + /* Command type (one of CMDTABTYPE_*). */ + int uuconf_itype; + /* If not CMDTABTYPE_FN or CMDTABTYPE_PREFIX, the address of the + associated variable. Otherwise, a pointer value to pass to the + function pifn. */ + UUCONF_POINTER uuconf_pvar; + /* The function to call if CMDTABTYPE_FN or CMDTABTYPE_PREFIX. */ + uuconf_cmdtabfn uuconf_pifn; +}; + +/* Bit flags to pass to uuconf_processcmds. */ + +/* If set, case is significant when checking commands. Normally case + is ignored. */ +#define UUCONF_CMDTABFLAG_CASE (0x1) + +/* If set, a backslash at the end of a line may be used to include the + next physical line in the logical line. */ +#define UUCONF_CMDTABFLAG_BACKSLASH (0x2) + +#if UUCONF_ANSI_C + +/* Read commands from a file, look them up in a table, and take the + appropriate action. This continues reading lines from the file + until EOF, or until a function returns with UUCONF_CMDTABRET_EXIT + set, or until an error occurs. The qtab argument must point to a + table of struct uuconf_cmdtab; the last element in the table should + have uuconf_zcmd == NULL. When a UUCONF_CMDTABTYPE_FN or + UUCONF_CMDTABTYPE_PREFIX command is found, the pinfo argument will + be passed to the called function. If an a command is found that is + not in the table, then if pfiunknownfn is NULL the unknown command + is ignored; otherwise it is passed to pfiunknownfn, which should + return a uuconf return code which is handled as for any other + function (the pvar argument to pfiunknownfn will always be NULL). + The iflags argument is any combination of the above + UUCONF_CMDTABFLAG bits. The pblock argument may also be a memory + block, as returned by uuconf_malloc_block (described below), in + which case all memory preserved because of UUCONF_CMDTABRET_KEEP + will be added to the block so that it may be freed later; it may + also be NULL, in which case any such memory is permanently lost. + + This function initially sets the internal line number to 0, and + then increments it as each line is read. It is permitted for any + called function to use the uuconf_lineno function to obtain it. If + this function is called when not at the start of a file, the value + returned by uuconf_lineno (which is, in any case, only valid if an + error code with UUCONF_ERROR_LINENO set is returned) must be + adjusted by the caller. + + This returns a normal uuconf return value, as described above. */ +extern int uuconf_cmd_file (void *uuconf_pglobal, + FILE *uuconf_e, + const struct uuconf_cmdtab *uuconf_qtab, + void *uuconf_pinfo, + uuconf_cmdtabfn uuconf_pfiunknownfn, + int uuconf_iflags, + void *pblock); + +/* This utility function is just like uuconf_cmd_file, except that it + only operates on a single string. If a function is called via + qtab, its return value will be the return value of this function. + UUCONF_CMDTABFLAG_BACKSLASH is ignored in iflags. The string z is + modified in place. The return value may include the + UUCONF_CMDTABRET_KEEP and, on error, the UUCONF_CMDTABRET_EXIT + bits, which should be honored by the calling code. */ +extern int uuconf_cmd_line (void *uuconf_pglobal, + char *uuconf_z, + const struct uuconf_cmdtab *uuconf_qtab, + void *uuconf_pinfo, + uuconf_cmdtabfn uuconf_pfiunknownfn, + int uuconf_iflags, + void *pblock); + +/* This utility function is just like uuconf_cmd_line, except it is + given a list of already parsed arguments. */ +extern int uuconf_cmd_args (void *uuconf_pglobal, + int uuconf_cargs, + char **uuconf_pzargs, + const struct uuconf_cmdtab *uuconf_qtab, + void *uuconf_pinfo, + uuconf_cmdtabfn uuconf_pfiunknownfn, + int uuconf_iflags, + void *pblock); + +#else /* ! UUCONF_ANSI_C */ + +extern int uuconf_cmd_file (); +extern int uuconf_cmd_line (); +extern int uuconf_cmd_args (); + +#endif /* ! UUCONF_ANSI_C */ + +#if UUCONF_ANSI_C + +/* The uuconf_cmd_file function may allocate memory permanently, as + for setting a UUCONF_CMDTABTYPE_STRING value, in ways which are + difficult to free up. A memory block may be used to record all + allocated memory, so that it can all be freed up at once at some + later time. These functions do not take a uuconf global pointer, + and are independent of the rest of the uuconf library. */ + +/* Allocate a block of memory. If this returns NULL, then malloc + returned NULL, and errno is whatever malloc set it to. */ +extern void *uuconf_malloc_block (void); + +/* Allocate memory within a memory block. If this returns NULL, then + malloc returned NULL, and errno is whatever malloc set it to. */ +extern void *uuconf_malloc (void *uuconf_pblock, + UUCONF_SIZE_T uuconf_cbytes); + +/* Add a block returned by the generic malloc routine to a memory + block. This returns zero on success, non-zero on failure. If this + fails (returns non-zero), then malloc returned NULL, and errno is + whatever malloc set it to. */ +extern int uuconf_add_block (void *uuconf_pblock, void *uuconf_padd); + +/* Free a value returned by uuconf_malloc from a memory block. In the + current implementation, this will normally not do anything, but it + doesn't hurt. No errors can occur. */ +extern void uuconf_free (void *uuconf_pblock, void *uuconf_pfree); + +/* Free an entire memory block, including all values returned by + uuconf_malloc from it and all values added to it with + uuconf_add_block. No errors can occur. */ +extern void uuconf_free_block (void *uuconf_pblock); + +#else /* ! UUCONF_ANSI_C */ + +extern UUCONF_POINTER uuconf_malloc_block (); +extern UUCONF_POINTER uuconf_malloc (); +extern int uuconf_add_block (); +extern /* void */ uuconf_free (); +extern /* void */ uuconf_free_block (); + +#endif /* ! UUCONF_ANSI_C */ + +#endif /* ! defined (UUCONF_H) */ diff --git a/gnu/libexec/uucp/common_sources/uucp.h b/gnu/libexec/uucp/common_sources/uucp.h new file mode 100644 index 000000000000..8df3ec4c3e79 --- /dev/null +++ b/gnu/libexec/uucp/common_sources/uucp.h @@ -0,0 +1,367 @@ +/* uucp.h + Header file for the UUCP package. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +/* Get the system configuration parameters. */ +#include "conf.h" +#include "policy.h" + +/* Get a definition for ANSI_C if we weren't given one. */ +#ifndef ANSI_C +#ifdef __STDC__ +#define ANSI_C 1 +#else /* ! defined (__STDC__) */ +#define ANSI_C 0 +#endif /* ! defined (__STDC__) */ +#endif /* ! defined (ANSI_C) */ + +/* Pass this definition into uuconf.h. */ +#define UUCONF_ANSI_C ANSI_C + +/* We always include some standard header files. We need <signal.h> + to define sig_atomic_t. */ +#if HAVE_STDDEF_H +#include <stddef.h> +#endif +#include <stdio.h> +#include <signal.h> + +/* On some systems we need <sys/types.h> to get sig_atomic_t or + size_t or time_t. */ +#if ! HAVE_SIG_ATOMIC_T_IN_SIGNAL_H && HAVE_SIG_ATOMIC_T_IN_TYPES_H +#define USE_TYPES_H 1 +#else +#if ! HAVE_SIZE_T_IN_STDDEF_H && HAVE_SIZE_T_IN_TYPES_H +#define USE_TYPES_H 1 +#else +#if ! HAVE_TIME_T_IN_TIME_H && HAVE_TIME_T_IN_TYPES_H +#define USE_TYPES_H 1 +#endif +#endif +#endif + +#ifndef USE_TYPES_H +#define USE_TYPES_H 0 +#endif + +#if USE_TYPES_H +#include <sys/types.h> +#endif + +/* Make sure we have sig_atomic_t. */ +#if ! HAVE_SIG_ATOMIC_T_IN_SIGNAL_H && ! HAVE_SIG_ATOMIC_T_IN_TYPES_H +#ifndef SIG_ATOMIC_T +/* There is no portable definition for sig_atomic_t. */ +#define SIG_ATOMIC_T char +#endif /* ! defined (SIG_ATOMIC_T) */ +typedef SIG_ATOMIC_T sig_atomic_t; +#endif /* ! HAVE_SIG_ATOMIC_T_IN_SIGNAL_H && ! HAVE_SIG_ATOMIC_T_IN_TYPES_H */ + +/* Make sure we have size_t. We use int as the default because the + main use of this type is to provide an argument to malloc and + realloc. On a system which does not define size_t, int is + certainly the correct type to use. */ +#if ! HAVE_SIZE_T_IN_STDDEF_H && ! HAVE_SIZE_T_IN_TYPES_H +#ifndef SIZE_T +#define SIZE_T unsigned +#endif /* ! defined (SIZE_T) */ +typedef SIZE_T size_t; +#endif /* ! HAVE_SIZE_T_IN_STDDEF_H && ! HAVE_SIZE_T_IN_TYPES_H */ + +/* Make sure we have time_t. We use long as the default. We don't + bother to let conf.h override this, since on a system which doesn't + define time_t long must be correct. */ +#if ! HAVE_TIME_T_IN_TIME_H && ! HAVE_TIME_T_IN_TYPES_H +typedef long time_t; +#endif + +/* Set up some definitions for both ANSI C and Classic C. + + P() -- for function prototypes (e.g. extern int foo P((int)) ). + pointer -- for a generic pointer (i.e. void *). + constpointer -- for a generic pointer to constant data. + BUCHAR -- to convert a character to unsigned. */ +#if ANSI_C +#if ! HAVE_VOID || ! HAVE_UNSIGNED_CHAR + #error ANSI C compiler without void or unsigned char +#endif +#define P(x) x +typedef void *pointer; +typedef const void *constpointer; +#define BUCHAR(b) ((unsigned char) (b)) +#else /* ! ANSI_C */ +/* Handle uses of const, volatile and void in Classic C. */ +#define const +#define volatile +#if ! HAVE_VOID +#define void int +#endif +#define P(x) () +typedef char *pointer; +typedef const char *constpointer; +#if HAVE_UNSIGNED_CHAR +#define BUCHAR(b) ((unsigned char) (b)) +#else /* ! HAVE_UNSIGNED_CHAR */ +/* This should work on most systems, but not necessarily all. */ +#define BUCHAR(b) ((b) & 0xff) +#endif /* ! HAVE_UNSIGNED_CHAR */ +#endif /* ! ANSI_C */ + +/* Make sure we have a definition for offsetof. */ +#ifndef offsetof +#define offsetof(type, field) \ + ((size_t) ((char *) &(((type *) 0)->field) - (char *) (type *) 0)) +#endif + +/* Only use inline with gcc. */ +#ifndef __GNUC__ +#define __inline__ +#endif + +/* Get the string functions, which are used throughout the code. */ +#if HAVE_MEMORY_H +#include <memory.h> +#else +/* We really need a definition for memchr, and this should not + conflict with anything in <string.h>. I hope. */ +extern pointer memchr (); +#endif + +#if HAVE_STRING_H +#include <string.h> +#else /* ! HAVE_STRING_H */ +#if HAVE_STRINGS_H +#include <strings.h> +#else /* ! HAVE_STRINGS_H */ +extern char *strcpy (), *strncpy (), *strchr (), *strrchr (), *strtok (); +extern char *strcat (), *strerror (), *strstr (); +extern size_t strlen (), strspn (), strcspn (); +#if ! HAVE_MEMORY_H +extern pointer memcpy (), memchr (); +#endif /* ! HAVE_MEMORY_H */ +#endif /* ! HAVE_STRINGS_H */ +#endif /* ! HAVE_STRING_H */ + +/* Get what we need from <stdlib.h>. */ +#if HAVE_STDLIB_H +#include <stdlib.h> +#else /* ! HAVE_STDLIB_H */ +extern pointer malloc (), realloc (), bsearch (); +extern long strtol (); +extern char *getenv (); +#endif /* ! HAVE_STDLIB_H */ + +/* NeXT uses <libc.h> to declare a bunch of functions. */ +#if HAVE_LIBC_H +#include <libc.h> +#endif + +/* Make sure we have the EXIT_ macros. */ +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS (0) +#endif +#ifndef EXIT_FAILURE +#define EXIT_FAILURE (1) +#endif + +/* If we need to declare errno, do so. I don't want to always do + this, because some system might theoretically have a different + declaration for errno. On a POSIX system this is sure to work. */ +#if ! HAVE_ERRNO_DECLARATION +extern int errno; +#endif + +/* If the system has the socket call, guess that we can compile the + TCP code. */ +#define HAVE_TCP HAVE_SOCKET + +/* If the system has the t_open call, guess that we can compile the + TLI code. */ +#define HAVE_TLI HAVE_T_OPEN + +/* The boolean type holds boolean values. */ +typedef int boolean; +#undef TRUE +#undef FALSE +#define TRUE (1) +#define FALSE (0) + +/* The openfile_t type holds an open file. This depends on whether we + are using stdio or not. */ +#if USE_STDIO + +typedef FILE *openfile_t; +#define EFILECLOSED ((FILE *) NULL) +#define ffileisopen(e) ((e) != NULL) +#define ffileeof(e) feof (e) +#define cfileread(e, z, c) fread ((z), 1, (c), (e)) +#define ffilereaderror(e, c) ferror (e) +#define cfilewrite(e, z, c) fwrite ((z), 1, (c), (e)) +#ifdef SEEK_SET +#define ffileseek(e, i) (fseek ((e), (long) (i), SEEK_SET) == 0) +#define ffilerewind(e) (fseek ((e), (long) 0, SEEK_SET) == 0) +#else +#define ffileseek(e, i) (fseek ((e), (long) (i), 0) == 0) +#define ffilerewind(e) (fseek ((e), (long) 0, 0) == 0) +#endif +#define ffileclose(e) (fclose (e) == 0) + +#else /* ! USE_STDIO */ + +#if HAVE_UNISTD_H +#include <unistd.h> +#endif + +typedef int openfile_t; +#define EFILECLOSED (-1) +#define ffileisopen(e) ((e) >= 0) +#define ffileeof(e) (FALSE) +#define cfileread(e, z, c) read ((e), (z), (c)) +#define ffilereaderror(e, c) ((c) < 0) +#define cfilewrite(e, z, c) write ((e), (z), (c)) +#ifdef SEEK_SET +#define ffileseek(e, i) (lseek ((e), (long) i, SEEK_SET) >= 0) +#define ffilerewind(e) (lseek ((e), (long) 0, SEEK_SET) >= 0) +#else +#define ffileseek(e, i) (lseek ((e), (long) i, 0) >= 0) +#define ffilerewind(e) (lseek ((e), (long) 0, 0) >= 0) +#endif +#define ffileclose(e) (close (e) >= 0) + +#endif /* ! USE_STDIO */ + +/* A prototype for main to avoid warnings from gcc 2.0 + -Wmissing-prototype option. */ +extern int main P((int argc, char **argv)); + +/* Some standard routines which we only define if they are not present + on the system we are compiling on. */ + +#if ! HAVE_GETLINE +/* Read a line from a file. */ +extern int getline P((char **pz, size_t *pc, FILE *e)); +#endif + +#if ! HAVE_REMOVE +/* Erase a file. */ +#undef remove +extern int remove P((const char *zfile)); +#endif + +#if ! HAVE_STRDUP +/* Copy a string into memory. */ +extern char *strdup P((const char *z)); +#endif + +#if ! HAVE_STRSTR +/* Look for one string within another. */ +extern char *strstr P((const char *zouter, const char *zinner)); +#endif + +#if ! HAVE_STRCASECMP +#if HAVE_STRICMP +#define strcasecmp stricmp +#else /* ! HAVE_STRICMP */ +/* Rename strcasecmp to avoid ANSI C name space. */ +#define strcasecmp xstrcasecmp +extern int strcasecmp P((const char *z1, const char *z2)); +#endif /* ! HAVE_STRICMP */ +#endif /* ! HAVE_STRCASECMP */ + +#if ! HAVE_STRNCASECMP +#if HAVE_STRNICMP +#define strncasecmp strnicmp +#else /* ! HAVE_STRNICMP */ +/* Rename strncasecmp to avoid ANSI C name space. */ +#define strncasecmp xstrncasecmp +extern int strncasecmp P((const char *z1, const char *z2, size_t clen)); +#endif /* ! HAVE_STRNICMP */ +#endif /* ! HAVE_STRNCASECMP */ + +#if ! HAVE_STRERROR +/* Get a string corresponding to an error message. */ +#undef strerror +extern char *strerror P((int ierr)); +#endif + +/* Get the appropriate definitions for memcmp, memcpy, memchr and + bzero. */ +#if ! HAVE_MEMCMP +#if HAVE_BCMP +#define memcmp(p1, p2, c) bcmp ((p1), (p2), (c)) +#else /* ! HAVE_BCMP */ +extern int memcmp P((constpointer p1, constpointer p2, size_t c)); +#endif /* ! HAVE_BCMP */ +#endif /* ! HAVE_MEMCMP */ + +#if ! HAVE_MEMCPY +#if HAVE_BCOPY +#define memcpy(pto, pfrom, c) bcopy ((pfrom), (pto), (c)) +#else /* ! HAVE_BCOPY */ +extern pointer memcpy P((pointer pto, constpointer pfrom, size_t c)); +#endif /* ! HAVE_BCOPY */ +#endif /* ! HAVE_MEMCPY */ + +#if ! HAVE_MEMCHR +extern pointer memchr P((constpointer p, int b, size_t c)); +#endif + +#if ! HAVE_BZERO +#if HAVE_MEMSET +#define bzero(p, c) memset ((p), 0, (c)) +#else /* ! HAVE_MEMSET */ +extern void bzero P((pointer p, int c)); +#endif /* ! HAVE_MEMSET */ +#endif /* ! HAVE_BZERO */ + +/* Look up a character in a string. */ +#if ! HAVE_STRCHR +#if HAVE_INDEX +#define strchr index +extern char *index (); +#else /* ! HAVE_INDEX */ +extern char *strchr P((const char *z, int b)); +#endif /* ! HAVE_INDEX */ +#endif /* ! HAVE_STRCHR */ + +#if ! HAVE_STRRCHR +#if HAVE_RINDEX +#define strrchr rindex +extern char *rindex (); +#else /* ! HAVE_RINDEX */ +extern char *strrchr P((const char *z, int b)); +#endif /* ! HAVE_RINDEX */ +#endif /* ! HAVE_STRRCHR */ + +/* Turn a string into a long integer. */ +#if ! HAVE_STRTOL +extern long strtol P((const char *, char **, int)); +#endif + +/* Lookup a key in a sorted array. */ +#if ! HAVE_BSEARCH +extern pointer bsearch P((constpointer pkey, constpointer parray, + size_t celes, size_t cbytes, + int (*pficmp) P((constpointer, constpointer)))); +#endif diff --git a/gnu/libexec/uucp/common_sources/uudefs.h b/gnu/libexec/uucp/common_sources/uudefs.h new file mode 100644 index 000000000000..47d2c89896ef --- /dev/null +++ b/gnu/libexec/uucp/common_sources/uudefs.h @@ -0,0 +1,445 @@ +/* uudefs.h + Miscellaneous definitions for the UUCP package. + + Copyright (C) 1991, 1992 Ian Lance Taylor + + This file is part of the Taylor UUCP package. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + The author of the program may be contacted at ian@airs.com or + c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. + */ + +#if ANSI_C +/* These structures are used in prototypes but are not defined in this + header file. */ +struct uuconf_system; +struct uuconf_timespan; +#endif + +/* The tlog enumeration holds the different types of logging. */ +enum tlog +{ + /* Normal log entry. */ + LOG_NORMAL, + /* Error log entry. */ + LOG_ERROR, + /* Fatal log entry. */ + LOG_FATAL +#if DEBUG > 1 + , + /* Debugging log entry. */ + LOG_DEBUG, + /* Start debugging log entry. */ + LOG_DEBUG_START, + /* Continue debugging log entry. */ + LOG_DEBUG_CONTINUE, + /* End debugging log entry. */ + LOG_DEBUG_END +#endif +}; + +/* The tstatus_type enumeration holds the kinds of status information + we put in the status file. The order of entries here corresponds + to the order of entries in the azStatus array. */ +enum tstatus_type +{ + /* Conversation complete. */ + STATUS_COMPLETE, + /* Port unavailable. */ + STATUS_PORT_FAILED, + /* Dial failed. */ + STATUS_DIAL_FAILED, + /* Login failed. */ + STATUS_LOGIN_FAILED, + /* Handshake failed. */ + STATUS_HANDSHAKE_FAILED, + /* Failed after logging in. */ + STATUS_FAILED, + /* Talking to remote system. */ + STATUS_TALKING, + /* Wrong time to call. */ + STATUS_WRONG_TIME, + /* Number of status values. */ + STATUS_VALUES +}; + +/* An array to convert status entries to strings. If more status entries + are added, this array must be extended. */ +extern const char *azStatus[]; + +/* The sstatus structure holds the contents of a system status file. */ +struct sstatus +{ + /* Current status of conversation. */ + enum tstatus_type ttype; + /* Number of failed retries. */ + int cretries; + /* Time of last call in seconds since epoch (determined by + ixsysdep_time). */ + long ilast; + /* Number of seconds until a retry is permitted. */ + int cwait; +}; + +/* How long we have to wait for the next call, given the number of retries + we have already made. This should probably be configurable. */ +#define CRETRY_WAIT(c) ((c) * 10 * 60) + +/* The scmd structure holds a complete UUCP command. */ +struct scmd +{ + /* Command ('S' for send, 'R' for receive, 'X' for execute, 'E' for + simple execution, 'H' for hangup, 'Y' for hangup confirm, 'N' for + hangup deny). */ + char bcmd; + /* At least one compiler needs an explicit padding byte here. */ + char bdummy; + /* Sequence handle for fsysdep_did_work. */ + pointer pseq; + /* File name to transfer from. */ + const char *zfrom; + /* File name to transfer to. */ + const char *zto; + /* User who requested transfer. */ + const char *zuser; + /* Options. */ + const char *zoptions; + /* Temporary file name ('S' and 'E'). */ + const char *ztemp; + /* Mode to give newly created file ('S' and 'E'). */ + unsigned int imode; + /* User to notify on remote system (optional; 'S' and 'E'). */ + const char *znotify; + /* File size (-1 if not supplied) ('S', 'E' and 'R'). */ + long cbytes; + /* Command to execute ('E'). */ + const char *zcmd; + /* Position to restart from ('R'). */ + long ipos; +}; + +#if DEBUG > 1 + +/* We allow independent control over several different types of + debugging output, using a bit string with individual bits dedicated + to particular debugging types. */ + +/* The bit string is stored in iDebug. */ +extern int iDebug; + +/* Debug abnormal events. */ +#define DEBUG_ABNORMAL (01) +/* Debug chat scripts. */ +#define DEBUG_CHAT (02) +/* Debug initial handshake. */ +#define DEBUG_HANDSHAKE (04) +/* Debug UUCP protocol. */ +#define DEBUG_UUCP_PROTO (010) +/* Debug protocols. */ +#define DEBUG_PROTO (020) +/* Debug port actions. */ +#define DEBUG_PORT (040) +/* Debug configuration files. */ +#define DEBUG_CONFIG (0100) +/* Debug spool directory actions. */ +#define DEBUG_SPOOLDIR (0200) +/* Debug executions. */ +#define DEBUG_EXECUTE (0400) +/* Debug incoming data. */ +#define DEBUG_INCOMING (01000) +/* Debug outgoing data. */ +#define DEBUG_OUTGOING (02000) + +/* Maximum possible value for iDebug. */ +#define DEBUG_MAX (03777) + +/* Intializer for array of debug names. The index of the name in the + array is the corresponding bit position in iDebug. We only check + for prefixes, so these names only need to be long enough to + distinguish each name from every other. The last entry must be + NULL. The string "all" is also recognized to turn on all + debugging. */ +#define DEBUG_NAMES \ + { "a", "ch", "h", "u", "pr", "po", "co", "s", "e", "i", "o", NULL } + +/* The prefix to use to turn off all debugging. */ +#define DEBUG_NONE "n" + +/* Check whether a particular type of debugging is being done. */ +#define FDEBUGGING(i) ((iDebug & (i)) != 0) + +/* These macros are used to output debugging information. I use + several different macros depending on the number of arguments + because no macro can take a variable number of arguments and I + don't want to use double parentheses. */ +#define DEBUG_MESSAGE0(i, z) \ + do { if (FDEBUGGING (i)) ulog (LOG_DEBUG, (z)); } while (0) +#define DEBUG_MESSAGE1(i, z, a1) \ + do { if (FDEBUGGING (i)) ulog (LOG_DEBUG, (z), (a1)); } while (0) +#define DEBUG_MESSAGE2(i, z, a1, a2) \ + do { if (FDEBUGGING (i)) ulog (LOG_DEBUG, (z), (a1), (a2)); } while (0) +#define DEBUG_MESSAGE3(i, z, a1, a2, a3) \ + do \ + { \ + if (FDEBUGGING (i)) \ + ulog (LOG_DEBUG, (z), (a1), (a2), (a3)); \ + } \ + while (0) +#define DEBUG_MESSAGE4(i, z, a1, a2, a3, a4) \ + do \ + { \ + if (FDEBUGGING (i)) \ + ulog (LOG_DEBUG, (z), (a1), (a2), (a3), (a4)); \ + } \ + while (0) + +#else /* DEBUG <= 1 */ + +/* If debugging information is not being compiled, provide versions of + the debugging macros which just disappear. */ +#define DEBUG_MESSAGE0(i, z) +#define DEBUG_MESSAGE1(i, z, a1) +#define DEBUG_MESSAGE2(i, z, a1, a2) +#define DEBUG_MESSAGE3(i, z, a1, a2, a3) +#define DEBUG_MESSAGE4(i, z, a1, a2, a3, a4) + +#endif /* DEBUG <= 1 */ + +/* Functions. */ + +/* Given an unknown system name, return information for an unknown + system. If unknown systems are not permitted, this returns FALSE. + Otherwise, it translates the name as necessary for the spool + directory, and fills in *qsys. */ +extern boolean funknown_system P((pointer puuconf, const char *zsystem, + struct uuconf_system *qsys)); + +/* See whether a file belongs in the spool directory. */ +extern boolean fspool_file P((const char *zfile)); + +/* See if the current time matches a time span. If not, return FALSE. + Otherwise, return TRUE and set *pival and *pcretry to the values + from the matching element of the span. */ +extern boolean ftimespan_match P((const struct uuconf_timespan *qspan, + long *pival, int *pcretry)); + +/* Determine the maximum size that may ever be transferred, given a + timesize span. If there are any time gaps larger than 1 hour not + described by the timesize span, this returns -1. Otherwise it + returns the largest size that may be transferred at some time. */ +extern long cmax_size_ever P((const struct uuconf_timespan *qtimesize)); + +/* Send mail about a file transfer. */ +extern boolean fmail_transfer P((boolean fok, const char *zuser, + const char *zmail, const char *zwhy, + const char *zfrom, const char *zfromsys, + const char *zto, const char *ztosys, + const char *zsaved)); + +/* See whether a file is in one of a list of directories. The zpubdir + argument is used to pass the directory names to zsysdep_local_file. + If fcheck is FALSE, this does not check accessibility. Otherwise, + if freadable is TRUE, the user zuser must have read access to the + file and all appropriate directories; if freadable is FALSE zuser + must have write access to the appropriate directories. The zuser + argument may be NULL, in which case all users must have the + appropriate access (this is used for a remote request). */ +extern boolean fin_directory_list P((const char *zfile, + char **pzdirs, + const char *zpubdir, + boolean fcheck, + boolean freadable, + const char *zuser)); + +/* Parse a command string. */ +extern boolean fparse_cmd P((char *zcmd, struct scmd *qcmd)); + +/* Make a log entry. */ +#ifdef __GNUC__ +#define GNUC_VERSION __GNUC__ +#else +#define GNUC_VERSION 0 +#endif + +#if ANSI_C && HAVE_VFPRINTF +extern void ulog P((enum tlog ttype, const char *zfmt, ...)) +#if GNUC_VERSION > 1 + __attribute__ ((format (printf, 2, 3))) +#endif + ; +#else +extern void ulog (); +#endif + +#undef GNUC_VERSION + +/* Report an error returned by one of the uuconf routines. */ +extern void ulog_uuconf P((enum tlog ttype, pointer puuconf, + int iuuconf)); + +/* Set the function to call if a fatal error occurs. */ +extern void ulog_fatal_fn P((void (*pfn) P((void)))); + +/* If ffile is TRUE, send log entries to the log file rather than to + stderr. */ +extern void ulog_to_file P((pointer puuconf, boolean ffile)); + +/* Set the ID number used by the logging functions. */ +extern void ulog_id P((int iid)); + +/* Set the system name used by the logging functions. */ +extern void ulog_system P((const char *zsystem)); + +/* Set the system and user name used by the logging functions. */ +extern void ulog_user P((const char *zuser)); + +/* Set the device name used by the logging functions. */ +extern void ulog_device P((const char *zdevice)); + +/* Close the log file. */ +extern void ulog_close P((void)); + +/* Make an entry in the statistics file. */ +extern void ustats P((boolean fsucceeded, const char *zuser, + const char *zsystem, boolean fsent, + long cbytes, long csecs, long cmicros, + boolean fmaster)); + +/* Close the statistics file. */ +extern void ustats_close P((void)); + +#if DEBUG > 1 +/* A debugging routine to output a buffer. This outputs zhdr, the + buffer length clen, and the contents of the buffer in quotation + marks. */ +extern void udebug_buffer P((const char *zhdr, const char *zbuf, + size_t clen)); + +/* A debugging routine to make a readable version of a character. + This takes a buffer at least 5 bytes long, and returns the length + of the string it put into it (not counting the null byte). */ +extern size_t cdebug_char P((char *z, int ichar)); + +/* Parse a debugging option string. This can either be a number or a + comma separated list of debugging names. This returns a value for + iDebug. */ +extern int idebug_parse P((const char *)); + +#endif /* DEBUG <= 1 */ + +/* Copy one file to another. */ +extern boolean fcopy_file P((const char *zfrom, const char *zto, + boolean fpublic, boolean fmkdirs)); + +/* Copy an open file to another. */ +extern boolean fcopy_open_file P((openfile_t efrom, const char *zto, + boolean fpublic, boolean fmkdirs)); + +/* Translate escape sequences in a buffer, leaving the result in the + same buffer and returning the length. */ +extern size_t cescape P((char *zbuf)); + +/* Get a buffer to hold a string of a given size. The buffer should + be freed with ubuffree. */ +extern char *zbufalc P((size_t csize)); + +/* Call zbufalc to allocate a buffer and copy a string into it. */ +extern char *zbufcpy P((const char *z)); + +/* Free up a buffer returned by zbufalc or zbufcpy. */ +extern void ubuffree P((char *z)); + +/* Allocate memory without fail. */ +extern pointer xmalloc P((size_t)); + +/* Realloc memory without fail. */ +extern pointer xrealloc P((pointer, size_t)); + +/* Free memory (accepts NULL pointers, which some libraries erroneously + do not). */ +extern void xfree P((pointer)); + +/* Global variables. */ + +/* The name of the program being run. This is statically initialized, + although it should perhaps be set from argv[0]. */ +extern char abProgram[]; + +/* When a signal occurs, the signal handlers sets the appropriate + element of the arrays afSignal and afLog_signal to TRUE. The + afSignal array is used to check whether a signal occurred. The + afLog_signal array tells ulog to log the signal; ulog will clear + the element after logging it, which means that if a signal comes in + at just the right moment it will not be logged. It will always be + recorded in afSignal, though. At the moment we handle 5 signals: + SIGHUP, SIGINT, SIGQUIT, SIGTERM and SIGPIPE (the Unix code also + handles SIGALRM). If we want to handle more, the afSignal array + must be extended; I see little point to handling any of the other + ANSI C or POSIX signals, as they are either unlikely to occur + (SIGABRT, SIGUSR1) or nearly impossible to handle cleanly (SIGILL, + SIGSEGV). SIGHUP is only logged if fLog_sighup is TRUE. */ +#define INDEXSIG_SIGHUP (0) +#define INDEXSIG_SIGINT (1) +#define INDEXSIG_SIGQUIT (2) +#define INDEXSIG_SIGTERM (3) +#define INDEXSIG_SIGPIPE (4) +#define INDEXSIG_COUNT (5) + +extern volatile sig_atomic_t afSignal[INDEXSIG_COUNT]; +extern volatile sig_atomic_t afLog_signal[INDEXSIG_COUNT]; +extern boolean fLog_sighup; + +/* The names of the signals to use in error messages, as an + initializer for an array. */ +#define INDEXSIG_NAMES \ + { "hangup", "interrupt", "quit", "termination", "SIGPIPE" } + +/* Check to see whether we've received a signal. It would be nice if + we could use a single variable for this, but we sometimes want to + clear our knowledge of a signal and that would cause race + conditions (clearing a single element of the array is not a race + assuming that we don't care about a particular signal, even if it + occurs after we've examined the array). */ +#define FGOT_SIGNAL() \ + (afSignal[INDEXSIG_SIGHUP] || afSignal[INDEXSIG_SIGINT] \ + || afSignal[INDEXSIG_SIGQUIT] || afSignal[INDEXSIG_SIGTERM] \ + || afSignal[INDEXSIG_SIGPIPE]) + +/* If we get a SIGINT in uucico, we continue the current communication + session but don't start any new ones. This macros checks for any + signal other than SIGINT, which means we should get out + immediately. */ +#define FGOT_QUIT_SIGNAL() \ + (afSignal[INDEXSIG_SIGHUP] || afSignal[INDEXSIG_SIGQUIT] \ + || afSignal[INDEXSIG_SIGTERM] || afSignal[INDEXSIG_SIGPIPE]) + +/* File being sent. */ +extern openfile_t eSendfile; + +/* File being received. */ +extern openfile_t eRecfile; + +/* Device name to log. This is set by fconn_open. It may be NULL. */ +extern char *zLdevice; + +/* If not NULL, ulog calls this function before outputting anything. + This is used to support cu. */ +extern void (*pfLstart) P((void)); + +/* If not NULL, ulog calls this function after outputting everything. + This is used to support cu. */ +extern void (*pfLend) P((void)); |
