Category : C Source Code
Archive   : PATCH12.ZIP
Filename : UTIL.C

 
Output of file : UTIL.C contained in archive : PATCH12.ZIP
/* $Header: pch.c,v 2.0.1 90/05/30 11:30:00 mward $
*
* $Log: pch.c,v $
* Revision 2.0.1 90/05/30 11:30:00 mward
* modify calls to read, write to detect error on return of value -1
* added TURBOC20 ifdef stuff:
* no inodes: modify move_file same file detect accordingly
* no links: modify move_file link calls to copy_file calls
* no SIGHUP: modify signal routines accordingly
*
*/

#include "EXTERN.h"
#include "common.h"
#include "INTERN.h"
#include "util.h"

#ifdef TURBOC20
#include
/* fnappend : Append first char of bext to a MSDOS file name.
* bext should not start with a letter or digit.
*/

void
fnappend(fspec,bext)
char *fspec, *bext;
{
char *fnmex;
char fname[MAXFILE];
char fext[MAXEXT];
int i,j;
int fnlen;
int felen;

/* fnmex should point to first char of file name/extension
* (not path or drive)
*/
fnmex = fspec + strlen(fspec);
while ((fnmex!=fspec) && (strchr("/\\:",*(fnmex-1))==NULL)) {
fnmex--;
}

/* get file name and length */
for (fnlen=i=0; fnmex[i] && fnmex[i]!= '.' && i fname[i] = fnmex[i];
fnlen++;
}
fname[fnlen] = '\0';

/* get file ext and len */
while (fnmex[i] && fnmex[i]!='.') {
i++;
}
if (fnmex[i] == '.')
i++;
for (felen=j=0; fnmex[j+i] && j fext[j] = fnmex[j+i];
felen++;
}
fext[felen] = '\0';

/* Three cases:
* full filename/ext: 12345678.ABC -> 2345678A.BCX
* full file ext: 1234567.ABC -> 1234567A.BCX
* other: 12345678.AB -> 12345678.ABX
*/
if ((fnlen == MAXFILE-1) && (felen == MAXEXT-2)) {
sprintf(fnmex,"%s%c.%s%c",fname+1,fext[0],fext+1,*bext);
} else if (felen == MAXEXT-2) {
sprintf(fnmex,"%s%c.%s%c",fname,fext[0],fext+1,*bext);
} else {
sprintf(fnmex,"%s.%s%c",fname,fext,*bext);
}
}


/* fninc : increment/add last char of/to fspec.
* used with fappend (call fnappend once, then fninc many times
*/

void
fninc(fspec)
char *fspec;
{
char *cp;
int lastp,lastc;

lastc = fspec[lastp = strlen(fspec)-1];
if (strchr("012345678ABCDEFGHIJKLMNOPQRSTUVWXY",lastc) != NULL) {
fspec[lastp]++;
} else if (lastc == '9') {
fspec[lastp] = 'A';
} else if (lastc == 'Z') {
for (cp=&fspec[lastp]; *cp=='Z' || *cp=='.'; cp--) {
if (*cp == 'Z') {
*cp = '0';
}
}
if (strchr("012345678ABCDEFGHIJKLMNOPQRSTUVWXY",*cp) != NULL) {
(*cp)++;
} else if (*cp == '9') {
*cp = 'A';
} else {
if (*(cp+1) == '.') cp++;
*(cp+1) = '1';
fnappend(fspec,"0");
}
} else {
fnappend(fspec,"0");
}
}
#endif


/* Rename a file, copying it if necessary. */

