Annotation of coherent/g/usr/lib/uucp/tay104/send.c, revision 1.1

1.1     ! root        1: /* send.c
        !             2:    Routines to send a file.
        !             3: 
        !             4:    Copyright (C) 1991, 1992 Ian Lance Taylor
        !             5: 
        !             6:    This file is part of the Taylor UUCP package.
        !             7: 
        !             8:    This program is free software; you can redistribute it and/or
        !             9:    modify it under the terms of the GNU General Public License as
        !            10:    published by the Free Software Foundation; either version 2 of the
        !            11:    License, or (at your option) any later version.
        !            12: 
        !            13:    This program is distributed in the hope that it will be useful, but
        !            14:    WITHOUT ANY WARRANTY; without even the implied warranty of
        !            15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            16:    General Public License for more details.
        !            17: 
        !            18:    You should have received a copy of the GNU General Public License
        !            19:    along with this program; if not, write to the Free Software
        !            20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            21: 
        !            22:    The author of the program may be contacted at [email protected] or
        !            23:    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
        !            24:    */
        !            25: 
        !            26: #include "uucp.h"
        !            27: 
        !            28: #if USE_RCS_ID
        !            29: const char send_rcsid[] = "$Id: send.c,v 1.1 93/07/30 07:54:01 bin Exp Locker: bin $";
        !            30: #endif
        !            31: 
        !            32: #include <errno.h>
        !            33: 
        !            34: #include "uudefs.h"
        !            35: #include "uuconf.h"
        !            36: #include "system.h"
        !            37: #include "prot.h"
        !            38: #include "trans.h"
        !            39: 
        !            40: /* We keep this information in the pinfo field of the stransfer
        !            41:    structure.  */
        !            42: struct ssendinfo
        !            43: {
        !            44:   /* Local user to send mail to (may be NULL).  */
        !            45:   char *zmail;
        !            46:   /* Full file name.  */
        !            47:   char *zfile;
        !            48:   /* Number of bytes in file.  */
        !            49:   long cbytes;
        !            50:   /* TRUE if this was a local request.  */
        !            51:   boolean flocal;
        !            52:   /* TRUE if this is a spool directory file.  */
        !            53:   boolean fspool;
        !            54:   /* TRUE if the file has been completely sent.  */
        !            55:   boolean fsent;
        !            56:   /* Execution file for sending an unsupported E request.  */
        !            57:   char *zexec;
        !            58: };
        !            59: 
        !            60: /* Local functions.  */
        !            61: 
        !            62: static void usfree_send P((struct stransfer *qtrans));
        !            63: static boolean flocal_send_fail P((struct stransfer *qtrans,
        !            64:                                   struct scmd *qcmd,
        !            65:                                   const struct uuconf_system *qsys,
        !            66:                                   const char *zwhy));
        !            67: static boolean flocal_send_request P((struct stransfer *qtrans,
        !            68:                                      struct sdaemon *qdaemon));
        !            69: static boolean flocal_send_await_reply P((struct stransfer *qtrans,
        !            70:                                          struct sdaemon *qdaemon,
        !            71:                                          const char *zdata, size_t cdata));
        !            72: static boolean flocal_send_cancelled P((struct stransfer *qtrans,
        !            73:                                        struct sdaemon *qdaemon));
        !            74: static boolean flocal_send_open_file P((struct stransfer *qtrans,
        !            75:                                        struct sdaemon *qdaemon));
        !            76: static boolean fremote_rec_fail P((struct sdaemon *qdaemon,
        !            77:                                   enum tfailure twhy, int iremote));
        !            78: static boolean fremote_rec_fail_send P((struct stransfer *qtrans,
        !            79:                                        struct sdaemon *qdaemon));
        !            80: static boolean fremote_rec_reply P((struct stransfer *qtrans,
        !            81:                                    struct sdaemon *qdaemon));
        !            82: static boolean fsend_file_end P((struct stransfer *qtrans,
        !            83:                                 struct sdaemon *qdaemon));
        !            84: static boolean fsend_await_confirm P((struct stransfer *qtrans,
        !            85:                                      struct sdaemon *qdaemon,
        !            86:                                      const char *zdata, size_t cdata));
        !            87: static boolean fsend_exec_file_init P((struct stransfer *qtrans,
        !            88:                                       struct sdaemon *qdaemon));
        !            89: static void usadd_exec_line P((char **pz, size_t *pcalc, size_t *pclen,
        !            90:                               int bcmd, const char *z1, const char *z2));
        !            91: static boolean fsend_exec_file P((struct stransfer *qtrans,
        !            92:                                  struct sdaemon *qdaemon));
        !            93: 
        !            94: /* Free up a send stransfer structure.  */
        !            95: 
        !            96: static void
        !            97: usfree_send (qtrans)
        !            98:      struct stransfer *qtrans;
        !            99: {
        !           100:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !           101: 
        !           102:   if (qinfo != NULL)
        !           103:     {
        !           104:       ubuffree (qinfo->zmail);
        !           105:       ubuffree (qinfo->zfile);
        !           106:       ubuffree (qinfo->zexec);
        !           107:       xfree (qtrans->pinfo);
        !           108:     }
        !           109: 
        !           110:   utransfree (qtrans);
        !           111: }      
        !           112: 
        !           113: /* Set up a local request to send a file.  This may be called before
        !           114:    we have even tried to call the remote system.
        !           115: 
        !           116:    If we are using a traditional protocol, which doesn't support
        !           117:    channel numbers and doesn't permit the file to be sent until an
        !           118:    acknowledgement has been received, the sequence of function calls
        !           119:    looks like this:
        !           120: 
        !           121:    flocal_send_file_init --> fqueue_local
        !           122:    flocal_send_request (sends S request) --> fqueue_receive
        !           123:    flocal_send_await_reply (waits for SY) --> fqueue_send
        !           124:    flocal_send_open_file (opens file, calls pffile) --> fqueue_send
        !           125:    send file
        !           126:    fsend_file_end (calls pffile) --> fqueue_receive
        !           127:    fsend_await_confirm (waits for CY)
        !           128: 
        !           129:    If flocal_send_await_reply gets an SN, it deletes the request.  If
        !           130:    the SY reply contains a file position at which to start sending,
        !           131:    flocal_send_await_reply sets qinfo->ipos.
        !           132: 
        !           133:    This gets more complex if the protocol supports channels.  In that
        !           134:    case, we want to start sending the file data immediately, to avoid
        !           135:    the round trip delay between flocal_send_request and
        !           136:    flocal_send_await_reply.  To do this, flocal_send_request calls
        !           137:    fqueue_send rather than fqueue_receive.  The main execution
        !           138:    sequence looks like this:
        !           139: 
        !           140:    flocal_send_file_init --> fqueue_local
        !           141:    flocal_send_request (sends S request) --> fqueue_send
        !           142:    flocal_send_open_file (opens file, calls pffile) --> fqueue_send
        !           143:    send file
        !           144:    fsend_file_end (calls pffile) --> fqueue_receive
        !           145:    sometime: flocal_send_await_reply (waits for SY)
        !           146:    fsend_await_confirm (waits for CY)
        !           147: 
        !           148:    In this case flocal_send_await_reply must be run before
        !           149:    fsend_await_confirm; it may be run anytime after
        !           150:    flocal_send_request.
        !           151: 
        !           152:    If flocal_send_await_reply is called before the entire file has
        !           153:    been sent: if it gets an SN, it calls flocal_send_cancelled to send
        !           154:    an empty data block to inform the remote system that the file
        !           155:    transfer has stopped.  If it gets a file position request, it must
        !           156:    adjust the file position accordingly.
        !           157: 
        !           158:    If flocal_send_await_reply is called after the entire file has been
        !           159:    sent: if it gets an SN, it can simply delete the request.  It can
        !           160:    ignore any file position request.
        !           161: 
        !           162:    If the request is not deleted, flocal_send_await_reply must arrange
        !           163:    for the next string to be passed to fsend_await_confirm.
        !           164:    Presumably fsend_await_confirm will only be called after the entire
        !           165:    file has been sent.
        !           166: 
        !           167:    Just to make things even more complex, these same routines support
        !           168:    sending execution requests, since that is much like sending a file.
        !           169:    For an execution request, the bcmd character will be E rather than
        !           170:    S.  If an execution request is being sent to a system which does
        !           171:    not support them, it must be sent as two S requests instead.  The
        !           172:    second one will be the execution file, but no actual file is
        !           173:    created; instead the zexec and znext fields in the ssendinfo
        !           174:    structure are used.  So if the bcmd character is E, then if the
        !           175:    zexec field is NULL, the data file is being sent, otherwise the
        !           176:    fake execution file is being sent.  */
        !           177: 
        !           178: boolean
        !           179: flocal_send_file_init (qdaemon, qcmd)
        !           180:      struct sdaemon *qdaemon;
        !           181:      struct scmd *qcmd;
        !           182: {
        !           183:   const struct uuconf_system *qsys;
        !           184:   boolean fspool;
        !           185:   char *zfile;
        !           186:   long cbytes;
        !           187:   struct ssendinfo *qinfo;
        !           188:   struct stransfer *qtrans;
        !           189: 
        !           190:   qsys = qdaemon->qsys;
        !           191: 
        !           192:   if (qdaemon->fcaller
        !           193:       ? ! qsys->uuconf_fcall_transfer
        !           194:       : ! qsys->uuconf_fcalled_transfer)
        !           195:     {
        !           196:       /* uux or uucp should have already made sure that the transfer
        !           197:         is possible, but it might have changed since then.  */
        !           198:       if (! qsys->uuconf_fcall_transfer
        !           199:          && ! qsys->uuconf_fcalled_transfer)
        !           200:        return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
        !           201:                                 "not permitted to transfer files");
        !           202: 
        !           203:       /* We can't do the request now, but it may get done later.  */
        !           204:       return TRUE;
        !           205:     }
        !           206: 
        !           207:   /* The 'C' option means that the file has been copied to the spool
        !           208:      directory.  */
        !           209:   if (strchr (qcmd->zoptions, 'C') == NULL
        !           210:       && ! fspool_file (qcmd->zfrom))
        !           211:     {
        !           212:       fspool = FALSE;
        !           213:       if (! fin_directory_list (qcmd->zfrom,
        !           214:                                qsys->uuconf_pzlocal_send,
        !           215:                                qsys->uuconf_zpubdir, TRUE,
        !           216:                                TRUE, qcmd->zuser))
        !           217:        return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
        !           218:                                 "not permitted to send");
        !           219:       zfile = zbufcpy (qcmd->zfrom);
        !           220:     }
        !           221:   else
        !           222:     {
        !           223:       fspool = TRUE;
        !           224:       zfile = zsysdep_spool_file_name (qsys, qcmd->ztemp, qcmd->pseq);
        !           225:       if (zfile == NULL)
        !           226:        return FALSE;
        !           227:     }
        !           228: 
        !           229:   /* Make sure we meet any local size restrictions.  The connection
        !           230:      may not have been opened at this point, so we can't check remote
        !           231:      size restrictions.  */
        !           232:   cbytes = csysdep_size (zfile);
        !           233:   if (cbytes < 0)
        !           234:     {
        !           235:       ubuffree (zfile);
        !           236:       if (cbytes != -1)
        !           237:        return FALSE;
        !           238:       /* A cbytes value of -1 means that the file does not exist.
        !           239:         This can happen legitimately if it has already been sent from
        !           240:         the spool directory.  */
        !           241:       if (! fspool)
        !           242:        return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
        !           243:                                 "does not exist");
        !           244:       (void) fsysdep_did_work (qcmd->pseq);
        !           245:       return TRUE;
        !           246:     }
        !           247: 
        !           248:   if (qdaemon->clocal_size != -1
        !           249:       && qdaemon->clocal_size < cbytes)
        !           250:     {
        !           251:       ubuffree (zfile);
        !           252: 
        !           253:       if (qdaemon->cmax_ever == -2)
        !           254:        {
        !           255:          long c1, c2;
        !           256: 
        !           257:          c1 = cmax_size_ever (qsys->uuconf_qcall_local_size);
        !           258:          c2 = cmax_size_ever (qsys->uuconf_qcalled_local_size);
        !           259:          if (c1 > c2)
        !           260:            qdaemon->cmax_ever = c1;
        !           261:          else
        !           262:            qdaemon->cmax_ever = c2;
        !           263:        }
        !           264:                      
        !           265:       if (qdaemon->cmax_ever != -1
        !           266:          && qdaemon->cmax_ever < qcmd->cbytes)
        !           267:        return flocal_send_fail ((struct stransfer *) NULL, qcmd, qsys,
        !           268:                                 "too large to send");
        !           269: 
        !           270:       return TRUE;
        !           271:     }
        !           272: 
        !           273:   /* We are now prepared to send the command to the remote system.  We
        !           274:      queue up a transfer request to send the command when we are
        !           275:      ready.  */
        !           276:   qinfo = (struct ssendinfo *) xmalloc (sizeof (struct ssendinfo));
        !           277:   if (strchr (qcmd->zoptions, 'm') == NULL)
        !           278:     qinfo->zmail = NULL;
        !           279:   else
        !           280:     qinfo->zmail = zbufcpy (qcmd->zuser);
        !           281:   qinfo->zfile = zfile;
        !           282:   qinfo->cbytes = cbytes;
        !           283:   qinfo->flocal = TRUE;
        !           284:   qinfo->fspool = fspool;
        !           285:   qinfo->fsent = FALSE;
        !           286:   qinfo->zexec = NULL;
        !           287: 
        !           288:   qtrans = qtransalc (qcmd);
        !           289:   qtrans->psendfn = flocal_send_request;
        !           290:   qtrans->pinfo = (pointer) qinfo;
        !           291: 
        !           292:   return fqueue_local (qdaemon, qtrans);
        !           293: }
        !           294: 
        !           295: /* Clean up after a failing local send request.  If zwhy is not NULL,
        !           296:    this reports an error to the log file and to the user.  */
        !           297: 
        !           298: static boolean
        !           299: flocal_send_fail (qtrans, qcmd, qsys, zwhy)
        !           300:      struct stransfer *qtrans;
        !           301:      struct scmd *qcmd;
        !           302:      const struct uuconf_system *qsys;
        !           303:      const char *zwhy;
        !           304: {
        !           305:   if (zwhy != NULL)
        !           306:     {
        !           307:       char *zfree;
        !           308: 
        !           309:       if (qcmd->bcmd != 'E')
        !           310:        zfree = NULL;
        !           311:       else
        !           312:        {
        !           313:          zfree = zbufalc (sizeof "Execution of \"\": "
        !           314:                           + strlen (qcmd->zcmd)
        !           315:                           + strlen (zwhy));
        !           316:          sprintf (zfree, "Execution of \"%s\": %s", qcmd->zcmd, zwhy);
        !           317:          zwhy = zfree;
        !           318:        }
        !           319: 
        !           320:       ulog (LOG_ERROR, "%s: %s", qcmd->zfrom, zwhy);
        !           321:       (void) fmail_transfer (FALSE, qcmd->zuser, (const char *) NULL,
        !           322:                             zwhy, qcmd->zfrom, (const char *) NULL,
        !           323:                             qcmd->zto, qsys->uuconf_zname,
        !           324:                             zsysdep_save_temp_file (qcmd->pseq));
        !           325: 
        !           326:       ubuffree (zfree);
        !           327:     }
        !           328: 
        !           329:   (void) fsysdep_did_work (qcmd->pseq);
        !           330: 
        !           331:   if (qtrans != NULL)
        !           332:     usfree_send (qtrans);
        !           333: 
        !           334:   return TRUE;
        !           335: }
        !           336: 
        !           337: /* This is called when we are ready to send the request to the remote
        !           338:    system.  We form the request and send it over.  If the protocol
        !           339:    does not support multiple channels, we start waiting for the
        !           340:    response; otherwise we can start sending the file immediately.  */
        !           341: 
        !           342: static boolean
        !           343: flocal_send_request (qtrans, qdaemon)
        !           344:      struct stransfer *qtrans;
        !           345:      struct sdaemon *qdaemon;
        !           346: {
        !           347:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !           348:   char *zsend;
        !           349:   const char *znotify;
        !           350:   char absize[20];
        !           351:   boolean fret;
        !           352: 
        !           353:   /* Make sure the file meets any remote size restrictions.  */
        !           354:   if (qdaemon->cmax_receive != -1
        !           355:       && qdaemon->cmax_receive < qinfo->cbytes)
        !           356:     return flocal_send_fail (qtrans, &qtrans->s, qdaemon->qsys,
        !           357:                             "too large for receiver");
        !           358: 
        !           359:   /* Construct the notify string to send.  If we are going to send a
        !           360:      size or an execution command, it must be non-empty.  */
        !           361:   znotify = qtrans->s.znotify;
        !           362:   if (znotify == NULL)
        !           363:     znotify = "";
        !           364:   if ((qdaemon->ifeatures & FEATURE_SIZES) != 0
        !           365:       || (qtrans->s.bcmd == 'E'
        !           366:          && (qdaemon->ifeatures & FEATURE_EXEC) != 0))
        !           367:     {
        !           368:       if (*znotify == '\0')
        !           369:        znotify = "\"\"";
        !           370:     }
        !           371:   else
        !           372:     {
        !           373:       /* We don't need a notify string.  Some crufty UUCP code can't
        !           374:         handle a pair of double quotes.  */
        !           375:       if (strcmp (znotify, "\"\"") == 0)
        !           376:        znotify = "";
        !           377:     }
        !           378: 
        !           379:   /* Construct the size string to send.  */
        !           380:   if ((qdaemon->ifeatures & FEATURE_SIZES) == 0
        !           381:       && (qtrans->s.bcmd != 'E'
        !           382:          || (qdaemon->ifeatures & FEATURE_EXEC) == 0))
        !           383:     absize[0] = '\0';
        !           384:   else if ((qdaemon->ifeatures & FEATURE_V103) == 0)
        !           385:     sprintf (absize, "0x%lx", (unsigned long) qinfo->cbytes);
        !           386:   else
        !           387:     sprintf (absize, "%ld", qinfo->cbytes);
        !           388: 
        !           389:   zsend = zbufalc (strlen (qtrans->s.zfrom) + strlen (qtrans->s.zto)
        !           390:                   + strlen (qtrans->s.zuser) + strlen (qtrans->s.zoptions)
        !           391:                   + strlen (qtrans->s.ztemp) + strlen (znotify)
        !           392:                   + strlen (absize)
        !           393:                   + (qtrans->s.zcmd != NULL ? strlen (qtrans->s.zcmd) : 0)
        !           394:                   + 50);
        !           395: 
        !           396:   /* If this an execution request and the other side supports
        !           397:      execution requests, we send an E command.  Otherwise we send an S
        !           398:      command.  The case of an execution request when we are sending
        !           399:      the fake execution file is handled just like an S request at this
        !           400:      point.  */
        !           401:   if (qtrans->s.bcmd == 'E'
        !           402:       && (qdaemon->ifeatures & FEATURE_EXEC) != 0)
        !           403:     {
        !           404:       /* Send the string
        !           405:         E zfrom zto zuser zoptions ztemp imode znotify size zcmd
        !           406:         to the remote system.  We put a '-' in front of the (possibly
        !           407:         empty) options and a '0' in front of the mode.  */
        !           408:       sprintf (zsend, "E %s %s %s -%s %s 0%o %s %s %s", qtrans->s.zfrom,
        !           409:               qtrans->s.zto, qtrans->s.zuser, qtrans->s.zoptions,
        !           410:               qtrans->s.ztemp, qtrans->s.imode, znotify, absize,
        !           411:               qtrans->s.zcmd);
        !           412:     }
        !           413:   else
        !           414:     {
        !           415:       const char *zoptions, *zdummy;
        !           416: 
        !           417:       /* Send the string
        !           418:         S zfrom zto zuser zoptions ztemp imode znotify
        !           419:         to the remote system.  We put a '-' in front of the (possibly
        !           420:         empty) options and a '0' in front of the mode.  If size
        !           421:         negotiation is supported, we also send the size; in this case
        !           422:         if znotify is empty we must send it as "".  If this is really
        !           423:         an execution request, we have to simplify the options string
        !           424:         to remove the various execution options which may confuse the
        !           425:         remote system.  SVR4 expects a string "dummy" between the
        !           426:         notify string and the size; I don't know why.  */
        !           427:       if (qtrans->s.bcmd != 'E')
        !           428:        zoptions = qtrans->s.zoptions;
        !           429:       else if (strchr (qtrans->s.zoptions, 'C') != NULL)
        !           430:        {
        !           431:          /* This should set zoptions to "C", but at least one UUCP
        !           432:             program gets confused by it.  That means that it will
        !           433:             fail in certain cases, but I suppose we might as well
        !           434:             kowtow to compatibility.  This shouldn't matter to any
        !           435:             other program, I hope.  */
        !           436:          zoptions = "";
        !           437:        }
        !           438:       else
        !           439:        zoptions = "c";
        !           440: 
        !           441:       if ((qdaemon->ifeatures & FEATURE_SVR4) != 0)
        !           442:        zdummy = " dummy ";
        !           443:       else
        !           444:        zdummy = " ";
        !           445: 
        !           446:       sprintf (zsend, "S %s %s %s -%s %s 0%o %s%s%s", qtrans->s.zfrom,
        !           447:               qtrans->s.zto, qtrans->s.zuser, zoptions,
        !           448:               qtrans->s.ztemp, qtrans->s.imode, znotify, zdummy,
        !           449:               absize);
        !           450:     }
        !           451: 
        !           452:   fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, zsend, qtrans->ilocal,
        !           453:                                        qtrans->iremote);
        !           454:   ubuffree (zsend);
        !           455:   if (! fret)
        !           456:     {
        !           457:       usfree_send (qtrans);
        !           458:       return FALSE;
        !           459:     }
        !           460: 
        !           461:   /* If we are using a protocol which can make multiple channels, then
        !           462:      we can open and send the file whenever we are ready.  This is
        !           463:      because we will be able to distinguish the response by the
        !           464:      channel it is directed to.  This assumes that every protocol
        !           465:      which supports multiple channels also supports sending the file
        !           466:      position in mid-stream, since otherwise we would not be able to
        !           467:      restart files.  */
        !           468:   qtrans->fcmd = TRUE;
        !           469:   qtrans->psendfn = flocal_send_open_file;
        !           470:   qtrans->precfn = flocal_send_await_reply;
        !           471: 
        !           472:   if (qdaemon->qproto->cchans > 1)
        !           473:     return fqueue_send (qdaemon, qtrans);
        !           474:   else
        !           475:     return fqueue_receive (qdaemon, qtrans);
        !           476: }
        !           477: 
        !           478: /* This is called when a reply is received for the send request.  As
        !           479:    described at length above, if the protocol supports multiple
        !           480:    channels we may be in the middle of sending the file, or we may
        !           481:    even finished sending the file.  */
        !           482: 
        !           483: static boolean
        !           484: flocal_send_await_reply (qtrans, qdaemon, zdata, cdata)
        !           485:      struct stransfer *qtrans;
        !           486:      struct sdaemon *qdaemon;
        !           487:      const char *zdata;
        !           488:      size_t cdata;
        !           489: {
        !           490:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !           491:   char bcmd;
        !           492: 
        !           493:   if (qtrans->s.bcmd == 'E'
        !           494:       && (qdaemon->ifeatures & FEATURE_EXEC) != 0)
        !           495:     bcmd = 'E';
        !           496:   else
        !           497:     bcmd = 'S';
        !           498:   if (zdata[0] != bcmd
        !           499:       || (zdata[1] != 'Y' && zdata[1] != 'N'))
        !           500:     {
        !           501:       ulog (LOG_ERROR, "%s: Bad response to %c request: \"%s\"",
        !           502:            qtrans->s.zfrom, bcmd, zdata);
        !           503:       usfree_send (qtrans);
        !           504:       return FALSE;
        !           505:     }
        !           506: 
        !           507:   if (zdata[1] == 'N')
        !           508:     {
        !           509:       const char *zerr;
        !           510:       boolean fnever;
        !           511: 
        !           512:       fnever = TRUE;
        !           513:       if (zdata[2] == '2')
        !           514:        zerr = "permission denied by remote";
        !           515:       else if (zdata[2] == '4')
        !           516:        {
        !           517:          zerr = "remote cannot create work files";
        !           518:          fnever = FALSE;
        !           519:        }
        !           520:       else if (zdata[2] == '6')
        !           521:        {
        !           522:          zerr = "too large for remote now";
        !           523:          fnever = FALSE;
        !           524:        }
        !           525:       else if (zdata[2] == '7')
        !           526:        {
        !           527:          /* The file is too large to ever send.  */
        !           528:          zerr = "too large for remote";
        !           529:        }
        !           530:       else if (zdata[2] == '8')
        !           531:        {
        !           532:          /* The file was already received by the remote system.  This
        !           533:             is not an error, it just means that the ack from the
        !           534:             remote was lost in the previous conversation, and there
        !           535:             is no need to resend the file.  */
        !           536:          zerr = NULL;
        !           537:        }
        !           538:       else
        !           539:        zerr = "unknown reason";
        !           540: 
        !           541:       if (! fnever)
        !           542:        {
        !           543:          if (qtrans->s.bcmd == 'E')
        !           544:            ulog (LOG_ERROR, "Execution of \"%s\": %s", qtrans->s.zcmd,
        !           545:                  zerr);
        !           546:          else
        !           547:            ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
        !           548:        }
        !           549:       else
        !           550:        {
        !           551:          if (! flocal_send_fail ((struct stransfer *) NULL, &qtrans->s,
        !           552:                                  qdaemon->qsys, zerr))
        !           553:            return FALSE;
        !           554:        }
        !           555: 
        !           556:       /* If the protocol does not support multiple channels, we can
        !           557:         simply remove the transaction.  Otherwise we must make sure
        !           558:         the remote side knows that we have finished sending the file
        !           559:         data.  If we have already sent the entire file, there will be
        !           560:         no confusion.  */
        !           561:       if (qdaemon->qproto->cchans == 1 || qinfo->fsent)
        !           562:        {
        !           563:          usfree_send (qtrans);
        !           564:          return TRUE;
        !           565:        }
        !           566:       else
        !           567:        {
        !           568:          qtrans->psendfn = flocal_send_cancelled;
        !           569:          qtrans->precfn = NULL;
        !           570:          qtrans->fsendfile = FALSE;
        !           571:          return fqueue_send (qdaemon, qtrans);
        !           572:        }
        !           573:     }
        !           574: 
        !           575:   /* A number following the SY or EY is the file position to start
        !           576:      sending from.  If we are already sending the file, we must set
        !           577:      the position accordingly.  */
        !           578:   if (zdata[2] != '\0')
        !           579:     {
        !           580:       long cskip;
        !           581: 
        !           582:       cskip = strtol ((char *) (zdata + 2), (char **) NULL, 0);
        !           583:       if (cskip > 0 && qtrans->ipos < cskip)
        !           584:        {
        !           585:          if (qtrans->fsendfile && ! qinfo->fsent)
        !           586:            {
        !           587:              if (! ffileseek (qtrans->e, cskip))
        !           588:                {
        !           589:                  ulog (LOG_ERROR, "seek: %s", strerror (errno));
        !           590:                  usfree_send (qtrans);
        !           591:                  return FALSE;
        !           592:                }
        !           593:            }
        !           594:          qtrans->ipos = cskip;
        !           595:        }
        !           596:     }
        !           597: 
        !           598:   /* Now queue up to send the file or to wait for the confirmation.
        !           599:      We already set psendfn at the end of flocal_send_request.  If the
        !           600:      protocol supports multiple channels, we have already called
        !           601:      fqueue_send; calling it again would move the request in the
        !           602:      queue, which would make the log file a bit confusing.  */
        !           603:   qtrans->precfn = fsend_await_confirm;
        !           604:   if (qinfo->fsent)
        !           605:     return fqueue_receive (qdaemon, qtrans);
        !           606:   else if (qdaemon->qproto->cchans <= 1)
        !           607:     return fqueue_send (qdaemon, qtrans);
        !           608:   else
        !           609:     return TRUE;
        !           610: }
        !           611: 
        !           612: /* Open the file, if any, and prepare to send it.  */
        !           613: 
        !           614: static boolean
        !           615: flocal_send_open_file (qtrans, qdaemon)
        !           616:      struct stransfer *qtrans;
        !           617:      struct sdaemon *qdaemon;
        !           618: {
        !           619:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !           620:   const char *zuser;
        !           621: 
        !           622:   /* If this is not a fake execution file, open it.  */
        !           623:   if (qinfo->zexec == NULL)
        !           624:     {
        !           625:       /* If there is an ! in the user name, this is a remote request
        !           626:         queued up by fremote_xcmd_init.  */
        !           627:       zuser = qtrans->s.zuser;
        !           628:       if (strchr (zuser, '!') != NULL)
        !           629:        zuser = NULL;
        !           630: 
        !           631:       qtrans->e = esysdep_open_send (qdaemon->qsys, qinfo->zfile,
        !           632:                                     ! qinfo->fspool, zuser);
        !           633:       if (! ffileisopen (qtrans->e))
        !           634:        {
        !           635:          (void) fmail_transfer (FALSE, qtrans->s.zuser,
        !           636:                                 (const char *) NULL,
        !           637:                                 "cannot open file",
        !           638:                                 qtrans->s.zfrom, (const char *) NULL,
        !           639:                                 qtrans->s.zto,
        !           640:                                 qdaemon->qsys->uuconf_zname,
        !           641:                                 zsysdep_save_temp_file (qtrans->s.pseq));
        !           642:          (void) fsysdep_did_work (qtrans->s.pseq);
        !           643:          usfree_send (qtrans);
        !           644: 
        !           645:          /* Unfortunately, there is no way to cancel a file send
        !           646:             after we've already put it in progress.  So we have to
        !           647:             return FALSE to drop the connection.  */
        !           648:          return FALSE;
        !           649:        }
        !           650:     }
        !           651: 
        !           652:   /* If flocal_send_await_reply has received a reply with a file
        !           653:      position, it will have set qtrans->ipos to the position at which
        !           654:      to start.  */
        !           655:   if (qtrans->ipos > 0)
        !           656:     {
        !           657:       if (qinfo->zexec != NULL)
        !           658:        {
        !           659:          if (qtrans->ipos > qtrans->cbytes)
        !           660:            qtrans->ipos = qtrans->cbytes;
        !           661:        }
        !           662:       else
        !           663:        {
        !           664:          if (! ffileseek (qtrans->e, qtrans->ipos))
        !           665:            {
        !           666:              ulog (LOG_ERROR, "seek: %s", strerror (errno));
        !           667:              usfree_send (qtrans);
        !           668:              return FALSE;
        !           669:            }
        !           670:        }
        !           671:     }
        !           672: 
        !           673:   /* We don't bother to log sending the execution file.  */
        !           674:   if (qinfo->zexec == NULL)
        !           675:     {
        !           676:       const char *zsend;
        !           677:       char *zalc;
        !           678: 
        !           679:       if (qtrans->s.bcmd != 'E')
        !           680:        {
        !           681:          zsend = qtrans->s.zfrom;
        !           682:          zalc = NULL;
        !           683:        }
        !           684:       else
        !           685:        {
        !           686:          zalc = zbufalc (strlen (qtrans->s.zcmd) + sizeof " ()"
        !           687:                          + strlen (qtrans->s.zfrom));
        !           688:          sprintf (zalc, "%s (%s)", qtrans->s.zcmd, qtrans->s.zfrom);
        !           689:          zsend = zalc;
        !           690:        }
        !           691:       qtrans->zlog = zbufalc (sizeof "Sending " + strlen (zsend));
        !           692:       sprintf (qtrans->zlog, "Sending %s", zsend);
        !           693:       ubuffree (zalc);
        !           694:     }
        !           695: 
        !           696:   if (qdaemon->qproto->pffile != NULL)
        !           697:     {
        !           698:       boolean fhandled;
        !           699: 
        !           700:       if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, TRUE,
        !           701:                                        qinfo->cbytes, &fhandled))
        !           702:        {
        !           703:          usfree_send (qtrans);
        !           704:          return FALSE;
        !           705:        }
        !           706: 
        !           707:       if (fhandled)
        !           708:        return TRUE;
        !           709:     }
        !           710: 
        !           711:   if (qinfo->zexec != NULL)
        !           712:     qtrans->psendfn = fsend_exec_file;
        !           713:   else
        !           714:     {
        !           715:       qtrans->fsendfile = TRUE;
        !           716:       qtrans->psendfn = fsend_file_end;
        !           717:     }
        !           718: 
        !           719:   return fqueue_send (qdaemon, qtrans);
        !           720: }
        !           721: 
        !           722: /* Cancel a file send by sending an empty buffer.  This is only called
        !           723:    for a protocol which supports multiple channels.  It is needed
        !           724:    so that both systems agree as to when a channel is no longer
        !           725:    needed.  */
        !           726: 
        !           727: static boolean
        !           728: flocal_send_cancelled (qtrans, qdaemon)
        !           729:      struct stransfer *qtrans;
        !           730:      struct sdaemon *qdaemon;
        !           731: {
        !           732:   char *zdata;
        !           733:   size_t cdata;
        !           734:   boolean fret;
        !           735:   
        !           736:   zdata = (*qdaemon->qproto->pzgetspace) (qdaemon, &cdata);
        !           737:   if (zdata == NULL)
        !           738:     {
        !           739:       usfree_send (qtrans);
        !           740:       return FALSE;
        !           741:     }
        !           742: 
        !           743:   fret = (*qdaemon->qproto->pfsenddata) (qdaemon, zdata, (size_t) 0,
        !           744:                                         qtrans->ilocal, qtrans->iremote,
        !           745:                                         qtrans->ipos);
        !           746:   usfree_send (qtrans);
        !           747:   return fret;
        !           748: }
        !           749: 
        !           750: /* A remote request to receive a file (meaning that we have to send a
        !           751:    file).  The sequence of functions calls is as follows:
        !           752: 
        !           753:    fremote_rec_file_init (open file) --> fqueue_remote
        !           754:    fremote_rec_reply (send RY, call pffile) --> fqueue_send
        !           755:    send file
        !           756:    fsend_file_end (calls pffile) --> fqueue_receive
        !           757:    fsend_await_confirm (waits for CY)
        !           758:    */
        !           759: 
        !           760: boolean
        !           761: fremote_rec_file_init (qdaemon, qcmd, iremote)
        !           762:      struct sdaemon *qdaemon;
        !           763:      struct scmd *qcmd;
        !           764:      int iremote;
        !           765: {
        !           766:   const struct uuconf_system *qsys;
        !           767:   char *zfile;
        !           768:   long cbytes;
        !           769:   unsigned int imode;
        !           770:   openfile_t e;
        !           771:   struct ssendinfo *qinfo;
        !           772:   struct stransfer *qtrans;
        !           773: 
        !           774:   qsys = qdaemon->qsys;
        !           775: 
        !           776:   if (! qsys->uuconf_fsend_request)
        !           777:     {
        !           778:       ulog (LOG_ERROR, "%s: not permitted to send files to remote",
        !           779:            qcmd->zfrom);
        !           780:       return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
        !           781:     }
        !           782: 
        !           783:   if (fspool_file (qcmd->zfrom))
        !           784:     {
        !           785:       ulog (LOG_ERROR, "%s: not permitted to send", qcmd->zfrom);
        !           786:       return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
        !           787:     }
        !           788: 
        !           789:   zfile = zsysdep_local_file (qcmd->zfrom, qsys->uuconf_zpubdir);
        !           790:   if (zfile != NULL)
        !           791:     {
        !           792:       char *zbased;
        !           793: 
        !           794:       zbased = zsysdep_add_base (zfile, qcmd->zto);
        !           795:       ubuffree (zfile);
        !           796:       zfile = zbased;
        !           797:     }
        !           798:   if (zfile == NULL)
        !           799:     return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
        !           800: 
        !           801:   if (! fin_directory_list (zfile, qsys->uuconf_pzremote_send,
        !           802:                            qsys->uuconf_zpubdir, TRUE, TRUE,
        !           803:                            (const char *) NULL))
        !           804:     {
        !           805:       ulog (LOG_ERROR, "%s: not permitted to send", zfile);
        !           806:       ubuffree (zfile);
        !           807:       return fremote_rec_fail (qdaemon, FAILURE_PERM, iremote);
        !           808:     }
        !           809: 
        !           810:   /* If the file is larger than the amount of space the other side
        !           811:      reported, we can't send it.  Should we adjust this check based on
        !           812:      the restart position?  */
        !           813:   cbytes = csysdep_size (zfile);
        !           814:   if (cbytes != -1
        !           815:       && ((qcmd->cbytes != -1 && qcmd->cbytes < cbytes)
        !           816:          || (qdaemon->cremote_size != -1
        !           817:              && qdaemon->cremote_size < cbytes)
        !           818:          || (qdaemon->cmax_receive != -1
        !           819:              && qdaemon->cmax_receive < cbytes)))
        !           820:     {
        !           821:       ulog (LOG_ERROR, "%s: too large to send", zfile);
        !           822:       ubuffree (zfile);
        !           823:       return fremote_rec_fail (qdaemon, FAILURE_SIZE, iremote);
        !           824:     }
        !           825: 
        !           826:   imode = ixsysdep_file_mode (zfile);
        !           827: 
        !           828:   e = esysdep_open_send (qsys, zfile, TRUE, (const char *) NULL);
        !           829:   if (! ffileisopen (e))
        !           830:     {
        !           831:       ubuffree (zfile);
        !           832:       return fremote_rec_fail (qdaemon, FAILURE_OPEN, iremote);
        !           833:     }
        !           834: 
        !           835:   /* If the remote requested that the file send start from a
        !           836:      particular position, arrange to do so.  */
        !           837:   if (qcmd->ipos > 0)
        !           838:     {
        !           839:       if (! ffileseek (e, qcmd->ipos))
        !           840:        {
        !           841:          ulog (LOG_ERROR, "seek: %s", strerror (errno));
        !           842:          ubuffree (zfile);
        !           843:          return FALSE;
        !           844:        }
        !           845:     }
        !           846: 
        !           847:   qinfo = (struct ssendinfo *) xmalloc (sizeof (struct ssendinfo));
        !           848:   qinfo->zmail = NULL;
        !           849:   qinfo->zfile = zfile;
        !           850:   qinfo->cbytes = cbytes;
        !           851:   qinfo->flocal = FALSE;
        !           852:   qinfo->fspool = FALSE;
        !           853:   qinfo->fsent = FALSE;
        !           854:   qinfo->zexec = NULL;
        !           855: 
        !           856:   qtrans = qtransalc (qcmd);
        !           857:   qtrans->psendfn = fremote_rec_reply;
        !           858:   qtrans->iremote = iremote;
        !           859:   qtrans->pinfo = (pointer) qinfo;
        !           860:   qtrans->e = e;
        !           861:   qtrans->ipos = qcmd->ipos;
        !           862:   qtrans->s.imode = imode;
        !           863: 
        !           864:   return fqueue_remote (qdaemon, qtrans);
        !           865: }
        !           866: 
        !           867: /* Reply to a receive request from the remote system, and prepare to
        !           868:    start sending the file.  */
        !           869: 
        !           870: static boolean
        !           871: fremote_rec_reply (qtrans, qdaemon)
        !           872:      struct stransfer *qtrans;
        !           873:      struct sdaemon *qdaemon;
        !           874: {
        !           875:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !           876:   char absend[50];
        !           877: 
        !           878:   sprintf (absend, "RY 0%o 0x%lx", qtrans->s.imode,
        !           879:           (unsigned long) qinfo->cbytes);
        !           880:   if (! (*qdaemon->qproto->pfsendcmd) (qdaemon, absend, qtrans->ilocal,
        !           881:                                       qtrans->iremote))
        !           882:     {
        !           883:       (void) ffileclose (qtrans->e);
        !           884:       usfree_send (qtrans);
        !           885:       return FALSE;
        !           886:     }
        !           887: 
        !           888:   qtrans->zlog = zbufalc (sizeof "Sending " + strlen (qtrans->s.zfrom));
        !           889:   sprintf (qtrans->zlog, "Sending %s", qtrans->s.zfrom);
        !           890: 
        !           891:   if (qdaemon->qproto->pffile != NULL)
        !           892:     {
        !           893:       boolean fhandled;
        !           894: 
        !           895:       if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, TRUE, TRUE,
        !           896:                                        qinfo->cbytes, &fhandled))
        !           897:        {
        !           898:          usfree_send (qtrans);
        !           899:          return FALSE;
        !           900:        }
        !           901: 
        !           902:       if (fhandled)
        !           903:        return TRUE;
        !           904:     }
        !           905: 
        !           906:   qtrans->fsendfile = TRUE;
        !           907:   qtrans->psendfn = fsend_file_end;
        !           908:   qtrans->precfn = fsend_await_confirm;
        !           909: 
        !           910:   return fqueue_send (qdaemon, qtrans);
        !           911: }
        !           912: 
        !           913: /* If we can't send a file as requested by the remote system, queue up
        !           914:    a failure reply which will be sent when possible.  */
        !           915: 
        !           916: static boolean
        !           917: fremote_rec_fail (qdaemon, twhy, iremote)
        !           918:      struct sdaemon *qdaemon;
        !           919:      enum tfailure twhy;
        !           920:      int iremote;
        !           921: {
        !           922:   enum tfailure *ptinfo;
        !           923:   struct stransfer *qtrans;
        !           924: 
        !           925:   ptinfo = (enum tfailure *) xmalloc (sizeof (enum tfailure));
        !           926:   *ptinfo = twhy;
        !           927: 
        !           928:   qtrans = qtransalc ((struct scmd *) NULL);
        !           929:   qtrans->psendfn = fremote_rec_fail_send;
        !           930:   qtrans->iremote = iremote;
        !           931:   qtrans->pinfo = (pointer) ptinfo;
        !           932: 
        !           933:   return fqueue_remote (qdaemon, qtrans);
        !           934: }
        !           935: 
        !           936: /* Send a failure string for a receive command to the remote system;
        !           937:    this is called when we are ready to reply to the command.  */
        !           938: 
        !           939: static boolean
        !           940: fremote_rec_fail_send (qtrans, qdaemon)
        !           941:      struct stransfer *qtrans;
        !           942:      struct sdaemon *qdaemon;
        !           943: {
        !           944:   enum tfailure *ptinfo = (enum tfailure *) qtrans->pinfo;
        !           945:   const char *z;
        !           946:   boolean fret;
        !           947: 
        !           948:   switch (*ptinfo)
        !           949:     {
        !           950:     case FAILURE_PERM:
        !           951:     case FAILURE_OPEN:
        !           952:       z = "RN2";
        !           953:       break;
        !           954:     case FAILURE_SIZE:
        !           955:       z = "RN6";
        !           956:       break;
        !           957:     default:
        !           958:       z = "RN";
        !           959:       break;
        !           960:     }
        !           961:   
        !           962:   fret = (*qdaemon->qproto->pfsendcmd) (qdaemon, z, qtrans->ilocal,
        !           963:                                        qtrans->iremote);
        !           964:   xfree (qtrans->pinfo);
        !           965:   utransfree (qtrans);
        !           966:   return fret;
        !           967: }
        !           968: 
        !           969: /* This is called when the main loop has finished sending a file.  It
        !           970:    prepares to wait for a response from the remote system.  Note that
        !           971:    if this is a local request and the protocol supports multiple
        !           972:    channels, we may not even have received a confirmation of the send
        !           973:    request.  */
        !           974: 
        !           975: static boolean
        !           976: fsend_file_end (qtrans, qdaemon)
        !           977:      struct stransfer *qtrans;
        !           978:      struct sdaemon *qdaemon;
        !           979: {
        !           980:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !           981: 
        !           982:   if (qdaemon->qproto->pffile != NULL)
        !           983:     {
        !           984:       boolean fhandled;
        !           985: 
        !           986:       if (! (*qdaemon->qproto->pffile) (qdaemon, qtrans, FALSE, TRUE,
        !           987:                                        (long) -1, &fhandled))
        !           988:        {
        !           989:          usfree_send (qtrans);
        !           990:          return FALSE;
        !           991:        }
        !           992: 
        !           993:       if (fhandled)
        !           994:        return TRUE;
        !           995:     }
        !           996: 
        !           997:   qinfo->fsent = TRUE;
        !           998: 
        !           999:   /* qtrans->precfn should have been set by a previous function.  */
        !          1000:   qtrans->fcmd = TRUE;
        !          1001:   return fqueue_receive (qdaemon, qtrans);
        !          1002: }
        !          1003: 
        !          1004: /* Handle the confirmation string received after sending a file.  */
        !          1005: 
        !          1006: /*ARGSUSED*/
        !          1007: static boolean
        !          1008: fsend_await_confirm (qtrans, qdaemon, zdata, cdata)
        !          1009:      struct stransfer *qtrans;
        !          1010:      struct sdaemon *qdaemon;
        !          1011:      const char *zdata;
        !          1012:      size_t cdata;
        !          1013: {
        !          1014:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !          1015:   boolean fnever;
        !          1016:   const char *zerr;
        !          1017: 
        !          1018:   if (qinfo->zexec == NULL)
        !          1019:     (void) ffileclose (qtrans->e);
        !          1020: 
        !          1021:   fnever = FALSE;
        !          1022:   if (zdata[0] != 'C'
        !          1023:       || (zdata[1] != 'Y' && zdata[1] != 'N'))
        !          1024:     {
        !          1025:       zerr = "bad confirmation from remote";
        !          1026:       ulog (LOG_ERROR, "%s: %s \"%s\"", qtrans->s.zfrom, zerr, zdata);
        !          1027:     }
        !          1028:   else if (zdata[1] == 'N')
        !          1029:     {
        !          1030:       fnever = TRUE;
        !          1031:       if (zdata[2] == '5')
        !          1032:        {
        !          1033:          zerr = "file could not be stored in final location";
        !          1034:          ulog (LOG_ERROR, "%s: %s", qtrans->s.zfrom, zerr);
        !          1035:        }
        !          1036:       else
        !          1037:        {
        !          1038:          zerr = "file send failed for unknown reason";
        !          1039:          ulog (LOG_ERROR, "%s: %s \"%s\"", qtrans->s.zfrom, zerr, zdata);
        !          1040:        }
        !          1041:     }
        !          1042:   else
        !          1043:     {
        !          1044:       zerr = NULL;
        !          1045: 
        !          1046:       /* If we receive CYM, it means that the other side wants us to
        !          1047:         hang up so that they can send us something.  The
        !          1048:         fhangup_requested field is checked in the main loop.  */
        !          1049:       if (zdata[2] == 'M' && qdaemon->fmaster)
        !          1050:        {
        !          1051:          DEBUG_MESSAGE0 (DEBUG_UUCP_PROTO,
        !          1052:                          "fsend_await_confirm: Remote has requested transfer of control");
        !          1053:          qdaemon->fhangup_requested = TRUE;
        !          1054:        }
        !          1055:     }
        !          1056: 
        !          1057:   ustats (zerr == NULL, qtrans->s.zuser, qdaemon->qsys->uuconf_zname,
        !          1058:          TRUE, qtrans->cbytes, qtrans->isecs, qtrans->imicros,
        !          1059:          qdaemon->fmaster);
        !          1060: 
        !          1061:   if (zerr == NULL)
        !          1062:     {
        !          1063:       /* If this is an execution request, and the remote system
        !          1064:         doesn't support execution requests, we have to set up the
        !          1065:         fake execution file and loop around again.  */
        !          1066:       if (qtrans->s.bcmd == 'E'
        !          1067:          && (qdaemon->ifeatures & FEATURE_EXEC) == 0
        !          1068:          && qinfo->zexec == NULL)
        !          1069:        return fsend_exec_file_init (qtrans, qdaemon);
        !          1070: 
        !          1071:       /* Send mail about the transfer if requested.  */
        !          1072:       if (qinfo->zmail != NULL && *qinfo->zmail != '\0')
        !          1073:        (void) fmail_transfer (TRUE, qtrans->s.zuser, qinfo->zmail,
        !          1074:                               (const char *) NULL,
        !          1075:                               qtrans->s.zfrom, (const char *) NULL,
        !          1076:                               qtrans->s.zto, qdaemon->qsys->uuconf_zname,
        !          1077:                               (const char *) NULL);
        !          1078: 
        !          1079:       if (qtrans->s.pseq != NULL)
        !          1080:        (void) fsysdep_did_work (qtrans->s.pseq);
        !          1081:     }
        !          1082:   else
        !          1083:     {
        !          1084:       /* If the file send failed, we only try to save the file and
        !          1085:         send mail if it was requested locally and it will never
        !          1086:         succeed.  We send mail to qinfo->zmail if set, otherwise to
        !          1087:         qtrans->s.zuser.  I hope this is reasonable.  */
        !          1088:       if (fnever && qinfo->flocal)
        !          1089:        {
        !          1090:          (void) fmail_transfer (FALSE, qtrans->s.zuser, qinfo->zmail,
        !          1091:                                 zerr, qtrans->s.zfrom, (const char *) NULL,
        !          1092:                                 qtrans->s.zto, qdaemon->qsys->uuconf_zname,
        !          1093:                                 zsysdep_save_temp_file (qtrans->s.pseq));
        !          1094:          (void) fsysdep_did_work (qtrans->s.pseq);
        !          1095:        }
        !          1096:     }
        !          1097: 
        !          1098:   usfree_send (qtrans);
        !          1099: 
        !          1100:   return TRUE;
        !          1101: }
        !          1102: 
        !          1103: /* Prepare to send an execution file to a system which does not
        !          1104:    support execution requests.  We build the execution file in memory,
        !          1105:    and then call flocal_send_request as though we were sending a real
        !          1106:    file.  Instead of sending a file, the code in flocal_send_open_file
        !          1107:    will arrange to call fsend_exec_file which will send data out of
        !          1108:    the buffer we have created.  */
        !          1109: 
        !          1110: static boolean
        !          1111: fsend_exec_file_init (qtrans, qdaemon)
        !          1112:      struct stransfer *qtrans;
        !          1113:      struct sdaemon *qdaemon;
        !          1114: {
        !          1115:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !          1116:   char *zxqtfile;
        !          1117:   char abtname[CFILE_NAME_LEN];
        !          1118:   char abxname[CFILE_NAME_LEN];
        !          1119:   char *z;
        !          1120:   size_t calc, clen;
        !          1121: 
        !          1122:   z = NULL;
        !          1123:   calc = 0;
        !          1124:   clen = 0;
        !          1125: 
        !          1126:   usadd_exec_line (&z, &calc, &clen, 'U', qtrans->s.zuser,
        !          1127:                   qdaemon->zlocalname);
        !          1128:   usadd_exec_line (&z, &calc, &clen, 'F', qtrans->s.zto, "");
        !          1129:   usadd_exec_line (&z, &calc, &clen, 'I', qtrans->s.zto, "");
        !          1130:   if (strchr (qtrans->s.zoptions, 'N') != NULL)
        !          1131:     usadd_exec_line (&z, &calc, &clen, 'N', "", "");
        !          1132:   if (strchr (qtrans->s.zoptions, 'Z') != NULL)
        !          1133:     usadd_exec_line (&z, &calc, &clen, 'Z', "", "");
        !          1134:   if (strchr (qtrans->s.zoptions, 'R') != NULL)
        !          1135:     usadd_exec_line (&z, &calc, &clen, 'R', qtrans->s.znotify, "");
        !          1136:   if (strchr (qtrans->s.zoptions, 'e') != NULL)
        !          1137:     usadd_exec_line (&z, &calc, &clen, 'e', "", "");
        !          1138:   usadd_exec_line (&z, &calc, &clen, 'C', qtrans->s.zcmd, "");
        !          1139: 
        !          1140:   qinfo->zexec = z;
        !          1141:   qinfo->cbytes = clen;
        !          1142: 
        !          1143:   zxqtfile = zsysdep_data_file_name (qdaemon->qsys, qdaemon->zlocalname,
        !          1144:                                     BDEFAULT_UUX_GRADE, TRUE, abtname,
        !          1145:                                     (char *) NULL, abxname);
        !          1146:   if (zxqtfile == NULL)
        !          1147:     {
        !          1148:       usfree_send (qtrans);
        !          1149:       return FALSE;
        !          1150:     }
        !          1151:   ubuffree (zxqtfile);
        !          1152: 
        !          1153:   ubuffree ((char *) qtrans->s.zfrom);
        !          1154:   qtrans->s.zfrom = zbufcpy (abtname);
        !          1155:   ubuffree ((char *) qtrans->s.zto);
        !          1156:   qtrans->s.zto = zbufcpy (abxname);
        !          1157:   ubuffree ((char *) qtrans->s.zoptions);
        !          1158:   qtrans->s.zoptions = zbufcpy ("C");
        !          1159:   ubuffree ((char *) qtrans->s.ztemp);
        !          1160:   qtrans->s.ztemp = zbufcpy (abtname);
        !          1161: 
        !          1162:   qtrans->psendfn = flocal_send_request;
        !          1163:   qtrans->precfn = NULL;
        !          1164:   qtrans->ipos = 0;
        !          1165:   qtrans->cbytes = 0;
        !          1166:   qtrans->isecs = 0;
        !          1167:   qtrans->imicros = 0;
        !          1168:   qinfo->fsent = FALSE;
        !          1169: 
        !          1170:   return fqueue_send (qdaemon, qtrans);
        !          1171: }
        !          1172: 
        !          1173: /* Add a line to the fake execution file.  */
        !          1174: 
        !          1175: static void
        !          1176: usadd_exec_line (pz, pcalc, pclen, bcmd, z1, z2)
        !          1177:      char **pz;
        !          1178:      size_t *pcalc;
        !          1179:      size_t *pclen;
        !          1180:      int bcmd;
        !          1181:      const char *z1;
        !          1182:      const char *z2;
        !          1183: {
        !          1184:   size_t c1, c2;
        !          1185:   char *znew;
        !          1186: 
        !          1187:   c1 = strlen (z1);
        !          1188:   c2 = strlen (z2);
        !          1189: 
        !          1190:   if (*pclen + c1 + c2 + 4 >= *pcalc)
        !          1191:     {
        !          1192:       *pcalc += c1 + c2 + 100;
        !          1193:       znew = zbufalc (*pcalc);
        !          1194:       if (*pclen > 0)
        !          1195:        {
        !          1196:          memcpy (znew, *pz, *pclen);
        !          1197:          ubuffree (*pz);
        !          1198:        }
        !          1199:       *pz = znew;
        !          1200:     }
        !          1201: 
        !          1202:   znew = *pz + *pclen;
        !          1203:   *znew++ = bcmd;
        !          1204:   if (*z1 != '\0')
        !          1205:     {
        !          1206:       *znew++ = ' ';
        !          1207:       memcpy (znew, z1, c1);
        !          1208:       znew += c1;
        !          1209:       if (*z2 != '\0')
        !          1210:        {
        !          1211:          *znew++ = ' ';
        !          1212:          memcpy (znew, z2, c2);
        !          1213:          znew += c2;
        !          1214:        }
        !          1215:     }
        !          1216: 
        !          1217:   /* In some bizarre non-Unix case we might have to worry about the
        !          1218:      newline here.  We don't know how a newline is normally written
        !          1219:      out to a file, but whatever is written to a file is what we will
        !          1220:      normally transfer.  If that is not simply \n then this fake
        !          1221:      execution file will not look like other execution files.  */
        !          1222:   *znew++ = '\n';
        !          1223: 
        !          1224:   *pclen = znew - *pz;
        !          1225: }
        !          1226: 
        !          1227: /* This routine is called to send the contents of the fake execution
        !          1228:    file.  Normally file data is sent by the floop routine in trans.c,
        !          1229:    but since we don't have an actual file we must do it here.  This
        !          1230:    routine sends the complete buffer, followed by a zero length
        !          1231:    packet, and then calls fsend_file_end.  */
        !          1232: 
        !          1233: static boolean
        !          1234: fsend_exec_file (qtrans, qdaemon)
        !          1235:      struct stransfer *qtrans;
        !          1236:      struct sdaemon *qdaemon;
        !          1237: {
        !          1238:   struct ssendinfo *qinfo = (struct ssendinfo *) qtrans->pinfo;
        !          1239:   char *zdata;
        !          1240:   size_t cdata;
        !          1241:   size_t csend;
        !          1242: 
        !          1243:   zdata = (*qdaemon->qproto->pzgetspace) (qdaemon, &cdata);
        !          1244:   if (zdata == NULL)
        !          1245:     {
        !          1246:       usfree_send (qtrans);
        !          1247:       return FALSE;
        !          1248:     }
        !          1249: 
        !          1250:   csend = qinfo->cbytes - qtrans->ipos;
        !          1251:   if (csend > cdata)
        !          1252:     csend = cdata;
        !          1253: 
        !          1254:   memcpy (zdata, qinfo->zexec + qtrans->ipos, csend);
        !          1255: 
        !          1256:   if (! (*qdaemon->qproto->pfsenddata) (qdaemon, zdata, csend,
        !          1257:                                        qtrans->ilocal, qtrans->iremote,
        !          1258:                                        qtrans->ipos))
        !          1259:     {
        !          1260:       usfree_send (qtrans);
        !          1261:       return FALSE;
        !          1262:     }
        !          1263: 
        !          1264:   qtrans->cbytes += csend;
        !          1265:   qtrans->ipos += csend;
        !          1266: 
        !          1267:   if (csend == 0)
        !          1268:     return fsend_file_end (qtrans, qdaemon);
        !          1269: 
        !          1270:   /* Leave the job on the send queue.  */
        !          1271: 
        !          1272:   return TRUE;
        !          1273: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.