Home | History | Annotate | Line # | Download | only in patch
util.c revision 1.1.1.1
      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     Strcpy(bakname, to);
     35     Strcat(bakname, origext?origext:ORIGEXT);
     36     if (stat(to, &filestat) >= 0) {	/* output file exists */
     37 	dev_t to_device = filestat.st_dev;
     38 	ino_t to_inode  = filestat.st_ino;
     39 	char *simplename = bakname;
     40 
     41 	for (s=bakname; *s; s++) {
     42 	    if (*s == '/')
     43 		simplename = s+1;
     44 	}
     45 	/* find a backup name that is not the same file */
     46 	while (stat(bakname, &filestat) >= 0 &&
     47 		to_device == filestat.st_dev && to_inode == filestat.st_ino) {
     48 	    for (s=simplename; *s && !islower(*s); s++) ;
     49 	    if (*s)
     50 		*s = toupper(*s);
     51 	    else
     52 		Strcpy(simplename, simplename+1);
     53 	}
     54 	while (unlink(bakname) >= 0) ;	/* while() is for benefit of Eunice */
     55 #ifdef DEBUGGING
     56 	if (debug & 4)
     57 	    say3("Moving %s to %s.\n", to, bakname);
     58 #endif
     59 	if (link(to, bakname) < 0) {
     60 	    say3("patch: can't backup %s, output is in %s\n",
     61 		to, from);
     62 	    return -1;
     63 	}
     64 	while (unlink(to) >= 0) ;
     65     }
     66 #ifdef DEBUGGING
     67     if (debug & 4)
     68 	say3("Moving %s to %s.\n", from, to);
     69 #endif
     70     if (link(from, to) < 0) {		/* different file system? */
     71 	Reg4 int tofd;
     72 
     73 	tofd = creat(to, 0666);
     74 	if (tofd < 0) {
     75 	    say3("patch: can't create %s, output is in %s.\n",
     76 	      to, from);
     77 	    return -1;
     78 	}
     79 	fromfd = open(from, 0);
     80 	if (fromfd < 0)
     81 	    fatal2("patch: internal error, can't reopen %s\n", from);
     82 	while ((i=read(fromfd, buf, sizeof buf)) > 0)
     83 	    if (write(tofd, buf, i) != i)
     84 		fatal1("patch: write failed\n");
     85 	Close(fromfd);
     86 	Close(tofd);
     87     }
     88     Unlink(from);
     89     return 0;
     90 }
     91 
     92 /* Copy a file. */
     93 
     94 void
     95 copy_file(from,to)
     96 char *from, *to;
     97 {
     98     Reg3 int tofd;
     99     Reg2 int fromfd;
    100     Reg1 int i;
    101 
    102     tofd = creat(to, 0666);
    103     if (tofd < 0)
    104 	fatal2("patch: can't create %s.\n", to);
    105     fromfd = open(from, 0);
    106     if (fromfd < 0)
    107 	fatal2("patch: internal error, can't reopen %s\n", from);
    108     while ((i=read(fromfd, buf, sizeof buf)) > 0)
    109 	if (write(tofd, buf, i) != i)
    110 	    fatal2("patch: write (%s) failed\n", to);
    111     Close(fromfd);
    112     Close(tofd);
    113 }
    114 
    115 /* Allocate a unique area for a string. */
    116 
    117 char *
    118 savestr(s)
    119 Reg1 char *s;
    120 {
    121     Reg3 char *rv;
    122     Reg2 char *t;
    123 
    124     if (!s)
    125 	s = "Oops";
    126     t = s;
    127     while (*t++);
    128     rv = malloc((MEM) (t - s));
    129     if (rv == Nullch) {
    130 	if (using_plan_a)
    131 	    out_of_mem = TRUE;
    132 	else
    133 	    fatal1("patch: out of memory (savestr)\n");
    134     }
    135     else {
    136 	t = rv;
    137 	while (*t++ = *s++);
    138     }
    139     return rv;
    140 }
    141 
    142 #if defined(lint) && defined(CANVARARG)
    143 
    144 /*VARARGS ARGSUSED*/
    145 say(pat) char *pat; { ; }
    146 /*VARARGS ARGSUSED*/
    147 fatal(pat) char *pat; { ; }
    148 /*VARARGS ARGSUSED*/
    149 ask(pat) char *pat; { ; }
    150 
    151 #else
    152 
    153 /* Vanilla terminal output (buffered). */
    154 
    155 void
    156 say(pat,arg1,arg2,arg3)
    157 char *pat;
    158 int arg1,arg2,arg3;
    159 {
    160     fprintf(stderr, pat, arg1, arg2, arg3);
    161     Fflush(stderr);
    162 }
    163 
    164 /* Terminal output, pun intended. */
    165 
    166 void				/* very void */
    167 fatal(pat,arg1,arg2,arg3)
    168 char *pat;
    169 int arg1,arg2,arg3;
    170 {
    171     void my_exit();
    172 
    173     say(pat, arg1, arg2, arg3);
    174     my_exit(1);
    175 }
    176 
    177 /* Get a response from the user, somehow or other. */
    178 
    179 void
    180 ask(pat,arg1,arg2,arg3)
    181 char *pat;
    182 int arg1,arg2,arg3;
    183 {
    184     int ttyfd;
    185     int r;
    186     bool tty2 = isatty(2);
    187 
    188     Sprintf(buf, pat, arg1, arg2, arg3);
    189     Fflush(stderr);
    190     write(2, buf, strlen(buf));
    191     if (tty2) {				/* might be redirected to a file */
    192 	r = read(2, buf, sizeof buf);
    193     }
    194     else if (isatty(1)) {		/* this may be new file output */
    195 	Fflush(stdout);
    196 	write(1, buf, strlen(buf));
    197 	r = read(1, buf, sizeof buf);
    198     }
    199     else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
    200 					/* might be deleted or unwriteable */
    201 	write(ttyfd, buf, strlen(buf));
    202 	r = read(ttyfd, buf, sizeof buf);
    203 	Close(ttyfd);
    204     }
    205     else if (isatty(0)) {		/* this is probably patch input */
    206 	Fflush(stdin);
    207 	write(0, buf, strlen(buf));
    208 	r = read(0, buf, sizeof buf);
    209     }
    210     else {				/* no terminal at all--default it */
    211 	buf[0] = '\n';
    212 	r = 1;
    213     }
    214     if (r <= 0)
    215 	buf[0] = 0;
    216     else
    217 	buf[r] = '\0';
    218     if (!tty2)
    219 	say1(buf);
    220 }
    221 #endif lint
    222 
    223 /* How to handle certain events when not in a critical region. */
    224 
    225 void
    226 set_signals()
    227 {
    228     void my_exit();
    229 
    230 #ifndef lint
    231     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
    232 	Signal(SIGHUP, my_exit);
    233     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
    234 	Signal(SIGINT, my_exit);
    235 #endif
    236 }
    237 
    238 /* How to handle certain events when in a critical region. */
    239 
    240 void
    241 ignore_signals()
    242 {
    243 #ifndef lint
    244     Signal(SIGHUP, SIG_IGN);
    245     Signal(SIGINT, SIG_IGN);
    246 #endif
    247 }
    248 
    249 /* Make sure we'll have the directories to create a file. */
    250 
    251 void
    252 makedirs(filename,striplast)
    253 Reg1 char *filename;
    254 bool striplast;
    255 {
    256     char tmpbuf[256];
    257     Reg2 char *s = tmpbuf;
    258     char *dirv[20];
    259     Reg3 int i;
    260     Reg4 int dirvp = 0;
    261 
    262     while (*filename) {
    263 	if (*filename == '/') {
    264 	    filename++;
    265 	    dirv[dirvp++] = s;
    266 	    *s++ = '\0';
    267 	}
    268 	else {
    269 	    *s++ = *filename++;
    270 	}
    271     }
    272     *s = '\0';
    273     dirv[dirvp] = s;
    274     if (striplast)
    275 	dirvp--;
    276     if (dirvp < 0)
    277 	return;
    278     strcpy(buf, "mkdir");
    279     s = buf;
    280     for (i=0; i<=dirvp; i++) {
    281 	while (*s) s++;
    282 	*s++ = ' ';
    283 	strcpy(s, tmpbuf);
    284 	*dirv[i] = '/';
    285     }
    286     system(buf);
    287 }
    288 
    289 /* Make filenames more reasonable. */
    290 
    291 char *
    292 fetchname(at,strip_leading,assume_exists)
    293 char *at;
    294 int strip_leading;
    295 int assume_exists;
    296 {
    297     char *s;
    298     char *name;
    299     Reg1 char *t;
    300     char tmpbuf[200];
    301 
    302     if (!at)
    303 	return Nullch;
    304     s = savestr(at);
    305     for (t=s; isspace(*t); t++) ;
    306     name = t;
    307 #ifdef DEBUGGING
    308     if (debug & 128)
    309 	say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
    310 #endif
    311     if (strnEQ(name, "/dev/null", 9))	/* so files can be created by diffing */
    312 	return Nullch;			/*   against /dev/null. */
    313     for (; *t && !isspace(*t); t++)
    314 	if (*t == '/')
    315 	    if (--strip_leading >= 0)
    316 		name = t+1;
    317     *t = '\0';
    318     if (name != s && *s != '/') {
    319 	name[-1] = '\0';
    320 	if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
    321 	    name[-1] = '/';
    322 	    name=s;
    323 	}
    324     }
    325     name = savestr(name);
    326     Sprintf(tmpbuf, "RCS/%s", name);
    327     free(s);
    328     if (stat(name, &filestat) < 0 && !assume_exists) {
    329 	Strcat(tmpbuf, RCSSUFFIX);
    330 	if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
    331 	    Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
    332 	    if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
    333 		free(name);
    334 		name = Nullch;
    335 	    }
    336 	}
    337     }
    338     return name;
    339 }
    340