Annotation of coherent/g/usr/lib/uucp/tay104/send.c, revision 1.1.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.