home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 278.lha / Patch_v0.91 / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-06  |  13.7 KB  |  605 lines

  1. #include "EXTERN.h"
  2. #include "common.h"
  3. #include "INTERN.h"
  4. #include "util.h"
  5.  
  6. /* Rename a file, copying it if necessary. */
  7.  
  8.  
  9. #ifdef AMIGA
  10.  
  11. #include <libraries/dos.h>
  12. #include <libraries/dosextens.h>
  13.  
  14.  
  15. /* backup & copy the file */
  16.   static void copy_file();
  17.  
  18. int
  19. move_file(from,to)
  20.  char *from, *to;
  21. {
  22.   register long success;
  23.   register int fromfd;
  24.   register int i;
  25.   register struct FileLock *destlock;
  26.   int curnum='0';
  27.  
  28.   static char bakname[256];
  29.  
  30. /* declare us some AmigaDOS functions: */
  31.   extern long DeleteFile();
  32.   extern struct FileLock *Lock();
  33.   extern void UnLock();
  34.   extern long Rename();
  35.  
  36.  
  37.     if (strEQ(to, "-")) {   /* cat it to stdout. */
  38. #ifdef DEBUGGING
  39.         if (debug & 4)
  40.             say2("Moving %s to stdout.\n", from);
  41. #endif
  42.         fromfd = open(from, 0);
  43.         if (fromfd < 0)
  44.             fatal2("patch: internal error, can't reopen %s\n", from);
  45.         while ((i=read(fromfd, buf, sizeof buf)) > 0)
  46.             if (write(1, buf, i) != 1)
  47.                 fatal1("patch: write failed\n");
  48.         Close(fromfd);
  49.         return 0;
  50.     }
  51.  
  52. /* add the extension to the name */
  53.     Strcpy(bakname, to);
  54. /* see if the "to" exists. If not, don't add the extension. */
  55.     if (destlock=Lock(bakname)) {
  56.         UnLock(destlock);
  57.         Strcat(bakname, ORIGEXT);
  58.  
  59.         i = strlen(bakname);   /* find the end of string */
  60.         bakname[i+1]=0;        /* so that the following will work: */
  61.  
  62. /* now to see if the destination exists: */
  63.         while (destlock=Lock(bakname)) {
  64.             UnLock(destlock);   /* clean up after ourselves. */
  65.             bakname[i]=curnum++;
  66.         }
  67. /* ok, now we can do the relinking! */
  68.         success = Rename(to,bakname);
  69.         if (success==0) {
  70.             say3("patch: can't backup %s, output is in %s\n",
  71.                 to, from);
  72.             return -1;
  73.         }
  74.     }
  75. /* ok, now copy the from to the to file. */
  76. /* try renaming it first, & if that don't work, then copy it. */
  77.     success = Rename(from,to);
  78.     if (success==0) {                  /* if don't work, then copy! */
  79.        copy_file(from,to);
  80.        success=DeleteFile(from);
  81.     }
  82.     return 0;
  83. }
  84. #endif
  85.  
  86. #ifndef AMIGA
  87. int
  88. move_file(from,to)
  89. char *from, *to;
  90. {
  91.     char bakname[512];
  92.     Reg1 char *s;
  93.     Reg2 int i;
  94.     Reg3 int fromfd;
  95.  
  96.     /* to stdout? */
  97.  
  98.     if (strEQ(to, "-")) {
  99. #ifdef DEBUGGING
  100.         if (debug & 4)
  101.             say2("Moving %s to stdout.\n", from);
  102. #endif
  103.         fromfd = open(from, 0);
  104.         if (fromfd < 0)
  105.             fatal2("patch: internal error, can't reopen %s\n", from);
  106.         while ((i=read(fromfd, buf, sizeof buf)) > 0)
  107.             if (write(1, buf, i) != 1)
  108.                 fatal1("patch: write failed\n");
  109.         Close(fromfd);
  110.         return 0;
  111.     }
  112.  
  113.         if (origprae) {
  114.                 Strcpy (bakname, origprae);
  115.         Strcat(bakname, to);
  116.         } else {
  117.                 Strcpy(bakname, to);
  118.         Strcat(bakname, origext?origext:ORIGEXT);
  119.         }
  120.     if (stat(to, &filestat) >= 0) {     /* output file exists */
  121.         dev_t to_device = filestat.st_dev;
  122.         ino_t to_inode  = filestat.st_ino;
  123.         char *simplename = bakname;
  124.  
  125.         for (s=bakname; *s; s++) {
  126.             if (*s == '/')
  127.                 simplename = s+1;
  128.         }
  129.         /* find a backup name that is not the same file */
  130.         while (stat(bakname, &filestat) >= 0 &&
  131.                 to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  132.             for (s=simplename; *s && !islower(*s); s++) ;
  133.             if (*s)
  134.                 *s = toupper(*s);
  135.             else
  136.                 Strcpy(simplename, simplename+1);
  137.         }
  138.         while (unlink(bakname) >= 0) ;  /* while() is for benefit of Eunice */
  139. #ifdef DEBUGGING
  140.         if (debug & 4)
  141.             say3("Moving %s to %s.\n", to, bakname);
  142. #endif
  143.         if (link(to, bakname) < 0) {
  144.             say3("patch: can't backup %s, output is in %s\n",
  145.                 to, from);
  146.             return -1;
  147.         }
  148.         while (unlink(to) >= 0) ;
  149.     }
  150. #ifdef DEBUGGING
  151.     if (debug & 4)
  152.         say3("Moving %s to %s.\n", from, to);
  153. #endif
  154.     if (link(from, to) < 0) {           /* different file system? */
  155.         Reg4 int tofd;
  156.  
  157.         tofd = creat(to, 0666);
  158.         if (tofd < 0) {
  159.             say3("patch: can't create %s, output is in %s.\n",
  160.               to, from);
  161.             return -1;
  162.         }
  163.         fromfd = open(from, 0);
  164.         if (fromfd < 0)
  165.             fatal2("patch: internal error, can't reopen %s\n", from);
  166.         while ((i=read(fromfd, buf, sizeof buf)) > 0)
  167.             if (write(tofd, buf, i) != i)
  168.                 fatal1("patch: write failed\n");
  169.         Close(fromfd);
  170.         Close(tofd);
  171.     }
  172.     Unlink(from);
  173.     return 0;
  174. }
  175. #endif
  176.  
  177. /* Copy a file. */
  178.  
  179. void
  180. copy_file(from,to)
  181. char *from, *to;
  182. {
  183.     Reg3 int tofd;
  184.     Reg2 int fromfd;
  185.     Reg1 int i;
  186.  
  187.     tofd = creat(to, 0666);
  188.  
  189.     if (tofd < 0)
  190.         fatal2("patch: can't create %s.\n", to);
  191.     fromfd = open(from, 0);
  192.     if (fromfd < 0)
  193.         fatal2("patch: internal error, can't reopen %s\n", from);
  194.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  195.         if (write(tofd, buf, i) != i)
  196.             fatal2("patch: write (%s) failed\n", to);
  197.     Close(fromfd);
  198.     Close(tofd);
  199. }
  200.  
  201. /* Allocate a unique area for a string. */
  202.  
  203. char *
  204. savestr(s)
  205. Reg1 char *s;
  206. {
  207.     Reg3 char *rv;
  208.     Reg2 char *t;
  209.  
  210.     if (!s)
  211.         s = "Oops";
  212.     t = s;
  213.     while (*t++);
  214.     rv = malloc((MEM) (t - s));
  215.     if (rv == Nullch) {
  216.         if (using_plan_a)
  217.             out_of_mem = TRUE;
  218.         else
  219.             fatal1("patch: out of memory (savestr)\n");
  220.     }
  221.     else {
  222.         t = rv;
  223.         while (*t++ = *s++);
  224.     }
  225.     return rv;
  226. }
  227.  
  228. #ifdef lint
  229.  
  230. #ifdef CANVARARG
  231.  
  232. /*VARARGS ARGSUSED*/
  233. say(pat) char *pat; { ; }
  234. /*VARARGS ARGSUSED*/
  235. fatal(pat) char *pat; { ; }
  236. /*VARARGS ARGSUSED*/
  237. ask(pat) char *pat; { ; }
  238. #endif
  239.  
  240. #else
  241.  
  242. /* Vanilla terminal output (buffered). */
  243.  
  244. void
  245. say(pat,arg1,arg2,arg3)
  246. char *pat;
  247. long arg1,arg2,arg3;
  248. {
  249.     fprintf(stderr, pat, arg1, arg2, arg3);
  250.     Fflush(stderr);
  251. }
  252.  
  253. /* Terminal output, pun intended. */
  254.  
  255. void                            /* very void */
  256. fatal(pat,arg1,arg2,arg3)
  257. char *pat;
  258. long arg1,arg2,arg3;
  259. {
  260.     void my_exit();
  261.  
  262.     say(pat, arg1, arg2, arg3);
  263.     my_exit(1);
  264. }
  265.  
  266.  
  267. #ifndef AMIGA
  268.  
  269. /* Get a response from the user, somehow or other. */
  270.  
  271. void
  272. ask(pat,arg1,arg2,arg3)
  273. char *pat;
  274. long arg1,arg2,arg3;
  275. {
  276.     int ttyfd;
  277.     int r;
  278.     bool tty2 = isatty(2);
  279.  
  280.     Sprintf(buf, pat, arg1, arg2, arg3);
  281.     Fflush(stderr);
  282.     write(2, buf, strlen(buf));
  283.     if (tty2) {                         /* might be redirected to a file */
  284.         r = read(2, buf, sizeof buf);
  285.     }
  286.     else if (isatty(1)) {               /* this may be new file output */
  287.         Fflush(stdout);
  288.         write(1, buf, strlen(buf));
  289.         r = read(1, buf, sizeof buf);
  290.     }
  291.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  292.                                         /* might be deleted or unwriteable */
  293.         write(ttyfd, buf, strlen(buf));
  294.         r = read(ttyfd, buf, sizeof buf);
  295.         Close(ttyfd);
  296.     }
  297.     else if (isatty(0)) {               /* this is probably patch input */
  298.         Fflush(stdin);
  299.         write(0, buf, strlen(buf));
  300.         r = read(0, buf, sizeof buf);
  301.     }
  302.     else {                              /* no terminal at all--default it */
  303.         buf[0] = '\n';
  304.         r = 1;
  305.     }
  306.     if (r <= 0)
  307.         buf[0] = 0;
  308.     else
  309.         buf[r] = '\0';
  310.     if (!tty2)
  311.         say1(buf);
  312. }
  313. #else  /* Amiga */
  314.  
  315. /* for the Amiga we're going to have to do some heavy-duty magic.
  316.    We can't open /dev/tty! So open a whole new window!
  317. */
  318.  
  319. void
  320. ask(pat,arg1,arg2,arg3)
  321. char *pat;
  322. long arg1,arg2,arg3;
  323. {
  324.     int rwin;
  325.     long actual_read;
  326.  
  327.  
  328.     Sprintf(buf, pat, arg1, arg2, arg3);
  329.     rwin=open("CON:0/10/400/100/Patch Response Window",O_RDWR+O_CREAT);
  330.     if (rwin==0) {
  331.         printf("Error:No window dressing.");
  332.     }
  333.     write(rwin,buf,strlen(buf));
  334.     actual_read=read(rwin,buf,sizeof buf);
  335.     if (actual_read==0)
  336.        buf[0]=0;
  337.     buf[actual_read]=0;
  338. /*    printf("actual_read=%d buf=%s\n",actual_read,buf); */
  339.     Close(rwin);
  340. }
  341. #endif  /* amiga */
  342. #endif  /* lint */
  343.  
  344.  
  345. /* How to handle certain events when not in a critical region. */
  346.  
  347. void
  348. set_signals(reset)
  349.  int reset;
  350. {
  351.     void my_exit();
  352.  
  353. #ifdef AMIGA
  354.     extern short Enable_Abort;
  355.  
  356.     Enable_Abort=1;
  357.  
  358. #else
  359.  
  360. #ifndef lint
  361. #ifdef VOIDSIG
  362.     static void (*hupval)(),(*intval)();
  363. #else
  364.     static int (*hupval)(),(*intval)();
  365. #endif
  366.     if (!reset) {
  367.       hupval = signal(SIGHUP, SIG_IGN);
  368.       if (hupval != SIG_IGN)
  369. #ifdef VOIDSIG
  370.           hupval = my_exit;
  371. #else
  372.           hupval = (int(*)())my_exit;
  373. #endif
  374.       intval = signal(SIGINT, SIG_IGN);
  375.       if (intval != SIG_IGN)
  376. #ifdef VOIDSIG
  377.           intval = my_exit;
  378. #else
  379.           intval = (int(*)())my_exit;
  380. #endif
  381.     }
  382.     Signal(SIGHUP, hupval);
  383.     Signal(SIGINT, intval);
  384. #endif
  385.  
  386. #endif
  387. }
  388.  
  389. /* How to handle certain events when in a critical region. */
  390.  
  391. void
  392. ignore_signals()
  393. {
  394. #ifdef AMIGA
  395.   extern short Enable_Abort;
  396.  
  397.   Enable_Abort=0;
  398. #else
  399.  
  400. #ifndef lint
  401.     Signal(SIGHUP, SIG_IGN);
  402.     Signal(SIGINT, SIG_IGN);
  403. #endif
  404. #endif
  405.  
  406. }
  407.  
  408. #ifdef AMIGA
  409.  
  410. /* this is a recursive subroutine. It isn't the epitomy of efficiency.
  411.    On the other hand, even as a recursive subroutine it's more
  412.    space-efficient than Larry Wall's monstrosity, because it doesn't
  413.    allocate huge structures on the stack.
  414. */
  415.  
  416. void
  417. makedirs(filename,striplast)
  418.   char *filename;
  419.   bool striplast;
  420. {
  421.     register char *walkptr=filename;
  422.     register char temp;
  423.     register char *tmpptr;
  424.     struct FileLock *new_dir;
  425.     struct FileLock *old_dir;
  426.  
  427.     extern char *index();
  428.     extern struct FileLock *CurrentDir();
  429.     extern struct FileLock *CreateDir();
  430.  
  431. /* first the easy part: */
  432.     if (walkptr[0]=0)    /* don't try to walk a null filename! */
  433.         return;          /* end recursing. */
  434.     if (walkptr[0]=='.' && walkptr[1]=='/')
  435.         walkptr+=2;
  436.     if (walkptr[0]=='/')  /* starting at root: */
  437.        walkptr[0]=':';    /* AmigaDOS root. */
  438.  
  439.     tmpptr=index(walkptr,'/'); /* see if there's subdirectories. */
  440.     if (tmpptr==0 && striplast) { /* oops, no more filenames. Do we striplast? */
  441.           return;  /* yes, strip last, quit recursing. */
  442.     }
  443.  
  444.     temp=*tmpptr;
  445.     *tmpptr++=0;                    /* walkptr now points to dirname. */
  446.  
  447. /* the next stuff is very Amiga-dependent: */
  448.     new_dir=Lock(walkptr,ACCESS_READ);  /* see if new dir exists. */
  449.     if (new_dir==NULL) {
  450.         (void) printf("Creating directory %s ...\n",walkptr);
  451.         (void) fflush(stdout);
  452.         new_dir=CreateDir(walkptr);    /* if not, create it. */
  453.     }
  454.     old_dir=CurrentDir(new_dir);  /* change working directory to new dir */
  455.  
  456.     (void) makedirs(tmpptr,striplast);    /* recurse, create further dirs. */
  457.     (void) CurrentDir(old_dir);       /* get old dir back. */
  458.     UnLock(new_dir);                 /* free the lock. */
  459.     *(tmpptr-1)=temp;                /* restore original filename */
  460.     /* and return. */
  461. }
  462.  
  463. #else
  464.  
  465. /* Make sure we'll have the directories to create a file. */
  466.  
  467. void
  468. makedirs(filename,striplast)
  469. Reg1 char *filename;
  470. bool striplast;
  471. {
  472.     char tmpbuf[256];
  473.     Reg2 char *s = tmpbuf;
  474.     char *dirv[20];
  475.     Reg3 int i;
  476.     Reg4 int dirvp = 0;
  477.  
  478.     while (*filename) {
  479.         if (*filename == '/') {
  480.             filename++;
  481.             dirv[dirvp++] = s;
  482.             *s++ = '\0';
  483.         }
  484.         else {
  485.             *s++ = *filename++;
  486.         }
  487.     }
  488.     *s = '\0';
  489.     dirv[dirvp] = s;
  490.     if (striplast)
  491.         dirvp--;
  492.     if (dirvp < 0)
  493.         return;
  494.     strcpy(buf, "mkdir");
  495.     s = buf;
  496.     for (i=0; i<=dirvp; i++) {
  497.         while (*s) s++;
  498.         *s++ = ' ';
  499.         strcpy(s, tmpbuf);
  500.         *dirv[i] = '/';
  501.     }
  502.     system(buf);
  503.  
  504. }
  505.  
  506. #endif
  507.  
  508.  
  509. #ifdef AMIGA
  510.  
  511. /* returns 1 if result is a directory, 0 if not. */
  512. int IsDir(s)
  513.   register char *s;
  514. {
  515.    extern int Examine();
  516.    extern struct FileLock *Lock();
  517.    extern void UnLock();
  518.  
  519.    static struct FileInfoBlock fib;
  520.    register struct FileLock *destlock;
  521.    register int result;
  522.  
  523.     destlock=Lock(s);
  524.     if (s==0) return (0);
  525.     result=Examine(destlock,&fib);
  526.     UnLock(destlock);                /* clean up after ourselves. */
  527.     if (result==0) {
  528.         printf("Examine result = %d\n",result);
  529.         return 0;
  530.     }
  531.     if (fib.fib_DirEntryType > 0) return 1;
  532.     return 0;
  533. }
  534.  
  535.  
  536. /* chmod to satisfy us: */
  537.  
  538. void chmod() {}
  539.  
  540. /* abort to satisfy us: */
  541.  
  542. void abort() { exit(1); }
  543.  
  544. #endif
  545.  
  546. /* Make filenames more reasonable. */
  547.  
  548. char *
  549. fetchname(at,strip_leading,assume_exists)
  550. char *at;
  551. int strip_leading;
  552. int assume_exists;
  553. {
  554.     char *s;
  555.     char *name;
  556.     Reg1 char *t;
  557.     char tmpbuf[200];
  558.  
  559.     if (!at)
  560.         return Nullch;
  561.     s = savestr(at);
  562.     for (t=s; isspace(*t); t++) ;
  563.     name = t;
  564. #ifdef DEBUGGING
  565.     if (debug & 128)
  566.         say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
  567. #endif
  568.     if (strnEQ(name, "/dev/null", 9))   /* so files can be created by diffing */
  569.         return Nullch;                  /*   against /dev/null. */
  570.     for (; *t && !isspace(*t); t++)
  571.         if (*t == '/')
  572.             if (--strip_leading >= 0)
  573.                 name = t+1;
  574.     *t = '\0';
  575.     if (name != s && *s != '/') {
  576.         name[-1] = '\0';
  577. #ifdef AMIGA
  578.         if (IsDir(s)) {
  579. #else
  580.         if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
  581. #endif
  582.             name[-1] = '/';
  583.             name=s;
  584.         }
  585.     }
  586.     name = savestr(name);
  587.     Sprintf(tmpbuf, "RCS/%s", name);
  588.     free(s);
  589.     if (stat(name, &filestat) < 0 && !assume_exists) {
  590. #ifdef AMIGA
  591.         name = Nullch;   /* Amiga doesn't have RCS. */
  592. #else
  593.         Strcat(tmpbuf, RCSSUFFIX);
  594.         if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
  595.             Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
  596.             if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
  597.                 free(name);
  598.                 name = Nullch;
  599.             }
  600.         }
  601. #endif
  602.     }
  603.     return name;
  604. }
  605.