int
move_file(from,to)
char *from, *to;
{
char bakname[512];
Reg1 char *s;
Reg2 int i;
Reg3 int fromfd;

/* to stdout? */

if (strEQ(to, "-")) {
#ifdef DEBUGGING
if (debug & 4)
say2("Moving %s to stdout.\n", from);
#endif
fromfd = open(from, 0);
if (fromfd < 0)
fatal2("patch: internal error, can't reopen %s\n", from);
while ((i=read(fromfd, buf, sizeof buf))!=-1 && i!=0)
if (write(1, buf, i) == -1)
fatal1("patch: write failed\n");
Close(fromfd);
return 0;
}

if (origprae) {
Strcpy (bakname, origprae);
Strcat(bakname, to);
} else {
Strcpy(bakname, to);
#ifdef TURBOC20
fnappend(bakname, origext?origext:ORIGEXT);
}

if (stat(to, &filestat) >= 0) { /* output file exists */
short to_device = filestat.st_dev;
short to_mode = filestat.st_mode;
long to_size = filestat.st_size;
long to_time = filestat.st_mtime;

/* find a backup name that is not the same file */
while (stat(bakname, &filestat) >= 0 &&
to_device == filestat.st_dev &&
to_mode == filestat.st_mode &&
to_size == filestat.st_size &&
to_time == filestat.st_mtime
) {
fninc(bakname);
}
#else
Strcat(bakname, origext?origext:ORIGEXT);
}
if (stat(to, &filestat) >= 0) { /* output file exists */
dev_t to_device = filestat.st_dev;
ino_t to_inode = filestat.st_ino;
char *simplename = bakname;

for (s=bakname; *s; s++) {
if (*s == '/')
simplename = s+1;
}
/* find a backup name that is not the same file */
while (stat(bakname, &filestat) >= 0 &&
to_device == filestat.st_dev &&
to_inode == filestat.st_ino
) {
for (s=simplename; *s && !islower(*s); s++) ;
if (*s)
*s = toupper(*s);
else
Strcpy(simplename, simplename+1);
}
#endif
while (unlink(bakname) >= 0) ; /* while() is for benefit of Eunice */
#ifdef DEBUGGING
if (debug & 4)
say3("Moving %s to %s.\n", to, bakname);
#endif
#ifdef TURBOC20
copy_file(to, bakname);
#else
if (link(to, bakname) < 0) {
say3("patch: can't backup %s, output is in %s\n",
to, from);
return -1;
}
#endif
while (unlink(to) >= 0) ;
}
#ifdef DEBUGGING
if (debug & 4)
say3("Moving %s to %s.\n", from, to);
#endif
#ifdef TURBOC20
copy_file(from, to);
#else
if (link(from, to) < 0) { /* different file system? */
Reg4 int tofd;

tofd = creat(to, 0666);
if (tofd < 0) {
say3("patch: can't create %s, output is in %s.\n",
to, from);
return -1;
}
fromfd = open(from, 0);
if (fromfd < 0)
fatal2("patch: internal error, can't reopen %s\n", from);
while ((i=read(fromfd, buf, sizeof buf))!=-1 && i!=0)
if (write(tofd, buf, i) == -1)
fatal1("patch: write failed\n");
Close(fromfd);
Close(tofd);
}
#endif
Unlink(from);
return 0;
}

/* Copy a file. */

void
copy_file(from,to)
char *from, *to;
{
Reg3 int tofd;
Reg2 int fromfd;
Reg1 int i;

tofd = creat(to, 0666);
if (tofd < 0)
fatal2("patch: can't create %s.\n", to);
fromfd = open(from, 0);
if (fromfd < 0)
fatal2("patch: internal error, can't reopen %s\n", from);
while ((i=read(fromfd, buf, sizeof buf))!=-1 && i!=0)
if (write(tofd, buf, i) == -1)
fatal2("patch: write (%s) failed\n", to);
Close(fromfd);
Close(tofd);
}

/* Allocate a unique area for a string. */

char *
savestr(s)
Reg1 char *s;
{
Reg3 char *rv;
Reg2 char *t;

if (!s)
s = "Oops";
t = s;
while (*t++);
rv = malloc((MEM) (t - s));
if (rv == Nullch) {
if (using_plan_a)
out_of_mem = TRUE;
else
fatal1("patch: out of memory (savestr)\n");
}
else {
t = rv;
while (*t++ = *s++);
}
return rv;
}

#if defined(lint) && defined(CANVARARG)

/*VARARGS ARGSUSED*/
say(pat) char *pat; { ; }
/*VARARGS ARGSUSED*/
fatal(pat) char *pat; { ; }
/*VARARGS ARGSUSED*/
ask(pat) char *pat; { ; }

#else

/* Vanilla terminal output (buffered). */

void
say(pat,arg1,arg2,arg3)
char *pat;
long arg1,arg2,arg3;
{
fprintf(stderr, pat, arg1, arg2, arg3);
Fflush(stderr);
}

/* Terminal output, pun intended. */

void /* very void */
fatal(pat,arg1,arg2,arg3)
char *pat;
long arg1,arg2,arg3;
{
void my_exit();

say(pat, arg1, arg2, arg3);
my_exit(1);
}

/* Get a response from the user, somehow or other. */

