Init
This commit is contained in:
503
cmd/patch/util.c
Executable file
503
cmd/patch/util.c
Executable file
@@ -0,0 +1,503 @@
|
||||
#ident "@(#)util.c 1.2 95/09/07 SMI"
|
||||
/*
|
||||
* Copyright (c) 1995, Sun Microsystems, Inc.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* This module contains IBM CONFIDENTIAL code. -- (IBM
|
||||
* Confidential Restricted when combined with the aggregated
|
||||
* modules for this product)
|
||||
* OBJECT CODE ONLY SOURCE MATERIALS
|
||||
* (C) COPYRIGHT International Business Machines Corp. 1993
|
||||
* All Rights Reserved
|
||||
*
|
||||
* US Government Users Restricted Rights - Use, duplication or
|
||||
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
||||
*
|
||||
* (c) Copyright 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
|
||||
* ALL RIGHTS RESERVED
|
||||
*
|
||||
* OSF/1 1.2
|
||||
*
|
||||
* Copyright 1986, Larry Wall
|
||||
*
|
||||
* This program may be copied as long as you don't try to make any
|
||||
* money off of it, or pretend that you wrote it.
|
||||
*/
|
||||
|
||||
/*
|
||||
* File: util.c
|
||||
* Date: Sun Feb 12 18:48:18 PST 1995
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Common utility routines for patch.
|
||||
*
|
||||
* Modifications:
|
||||
* $Log$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include files:
|
||||
*/
|
||||
#include "common.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/*
|
||||
* Function: void fatal(char *, ...)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Terminal output, pun intended.
|
||||
* Printf message to stderr and die.
|
||||
*
|
||||
* Inputs:
|
||||
* pat -> Printf pattern string.
|
||||
* ... -> other printf arguments
|
||||
*
|
||||
* Returns:
|
||||
* It does not...
|
||||
*/
|
||||
|
||||
void
|
||||
fatal(char *pat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
(void) fprintf(stderr, "patch: ");
|
||||
va_start(ap, pat);
|
||||
(void) vfprintf(stderr, pat, ap);
|
||||
va_end(ap);
|
||||
dont_sync = TRUE;
|
||||
cleanup();
|
||||
exit(ABORT_EXIT_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: void pfatal(char *, ...)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Terminal output, pun intended.
|
||||
* Printf message to stderr and call perror, then die.
|
||||
*
|
||||
* Inputs:
|
||||
* pat -> Printf pattern string.
|
||||
* ... -> other printf arguments
|
||||
*
|
||||
* Returns:
|
||||
* It does not...
|
||||
*/
|
||||
|
||||
void
|
||||
pfatal(char *pat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, pat);
|
||||
(void) vsprintf(buf, pat, ap);
|
||||
va_end(ap);
|
||||
|
||||
(void) fprintf(stderr, "patch: ");
|
||||
perror(buf);
|
||||
dont_sync = TRUE;
|
||||
cleanup();
|
||||
exit(ABORT_EXIT_VALUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: char *savestr(char_t *)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Allocate a unique area for a string and report error if
|
||||
* memory can't be allocated...
|
||||
*
|
||||
* Inputs:
|
||||
* s -> A pointer to string to save.
|
||||
*
|
||||
* Returns:
|
||||
* Address of saved string
|
||||
*/
|
||||
|
||||
char *
|
||||
savestr(char *s)
|
||||
{
|
||||
char *rv;
|
||||
|
||||
rv = strdup(s);
|
||||
if (rv == NULL) {
|
||||
pfatal(gettext("Memory allocation error"));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: char *wsavestr(char_t *)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Allocate a unique area for a wide string and report error if
|
||||
* memory can't be allocated...
|
||||
*
|
||||
* Inputs:
|
||||
* s -> A pointer to wide string to save.
|
||||
*
|
||||
* Returns:
|
||||
* Address of saved wide string
|
||||
*/
|
||||
|
||||
wchar_t *
|
||||
wsavestr(wchar_t *s)
|
||||
{
|
||||
wchar_t *rv;
|
||||
|
||||
rv = wsdup(s);
|
||||
if (rv == NULL) {
|
||||
pfatal(gettext("Memory allocation error"));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
return (rv);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: void *allocate(size_t)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Functionally equal to calloc but prints error message and dies
|
||||
* if memory can't be allocated.
|
||||
*
|
||||
* Inputs:
|
||||
* size -> #of bytes to allocate
|
||||
*
|
||||
* Returns:
|
||||
* Address of allocated memory
|
||||
*/
|
||||
|
||||
void *
|
||||
allocate(size_t size)
|
||||
{
|
||||
void *address = calloc(1, size);
|
||||
|
||||
if (address == NULL) {
|
||||
pfatal(gettext("Memory allocation failure"));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
return (address);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: void *reallocate(size_t)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Functionally equal to realloc but prints error message and dies
|
||||
* if memory can't be reallocated.
|
||||
*
|
||||
* Inputs:
|
||||
* address -> Address of memory to reallocate
|
||||
* size -> #of bytes to reallocate
|
||||
*
|
||||
* Returns:
|
||||
* Address of allocated memory
|
||||
*/
|
||||
|
||||
void *
|
||||
reallocate(void *address, size_t size)
|
||||
{
|
||||
address = realloc(address, size);
|
||||
if (address == NULL) {
|
||||
pfatal(gettext("Memory reallocation failure"));
|
||||
/* NOTREACHED */
|
||||
}
|
||||
return (address);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: void say(char *, ...)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Vanilla terminal output (buffered).
|
||||
* Shorthand for fprintf(stderr, pat, ...);
|
||||
*
|
||||
* Inputs:
|
||||
* pat -> Printf pattern string.
|
||||
* ... -> other printf arguments
|
||||
*/
|
||||
|
||||
void
|
||||
say(char *pat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, pat);
|
||||
(void) vfprintf(stderr, pat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: char *ask(char *)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Print a question and get a response from the user into buf,
|
||||
* somehow or other.
|
||||
*
|
||||
* Inputs:
|
||||
* pat -> Printf pattern string.
|
||||
* ... -> other printf arguments
|
||||
*
|
||||
* Returns:
|
||||
* Answer to question in buf[].
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
ask(char *pat, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ttyfd;
|
||||
int r;
|
||||
bool tty2 = isatty(2);
|
||||
|
||||
va_start(ap, pat);
|
||||
(void) vsprintf(buf, pat, ap);
|
||||
va_end(ap);
|
||||
|
||||
(void) fflush(stderr);
|
||||
(void) 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 */
|
||||
(void) fflush(stdout);
|
||||
(void) 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 */
|
||||
(void) write(ttyfd, buf, strlen(buf));
|
||||
r = read(ttyfd, buf, sizeof (buf));
|
||||
(void) close(ttyfd);
|
||||
} else if (isatty(0)) { /* this is probably patch input */
|
||||
(void) fflush(stdin);
|
||||
(void) 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)
|
||||
say(buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: void set_signals(int)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* How to handle certain events.
|
||||
*
|
||||
* Inputs:
|
||||
* None
|
||||
*
|
||||
* Returns:
|
||||
* Nothing
|
||||
*/
|
||||
|
||||
void
|
||||
sig_handler(int sig)
|
||||
{
|
||||
exit(3);
|
||||
}
|
||||
|
||||
void
|
||||
set_signals(void)
|
||||
{
|
||||
(void) signal(SIGABRT, sig_handler);
|
||||
(void) signal(SIGALRM, sig_handler);
|
||||
(void) signal(SIGFPE, sig_handler);
|
||||
(void) signal(SIGHUP, sig_handler);
|
||||
(void) signal(SIGILL, sig_handler);
|
||||
(void) signal(SIGINT, sig_handler);
|
||||
(void) signal(SIGPIPE, sig_handler);
|
||||
(void) signal(SIGQUIT, sig_handler);
|
||||
(void) signal(SIGSEGV, sig_handler);
|
||||
(void) signal(SIGTERM, sig_handler);
|
||||
(void) signal(SIGUSR1, sig_handler);
|
||||
(void) signal(SIGUSR1, sig_handler);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: void ignore_signals(void)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* How to handle certain events when in a critical region. (ignore them)
|
||||
*/
|
||||
|
||||
void
|
||||
ignore_signals(void)
|
||||
{
|
||||
(void) signal(SIGABRT, SIG_IGN);
|
||||
(void) signal(SIGALRM, SIG_IGN);
|
||||
(void) signal(SIGFPE, SIG_IGN);
|
||||
(void) signal(SIGHUP, SIG_IGN);
|
||||
(void) signal(SIGILL, SIG_IGN);
|
||||
(void) signal(SIGINT, SIG_IGN);
|
||||
(void) signal(SIGPIPE, SIG_IGN);
|
||||
(void) signal(SIGQUIT, SIG_IGN);
|
||||
(void) signal(SIGSEGV, SIG_IGN);
|
||||
(void) signal(SIGTERM, SIG_IGN);
|
||||
(void) signal(SIGUSR1, SIG_IGN);
|
||||
(void) signal(SIGUSR1, SIG_IGN);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: char *fetchname(wchar_t, int, int)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Process file name we get from patch file or user.
|
||||
* Strip path components, check out from sccs or rcs if nescessary.
|
||||
*
|
||||
* Inputs:
|
||||
* at -> pointer to intial name.
|
||||
* strip_leading -> strip leading pathname components?
|
||||
* assume_exists -> check out from rcs/sccs if needed?
|
||||
*
|
||||
* Returns:
|
||||
* Pointer to char * (ready for use by open)
|
||||
*/
|
||||
|
||||
char *
|
||||
fetchname(wchar_t *at, int strip_leading, int assume_exists)
|
||||
{
|
||||
wchar_t *s, *t, *n;
|
||||
char *name;
|
||||
char tmpbuf[200];
|
||||
|
||||
if (!at)
|
||||
return (NULL);
|
||||
|
||||
s = wsavestr(at);
|
||||
for (t = s; iswspace(*t); t++)
|
||||
;
|
||||
|
||||
n = t;
|
||||
/* so files can be created by diffing */
|
||||
if (!wcsncmp(t, L"/dev/null", 9))
|
||||
return (NULL); /* against /dev/null. */
|
||||
for (; *t && !iswspace(*t); t++) {
|
||||
if (*t == '/') {
|
||||
if (--strip_leading >= 0)
|
||||
n = t+1;
|
||||
}
|
||||
}
|
||||
|
||||
*t = '\0';
|
||||
if (n != s && *s != '/') {
|
||||
n[-1] = '\0';
|
||||
|
||||
(void) wcstombs(tmpbuf, s, 199);
|
||||
tmpbuf[199] = 0;
|
||||
if (lstat(tmpbuf, &filestat) && filestat.st_mode & S_IFDIR) {
|
||||
n[-1] = '/';
|
||||
n = s;
|
||||
}
|
||||
}
|
||||
|
||||
(void) wcstombs(tmpbuf, n, 199);
|
||||
name = savestr(tmpbuf);
|
||||
free(s);
|
||||
if (!assume_exists && lstat(name, &filestat) < 0) {
|
||||
(void) sprintf(tmpbuf, "RCS/%s%s", name, RCSSUFFIX);
|
||||
if (lstat(tmpbuf, &filestat) >= 0 ||
|
||||
lstat(tmpbuf+4, &filestat) >= 0) {
|
||||
(void) sprintf(buf, CHECKOUT, name);
|
||||
if (verbose)
|
||||
say(gettext("Can't find %s--attempting to "
|
||||
"check it out from RCS.\n"), name);
|
||||
if (system(buf) || lstat(name, &filestat) < 0) {
|
||||
say(gettext("Can't check out %s.\n"), name);
|
||||
return (NULL);
|
||||
}
|
||||
return (name);
|
||||
}
|
||||
(void) sprintf(tmpbuf, "SCCS/%s%s", SCCSPREFIX, name);
|
||||
if (lstat(tmpbuf, &filestat) >= 0 ||
|
||||
lstat(tmpbuf+5, &filestat) >= 0) {
|
||||
(void) sprintf(buf, GET, name);
|
||||
if (verbose)
|
||||
say(gettext("Can't find %s--attempting"
|
||||
" to get it from SCCS.\n"), name);
|
||||
if (system(buf) || lstat(name, &filestat) < 0) {
|
||||
say(gettext("Can't get %s.\n"), name);
|
||||
return (NULL);
|
||||
}
|
||||
return (name);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
return (name);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Function: int rpmatch(char *)
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Internationalized get yes / no answer.
|
||||
*
|
||||
* Inputs:
|
||||
* s -> Pointer to answer to compare against.
|
||||
*
|
||||
* Returns:
|
||||
* TRUE -> Answer was affirmative
|
||||
* FALSE -> Answer was negative
|
||||
*/
|
||||
|
||||
int
|
||||
rpmatch(char *s)
|
||||
{
|
||||
static char *default_yesexpr = "^[Yy].*";
|
||||
static char *compiled_yesexpr = (char *)NULL;
|
||||
|
||||
/* Execute once to initialize */
|
||||
if (compiled_yesexpr == (char *)NULL) {
|
||||
char *yesexpr;
|
||||
|
||||
/* get yes expression according to current locale */
|
||||
yesexpr = nl_langinfo(YESEXPR);
|
||||
/*
|
||||
* If the was no expression or if there is a compile error
|
||||
* use default yes expression. Anchor
|
||||
*/
|
||||
if ((yesexpr == (char *)NULL) || (*yesexpr == (char)NULL) ||
|
||||
((compiled_yesexpr =
|
||||
regcmp(yesexpr, 0)) == NULL))
|
||||
compiled_yesexpr = regcmp(default_yesexpr, 0);
|
||||
}
|
||||
|
||||
/* match yesexpr */
|
||||
if (regex(compiled_yesexpr, s) == NULL) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
Reference in New Issue
Block a user