]> Dogcows Code - chaz/tar/blob - src/port.c
Initial revision
[chaz/tar] / src / port.c
1 /* Supporting routines which may sometimes be missing.
2 Copyright (C) 1988 Free Software Foundation
3
4 This file is part of GNU Tar.
5
6 GNU Tar is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Tar is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Tar; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <signal.h>
23 #include <errno.h>
24 #ifndef STDC_HEADERS
25 extern int errno;
26 #endif
27
28 #ifdef BSD42
29 #include <sys/file.h>
30 #else
31 #ifndef V7
32 #include <fcntl.h>
33 #endif
34 #endif
35
36 #include "tar.h"
37 #include "port.h"
38
39 extern long baserec;
40
41 /* All machine-dependent #ifdefs should appear here, instead of
42 being scattered through the file. For UN*X systems, it is better to
43 figure out what is needed in the configure script, for most of the
44 features. */
45
46 #ifdef __MSDOS__
47 char TTY_NAME[] = "con";
48
49 #define MKNOD_MISSING
50 #define UTILS_MISSING
51 #define VALLOC_MISSING
52
53 #else /* not __MSDOS__ */
54
55 char TTY_NAME[] ="/dev/tty";
56
57 #define UTILS_MISSING
58 #define CK_PIPE_MISSING
59
60 #endif /* not __MSDOS__ */
61
62 /* End of system-dependent #ifdefs */
63
64
65 #ifdef VALLOC_MISSING
66 /*
67 * valloc() does a malloc() on a page boundary. On some systems,
68 * this can make large block I/O more efficient.
69 */
70 char *
71 valloc (size)
72 unsigned size;
73 {
74 return (malloc (size));
75 }
76 #endif
77
78 #ifdef MKDIR_MISSING
79 /*
80 * Written by Robert Rother, Mariah Corporation, August 1985.
81 *
82 * If you want it, it's yours. All I ask in return is that if you
83 * figure out how to do this in a Bourne Shell script you send me
84 * a copy.
85 * sdcsvax!rmr or rmr@uscd
86 *
87 * Severely hacked over by John Gilmore to make a 4.2BSD compatible
88 * subroutine. 11Mar86; hoptoad!gnu
89 *
90 * Modified by rmtodd@uokmax 6-28-87 -- when making an already existing dir,
91 * subroutine didn't return EEXIST. It does now.
92 */
93
94 /*
95 * Make a directory.
96 */
97 int
98 mkdir(dpath, dmode)
99 char *dpath;
100 int dmode;
101 {
102 int cpid, status;
103 struct stat statbuf;
104
105 if (stat(dpath,&statbuf) == 0) {
106 errno = EEXIST; /* Stat worked, so it already exists */
107 return -1;
108 }
109
110 /* If stat fails for a reason other than non-existence, return error */
111 if (errno != ENOENT) return -1;
112
113 switch (cpid = fork()) {
114
115 case -1: /* Error in fork() */
116 return(-1); /* Errno is set already */
117
118 case 0: /* Child process */
119 /*
120 * Cheap hack to set mode of new directory. Since this
121 * child process is going away anyway, we zap its umask.
122 * FIXME, this won't suffice to set SUID, SGID, etc. on this
123 * directory. Does anybody care?
124 */
125 status = umask(0); /* Get current umask */
126 status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
127 execl("/bin/mkdir", "mkdir", dpath, (char *)0);
128 _exit(-1); /* Can't exec /bin/mkdir */
129
130 default: /* Parent process */
131 while (cpid != wait(&status)) ; /* Wait for kid to finish */
132 }
133
134 if (WTERMSIG(status) != 0 || WEXITSTATUS(status) != 0) {
135 errno = EIO; /* We don't know why, but */
136 return -1; /* /bin/mkdir failed */
137 }
138
139 return 0;
140 }
141
142 int
143 rmdir(dpath)
144 char *dpath;
145 {
146 int cpid, status;
147 struct stat statbuf;
148
149 if (stat(dpath,&statbuf) != 0) {
150 /* Stat just set errno. We don't have to */
151 return -1;
152 }
153
154 switch (cpid = fork()) {
155
156 case -1: /* Error in fork() */
157 return(-1); /* Errno is set already */
158
159 case 0: /* Child process */
160 execl("/bin/rmdir", "rmdir", dpath, (char *)0);
161 _exit(-1); /* Can't exec /bin/mkdir */
162
163 default: /* Parent process */
164 while (cpid != wait(&status)) ; /* Wait for kid to finish */
165 }
166
167 if (WTERMSIG(status) != 0 || WEXITSTATUS(status) != 0) {
168 errno = EIO; /* We don't know why, but */
169 return -1; /* /bin/mkdir failed */
170 }
171
172 return 0;
173 }
174 #endif
175
176 #ifdef RENAME_MISSING
177 /* Rename file FROM to file TO.
178 Return 0 if successful, -1 if not. */
179
180 int
181 rename (from, to)
182 char *from;
183 char *to;
184 {
185 struct stat from_stats;
186
187 if (stat (from, &from_stats) == 0)
188 {
189 if (unlink (to) && errno != ENOENT)
190 return -1;
191 if (link (from, to) == 0 && (unlink (from) == 0 || errno == ENOENT))
192 return 0;
193 }
194 return -1;
195 }
196 #endif
197
198 #ifdef BZERO_MISSING
199 /* Minix has bcopy but not bzero, and no memset. Thanks, Andy. */
200 void
201 bzero (s1, n)
202 register char *s1;
203 register int n;
204 {
205 while (n--) *s1++ = '\0';
206 }
207
208 /* It also has no bcmp() */
209 int
210 bcmp (s1, s2, n)
211 register char *s1,*s2;
212 register int n;
213 {
214 for ( ; n-- ; ++s1, ++s2) {
215 if (*s1 != *s2) return *s1 - *s2;
216 }
217 return 0;
218 }
219
220 /*
221 * Groan, Minix doesn't have execlp either!
222 *
223 * execlp(file,arg0,arg1...argn,(char *)NULL)
224 * exec a program, automatically searching for the program through
225 * all the directories on the PATH.
226 *
227 * This version is naive about variable argument lists, it assumes
228 * a straightforward C calling sequence. If your system has odd stacks
229 * *and* doesn't have execlp, YOU get to fix it.
230 */
231 int
232 execlp(filename, arg0)
233 char *filename, *arg0;
234 {
235 register char *p, *path;
236 register char *fnbuffer;
237 char **argstart = &arg0;
238 struct stat statbuf;
239 extern char **environ;
240
241 if ((p = getenv("PATH")) == NULL) {
242 /* couldn't find path variable -- try to exec given filename */
243 return execve(filename, argstart, environ);
244 }
245
246 /*
247 * make a place to build the filename. We malloc larger than we
248 * need, but we know it will fit in this.
249 */
250 fnbuffer = malloc( strlen(p) + 1 + strlen(filename) );
251 if (fnbuffer == NULL) {
252 errno = ENOMEM;
253 return -1;
254 }
255
256 /*
257 * try each component of the path to see if the file's there
258 * and executable.
259 */
260 for (path = p ; path ; path = p) {
261 /* construct full path name to try */
262 if ((p = index(path,':')) == NULL) {
263 strcpy(fnbuffer, path);
264 } else {
265 strncpy(fnbuffer, path, p-path);
266 fnbuffer[p-path] = '\0';
267 p++; /* Skip : for next time */
268 }
269 if (strlen(fnbuffer) != 0)
270 strcat(fnbuffer,"/");
271 strcat(fnbuffer,filename);
272
273 /* check to see if file is there and is a normal file */
274 if (stat(fnbuffer, &statbuf) < 0) {
275 if (errno == ENOENT)
276 continue; /* file not there,keep on looking */
277 else
278 goto fail; /* failed for some reason, return */
279 }
280 if (!S_ISREG(statbuf.st_mode)) continue;
281
282 if (execve(fnbuffer, argstart, environ) < 0
283 && errno != ENOENT
284 && errno != ENOEXEC) {
285 /* failed, for some other reason besides "file
286 * not found" or "not a.out format"
287 */
288 goto fail;
289 }
290
291 /*
292 * If we got error ENOEXEC, the file is executable but is
293 * not an object file. Try to execute it as a shell script,
294 * returning error if we can't execute /bin/sh.
295 *
296 * FIXME, this code is broken in several ways. Shell
297 * scripts should not in general be executed by the user's
298 * SHELL variable program. On more mature systems, the
299 * script can specify with #!/bin/whatever. Also, this
300 * code clobbers argstart[-1] if the exec of the shell
301 * fails.
302 */
303 if (errno == ENOEXEC) {
304 char *shell;
305
306 /* Try to execute command "sh arg0 arg1 ..." */
307 if ((shell = getenv("SHELL")) == NULL)
308 shell = "/bin/sh";
309 argstart[-1] = shell;
310 argstart[0] = fnbuffer;
311 execve(shell, &argstart[-1], environ);
312 goto fail; /* Exec didn't work */
313 }
314
315 /*
316 * If we succeeded, the execve() doesn't return, so we
317 * can only be here is if the file hasn't been found yet.
318 * Try the next place on the path.
319 */
320 }
321
322 /* all attempts failed to locate the file. Give up. */
323 errno = ENOENT;
324
325 fail:
326 free(fnbuffer);
327 return -1;
328 }
329 #endif
330
331
332 #ifdef EMUL_OPEN3
333 #include "open3.h"
334 /*
335 * open3 -- routine to emulate the 3-argument open system
336 * call that is present in most modern Unix systems.
337 * This version attempts to support all the flag bits except for O_NDELAY
338 * and O_APPEND, which are silently ignored. The emulation is not as efficient
339 * as the real thing (at worst, 4 system calls instead of one), but there's
340 * not much I can do about that.
341 *
342 * Written 6/10/87 by rmtodd@uokmax
343 *
344 * open3(path, flag, mode)
345 * Attempts to open the file specified by
346 * the given pathname. The following flag bits (#defined in tar.h)
347 * specify options to the routine:
348 * O_RDONLY file open for read only
349 * O_WRONLY file open for write only
350 * O_RDWR file open for both read & write
351 * (Needless to say, you should only specify one of the above).
352 * O_CREAT file is created with specified mode if it needs to be.
353 * O_TRUNC if file exists, it is truncated to 0 bytes
354 * O_EXCL used with O_CREAT--routine returns error if file exists
355 * Function returns file descriptor if successful, -1 and errno if not.
356 */
357
358 /*
359 * array to give arguments to access for various modes
360 * FIXME, this table depends on the specific integer values of O_XXX,
361 * and also contains integers (args to 'access') that should be #define's.
362 */
363 static int modes[] =
364 {
365 04, /* O_RDONLY */
366 02, /* O_WRONLY */
367 06, /* O_RDWR */
368 06, /* invalid but we'd better cope -- O_WRONLY+O_RDWR */
369 };
370
371 /* Shut off the automatic emulation of open(), we'll need it. */
372 #undef open
373
374 int
375 open3(path, flags, mode)
376 char *path;
377 int flags, mode;
378 {
379 int exists = 1;
380 int call_creat = 0;
381 int fd;
382 /*
383 * We actually do the work by calling the open() or creat() system
384 * call, depending on the flags. Call_creat is true if we will use
385 * creat(), false if we will use open().
386 */
387
388 /*
389 * See if the file exists and is accessible in the requested mode.
390 *
391 * Strictly speaking we shouldn't be using access, since access checks
392 * against real uid, and the open call should check against euid.
393 * Most cases real uid == euid, so it won't matter. FIXME.
394 * FIXME, the construction "flags & 3" and the modes table depends
395 * on the specific integer values of the O_XXX #define's. Foo!
396 */
397 if (access(path,modes[flags & 3]) < 0) {
398 if (errno == ENOENT) {
399 /* the file does not exist */
400 exists = 0;
401 } else {
402 /* probably permission violation */
403 if (flags & O_EXCL) {
404 /* Oops, the file exists, we didn't want it. */
405 /* No matter what the error, claim EEXIST. */
406 errno = EEXIST;
407 }
408 return -1;
409 }
410 }
411
412 /* if we have the O_CREAT bit set, check for O_EXCL */
413 if (flags & O_CREAT) {
414 if ((flags & O_EXCL) && exists) {
415 /* Oops, the file exists and we didn't want it to. */
416 errno = EEXIST;
417 return -1;
418 }
419 /*
420 * If the file doesn't exist, be sure to call creat() so that
421 * it will be created with the proper mode.
422 */
423 if (!exists) call_creat = 1;
424 } else {
425 /* If O_CREAT isn't set and the file doesn't exist, error. */
426 if (!exists) {
427 errno = ENOENT;
428 return -1;
429 }
430 }
431
432 /*
433 * If the O_TRUNC flag is set and the file exists, we want to call
434 * creat() anyway, since creat() guarantees that the file will be
435 * truncated and open()-for-writing doesn't.
436 * (If the file doesn't exist, we're calling creat() anyway and the
437 * file will be created with zero length.)
438 */
439 if ((flags & O_TRUNC) && exists) call_creat = 1;
440 /* actually do the call */
441 if (call_creat) {
442 /*
443 * call creat. May have to close and reopen the file if we
444 * want O_RDONLY or O_RDWR access -- creat() only gives
445 * O_WRONLY.
446 */
447 fd = creat(path,mode);
448 if (fd < 0 || (flags & O_WRONLY)) return fd;
449 if (close(fd) < 0) return -1;
450 /* Fall out to reopen the file we've created */
451 }
452
453 /*
454 * calling old open, we strip most of the new flags just in case.
455 */
456 return open(path, flags & (O_RDONLY|O_WRONLY|O_RDWR|O_BINARY));
457 }
458 #endif
459
460 #ifdef MKNOD_MISSING
461 #ifdef __MSDOS__
462 typedef int dev_t;
463 #endif
464 /* Fake mknod by complaining */
465 int
466 mknod(path, mode, dev)
467 char *path;
468 unsigned short mode;
469 dev_t dev;
470 {
471 int fd;
472
473 errno = ENXIO; /* No such device or address */
474 return -1; /* Just give an error */
475 }
476
477 /* Fake links by copying */
478 int
479 link(path1, path2)
480 char *path1;
481 char *path2;
482 {
483 char buf[256];
484 int ifd, ofd;
485 int nrbytes;
486 int nwbytes;
487
488 fprintf(stderr, "%s: %s: cannot link to %s, copying instead\n",
489 tar, path1, path2);
490 if ((ifd = open(path1, O_RDONLY|O_BINARY)) < 0)
491 return -1;
492 if ((ofd = creat(path2, 0666)) < 0)
493 return -1;
494 setmode(ofd, O_BINARY);
495 while ((nrbytes = read(ifd, buf, sizeof(buf))) > 0) {
496 if ((nwbytes = write(ofd, buf, nrbytes)) != nrbytes) {
497 nrbytes = -1;
498 break;
499 }
500 }
501 /* Note use of "|" rather than "||" below: we want to close
502 * the files even if an error occurs.
503 */
504 if ((nrbytes < 0) | (0 != close(ifd)) | (0 != close(ofd))) {
505 unlink(path2);
506 return -1;
507 }
508 return 0;
509 }
510
511 /* everyone owns everything on MS-DOS (or is it no one owns anything?) */
512 int
513 chown(path, uid, gid)
514 char *path;
515 int uid;
516 int gid;
517 {
518 return 0;
519 }
520
521 int
522 geteuid()
523 {
524 return 0;
525 }
526 #endif /* MKNOD_MISSING */
527
528 #ifdef __TURBOC__
529 #include <time.h>
530 #include <fcntl.h>
531 #include <io.h>
532
533 struct utimbuf
534 {
535 time_t actime; /* Access time. */
536 time_t modtime; /* Modification time. */
537 };
538
539 int
540 utime (char *filename, struct utimbuf *utb)
541 {
542 struct tm *tm;
543 struct ftime filetime;
544 time_t when;
545 int fd;
546 int status;
547
548 if (utb == 0)
549 when = time (0);
550 else
551 when = utb->modtime;
552
553 fd = _open (filename, O_RDWR);
554 if (fd == -1)
555 return -1;
556
557 tm = localtime (&when);
558 if (tm->tm_year < 80)
559 filetime.ft_year = 0;
560 else
561 filetime.ft_year = tm->tm_year - 80;
562 filetime.ft_month = tm->tm_mon + 1;
563 filetime.ft_day = tm->tm_mday;
564 if (tm->tm_hour < 0)
565 filetime.ft_hour = 0;
566 else
567 filetime.ft_hour = tm->tm_hour;
568 filetime.ft_min = tm->tm_min;
569 filetime.ft_tsec = tm->tm_sec / 2;
570
571 status = setftime (fd, &filetime);
572 _close (fd);
573 return status;
574 }
575 #endif
576
577 #ifdef UTILS_MISSING
578 /* Stash argv[0] here so panic will know what the program is called */
579 char *myname = 0;
580
581 void
582 panic(s)
583 char *s;
584 {
585 if(myname)
586 fprintf(stderr,"%s:",myname);
587 fprintf(stderr,s);
588 putc('\n',stderr);
589 exit(12);
590 }
591
592
593 PTR
594 ck_malloc(size)
595 size_t size;
596 {
597 PTR ret;
598
599 if(!size)
600 size++;
601 ret=malloc(size);
602 if(ret==0)
603 panic("Couldn't allocate memory");
604 return ret;
605 }
606
607 /* Used by alloca.c and bison.simple. */
608 char *
609 xmalloc(size)
610 size_t size;
611 {
612 return (char *) ck_malloc(size);
613 }
614
615 PTR
616 ck_realloc(ptr,size)
617 PTR ptr;
618 size_t size;
619 {
620 PTR ret;
621
622 if(!ptr)
623 ret=ck_malloc(size);
624 else
625 ret=realloc(ptr,size);
626 if(ret==0)
627 panic("Couldn't re-allocate memory");
628 return ret;
629 }
630
631 /* Implement a variable sized buffer of 'stuff'. We don't know what it is,
632 nor do we care, as long as it doesn't mind being aligned on a char boundry.
633 */
634
635 struct buffer {
636 int allocated;
637 int length;
638 char *b;
639 };
640
641 #define MIN_ALLOCATE 50
642
643 char *
644 init_buffer()
645 {
646 struct buffer *b;
647
648 b=(struct buffer *)ck_malloc(sizeof(struct buffer));
649 b->allocated=MIN_ALLOCATE;
650 b->b=(char *)ck_malloc(MIN_ALLOCATE);
651 b->length=0;
652 return (char *)b;
653 }
654
655 void
656 flush_buffer(bb)
657 char *bb;
658 {
659 struct buffer *b;
660
661 b=(struct buffer *)bb;
662 free(b->b);
663 b->b=0;
664 b->allocated=0;
665 b->length=0;
666 free((void *)b);
667 }
668
669 void
670 add_buffer(bb,p,n)
671 char *bb;
672 char *p;
673 int n;
674 {
675 struct buffer *b;
676
677 b=(struct buffer *)bb;
678 if(b->length+n>b->allocated) {
679 b->allocated=b->length+n+MIN_ALLOCATE;
680 b->b=(char *)ck_realloc(b->b,b->allocated);
681 }
682 bcopy(p,b->b+b->length,n);
683 b->length+=n;
684 }
685
686 char *
687 get_buffer(bb)
688 char *bb;
689 {
690 struct buffer *b;
691
692 b=(struct buffer *)bb;
693 return b->b;
694 }
695
696 char *
697 merge_sort(list,n,off,cmp)
698 char *list;
699 int (*cmp)();
700 unsigned n;
701 int off;
702 {
703 char *ret;
704
705 char *alist,*blist;
706 unsigned alength,blength;
707
708 char *tptr;
709 int tmp;
710 char **prev;
711 #define NEXTOF(ptr) (* ((char **)(((char *)(ptr))+off) ) )
712 if(n==1)
713 return list;
714 if(n==2) {
715 if((*cmp)(list,NEXTOF(list))>0) {
716 ret=NEXTOF(list);
717 NEXTOF(ret)=list;
718 NEXTOF(list)=0;
719 return ret;
720 }
721 return list;
722 }
723 alist=list;
724 alength=(n+1)/2;
725 blength=n/2;
726 for(tptr=list,tmp=(n-1)/2;tmp;tptr=NEXTOF(tptr),tmp--)
727 ;
728 blist=NEXTOF(tptr);
729 NEXTOF(tptr)=0;
730
731 alist=merge_sort(alist,alength,off,cmp);
732 blist=merge_sort(blist,blength,off,cmp);
733 prev = &ret;
734 for(;alist && blist;) {
735 if((*cmp)(alist,blist)<0) {
736 tptr=NEXTOF(alist);
737 *prev = alist;
738 prev = &(NEXTOF(alist));
739 alist=tptr;
740 } else {
741 tptr=NEXTOF(blist);
742 *prev = blist;
743 prev = &(NEXTOF(blist));
744 blist=tptr;
745 }
746 }
747 if(alist)
748 *prev = alist;
749 else
750 *prev = blist;
751
752 return ret;
753 }
754
755 void
756 ck_close(fd)
757 int fd;
758 {
759 if(close(fd)<0) {
760 msg_perror("can't close a file #%d",fd);
761 exit(EX_SYSTEM);
762 }
763 }
764
765 #include <ctype.h>
766
767 /* Quote_copy_string is like quote_string, but instead of modifying the
768 string in place, it malloc-s a copy of the string, and returns that.
769 If the string does not have to be quoted, it returns the NULL string.
770 The allocated copy can, of course, be freed with free() after the
771 caller is done with it.
772 */
773 char *
774 quote_copy_string(string)
775 char *string;
776 {
777 char *from_here;
778 char *to_there = 0;
779 char *copy_buf = 0;
780 int c;
781 int copying = 0;
782
783 from_here=string;
784 while(*from_here) {
785 c= *from_here++;
786 if(c=='\\') {
787 if(!copying) {
788 int n;
789
790 n=(from_here-string)-1;
791 copying++;
792 copy_buf=(char *)malloc(n+5+strlen(from_here)*4);
793 if(!copy_buf)
794 return 0;
795 bcopy(string,copy_buf,n);
796 to_there=copy_buf+n;
797 }
798 *to_there++='\\';
799 *to_there++='\\';
800 } else if(isprint(c)) {
801 if(copying)
802 *to_there++= c;
803 } else {
804 if(!copying) {
805 int n;
806
807 n=(from_here-string)-1;
808 copying++;
809 copy_buf=(char *)malloc(n+5+strlen(from_here)*4);
810 if(!copy_buf)
811 return 0;
812 bcopy(string,copy_buf,n);
813 to_there=copy_buf+n;
814 }
815 *to_there++='\\';
816 if(c=='\n') *to_there++='n';
817 else if(c=='\t') *to_there++='t';
818 else if(c=='\f') *to_there++='f';
819 else if(c=='\b') *to_there++='b';
820 else if(c=='\r') *to_there++='r';
821 else if(c=='\177') *to_there++='?';
822 else {
823 to_there[0]=(c>>6)+'0';
824 to_there[1]=((c>>3)&07)+'0';
825 to_there[2]=(c&07)+'0';
826 to_there+=3;
827 }
828 }
829 }
830 if(copying) {
831 *to_there='\0';
832 return copy_buf;
833 }
834 return (char *)0;
835 }
836
837
838 /* Un_quote_string takes a quoted c-string (like those produced by
839 quote_string or quote_copy_string and turns it back into the
840 un-quoted original. This is done in place.
841 */
842
843 /* There is no un-quote-copy-string. Write it yourself */
844
845 char *
846 un_quote_string(string)
847 char *string;
848 {
849 char *ret;
850 char *from_here;
851 char *to_there;
852 int tmp;
853
854 ret=string;
855 to_there=string;
856 from_here=string;
857 while(*from_here) {
858 if(*from_here!='\\') {
859 if(from_here!=to_there)
860 *to_there++= *from_here++;
861 else
862 from_here++,to_there++;
863 continue;
864 }
865 switch(*++from_here) {
866 case '\\':
867 *to_there++= *from_here++;
868 break;
869 case 'n':
870 *to_there++= '\n';
871 from_here++;
872 break;
873 case 't':
874 *to_there++= '\t';
875 from_here++;
876 break;
877 case 'f':
878 *to_there++= '\f';
879 from_here++;
880 break;
881 case 'b':
882 *to_there++= '\b';
883 from_here++;
884 break;
885 case 'r':
886 *to_there++= '\r';
887 from_here++;
888 break;
889 case '?':
890 *to_there++= 0177;
891 from_here++;
892 break;
893 case '0':
894 case '1':
895 case '2':
896 case '3':
897 case '4':
898 case '5':
899 case '6':
900 case '7':
901 tmp= *from_here - '0';
902 from_here++;
903 if(*from_here<'0' || *from_here>'7') {
904 *to_there++= tmp;
905 break;
906 }
907 tmp= tmp*8 + *from_here-'0';
908 from_here++;
909 if(*from_here<'0' || *from_here>'7') {
910 *to_there++= tmp;
911 break;
912 }
913 tmp=tmp*8 + *from_here-'0';
914 from_here++;
915 *to_there=tmp;
916 break;
917 default:
918 ret=0;
919 *to_there++='\\';
920 *to_there++= *from_here++;
921 break;
922 }
923 }
924 if(*to_there)
925 *to_there++='\0';
926 return ret;
927 }
928 #endif
929
930 #ifdef CK_PIPE_MISSING
931 void ck_pipe(pipes)
932 int *pipes;
933 {
934 if(pipe(pipes)<0) {
935 msg_perror("can't open a pipe");
936 exit(EX_SYSTEM);
937 }
938 }
939
940 #endif
941
942 #ifdef STRSTR_MISSING
943
944 /*
945 * strstr - find first occurrence of wanted in s
946 */
947
948 char * /* found string, or NULL if none */
949 strstr(s, wanted)
950 char *s;
951 char *wanted;
952 {
953 register char *scan;
954 register size_t len;
955 register char firstc;
956
957 if (*wanted == '\0')
958 return (char *)0;
959 /*
960 * The odd placement of the two tests is so "" is findable.
961 * Also, we inline the first char for speed.
962 * The ++ on scan has been moved down for optimization.
963 */
964 firstc = *wanted;
965 len = strlen(wanted);
966 for (scan = s; *scan != firstc || strncmp(scan, wanted, len) != 0; )
967 if (*scan++ == '\0')
968 return (char *)0;
969 return scan;
970 }
971 #endif
972
973 #ifdef FTRUNCATE_MISSING
974
975 #ifdef F_CHSIZE
976 int
977 ftruncate (fd, length)
978 int fd;
979 off_t length;
980 {
981 return fcntl (fd, F_CHSIZE, length);
982 }
983 #else
984 #ifdef F_FREESP
985 /* code courtesy of William Kucharski, kucharsk@Solbourne.com */
986
987 int
988 ftruncate(fd, length)
989 int fd; /* file descriptor */
990 off_t length; /* length to set file to */
991 {
992 struct flock fl;
993
994 fl.l_whence = 0;
995 fl.l_len = 0;
996 fl.l_start = length;
997 fl.l_type = F_WRLCK; /* write lock on file space */
998
999 /*
1000 * This relies on the UNDOCUMENTED F_FREESP argument to
1001 * fcntl(2), which truncates the file so that it ends at the
1002 * position indicated by fl.l_start.
1003 *
1004 * Will minor miracles never cease?
1005 */
1006
1007 if (fcntl(fd, F_FREESP, &fl) < 0)
1008 return -1;
1009
1010 return 0;
1011 }
1012
1013 #else
1014
1015 int
1016 ftruncate(fd, length)
1017 int fd;
1018 off_t length;
1019 {
1020 errno = EIO;
1021 return -1;
1022 }
1023 #endif
1024 #endif
1025 #endif
1026
1027
1028 extern FILE *msg_file;
1029
1030 #if !defined (VPRINTF_MISSING) && defined (__STDC__)
1031 #include <stdarg.h>
1032
1033 void
1034 msg(char *str,...)
1035 {
1036 va_list args;
1037
1038 va_start(args,str);
1039 fflush(msg_file);
1040 fprintf(stderr,"%s: ",tar);
1041 if(f_sayblock)
1042 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1043 vfprintf(stderr,str,args);
1044 va_end(args);
1045 putc('\n',stderr);
1046 fflush(stderr);
1047 }
1048
1049 void
1050 msg_perror(char *str,...)
1051 {
1052 va_list args;
1053 int save_e;
1054
1055 save_e=errno;
1056 fflush(msg_file);
1057 fprintf(stderr,"%s: ",tar);
1058 if(f_sayblock)
1059 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1060 va_start(args,str);
1061 vfprintf(stderr,str,args);
1062 va_end(args);
1063 errno=save_e;
1064 perror(" ");
1065 fflush(stderr);
1066 }
1067 #endif /* not VPRINTF_MISSING or __STDC__ */
1068
1069 #if !defined(VPRINTF_MISSING) && !defined(__STDC__)
1070 #include <varargs.h>
1071 void
1072 msg(str,va_alist)
1073 char *str;
1074 va_dcl
1075 {
1076 va_list args;
1077
1078 fflush(msg_file);
1079 fprintf(stderr,"%s: ",tar);
1080 if(f_sayblock)
1081 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1082 va_start(args);
1083 vfprintf(stderr,str,args);
1084 va_end(args);
1085 putc('\n',stderr);
1086 fflush(stderr);
1087 }
1088
1089 void
1090 msg_perror(str,va_alist)
1091 char *str;
1092 va_dcl
1093 {
1094 va_list args;
1095 int save_e;
1096
1097 save_e=errno;
1098 fflush(msg_file);
1099 fprintf(stderr,"%s: ",tar);
1100 if(f_sayblock)
1101 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1102 va_start(args);
1103 vfprintf(stderr,str,args);
1104 va_end(args);
1105 errno=save_e;
1106 perror(" ");
1107 fflush(stderr);
1108 }
1109 #endif /* not VPRINTF_MISSING and not __STDC__ */
1110
1111 #if defined(VPRINTF_MISSING) && !defined(DOPRNT_MISSING)
1112 void
1113 msg(str,args)
1114 char *str;
1115 int args;
1116 {
1117 fflush(msg_file);
1118 fprintf(stderr,"%s: ",tar);
1119 if(f_sayblock)
1120 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1121 _doprnt(str, &args, stderr);
1122 putc('\n',stderr);
1123 fflush(stderr);
1124 }
1125
1126 void
1127 msg_perror(str,args)
1128 char *str;
1129 {
1130 int save_e;
1131
1132 save_e=errno;
1133 fflush(msg_file);
1134 fprintf(stderr,"%s: ",tar);
1135 if(f_sayblock)
1136 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1137 _doprnt(str, &args, stderr);
1138 errno=save_e;
1139 perror(" ");
1140 fflush(stderr);
1141 }
1142 #endif /* VPRINTF_MISSING and not DOPRNT_MISSING */
1143
1144 #if defined(VPRINTF_MISSING) && defined(DOPRNT_MISSING)
1145 void msg(str,a1,a2,a3,a4,a5,a6)
1146 char *str;
1147 {
1148 fflush(msg_file);
1149 fprintf(stderr,"%s: ",tar);
1150 if(f_sayblock)
1151 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1152 fprintf(stderr,str,a1,a2,a3,a4,a5,a6);
1153 putc('\n',stderr);
1154 fflush(stderr);
1155 }
1156
1157 void
1158 msg_perror(str,a1,a2,a3,a4,a5,a6)
1159 char *str;
1160 {
1161 int save_e;
1162
1163 save_e=errno;
1164 fflush(msg_file);
1165 fprintf(stderr,"%s: ",tar);
1166 if(f_sayblock)
1167 fprintf(stderr,"rec %d: ",baserec + (ar_record - ar_block));
1168 fprintf(stderr,str,a1,a2,a3,a4,a5,a6);
1169 fprintf(stderr,": ");
1170 errno=save_e;
1171 perror(" ");
1172 }
1173 #endif /* VPRINTF_MISSING and DOPRNT_MISSING */
This page took 0.090601 seconds and 5 git commands to generate.