home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / rcs / sources / util.c < prev    next >
C/C++ Source or Header  |  1991-12-24  |  11KB  |  528 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. char *strchr();
  9. char *strrchr();
  10.  
  11. int
  12. move_file(from,to)
  13. char *from, *to;
  14. {
  15.     char bakname[512];
  16.     Reg1 char *s;
  17.     Reg2 int i;
  18.     Reg3 int fromfd;
  19.  
  20.     /* to stdout? */
  21.  
  22.     if (strEQ(to, "-")) {
  23. #ifdef DEBUGGING
  24.     if (debug & 4)
  25.         say2("Moving %s to stdout.\n", from);
  26. #endif
  27.         fromfd = open(from, O_RDONLY|O_BINARY);
  28.     if (fromfd < 0)
  29.         fatal2("patch: internal error, can't reopen %s\n", from);
  30.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  31.         if (write(1, buf, i) != 1)
  32.         fatal1("patch: write failed\n");
  33.     Close(fromfd);
  34.     return 0;
  35.     }
  36.  
  37.     if (origprae) {
  38.         Strcpy (bakname, origprae);
  39.         Strcat(bakname, to);
  40.     } else {
  41.            Strcpy(bakname, to);
  42. #ifdef OS2
  43.         s = strchr(bakname, 0);
  44. #endif
  45.         Strcat(bakname, origext?origext:ORIGEXT);
  46. #ifdef OS2
  47.         if ( !IsFileNameValid(bakname) )
  48.         {
  49.           *s=0;
  50.  
  51.           if ((s=strrchr(bakname,'.'))!=NULL)
  52.             *s=0;
  53.  
  54.           strcat(bakname, ".org");
  55.         }
  56. #endif
  57.     }
  58.  
  59.     if (stat(to, &filestat) >= 0) {    /* output file exists */
  60.     dev_t to_device = filestat.st_dev;
  61.     ino_t to_inode  = filestat.st_ino;
  62.     char *simplename = bakname;
  63.  
  64.     for (s=bakname; *s; s++) {
  65. #ifdef OS2
  66.             if (*s == '/' || *s == '\\')
  67. #else
  68.         if (*s == '/')
  69. #endif
  70.         simplename = s+1;
  71.     }
  72.     /* find a backup name that is not the same file */
  73.     while (stat(bakname, &filestat) >= 0 &&
  74.         to_device == filestat.st_dev && to_inode == filestat.st_ino) {
  75.         for (s=simplename; *s && !islower(*s); s++) ;
  76.         if (*s)
  77.         *s = toupper(*s);
  78.         else
  79.         Strcpy(simplename, simplename+1);
  80.     }
  81.     while (unlink(bakname) >= 0) ;    /* while() is for benefit of Eunice */
  82. #ifdef DEBUGGING
  83.     if (debug & 4)
  84.         say3("Moving %s to %s.\n", to, bakname);
  85. #endif
  86.  
  87. #ifdef OS2
  88.         if (rename(to, bakname) < 0) {
  89. #else
  90.     if (link(to, bakname) < 0) {
  91. #endif
  92.         say3("patch: can't backup %s, output is in %s\n",
  93.         to, from);
  94.         return -1;
  95.     }
  96.  
  97. #ifndef OS2
  98.     while (unlink(to) >= 0) ;
  99. #endif
  100.     }
  101.  
  102. #ifdef DEBUGGING
  103.     if (debug & 4)
  104.     say3("Moving %s to %s.\n", from, to);
  105. #endif
  106.  
  107. #ifdef OS2
  108.     if (rename(from, to) < 0) {           /* different file system? */
  109. #else
  110.     if (link(from, to) < 0) {        /* different file system? */
  111. #endif
  112.     Reg4 int tofd;
  113.  
  114.         tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE|S_IREAD);
  115.     if (tofd < 0) {
  116.         say3("patch: can't create %s, output is in %s.\n",
  117.           to, from);
  118.         return -1;
  119.     }
  120.  
  121.         fromfd = open(from, O_RDONLY|O_BINARY);
  122.     if (fromfd < 0)
  123.         fatal2("patch: internal error, can't reopen %s\n", from);
  124.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  125.         if (write(tofd, buf, i) != i)
  126.         fatal1("patch: write failed\n");
  127.     Close(fromfd);
  128.     Close(tofd);
  129. #ifdef OS2
  130.     Unlink(from);
  131.     }
  132. #else
  133.     }
  134.     Unlink(from);
  135. #endif
  136.     return 0;
  137. }
  138.  
  139. /* Copy a file. */
  140.  
  141. void
  142. copy_file(from,to)
  143. char *from, *to;
  144. {
  145.     Reg3 int tofd;
  146.     Reg2 int fromfd;
  147.     Reg1 int i;
  148.  
  149.     tofd = open(to, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE|S_IREAD);
  150.     if (tofd < 0)
  151.     fatal2("patch: can't create %s.\n", to);
  152.     fromfd = open(from, O_RDONLY|O_BINARY);
  153.     if (fromfd < 0)
  154.     fatal2("patch: internal error, can't reopen %s\n", from);
  155.     while ((i=read(fromfd, buf, sizeof buf)) > 0)
  156.     if (write(tofd, buf, i) != i)
  157.         fatal2("patch: write (%s) failed\n", to);
  158.     Close(fromfd);
  159.     Close(tofd);
  160. }
  161.  
  162. /* Allocate a unique area for a string. */
  163.  
  164. char *
  165. savestr(s)
  166. Reg1 char *s;
  167. {
  168.     Reg3 char *rv;
  169.     Reg2 char *t;
  170.  
  171.     if (!s)
  172.     s = "Oops";
  173.     t = s;
  174.     while (*t++);
  175.     rv = malloc((MEM) (t - s));
  176.     if (rv == Nullch) {
  177.     if (using_plan_a)
  178.         out_of_mem = TRUE;
  179.     else
  180.         fatal1("patch: out of memory (savestr)\n");
  181.     }
  182.     else {
  183.     t = rv;
  184.     while (*t++ = *s++);
  185.     }
  186.     return rv;
  187. }
  188.  
  189. #if defined(lint) && defined(CANVARARG)
  190.  
  191. /*VARARGS ARGSUSED*/
  192. say(pat) char *pat; { ; }
  193. /*VARARGS ARGSUSED*/
  194. fatal(pat) char *pat; { ; }
  195. /*VARARGS ARGSUSED*/
  196. ask(pat) char *pat; { ; }
  197.  
  198. #else
  199.  
  200. /* Vanilla terminal output (buffered). */
  201.  
  202. #ifdef OS2
  203. #include <stdarg.h>
  204.  
  205. void say(char *pat,...)
  206. {
  207.     va_list argptr;
  208.  
  209.     va_start(argptr, pat);
  210.     vfprintf(stderr, pat, argptr);
  211.     va_end(argptr);
  212.     Fflush(stderr);
  213. }
  214.  
  215. void fatal(char *pat,...)
  216. {
  217.     void my_exit();
  218.     va_list argptr;
  219.  
  220.     va_start(argptr, pat);
  221.     vfprintf(stderr, pat, argptr);
  222.     va_end(argptr);
  223.     Fflush(stderr);
  224.     my_exit(1);
  225. }
  226.  
  227. #else
  228. void
  229. say(pat,arg1,arg2,arg3)
  230. char *pat;
  231. long arg1,arg2,arg3;
  232. {
  233.     fprintf(stderr, pat, arg1, arg2, arg3);
  234.     Fflush(stderr);
  235. }
  236.  
  237. /* Terminal output, pun intended. */
  238.  
  239. void                /* very void */
  240. fatal(pat,arg1,arg2,arg3)
  241. char *pat;
  242. long arg1,arg2,arg3;
  243. {
  244.     void my_exit();
  245.  
  246.     say(pat, arg1, arg2, arg3);
  247.     my_exit(1);
  248. }
  249. #endif
  250.  
  251. /* Get a response from the user, somehow or other. */
  252.  
  253. #ifdef OS2
  254. void ask(char *pat,...)
  255. {
  256.     int ttyfd;
  257.     int r;
  258.     bool tty2 = isatty(2);
  259.     va_list argptr;
  260.  
  261.     va_start(argptr, pat);
  262.     vsprintf(buf, pat, argptr);
  263.     va_end(argptr);
  264. #else
  265. void
  266. ask(pat,arg1,arg2,arg3)
  267. char *pat;
  268. long arg1,arg2,arg3;
  269. {
  270.     int ttyfd;
  271.     int r;
  272.     bool tty2 = isatty(2);
  273.  
  274.     Sprintf(buf, pat, arg1, arg2, arg3);
  275. #endif
  276.     Fflush(stderr);
  277.     write(2, buf, strlen(buf));
  278.     if (tty2) {                /* might be redirected to a file */
  279.     r = read(2, buf, sizeof buf);
  280.     }
  281.     else if (isatty(1)) {        /* this may be new file output */
  282.     Fflush(stdout);
  283.     write(1, buf, strlen(buf));
  284.     r = read(1, buf, sizeof buf);
  285.     }
  286. #ifdef OS2
  287.     else if ((ttyfd = open("con", O_RDWR)) >= 0 && isatty(ttyfd)) {
  288. #else
  289.     else if ((ttyfd = open("/dev/tty", O_RDWR)) >= 0 && isatty(ttyfd)) {
  290. #endif
  291.                     /* might be deleted or unwriteable */
  292.     write(ttyfd, buf, strlen(buf));
  293.     r = read(ttyfd, buf, sizeof buf);
  294.     Close(ttyfd);
  295.     }
  296.     else if (isatty(0)) {        /* this is probably patch input */
  297.     Fflush(stdin);
  298.     write(0, buf, strlen(buf));
  299.     r = read(0, buf, sizeof buf);
  300.     }
  301.     else {                /* no terminal at all--default it */
  302.     buf[0] = '\n';
  303.     r = 1;
  304.     }
  305.     if (r <= 0)
  306.     buf[0] = 0;
  307.     else
  308.     buf[r] = '\0';
  309.     if (!tty2)
  310.     say1(buf);
  311. }
  312. #endif /* lint */
  313.  
  314. /* How to handle certain events when not in a critical region. */
  315.  
  316. void
  317. set_signals(reset)
  318. int reset;
  319. {
  320.     void my_exit();
  321. #ifndef lint
  322. #ifdef VOIDSIG
  323.     static void (*hupval)(),(*intval)();
  324. #else
  325.     static int (*hupval)(),(*intval)();
  326. #endif
  327.  
  328.     if (!reset) {
  329. #ifndef OS2
  330.     hupval = signal(SIGHUP, SIG_IGN);
  331.     if (hupval != SIG_IGN)
  332. #ifdef VOIDSIG
  333.         hupval = my_exit;
  334. #else
  335.         hupval = (int(*)())my_exit;
  336. #endif
  337. #endif
  338.     intval = signal(SIGINT, SIG_IGN);
  339.     if (intval != SIG_IGN)
  340. #ifdef VOIDSIG
  341.         intval = my_exit;
  342. #else
  343.         intval = (int(*)())my_exit;
  344. #endif
  345.     }
  346. #ifndef OS2
  347.     Signal(SIGHUP, hupval);
  348. #endif
  349.     Signal(SIGINT, intval);
  350. #endif
  351. }
  352.  
  353. /* How to handle certain events when in a critical region. */
  354.  
  355. void
  356. ignore_signals()
  357. {
  358. #ifndef lint
  359. #ifndef OS2
  360.     Signal(SIGHUP, SIG_IGN);
  361. #endif
  362.     Signal(SIGINT, SIG_IGN);
  363. #endif
  364. }
  365.  
  366. /* Make sure we'll have the directories to create a file. */
  367.  
  368. void
  369. makedirs(filename,striplast)
  370. Reg1 char *filename;
  371. bool striplast;
  372. {
  373.     char tmpbuf[256];
  374.     Reg2 char *s = tmpbuf;
  375.     char *dirv[20];
  376.     Reg3 int i;
  377.     Reg4 int dirvp = 0;
  378.  
  379.     while (*filename) {
  380. #ifdef OS2
  381.         if (*filename == '/' || *filename == '\\') {
  382. #else
  383.     if (*filename == '/') {
  384. #endif
  385.         filename++;
  386.         dirv[dirvp++] = s;
  387.         *s++ = '\0';
  388.     }
  389.     else {
  390.         *s++ = *filename++;
  391.     }
  392.     }
  393.     *s = '\0';
  394.     dirv[dirvp] = s;
  395.     if (striplast)
  396.     dirvp--;
  397.     if (dirvp < 0)
  398.     return;
  399.     strcpy(buf, "mkdir");
  400.     s = buf;
  401.     for (i=0; i<=dirvp; i++) {
  402.     while (*s) s++;
  403.     *s++ = ' ';
  404.     strcpy(s, tmpbuf);
  405.     *dirv[i] = '/';
  406.     }
  407.     system(buf);
  408. }
  409.  
  410. /* Make filenames more reasonable. */
  411.  
  412. char *
  413. fetchname(at,strip_leading,assume_exists)
  414. char *at;
  415. int strip_leading;
  416. int assume_exists;
  417. {
  418.     char *s;
  419.     char *name;
  420.     Reg1 char *t;
  421.     char tmpbuf[200];
  422.  
  423.     if (!at)
  424.     return Nullch;
  425.     s = savestr(at);
  426.     for (t=s; isspace(*t); t++) ;
  427.     name = t;
  428. #ifdef DEBUGGING
  429.     if (debug & 128)
  430.     say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
  431. #endif
  432.     if (strnEQ(name, "/dev/null", 9))    /* so files can be created by diffing */
  433.     return Nullch;            /*   against /dev/null. */
  434.     for (; *t && !isspace(*t); t++)
  435. #ifdef OS2
  436.         if (*t == '/' || *t == '\\')
  437. #else
  438.     if (*t == '/')
  439. #endif
  440.         if (--strip_leading >= 0)
  441.         name = t+1;
  442.     *t = '\0';
  443. #ifdef OS2
  444.     if (name != s && *s != '/' && *s != '\\') {
  445. #else
  446.     if (name != s && *s != '/') {
  447. #endif
  448.     name[-1] = '\0';
  449.     if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
  450.         name[-1] = '/';
  451.         name=s;
  452.     }
  453.     }
  454.     name = savestr(name);
  455.     Sprintf(tmpbuf, "RCS/%s", name);
  456.     free(s);
  457.     if (stat(name, &filestat) < 0 && !assume_exists) {
  458.     Strcat(tmpbuf, RCSSUFFIX);
  459.     if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
  460.         Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
  461.         if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
  462.         free(name);
  463.         name = Nullch;
  464.         }
  465.     }
  466.     }
  467.     return name;
  468. }
  469.  
  470.  
  471. #ifdef OS2
  472.  
  473. /* only one pipe can be open at a time */
  474.  
  475. /* In fact, this is a pipe simulation for the dumb MS-DOS */
  476. /* but it works good enough for the situation where it is */
  477. /* needed in patch, even if OS/2 has real pipes. */
  478.  
  479. static char pipename[128], command[128];
  480. static int wrpipe;
  481.  
  482. FILE *popen(char *cmd, char *flags)
  483. {
  484.   wrpipe = (strchr(flags, 'w') != NULL);
  485.  
  486.   if ( wrpipe )
  487.   {
  488.     strcpy(command, cmd);
  489.     strcpy(pipename, "~WXXXXXX");
  490.     Mktemp(pipename);
  491.     return fopen(pipename, flags);  /* ordinary file */
  492.   }
  493.   else
  494.   {
  495.     strcpy(pipename, "~RXXXXXX");
  496.     Mktemp(pipename);
  497.     strcpy(command, cmd);
  498.     strcat(command, ">");
  499.     strcat(command, pipename);
  500.     system(command);
  501.     return fopen(pipename, flags);  /* ordinary file */
  502.   }
  503. }
  504.  
  505. int pclose(FILE *pipe)
  506. {
  507.   int rc;
  508.  
  509.   if ( fclose(pipe) == EOF )
  510.     return EOF;
  511.  
  512.   if ( wrpipe )
  513.   {
  514.     strcat(command, "<");
  515.     strcat(command, pipename);
  516.     rc = system(command);
  517.     unlink(pipename);
  518.     return rc;
  519.   }
  520.   else
  521.   {
  522.     unlink(pipename);
  523.     return 0;
  524.   }
  525. }
  526.  
  527. #endif
  528.