📄 rcsutil.c
字号:
#else static void setup_catchsig() { register i; for (i=SIGS; 0<=--i; ) if ( signal(sig[i], SIG_IGN) != SIG_IGN && signal(sig[i], catchsig) != SIG_IGN ) faterror("signal catcher failure"); }#endif#endif voidcatchints(){ static int catching_ints; if (!catching_ints) { catching_ints = true; setup_catchsig(); }}#endif /* has_signal */ voidfastcopy(inf,outf) register RILE *inf; FILE *outf;/* Function: copies the remainder of file inf to outf. */{#if large_memory# if has_mmap awrite((char const*)inf->ptr, (size_t)(inf->lim - inf->ptr), outf); inf->ptr = inf->lim;# else for (;;) { awrite((char const*)inf->ptr, (size_t)(inf->readlim - inf->ptr), outf); inf->ptr = inf->readlim; if (inf->ptr == inf->lim) break; VOID Igetmore(inf); }# endif#else char buf[BUFSIZ*8]; register fread_type rcount; /*now read the rest of the file in blocks*/ while (!feof(inf)) { if (!(rcount = Fread(buf,sizeof(*buf),sizeof(buf),inf))) { testIerror(inf); return; } awrite(buf, (size_t)rcount, outf); }#endif}#ifndef SSIZE_MAX /* This does not work in #ifs, but it's good enough for us. */ /* Underestimating SSIZE_MAX may slow us down, but it won't break us. */# define SSIZE_MAX ((unsigned)-1 >> 1)#endif voidawrite(buf, chars, f) char const *buf; size_t chars; FILE *f;{ /* Posix 1003.1-1990 ssize_t hack */ while (SSIZE_MAX < chars) { if (Fwrite(buf, sizeof(*buf), SSIZE_MAX, f) != SSIZE_MAX) Oerror(); buf += SSIZE_MAX; chars -= SSIZE_MAX; } if (Fwrite(buf, sizeof(*buf), chars, f) != chars) Oerror();} static intmovefd(old, new) int old, new;{ if (old < 0 || old == new) return old;# ifdef F_DUPFD new = fcntl(old, F_DUPFD, new);# else new = dup2(old, new);# endif return close(old)==0 ? new : -1;} static intfdreopen(fd, file, flags) int fd; char const *file; int flags;{ int newfd; VOID close(fd); newfd =#if !open_can_creat flags&O_CREAT ? creat(file, S_IRUSR|S_IWUSR) :#endif open(file, flags, S_IRUSR|S_IWUSR); return movefd(newfd, fd);}#if !has_spawn static voidtryopen(fd,file,flags) int fd, flags; char const *file;{ if (file && fdreopen(fd,file,flags) != fd) efaterror(file);}#else static inttryopen(fd,file,flags) int fd, flags; char const *file;{ int newfd = -1; if (file && ((newfd=dup(fd)) < 0 || fdreopen(fd,file,flags) != fd)) efaterror(file); return newfd;} static voidredirect(old, new) int old, new;{ if (0 <= old && (close(new) != 0 || movefd(old,new) < 0)) efaterror("spawn I/O redirection");}#endif#if !has_fork && !has_spawn static voidbufargcat(b, c, s) register struct buf *b; int c; register char const *s;/* Append to B a copy of C, plus a quoted copy of S. */{ register char *p; register char const *t; size_t bl, sl; for (t=s, sl=0; *t; ) sl += 3*(*t++=='\'') + 1; bl = strlen(b->string); bufrealloc(b, bl + sl + 4); p = b->string + bl; *p++ = c; *p++ = '\''; while (*s) { if (*s == '\'') { *p++ = '\''; *p++ = '\\'; *p++ = '\''; } *p++ = *s++; } *p++ = '\''; *p = 0;}#endif/** Run a command specified by the strings in 'inoutargs'.* inoutargs[0], if nonnil, is the name of the input file.* inoutargs[1], if nonnil, is the name of the output file.* inoutargs[2..] form the command to be run.*/ intrunv(inoutargs) char const **inoutargs;{ register char const **p; int wstatus; oflush(); eflush(); {#if has_spawn int in, out; p = inoutargs; in = tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY); out = tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY); wstatus = spawn_RCS(0, *p, (char*const*)p); if (wstatus == -1 && errno == ENOEXEC) { *--p = RCS_SHELL; wstatus = spawnv(0, *p, (char*const*)p); } redirect(in, STDIN_FILENO); redirect(out, STDOUT_FILENO);#else#if has_fork pid_t pid;# if !has_waitpid pid_t w;# endif if (!(pid = vfork())) { p = inoutargs; tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY); tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY); VOID exec_RCS(*p, (char*const*)p); if (errno == ENOEXEC) { *--p = RCS_SHELL; VOID execv(*p, (char*const*)p); } VOID write(STDERR_FILENO, *p, strlen(*p)); VOID write(STDERR_FILENO, ": not found\n", 12); _exit(EXIT_TROUBLE); } if (pid < 0) efaterror("fork");# if has_waitpid if (waitpid(pid, &wstatus, 0) < 0) efaterror("waitpid");# else do { if ((w = wait(&wstatus)) < 0) efaterror("wait"); } while (w != pid);# endif#else static struct buf b; /* Use system(). On many hosts system() discards signals. Yuck! */ p = inoutargs+2; bufscpy(&b, *p); while (*++p) bufargcat(&b, ' ', *p); if (inoutargs[0]) bufargcat(&b, '<', inoutargs[0]); if (inoutargs[1]) bufargcat(&b, '>', inoutargs[1]); wstatus = system(b.string);#endif#endif } if (!WIFEXITED(wstatus)) faterror("%s failed", inoutargs[2]); return WEXITSTATUS(wstatus);}#define CARGSMAX 20/** Run a command.* The first two arguments are the input and output files (if nonnil);* the rest specify the command and its arguments.*/ int#if has_prototypesrun(char const *infile, char const *outfile, ...)#else /*VARARGS2*/run(infile, outfile, va_alist) char const *infile; char const *outfile; va_dcl#endif{ va_list ap; char const *rgargs[CARGSMAX]; register i = 0; rgargs[0] = infile; rgargs[1] = outfile; vararg_start(ap, outfile); for (i = 2; (rgargs[i++] = va_arg(ap, char const*)); ) if (CARGSMAX <= i) faterror("too many command arguments"); va_end(ap); return runv(rgargs);} char const *date2str(date, datebuf) char const date[datesize]; char datebuf[datesize];/** Format a user-readable form of the RCS format DATE into the buffer DATEBUF.* Yield DATEBUF.*/{ register char const *p = date; while (*p++ != '.') ; VOID sprintf(datebuf, "19%.*s/%.2s/%.2s %.2s:%.2s:%s" + (date[2]=='.' && VERSION(5)<=RCSversion ? 0 : 2), (int)(p-date-1), date, p, p+3, p+6, p+9, p+12 ); return datebuf;}int RCSversion; voidsetRCSversion(str) char const *str;{ static int oldversion; register char const *s = str + 2; int v = VERSION_DEFAULT; if (oldversion) redefined('V'); oldversion = true; if (*s) { v = 0; while (isdigit(*s)) v = 10*v + *s++ - '0'; if (*s) faterror("%s isn't a number", str); if (v < VERSION_min || VERSION_max < v) faterror("%s out of range %d..%d", str, VERSION_min, VERSION_max); } RCSversion = VERSION(v);} intgetRCSINIT(argc, argv, newargv) int argc; char **argv, ***newargv;{ register char *p, *q, **pp; unsigned n; if (!(q = cgetenv("RCSINIT"))) *newargv = argv; else { n = argc + 2; /* * Count spaces in RCSINIT to allocate a new arg vector. * This is an upper bound, but it's OK even if too large. */ for (p = q; ; ) { switch (*p++) { default: continue; case ' ': case '\b': case '\f': case '\n': case '\r': case '\t': case '\v': n++; continue; case '\0': break; } break; } *newargv = pp = tnalloc(char*, n); *pp++ = *argv++; /* copy program name */ for (p = q; ; ) { for (;;) { switch (*q) { case '\0': goto copyrest; case ' ': case '\b': case '\f': case '\n': case '\r': case '\t': case '\v': q++; continue; } break; } *pp++ = p; ++argc; for (;;) { switch ((*p++ = *q++)) { case '\0': goto copyrest; case '\\': if (!*q) goto copyrest; p[-1] = *q++; continue; default: continue; case ' ': case '\b': case '\f': case '\n': case '\r': case '\t': case '\v': break; } break; } p[-1] = '\0'; } copyrest: while ((*pp++ = *argv++)) ; } return argc;}#define cacheid(E) static uid_t i; static int s; if (!s){ s=1; i=(E); } return i#if has_getuid uid_t ruid() { cacheid(getuid()); }#endif#if has_setuid uid_t euid() { cacheid(geteuid()); }#endif#if has_setuid/* * Setuid execution really works only with Posix 1003.1a Draft 5 seteuid(), * because it lets us switch back and forth between arbitrary users. * If seteuid() doesn't work, we fall back on setuid(), * which works if saved setuid is supported, * unless the real or effective user is root. * This area is such a mess that we always check switches at runtime. */ static voidset_uid_to(u) uid_t u;/* Become user u. */{ static int looping; if (euid() == ruid()) return;#if (has_fork||has_spawn) && DIFF_ABSOLUTE if (seteuid(u) != 0) efaterror("setuid");#endif if (geteuid() != u) { if (looping) return; looping = true; faterror("root setuid not supported" + (u?5:0)); }}static int stick_with_euid; void/* Ignore all calls to seteid() and setrid(). */nosetid(){ stick_with_euid = true;} voidseteid()/* Become effective user. */{ if (!stick_with_euid) set_uid_to(euid());} voidsetrid()/* Become real user. */{ if (!stick_with_euid) set_uid_to(ruid());}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -