home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OS9000 / APPS / rcs.lzh / rcs1 / rcsutil.c < prev    next >
Text File  |  1996-04-20  |  17KB  |  706 lines

  1. /*
  2.  *                     RCS utilities
  3.  */
  4. #ifndef lint
  5. static char rcsid[]= "$Id: rcsutil.c_v 1.2 96/04/07 00:26:37 hiro Exp $ Purdue CS";
  6. #endif
  7.  
  8. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  9.    Distributed under license by the Free Software Foundation, Inc.
  10.  
  11. This file is part of RCS.
  12.  
  13. RCS is free software; you can redistribute it and/or modify
  14. it under the terms of the GNU General Public License as published by
  15. the Free Software Foundation; either version 1, or (at your option)
  16. any later version.
  17.  
  18. RCS is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21. GNU General Public License for more details.
  22.  
  23. You should have received a copy of the GNU General Public License
  24. along with RCS; see the file COPYING.  If not, write to
  25. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  
  27. Report problems and direct all questions to:
  28.  
  29.     rcs-bugs@cs.purdue.edu
  30.  
  31. */
  32.  
  33.  
  34.  
  35.  
  36. /* $Log:    rcsutil.c_v $
  37.  * Revision 1.2  96/04/07  00:26:37  hiro
  38.  * time() returns time_t, not long.
  39.  * 
  40.  * Revision 1.1  93/04/02  01:37:21  hiro
  41.  * Initial revision
  42.  * 
  43.  * Revision 1.3  90/07/27  01:41:04  momo
  44.  * minor change
  45.  * 
  46.  * Revision 1.2  90/07/23  10:25:47  momo
  47.  * Minor change
  48.  * 
  49.  * Revision 1.1  90/07/19  15:22:37  momo
  50.  * Initial revision
  51.  * 
  52.  * revision 5.2 koya 90/01/25 00:37:14
  53.  * Modified the codes related to Child processes and Signals.
  54.  * 
  55.  * revision 5.1 koya 90/01/24 10:40:36
  56.  * Initial revision
  57.  * 
  58.  * Revision 4.6  89/05/01  15:13:40  narten
  59.  * changed copyright header to reflect current distribution rules
  60.  * 
  61.  * Revision 4.5  88/11/08  16:01:02  narten
  62.  * corrected use of varargs routines
  63.  * 
  64.  * Revision 4.4  88/11/08  12:00:28  narten
  65.  * changes from  eggert@sm.unisys.com (Paul Eggert)
  66.  * 
  67.  * Revision 4.4  88/08/09  19:13:24  eggert
  68.  * Check for memory exhaustion.
  69.  * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
  70.  * Use execv(), not system(); yield exit status like diff(1)'s.
  71.  * 
  72.  * Revision 4.3  87/10/18  10:40:22  narten
  73.  * Updating version numbers. Changes relative to 1.1 actually
  74.  * relative to 4.1
  75.  * 
  76.  * Revision 1.3  87/09/24  14:01:01  narten
  77.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  78.  * warnings)
  79.  * 
  80.  * Revision 1.2  87/03/27  14:22:43  jenkins
  81.  * Port to suns
  82.  * 
  83.  * Revision 1.1  84/01/23  14:50:43  kcs
  84.  * Initial revision
  85.  * 
  86.  * Revision 4.1  83/05/10  15:53:13  wft
  87.  * Added getcaller() and findlock().
  88.  * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
  89.  * (needed for background jobs in older shells). Added restoreints().
  90.  * Removed printing of full RCS path from logcommand().
  91.  * 
  92.  * Revision 3.8  83/02/15  15:41:49  wft
  93.  * Added routine fastcopy() to copy remainder of a file in blocks.
  94.  *
  95.  * Revision 3.7  82/12/24  15:25:19  wft
  96.  * added catchints(), ignoreints() for catching and ingnoring interrupts;
  97.  * fixed catchsig().
  98.  *
  99.  * Revision 3.6  82/12/08  21:52:05  wft
  100.  * Using DATEFORM to format dates.
  101.  *
  102.  * Revision 3.5  82/12/04  18:20:49  wft
  103.  * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
  104.  * lockedby-field.
  105.  *
  106.  * Revision 3.4  82/12/03  17:17:43  wft
  107.  * Added check to addlock() ensuring only one lock per person.
  108.  * Addlock also returns a pointer to the lock created. Deleted fancydate().
  109.  *
  110.  * Revision 3.3  82/11/27  12:24:37  wft
  111.  * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
  112.  * Introduced macro SNOOP so that snoop can be placed in directory other than
  113.  * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
  114.  *
  115.  * Revision 3.2  82/10/18  21:15:11  wft
  116.  * added function getfullRCSname().
  117.  *
  118.  * Revision 3.1  82/10/13  16:17:37  wft
  119.  * Cleanup message is now suppressed in quiet mode.
  120.  */
  121.  
  122. #include "rcsbase.h"
  123. #ifdef OSK
  124. #    include "time.h"
  125. #    include "stat.h"
  126. #else
  127. #    include <sys/types.h>
  128. #    include <sys/stat.h>
  129. #endif
  130. #include <signal.h>
  131.  
  132. #ifndef MSDOS
  133. #    ifndef OSK
  134. #        include <pwd.h>
  135. #    endif
  136. #endif /* NOT MSDOS */
  137. #ifndef OSK
  138. #include <varargs.h>
  139. #endif
  140.  
  141. #if defined(USG) || defined(V4_2BSD)
  142. #include <fcntl.h>
  143. #endif
  144.  
  145. #ifndef MSDOS
  146. #ifndef V4_2BSD
  147. #define vfork fork
  148. #endif
  149. #endif /* NOT MSDOS */
  150.  
  151. extern char * bindex();
  152. extern FILE * finptr;
  153. extern char * RCSfilename;
  154. #ifndef MSDOS
  155. extern char * getlogin();
  156. extern struct passwd *getpwuid();
  157. #endif /* NOT MSDOS */
  158. extern char * malloc();
  159.  
  160.  
  161. char * talloc(size)
  162. unsigned size;
  163. {
  164.     char * p;
  165.     if (!(p = malloc(size))) {
  166.         faterror("out of memory");
  167.     }
  168.     return p;
  169. }
  170.  
  171.  
  172.  
  173. char * getcaller()
  174. /* Function: gets the callers login from his uid.
  175.  * If the uid is root, tries to get the true login with getlogin().
  176.  */
  177. {       char * name , *getenv();
  178. #ifdef MSDOS
  179.     strcpy( name, getenv("USR"));
  180.     if ( *name == NULL )
  181.         strcpy( name, "ROOT_DOS" );
  182.     return name;
  183. #else
  184. #    ifdef OSK
  185.     int uid;
  186.     static char uname[40];
  187.  
  188.     if ( (name=getenv("USER"))==NULL ) {
  189.             uid=getuid();
  190.             sprintf(uname,"ID[%03d.%-03d]",uid>>8,uid&0xff);
  191.     }
  192.     return name;
  193. #    else
  194.     int uid;
  195.     uid=getuid();
  196.     if (uid==0) {
  197.         /* super user; try getlogin() to distinguish */
  198.         name = getlogin();
  199.         if (name!=nil && *name!='\0')
  200.             return name;
  201.     }
  202.     return(getpwuid(uid)->pw_name);
  203. #    endif    /* OSK */
  204. #endif /* MSDOS */
  205. }
  206.  
  207.  
  208. struct hshentry *findlock(who,delete)
  209. char * who; int delete;
  210. /* Finds the first lock held by who and returns a pointer
  211.  * to the locked delta; also removes the lock if delete==true.
  212.  * Returns nil if there is no lock held by who.
  213.  */
  214. {
  215.         register struct lock * next, * trail;
  216.         struct lock dummy;
  217.  
  218.         dummy.nextlock=next=Locks;
  219.         trail = &dummy;
  220.         while (next!=nil) {
  221.                 if(strcmp(who,next->login)==0) break; /*found a lock*/
  222.                 trail=next;
  223.                 next=next->nextlock;
  224.         }
  225.         if (next!=nil) {
  226.         /* found one */
  227.         if (delete) {
  228.             /* delete it */
  229.             trail->nextlock=next->nextlock;
  230.             Locks=dummy.nextlock;
  231.             next->delta->lockedby=nil; /* reset locked-by */
  232.         }
  233.                 return next->delta;
  234.         } else  return nil;
  235. }
  236.  
  237.  
  238.  
  239.  
  240.  
  241. struct lock *addlock(delta,who)
  242. struct hshentry *delta;
  243. char * who;
  244. /* Given a delta, addlock checks whether
  245.  * the delta is locked by somebody other than who.
  246.  * If so, an error message is printed, and false returned.
  247.  * If the delta is not reserved at all, a lock for it is added,
  248.  * and a pointer for the lock returned.
  249.  */
  250. {
  251.         struct lock * next;
  252.  
  253.         next=Locks;
  254.         while (next!=nil) {
  255.                 if (cmpnum(delta->num,next->delta->num)==0) {
  256.                         if (strcmp(who,next->login)==0)
  257.                                 return next;
  258.                                 /* lock exists already */
  259.                         else {
  260.                                 error("revision %s already locked by %s",
  261.                                       delta->num, next->login);
  262.                                 return false;
  263.                         }
  264.                 } else {
  265.                         if (strcmp(who,next->login)==0) {
  266.                                 error("you already locked %s; only one lock allowed per person.",
  267.                                        next->delta->num);
  268.                                 return false;
  269.                         } else {
  270.                                 next=next->nextlock;
  271.                         }
  272.                 }
  273.         }
  274.         /* not found; set up new lockblock */
  275.         next= (struct lock *) talloc(sizeof (struct lock));
  276.         delta->lockedby=next->login=who;
  277.         next->delta= delta;
  278.         next->nextlock=Locks;
  279.         Locks=next;
  280.         return next;
  281. }
  282.  
  283.  
  284.  
  285. int addsymbol(delta,name,rebind)
  286. struct hshentry * delta; char * name; int rebind;
  287. /* Function: adds a new symbolic name and associates it with node delta.
  288.  * If name already exists and rebind is true, the name is associated
  289.  * with the new delta; otherwise, an error message is printed and
  290.  * false returned. Returns true it successful.
  291.  */
  292. {       register struct assoc * next;
  293.         next=Symbols;
  294.         while (next!=nil) {
  295.                 if (strcmp(name,next->symbol)==0) {
  296.                         if (rebind) {
  297.                                 next->delta=delta;
  298.                                 return true;
  299.                         } else {
  300.                                 error("symbolic name %s already bound to %s",
  301.                                         name,next->delta->num);
  302.                                 return false;
  303.                         }
  304.                 } else  next = next->nextassoc;
  305.         }
  306.         /* not found; insert new pair. */
  307.         next = (struct assoc *) talloc(sizeof(struct assoc));
  308.         next->symbol=name;
  309.         next->delta=delta;
  310.         next->nextassoc=Symbols;
  311.         Symbols = next;
  312.         return true;
  313. }
  314.  
  315.  
  316.  
  317.  
  318. int checkaccesslist(who)
  319. char * who;
  320. /* function: Returns true if who is the superuser, the owner of the
  321.  * file, the access list is empty, or who is on the access list.
  322.  * Prints an error message and returns false otherwise.
  323.  */
  324. {
  325.         register struct access * next;
  326.         struct stat statbuf;
  327.  
  328. #ifdef MSDOS
  329.         if ((AccessList==nil) || (strcmp(who,"ROOT_DOS")==0))
  330. #else
  331.         if ((AccessList==nil) || (strcmp(who,"root")==0))
  332. #endif /* MSDOS */
  333.                 return true;
  334.  
  335.         next=AccessList;
  336.         do {
  337.                 if (strcmp(who,next->login)==0)
  338.                         return true;
  339.                 next=next->nextaccess;
  340.         } while (next!=nil);
  341.  
  342. #ifdef MSDOS
  343. #else
  344.         VOID fstat(fileno(finptr),&statbuf);  /* get owner of file */
  345.         if (getuid() == statbuf.st_uid) return true;
  346. #endif /* MSDOS */
  347.  
  348.         error("User %s not on the access list",who);
  349.         return false;
  350. }
  351.  
  352. #ifdef OSK
  353. /*
  354. **    get signal routine
  355. */
  356. void catchsig(sig)
  357. int sig;
  358. {
  359.     int t;
  360.     diagnose("\nRCS: cleaning up\n");
  361. /*    close all path but stderr */
  362.     close( 0 );
  363.     close( 1 );
  364.     for ( t=3 ; t<32 ; t++ )
  365.         close(t);
  366.     VOID cleanup();
  367.     exit( sig );
  368. }
  369.  
  370.  
  371. void catchsig2(sig)
  372. int sig;
  373. {
  374.     ;
  375. }
  376. void ignoreints()
  377. {
  378.     intercept( catchsig2 );
  379. }
  380. void catchints()
  381. {
  382.     intercept( catchsig );
  383. }
  384. void restoreints()
  385. {
  386.     intercept( catchsig );
  387. }
  388.  
  389. #else
  390. /* In MSDOS, we have a few signals.     */
  391. /* So, we set signal handlar for only SIGINT. $Author: hiro $    */
  392.  
  393. #ifdef MSDOS
  394. static void catchsig(s)
  395. #else
  396. static SIGNAL_TYPE catchsig(s)
  397. #endif /* MSDOS */
  398. {
  399.     ignoreints();
  400.         diagnose("\nRCS: cleaning up\n");
  401.         VOID cleanup();
  402. #ifdef OSK
  403.     exit(1);
  404. #else
  405.     exit(2);
  406. #endif
  407. #ifdef lint
  408.     catchsig(s);
  409. #endif
  410. }
  411.  
  412. #ifndef MSDOS
  413. static sig[] = {SIGINT,SIGHUP,SIGQUIT,SIGPIPE,SIGTERM};
  414. #define SIGS (sizeof(sig)/sizeof(*sig))
  415. static SIGNAL_TYPE (*catcher[SIGS])();
  416. #endif /* NOT MSDOS */
  417.   void catchints()
  418.   {
  419. #ifdef MSDOS
  420.     signal(SIGINT ,SIG_IGN);
  421.     restoreints();
  422. #else
  423.     register i;
  424.     for (i=SIGS; 0<=--i; )
  425.         catcher[i]  =
  426.         signal(sig[i],SIG_IGN) == SIG_IGN  ?  SIG_IGN  :  catchsig;
  427.     restoreints();
  428. #endif /* MSDOS */
  429.   }
  430.  
  431.   void ignoreints()
  432.   {
  433. #ifdef MSDOS
  434.     VOID signal(SIGINT, SIG_IGN);
  435. #else
  436.     register i;
  437.     for (i=SIGS; 0<=--i; )
  438.         VOID signal(sig[i], SIG_IGN);
  439. #endif /* MSDOS */
  440.   }
  441.  
  442. void restoreints()
  443. {
  444. #ifdef MSDOS
  445.     VOID signal(SIGINT, SIG_IGN);
  446. #else
  447.     register i;
  448.     for (i=SIGS; 0<=--i; )
  449.         if (catcher[i] != SIG_IGN)
  450.             VOID signal(sig[i], catcher[i]);
  451. #endif /* MSDOS */
  452. }
  453. #endif /* OSK */
  454.  
  455. fastcopy(inf,outf)
  456. FILE * inf, * outf;
  457. /* Function: copies the remainder of file inf to outf. First copies the
  458.  * rest that is in the IO-buffer of inf character by character, and then
  459.  * copies the remainder in blocks.
  460.  */
  461. {       char buf[BUFSIZ];
  462.         register int rcount, wcount;
  463.  
  464.  
  465.         /* write the rest of the buffer to outf */
  466. #ifdef OSK
  467.         while ( (rcount=fread(buf,sizeof(char),BUFSIZ,inf))!=0 ) {
  468.             if ( fwrite(buf,sizeof(char),rcount,outf)!=rcount ) break;
  469.         }
  470.         fflush(outf);
  471.         if ( ferror(outf) ) writeerror();
  472. #ifdef DEBUG
  473.         fprintf(stderr,"fastcopy end\n");
  474. #endif
  475. #else
  476.         while ((--inf->_cnt)>=0) {
  477.                 VOID putc(*inf->_ptr++&0377,outf);
  478.         }
  479.         if (fflush(outf) == EOF) {
  480.             writeerror();
  481.         }
  482.         /*now read the rest of the file in blocks*/
  483.         while ((rcount=read(fileno(inf),buf,BUFSIZ))>0) {
  484.                 wcount=write(fileno(outf),buf,rcount);
  485.                 if (wcount!=rcount) {
  486.                     writeerror();
  487.                 }
  488.         }
  489. #endif
  490. }
  491.  
  492.  
  493.  
  494.  
  495. #ifdef SNOOPFILE
  496.  
  497. #ifndef TIMEID
  498. #include "time.h"
  499. #endif
  500.  
  501. extern struct tm* localtime();
  502. /*extern long time();*/
  503.  
  504. logcommand(commandname,delta, sequence,login)
  505. char* commandname; struct hshentry * delta, * sequence[];char * login;
  506. /* Function: start a process to write the file that
  507.  * logs the RCS command.
  508.  * Each line in the log file contains the following information:
  509.  * operation, revision(r), backward deltas applied(b), forward deltas applied(f),
  510.  * total deltas present(t), creation date of delta(d), date of operation(o),
  511.  * login of caller, RCS file name.
  512.  */
  513. {
  514.         char logline[200];
  515.         char curdate[datelength];
  516.     char *inoutargs[5];
  517.         register int i, backward, forward;
  518.         long clock;
  519.         struct tm * tm;
  520.  
  521.         clock=time((long *)0);
  522.         tm=localtime(&clock);
  523.  
  524.         VOID sprintf(curdate,DATEFORM,
  525.                 tm->tm_year, tm->tm_mon+1, tm->tm_mday,
  526.                 tm->tm_hour, tm->tm_min, tm->tm_sec);
  527.  
  528.         i= backward=forward=0;
  529.         while(sequence[i]!=nil) {  /* count deltas to be applied*/
  530.         if (countnumflds(sequence[i]->num) == 2)
  531.                 backward++;  /* reverse delta */
  532.         else    forward++;   /* branch delta  */
  533.         i++;
  534.         }
  535.     VOID sprintf(logline,"%s %10sr %3db %3df %3dt %sc %so %s %s",
  536.         commandname,delta->num,backward,forward,TotalDeltas,delta->date,
  537.         curdate,login,bindex(getfullRCSname(),'/'));
  538.     inoutargs[0] = nil;
  539.     inoutargs[1] = nil;
  540.     inoutargs[2] = SNOOP;
  541.     inoutargs[3] = logline;
  542.     inoutargs[4] = nil;
  543.     VOID run_back(inoutargs);
  544. }
  545. #endif
  546.  
  547. #ifndef OSK
  548. static int fdreopen(fd, file, flags, mode)
  549.     char *file;
  550. {
  551.     int newfd;
  552.     VOID close(fd);
  553.     newfd = flags==-1 ? creat(file,mode) : open(file,flags,mode);
  554.     if (newfd < 0  ||  newfd == fd)
  555.         return newfd;
  556. #ifdef F_DUPFD
  557.     fd = fcntl(newfd, F_DUPFD, fd);
  558. #else
  559.     fd = dup2(newfd, fd);
  560. #endif
  561.     VOID close(newfd);
  562.     return fd;
  563. }
  564.  
  565. static void tryopen(fd,file,flags)
  566.     char *file;
  567. {
  568.     if (file  &&  fdreopen(fd,file,flags,0600) != fd) {
  569.         VOID write(fileno(stderr), file, strlen(file));
  570.         VOID write(fileno(stderr), ": cannot open\n", 14);
  571. #ifdef OSK
  572.         _exit(1);
  573. #else
  574.         _exit(2);
  575. #endif
  576.     }
  577. }
  578. #endif
  579.  
  580. /*
  581. /* Run in the background a command specified by the strings in 'inoutargs'.
  582. /* inoutargs[0], if nonnil, is the name of the input file.
  583. /* inoutargs[1], if nonnil, is the name of the output file.
  584. /* inoutargs[2..] form the command to be run in the background.
  585. /*/
  586. static int run_back(inoutargs)
  587.     register char **inoutargs;
  588. {
  589. #ifdef MSDOS
  590.     int result;
  591.     
  592.     if (fflush(stdout) == EOF  ||  fflush(stderr) == EOF)
  593.         return -1;
  594.     tryopen(fileno(stdin), inoutargs[0], 0);
  595.     tryopen(fileno(stdout), inoutargs[1], -1);
  596.     result = spawnvp( 0, inoutargs[2], &inoutargs[2] );
  597.     return result;                
  598. #else
  599. #ifdef OSK
  600.     int pid , stdinp , stdoutp,
  601.         os9fork();
  602.     extern char **environ;
  603.     extern int errno;
  604.  
  605.     if (fflush(stdout) == EOF  ||  fflush(stderr) == EOF)
  606.         return -1;
  607.     stdinp=dup(0); stdoutp=dup(1);
  608.     if ( inoutargs[0] ) { close(0); open(inoutargs[0],1); }
  609.     if ( inoutargs[1] ) { close(1);
  610.         if ( creat(inoutargs[1],3)==-1 )
  611.             exit(_errmsg(errno,"%s : can't open\n",inoutargs[1]));
  612.     }
  613.     pid=os9exec(os9fork,inoutargs[2],&inoutargs[2],environ,0,128,3);
  614.     close(0); dup(stdinp); close(stdinp);
  615.     close(1); dup(stdoutp); close(stdoutp);
  616.     return pid;
  617. #else
  618.     int pid;
  619.     if (fflush(stdout) == EOF  ||  fflush(stderr) == EOF)
  620.         return -1;
  621.     if (!(pid = vfork())) {
  622.         tryopen(fileno(stdin), inoutargs[0], 0);
  623.         tryopen(fileno(stdout), inoutargs[1], -1);
  624.         VOID execv(inoutargs[2], &inoutargs[2]);
  625.         inoutargs[1] = "/bin/sh";
  626.         VOID execv(inoutargs[1], &inoutargs[1]);
  627.         VOID write(fileno(stderr), "/bin/sh: not found\n", 19);
  628.         _exit(2);
  629.     }
  630.     return pid;
  631. #endif     /* OSK*/
  632. #endif /* MSDOS */
  633. }
  634.  
  635. #define CARGSMAX 20
  636. #ifndef OSK
  637. /*
  638. /* Run a command.
  639. /* The first two arguments are the input and output files (if nonnil);
  640. /* the rest specify the command and its arguments.
  641. /*/
  642. int run(va_alist)
  643.     va_dcl
  644. {
  645.     va_list ap;
  646.     int pid, wstatus, w;
  647.     char *rgargs[CARGSMAX];
  648.     register i = 0;
  649.     va_start(ap);
  650.     rgargs[0] = va_arg(ap, char *);
  651.     rgargs[1] = va_arg(ap, char *);
  652.     for (i =2; i< CARGSMAX; i++) {
  653.         rgargs[i] = va_arg(ap, char *);
  654.         if (rgargs[i] == NULL)
  655.         break;
  656.     }
  657.     va_end(ap);
  658.     pid = run_back(rgargs);
  659. #ifndef MSDOS
  660.     if (pid < 0)
  661. #endif /* MSDOS */
  662.         return pid;
  663. #ifndef MSDOS
  664.     for (;;)
  665.         if ((w = wait(&wstatus)) < 0)
  666.             return w;
  667.         else if (w == pid)
  668.             return wstatus;
  669. #endif /* NOT MSDOS */
  670. }
  671. #else
  672. run( va0 , va1 , va2 , va3 , va4 , va5 , va6 , va7 , va8 , va9 )
  673. char *va0 , *va1 , *va2 , *va3 , *va4 , *va5 , *va6 , *va7 , *va8 , *va9;
  674. {
  675.     register int i;
  676.     int w , wstatus , pid;
  677.     char *rgargs[10];
  678.  
  679.     rgargs[0]=va0; rgargs[1]=va1;
  680.     rgargs[2]=va2; rgargs[3]=va3;
  681.     rgargs[4]=va4; rgargs[5]=va5;
  682.     rgargs[6]=va6; rgargs[7]=va7;
  683.     rgargs[8]=va8; rgargs[9]=va9;
  684.     pid=run_back(rgargs);
  685.     if ( pid>0 ) {
  686.         while ( pid != wait(&wstatus) ) tsleep(10);
  687.         return wstatus;
  688.     }
  689.     return -1;
  690. }
  691. #endif        
  692. #ifdef MSDOS
  693. int Rename( from, to )
  694. char    *from;
  695. char    *to;
  696. {
  697.     if ( access( to, 0 ) == 0 ) {
  698.         if ( chmod( to, S_IWRITE | S_IREAD ) == -1 )
  699.             return (-1);
  700.         if ( unlink(to) != 0 )
  701.             return (-1);
  702.     }
  703.         return ( rename( from, to ) );
  704. }
  705. #endif /* MSDOS */
  706.