home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / gnu / patch / patch.zoo / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-10  |  8.7 KB  |  444 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. int
  9. move_file(from,to)
  10. char *from, *to;
  11. {
  12.     char bakname[512];
  13.     Reg1 char *s;
  14.     Reg2 int i;
  15.     Reg3 int fromfd;
  16.  
  17.     /* to stdout? */
  18.  
  19.     if (strEQ(to, "-")) {
  20. #ifdef DEBUGGING
  21.     if (debug & 4)
  22.         say2("Moving %s to stdout.\n", from);
  23. #endif
  24.     fromfd = open(from, 0);
  25.     if (fromfd < 0)
  26.         fatal2("patch: internal error, can't reopen %s\n", from);
  27.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  28.         if (write(1, buf, i) != 1)
  29.         fatal1("patch: write failed\n");
  30.     Close(fromfd);
  31.     return 0;
  32.     }
  33.  
  34.     if (origprae) {
  35.         Strcpy (bakname, origprae);
  36.         Strcat(bakname, to);
  37.     } else {
  38.            Strcpy(bakname, to);
  39.         Strcat(bakname, origext?origext:ORIGEXT);
  40.     }
  41.     if (stat(to, &filestat) >= 0) {    /* output file exists */
  42.     dev_t to_device = filestat.st_dev;
  43.     ino_t to_inode  = filestat.st_ino;
  44.     char *simplename = bakname;
  45.     
  46.     for (s=bakname; *s; s++) {
  47.         if (*s == '/')
  48.         simplename = s+1;
  49.     }
  50.     /* find a backup name that is not the same file */
  51.     while (stat(bakname, &filestat) >= 0 &&
  52.         to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  53.         for (s=simplename; *s && !islower(*s); s++) ;
  54.         if (*s)
  55.         *s = toupper(*s);
  56.         else
  57.         Strcpy(simplename, simplename+1);
  58.     }
  59.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  60. #ifdef DEBUGGING
  61.     if (debug & 4)
  62.         say3("Moving %s to %s.\n", to, bakname);
  63. #endif
  64. #ifdef TOS
  65.     copy_file(to, bakname);
  66. #else
  67.     if (link(to, bakname) < 0) {
  68.         say3("patch: can't backup %s, output is in %s\n",
  69.         to, from);
  70.         return -1;
  71.     }
  72. #endif
  73.     while (unlink(to) >= 0) ;
  74.     }
  75. #ifdef DEBUGGING
  76.     if (debug & 4)
  77.     say3("Moving %s to %s.\n", from, to);
  78. #endif
  79. #ifdef TOS
  80.     copy_file(from, to);
  81. #else
  82.     if (link(from, to) < 0) {        /* different file system? */
  83.     Reg4 int tofd;
  84.     
  85.     tofd = creat(to, 0666);
  86.     if (tofd < 0) {
  87.         say3("patch: can't create %s, output is in %s.\n",
  88.           to, from);
  89.         return -1;
  90.     }
  91.     fromfd = open(from, 0);
  92.     if (fromfd < 0)
  93.         fatal2("patch: internal error, can't reopen %s\n", from);
  94.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  95.         if (write(tofd, buf, i) != i)
  96.         fatal1("patch: write failed\n");
  97.     Close(fromfd);
  98.     Close(tofd);
  99.     }
  100. #endif
  101.     Unlink(from);
  102.     return 0;
  103. }
  104.  
  105. /* Copy a file. */
  106.  
  107. void
  108. copy_file(from,to)
  109. char *from, *to;
  110. {
  111.     Reg3 int tofd;
  112.     Reg2 int fromfd;
  113.     Reg1 int i;
  114.     
  115.     tofd = creat(to, 0666);
  116.     if (tofd < 0)
  117.     fatal2("patch: can't create %s.\n", to);
  118.     fromfd = open(from, 0);
  119.     if (fromfd < 0)
  120.     fatal2("patch: internal error, can't reopen %s\n", from);
  121.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  122.     if (write(tofd, buf, i) != i)
  123.         fatal2("patch: write (%s) failed\n", to);
  124.     Close(fromfd);
  125.     Close(tofd);
  126. }
  127.  
  128. /* Allocate a unique area for a string. */
  129.  
  130. char *
  131. savestr(s)
  132. Reg1 char *s;
  133. {
  134.     Reg3 char *rv;
  135.     Reg2 char *t;
  136.  
  137.     if (!s)
  138.     s = "Oops";
  139.     t = s;
  140.     while (*t++);
  141.     rv = malloc((MEM) (t - s));
  142.     if (rv == Nullch) {
  143.     if (using_plan_a)
  144.         out_of_mem = TRUE;
  145.     else
  146.         fatal1("patch: out of memory (savestr)\n");
  147.     }
  148.     else {
  149.     t = rv;
  150.     while (*t++ = *s++);
  151.     }
  152.     return rv;
  153. }
  154.  
  155. #if defined(lint) && defined(CANVARARG)
  156.  
  157. /*VARARGS ARGSUSED*/
  158. say(pat) char *pat; { ; }
  159. /*VARARGS ARGSUSED*/
  160. fatal(pat) char *pat; { ; }
  161. /*VARARGS ARGSUSED*/
  162. ask(pat) char *pat; { ; }
  163.  
  164. #else
  165.  
  166. /* Vanilla terminal output (buffered). */
  167.  
  168. void
  169. say(pat,arg1,arg2,arg3)
  170. char *pat;
  171. long arg1,arg2,arg3;
  172. {
  173.     fprintf(stderr, pat, arg1, arg2, arg3);
  174.     Fflush(stderr);
  175. }
  176.  
  177. /* Terminal output, pun intended. */
  178.  
  179. void                /* very void */
  180. fatal(pat,arg1,arg2,arg3)
  181. char *pat;
  182. long arg1,arg2,arg3;
  183. {
  184.     void my_exit();
  185.  
  186.     say(pat, arg1, arg2, arg3);
  187.     my_exit(1);
  188. }
  189.  
  190. /* Get a response from the user, somehow or other. */
  191.  
  192. void
  193. ask(pat,arg1,arg2,arg3)
  194. char *pat;
  195. long arg1,arg2,arg3;
  196. {
  197.     int ttyfd;
  198.     int r;
  199.     bool tty2 = isatty(2);
  200.  
  201.     Sprintf(buf, pat, arg1, arg2, arg3);
  202.     Fflush(stderr);
  203. #if (defined(MINIX) || defined(TOS))
  204.     /* minix/tos cannot read from 2 */
  205. #ifdef TOS
  206.     r = _tos_ask(buf);
  207. #else /* MINIX */
  208.     if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  209.                     /* might be deleted or unwriteable */
  210.     write(ttyfd, buf, strlen(buf));
  211.     r = read(ttyfd, buf, sizeof buf);
  212.     Close(ttyfd);
  213.     }
  214. #endif
  215.  
  216. #else /* !(MINIX || TOS) */
  217.  
  218.     write(2, buf, strlen(buf));
  219.     if (tty2) {                /* might be redirected to a file */
  220.     r = read(2, buf, sizeof buf);
  221.     }
  222.     else if (isatty(1)) {        /* this may be new file output */
  223.     Fflush(stdout);
  224.     write(1, buf, strlen(buf));
  225.     r = read(1, buf, sizeof buf);
  226.     }
  227.     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
  228.                     /* might be deleted or unwriteable */
  229.     write(ttyfd, buf, strlen(buf));
  230.     r = read(ttyfd, buf, sizeof buf);
  231.     Close(ttyfd);
  232.     }
  233.     else if (isatty(0)) {        /* this is probably patch input */
  234.     Fflush(stdin);
  235.     write(0, buf, strlen(buf));
  236.     r = read(0, buf, sizeof buf);
  237.     }
  238.     else {                /* no terminal at all--default it */
  239.     buf[0] = '\n';
  240.     r = 1;
  241.     }
  242. #endif /* MINIX || TOS */
  243.     if (r <= 0)
  244.     buf[0] = 0;
  245.     else
  246.     buf[r] = '\0';
  247.     if (!tty2)
  248.     say1(buf);
  249. }
  250. #endif /* lint */
  251.  
  252. /* How to handle certain events when not in a critical region. */
  253.  
  254. void
  255. set_signals(reset)
  256. int reset;
  257. {
  258.     void my_exit();
  259. #ifndef lint
  260. #ifdef VOIDSIG
  261.     static void (*hupval)(),(*intval)();
  262. #else
  263.     static int (*hupval)(),(*intval)();
  264. #endif
  265.  
  266.     if (!reset) {
  267.     hupval = signal(SIGHUP, SIG_IGN);
  268.     if (hupval != SIG_IGN)
  269. #ifdef VOIDSIG
  270.         hupval = my_exit;
  271. #else
  272.         hupval = (int(*)())my_exit;
  273. #endif
  274.     intval = signal(SIGINT, SIG_IGN);
  275.     if (intval != SIG_IGN)
  276. #ifdef VOIDSIG
  277.         intval = my_exit;
  278. #else
  279.         intval = (int(*)())my_exit;
  280. #endif
  281.     }
  282.     Signal(SIGHUP, hupval);
  283.     Signal(SIGINT, intval);
  284. #endif
  285. }
  286.  
  287. /* How to handle certain events when in a critical region. */
  288.  
  289. void
  290. ignore_signals()
  291. {
  292. #ifndef lint
  293.     Signal(SIGHUP, SIG_IGN);
  294.     Signal(SIGINT, SIG_IGN);
  295. #endif
  296. }
  297.  
  298. /* Make sure we'll have the directories to create a file. */
  299.  
  300. void
  301. makedirs(filename,striplast)
  302. Reg1 char *filename;
  303. bool striplast;
  304. {
  305.     char tmpbuf[256];
  306.     Reg2 char *s = tmpbuf;
  307.     char *dirv[20];
  308.     Reg3 int i;
  309.     Reg4 int dirvp = 0;
  310.  
  311.     while (*filename) {
  312.     if (*filename == '/') {
  313.         filename++;
  314.         dirv[dirvp++] = s;
  315.         *s++ = '\0';
  316.     }
  317.     else {
  318.         *s++ = *filename++;
  319.     }
  320.     }
  321.     *s = '\0';
  322.     dirv[dirvp] = s;
  323.     if (striplast)
  324.     dirvp--;
  325.     if (dirvp < 0)
  326.     return;
  327.     strcpy(buf, "mkdir");
  328.     s = buf;
  329.     for (i=0; i<=dirvp; i++) {
  330.     while (*s) s++;
  331.     *s++ = ' ';
  332.     strcpy(s, tmpbuf);
  333.     *dirv[i] = '/';
  334.     }
  335.     system(buf);
  336. }
  337.  
  338. /* Make filenames more reasonable. */
  339.  
  340. char *
  341. fetchname(at,strip_leading,assume_exists)
  342. char *at;
  343. int strip_leading;
  344. int assume_exists;
  345. {
  346.     char *s;
  347.     char *name;
  348.     Reg1 char *t;
  349.     char tmpbuf[200];
  350.  
  351.     if (!at)
  352.     return Nullch;
  353.     s = savestr(at);
  354.     for (t=s; isspace(*t); t++) ;
  355.     name = t;
  356. #ifdef DEBUGGING
  357.     if (debug & 128)
  358. #if 1
  359.     say4("fetchname |%s| %s %d %d\n",at,name,strip_leading,assume_exists);
  360. #else
  361.     say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
  362. #endif
  363. #endif
  364.     if (strnEQ(name, "/dev/null", 9))    /* so files can be created by diffing */
  365.     return Nullch;            /*   against /dev/null. */
  366.     for (; *t && !isspace(*t); t++)
  367.     if (*t == '/')
  368.         if (--strip_leading >= 0)
  369.         name = t+1;
  370.     *t = '\0';
  371.     if (name != s && *s != '/') {
  372.     name[-1] = '\0';
  373.     if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
  374.         name[-1] = '/';
  375.         name=s;
  376.     }
  377.     }
  378.     name = savestr(name);
  379.     Sprintf(tmpbuf, "RCS/%s", name);
  380.     free(s);
  381.     if (stat(name, &filestat) < 0 && !assume_exists) {
  382. #ifndef TOS
  383.     Strcat(tmpbuf, RCSSUFFIX);
  384.     if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
  385.         Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
  386.         if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
  387.         free(name);
  388.         name = Nullch;
  389.         }
  390.     }
  391. #else
  392.     free(name);
  393.         name = Nullch;
  394. #endif
  395.     }
  396.     return name;
  397. }
  398.  
  399. /* this kludge is necessary because stdin is most likely re-directed
  400.    and there is no way to read from CON: due to the braindamage
  401.    in handles -- thanks Atari
  402.  */
  403. #ifdef TOS
  404. #undef Fclose
  405. #undef Fseek
  406. #include <osbind.h>
  407. int _tos_ask(buf)
  408. char *buf;
  409. {
  410.     /* have to el-kludge it */
  411.     int c;
  412.     int r = 0;
  413.     char *p = buf;
  414.  
  415.     write(2, buf, strlen(buf));
  416.  
  417.     while(( c = (Bconin(2) & 0x7f)) != '\r')
  418.     {
  419.     switch(c)
  420.         {   /* we dont handle tabs/control chars nicely here */
  421.         case 0:
  422.         break;
  423.         case '\b':
  424.         case 0177:
  425.         if(r > 0)
  426.         { --p; --r; }
  427.         Bconout(2, '\b'); Bconout(2, ' '); Bconout(2, '\b');
  428.             break;
  429.         default:
  430.         if(c >= ' ')
  431.         {
  432.             *p++ = c; r++;
  433.             Bconout(2, c);
  434.         }
  435.         /* else ignore control chars/tabs */
  436.     }
  437.     }
  438.     Bconout(2, '\r');
  439.     Bconout(2, '\n');
  440.     *p++ = '\n'; *p = '\0';
  441.     return r+1;
  442. }
  443. #endif /* TOS */
  444.