local.c revision 3f54fd611f536639ec30dd53c48e5ec1897cc7d9
/***********************************************************************
* *
* This software is part of the BSD package *
*Copyright (c) 1978-2012 The Regents of the University of California an*
* *
* Redistribution and use in source and binary forms, with or *
* without modification, are permitted provided that the following *
* conditions are met: *
* *
* 1. Redistributions of source code must retain the above *
* copyright notice, this list of conditions and the *
* following disclaimer. *
* *
* 2. Redistributions in binary form must reproduce the above *
* copyright notice, this list of conditions and the *
* materials provided with the distribution. *
* *
* 3. Neither the name of The Regents of the University of California*
* names of its contributors may be used to endorse or *
* promote products derived from this software without *
* specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND *
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, *
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS *
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED *
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, *
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON *
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE *
* POSSIBILITY OF SUCH DAMAGE. *
* *
* Redistribution and use in source and binary forms, with or without *
* modification, are permitted provided that the following conditions *
* are met: *
* 1. Redistributions of source code must retain the above copyright *
* notice, this list of conditions and the following disclaimer. *
* 2. Redistributions in binary form must reproduce the above copyright *
* notice, this list of conditions and the following disclaimer in *
* distribution. *
* 3. Neither the name of the University nor the names of its *
* contributors may be used to endorse or promote products derived *
* from this software without specific prior written permission. *
* *
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" *
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS *
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT *
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF *
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND *
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, *
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT *
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF *
* SUCH DAMAGE. *
* *
* Kurt Shoens (UCB) *
* gsf *
* *
***********************************************************************/
#pragma prototyped
/*
* Mail -- a mail program
*
* Local installation dependent routines.
*/
#include "mailx.h"
#include <pwd.h>
#if _PACKAGE_ast
#include <tm.h>
#endif
/*
* Locate the user's mailbox file (ie, the place where new, unread
* mail is queued).
*/
char*
{
register char* s;
register int i;
int n = 0;
static const char* dir[] = {
};
return (char*)mail;
if (mail) {
return (char*)mail;
i = s - (char*)mail;
n = i;
}
}
if (n == 0) {
for (i = 0;; i++) {
if (i >= elementsof(dir)) {
i = 0;
break;
}
break;
}
n--;
}
}
/*
* Get rid of the queued mail.
*/
void
demail(void)
{
}
/*
* Discover user login name.
*/
char*
username(void)
{
register char* s;
register char* t;
if ((!(s = getenv("USER")) || !*s) &&
(!(s = getenv("LOGIN")) || !*s) &&
if (s)
{
if (t = strrchr(s, '/'))
s = t + 1;
if (!*s)
s = 0;
}
return s;
}
/*
* Convert name to a user id and return it.
* Mapping cached in state.userid.
* Return -1 on error.
*/
int
{
}
/*
* Make sure the lock doesn't hang -- NFS anyone?
*/
static void
{
}
/*
* Lock (set!=0) or unlock (set==0) open file fp.
*/
int
{
#if defined(F_SETLKW) && defined(F_WRLCK) && defined(F_UNLCK) || defined(LOCK_EX) && defined(LOCK_UN)
int r;
{
r = 5;
alarm(r);
{
}
#else
#endif
alarm(0);
else if (r)
}
#endif
return 0;
}
#if _PACKAGE_ast
/*
* Compute what the screen size for printing headers should be.
*/
void
setscreensize(void)
{
if (!state.realscreenheight)
if (!state.screenwidth)
}
/*
* check if date is valid with no trailing junk
*/
int
isdate(char* s)
{
char* t;
return *t == 0 && strmatch(s, "*[a-zA-Z]*[0-9]:[0-9]*");
}
#else /*_PACKAGE_ast*/
#include <termios.h>
#define CHUNK 32
char*
{
register unsigned char* s = (unsigned char*)as;
register char* b;
register int c;
static char* buf;
static int bufsiz;
if (bufsiz < c)
{
return 0;
}
b = buf;
while (c = *s++)
{
{
*b++ = '\\';
switch (c)
{
case '\007':
c = 'a';
break;
case '\b':
c = 'b';
break;
case '\f':
c = 'f';
break;
case '\n':
c = 'n';
break;
case '\r':
c = 'r';
break;
case '\t':
c = 't';
break;
case '\v':
c = 'v';
break;
case '\033':
c = 'E';
break;
default:
*b++ = '0' + ((c >> 6) & 07);
*b++ = '0' + ((c >> 3) & 07);
c = '0' + (c & 07);
break;
}
}
*b++ = c;
}
*b = 0;
return buf;
}
#define IDENT 01
#define USAGE 02
/*
*/
char*
fmtident(const char* a)
{
register char* s = (char*)a;
register char* t;
char* buf;
int i;
i = 0;
for (;;)
{
while (isspace(*s))
s++;
if (s[0] == '[')
{
while (*++s && *s != '\n');
i |= USAGE;
}
else if (s[0] == '@' && s[1] == '(' && s[2] == '#' && s[3] == ')')
s += 4;
{
s += 5;
i |= IDENT;
}
else
break;
}
if (i)
{
i &= IDENT;
for (t = s; isprint(*t) && *t != '\n'; t++)
if (i && t[0] == ' ' && t[1] == '$')
break;
while (t > s && isspace(t[-1]))
t--;
i = t - s;
return s;
s = buf;
s[i] = 0;
}
return s;
}
/*
* return the current shell path
*/
char*
pathshell(void)
{
char* shell;
shell = _PATH_SHELL;
return shell;
}
/*
* Compute what the screen size for printing headers should be.
* We use the following algorithm for the height:
* If baud rate < 1200, use 9
* If baud rate = 1200, use 14
* If baud rate > 1200, use 24 or ws_row
* Width is either 80 or ws_col;
*/
void
setscreensize(void)
{
int speed;
else
else
}
/*
* signal critical region support
*/
static const struct
{
int sig;
int op;
}
signals[] = /* held inside critical region */
{
#ifdef SIGQUIT
#endif
#ifdef SIGHUP
#endif
#ifdef SIGPIPE
#endif
#ifdef SIGCLD
#endif
#ifdef SIGCHLD
#endif
#ifdef SIGTSTP
#endif
#ifdef SIGTTIN
#endif
#ifdef SIGTTOU
#endif
};
/*
* critical signal region handler
*
* op>0 new region according to SIG_REG_*, return region level
* op==0 pop region, return region level
* op<0 return non-zero if any signals held in current region
*
* signals[] held until region popped
*/
int
sigcritical(int op)
{
register int i;
static int region;
static int level;
if (op > 0)
{
if (!level++)
{
if (op & SIG_REG_SET)
level--;
sigemptyset(&nmask);
for (i = 0; i < elementsof(signals); i++)
}
return level;
}
else if (op < 0)
{
sigpending(&nmask);
for (i = 0; i < elementsof(signals); i++)
{
return 1;
}
return 0;
}
else
{
/*
* a vfork() may have intervened so we
* allow apparent nesting mismatches
*/
if (--level < 0)
{
level = 0;
}
return level;
}
}
/*
* remove sig from the set of blocked signals
* sig==0 unblocks them all
*/
int
sigunblock(int sig)
{
int op;
sigemptyset(&mask);
if (sig)
{
op = SIG_UNBLOCK;
}
else op = SIG_SETMASK;
}
/*
* fork+execvp
*/
int
{
int pid;
sigcritical(1);
{
return -1;
}
sigcritical(0);
if (pid == 0)
{
_exit(1);
}
return pid;
}
/*
* return the next character in the string s
* \ character constants are converted
* p is updated to point to the next character in s
*/
int
chresc(register const char* s, char** p)
{
register const char* q;
register int c;
switch (c = *s++)
{
case 0:
s--;
break;
case '\\':
switch (c = *s++)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c -= '0';
q = s + 2;
while (s < q) switch (*s)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
c = (c << 3) + *s++ - '0';
break;
default:
q = s;
break;
}
break;
case 'a':
c = '\007';
break;
case 'b':
c = '\b';
break;
case 'f':
c = '\f';
break;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 's':
c = ' ';
break;
case 't':
c = '\t';
break;
case 'v':
c = '\013';
break;
case 'x':
c = 0;
q = s;
while (q) switch (*s)
{
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
c = (c << 4) + *s++ - 'a' + 10;
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
c = (c << 4) + *s++ - 'A' + 10;
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
c = (c << 4) + *s++ - '0';
break;
default:
q = 0;
break;
}
break;
case 'E':
c = '\033';
break;
case 0:
s--;
break;
}
break;
}
if (p) *p = (char*)s;
return c;
}
/*
* copy t into s, return a pointer to the end of s ('\0')
*/
char*
strcopy(register char* s, register const char* t)
{
if (!t)
return s;
while (*s++ = *t++);
return s - 1;
}
/*
* convert \x character constants in s in place
* the length of the converted s is returned (may have imbedded \0's)
*/
int
stresc(register char* s)
{
register char* t;
register int c;
char* b;
char* p;
b = t = s;
for (;;)
{
switch (c = *s++)
{
case '\\':
c = chresc(s - 1, &p);
s = p;
break;
case 0:
*t = 0;
return t - b;
}
*t++ = c;
}
}
/*
* return a pointer to the isalpha() identifier matching
* name in the sorted tab of num elements of
* size siz where the first member of each
* element is a char*
*
* [xxx] brackets optional identifier characters
*
* 0 returned if name not found
* otherwise if next!=0 then it points to the next
* unmatched char in name
*/
void*
{
register char* mid;
register unsigned char* s;
register unsigned char* t;
register int c;
register int v;
int sequential = 0;
c = *((unsigned char*)name);
t = (unsigned char*)name;
for (;;) {
if (!v && *s == '[') {
v = 1;
s++;
}
else if (v && *s == ']') {
v = 0;
s++;
}
else if (!isalpha(*t)) {
if (v || !*s) {
if (next)
*next = (char*)t;
return (void*)mid;
}
if (!sequential) {
sequential = 1;
}
v = 1;
break;
}
else if (*t != *s) {
v = *t - *s;
break;
}
else {
t++;
s++;
}
}
}
else if (sequential)
break;
if (v > 0)
else
}
return 0;
}
typedef int (*Compare_f)(const char*, const char*);
typedef int (*Compare_context_f)(const char*, const char*, void*);
/*
* return a pointer to the element matching
* name in the (*comparf*)() sorted tab of num elements of
* size siz where the first member of each
* element is a char*
*
* 0 returned if name not found
*/
void*
strsearch(const void* tab, size_t num, size_t siz, Compare_f comparf, const char* name, void* context)
{
register char* mid;
register int v;
{
if (!(v = context ? (*(Compare_context_f)comparf)(name, *((char**)mid), context) : (*(Compare_f)comparf)(name, *((char**)mid))))
return (void*)mid;
else if (v > 0)
}
return 0;
}
/*
* touch file access and modify times of file
* if force>0 then file will be created if it doesn't exist
* if force<0 then times are taken verbatim
* times have one second granularity
*
* (time_t)(-1) retain old time
* 0 use current time
*/
int
{
{
if (!force || close(open(file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY|O_cloexec, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)))
return -1;
}
if (force >= 0)
{
}
}
/*
* check if date is valid with no trailing junk
*/
int
isdate(const char* s)
{
return 1;
}
#endif /*_PACKAGE_ast*/