void
ask(pat,arg1,arg2,arg3)
char *pat;
long arg1,arg2,arg3;
{
int ttyfd;
int r;
bool tty2 = isatty(2);

Sprintf(buf, pat, arg1, arg2, arg3);
Fflush(stderr);
write(2, buf, strlen(buf));
if (tty2) { /* might be redirected to a file */
r = read(2, buf, sizeof buf);
}
else if (isatty(1)) { /* this may be new file output */
Fflush(stdout);
write(1, buf, strlen(buf));
r = read(1, buf, sizeof buf);
}
else if ((ttyfd = open("/dev/tty", 2)) >= 0 && isatty(ttyfd)) {
/* might be deleted or unwriteable */
write(ttyfd, buf, strlen(buf));
r = read(ttyfd, buf, sizeof buf);
Close(ttyfd);
}
else if (isatty(0)) { /* this is probably patch input */
Fflush(stdin);
write(0, buf, strlen(buf));
r = read(0, buf, sizeof buf);
}
else { /* no terminal at all--default it */
buf[0] = '\n';
r = 1;
}
if (r <= 0)
buf[0] = 0;
else
buf[r] = '\0';
if (!tty2)
say1(buf);
}
#endif /* lint */

/* How to handle certain events when not in a critical region. */

void
set_signals(reset)
int reset;
{
void my_exit();
#ifndef lint
#ifdef TURBOC20
#ifdef VOIDSIG
static void (*intval)();
#else
static int (*intval)();
#endif
#else
#ifdef VOIDSIG
static void (*hupval)(),(*intval)();
#else
static int (*hupval)(),(*intval)();
#endif
#endif

if (!reset) {
#ifndef TURBOC20
hupval = signal(SIGHUP, SIG_IGN);
if (hupval != SIG_IGN)
#ifdef VOIDSIG
hupval = my_exit;
#else
hupval = (int(*)())my_exit;
#endif
#endif

intval = signal(SIGINT, SIG_IGN);
if (intval != SIG_IGN)
#ifdef VOIDSIG
intval = my_exit;
#else
intval = (int(*)())my_exit;
#endif
}
#ifndef TURBOC20
Signal(SIGHUP, hupval);
#endif
Signal(SIGINT, intval);
#endif
}

/* How to handle certain events when in a critical region. */

void
ignore_signals()
{
#ifndef lint
#ifndef TURBOC20
Signal(SIGHUP, SIG_IGN);
#endif
Signal(SIGINT, SIG_IGN);
#endif
}

/* Make sure we'll have the directories to create a file. */

void
makedirs(filename,striplast)
Reg1 char *filename;
bool striplast;
{
char tmpbuf[256];
Reg2 char *s = tmpbuf;
char *dirv[20];
Reg3 int i;
Reg4 int dirvp = 0;

while (*filename) {
if (*filename == '/') {
filename++;
dirv[dirvp++] = s;
*s++ = '\0';
}
else {
*s++ = *filename++;
}
}
*s = '\0';
dirv[dirvp] = s;
if (striplast)
dirvp--;
if (dirvp < 0)
return;
strcpy(buf, "mkdir");
s = buf;
for (i=0; i<=dirvp; i++) {
while (*s) s++;
*s++ = ' ';
strcpy(s, tmpbuf);
*dirv[i] = '/';
}
system(buf);
}

/* Make filenames more reasonable. */

char *
fetchname(at,strip_leading,assume_exists)
char *at;
int strip_leading;
int assume_exists;
{
char *s;
char *name;
Reg1 char *t;
char tmpbuf[200];

if (!at)
return Nullch;
s = savestr(at);
for (t=s; isspace(*t); t++) ;
name = t;
#ifdef DEBUGGING
if (debug & 128)
say4("fetchname %s %d %d\n",name,strip_leading,assume_exists);
#endif
if (strnEQ(name, "/dev/null", 9)) /* so files can be created by diffing */
return Nullch; /* against /dev/null. */
for (; *t && !isspace(*t); t++)
if (*t == '/')
if (--strip_leading >= 0)
name = t+1;
*t = '\0';
if (name != s && *s != '/') {
name[-1] = '\0';
if (stat(s, &filestat) && filestat.st_mode & S_IFDIR) {
name[-1] = '/';
name=s;
}
}
name = savestr(name);
Sprintf(tmpbuf, "RCS/%s", name);
free(s);
if (stat(name, &filestat) < 0 && !assume_exists) {
Strcat(tmpbuf, RCSSUFFIX);
if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+4, &filestat) < 0) {
Sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
if (stat(tmpbuf, &filestat) < 0 && stat(tmpbuf+5, &filestat) < 0) {
free(name);
name = Nullch;
}
}
}
return name;
}


  3 Responses to “Category : C Source Code
Archive   : PATCH12.ZIP
Filename : UTIL.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/