-/* $Header: doio.c,v 3.0 89/10/18 15:10:54 lwall Locked $
+/* $Header: doio.c,v 3.0.1.9 90/08/09 02:56:19 lwall Locked $
*
* Copyright (c) 1989, Larry Wall
*
* as specified in the README file that comes with the perl 3.0 kit.
*
* $Log: doio.c,v $
+ * Revision 3.0.1.9 90/08/09 02:56:19 lwall
+ * patch19: various MSDOS and OS/2 patches folded in
+ * patch19: prints now check error status better
+ * patch19: printing a list with null elements only printed front of list
+ * patch19: on machines with vfork child would allocate memory in parent
+ * patch19: getsockname and getpeername gave bogus warning on error
+ * patch19: MACH doesn't have seekdir or telldir
+ *
+ * Revision 3.0.1.8 90/03/27 15:44:02 lwall
+ * patch16: MSDOS support
+ * patch16: support for machines that can't cast negative floats to unsigned ints
+ * patch16: system() can lose arguments passed to shell scripts on SysV machines
+ *
+ * Revision 3.0.1.7 90/03/14 12:26:24 lwall
+ * patch15: commands involving execs could cause malloc arena corruption
+ *
+ * Revision 3.0.1.6 90/03/12 16:30:07 lwall
+ * patch13: system 'FOO=bar command' didn't invoke sh as it should
+ *
+ * Revision 3.0.1.5 90/02/28 17:01:36 lwall
+ * patch9: open(FOO,"$filename\0") will now protect trailing spaces in filename
+ * patch9: removed obsolete checks to avoid opening block devices
+ * patch9: removed references to acusec and modusec that some utime.h's have
+ * patch9: added pipe function
+ *
+ * Revision 3.0.1.4 89/12/21 19:55:10 lwall
+ * patch7: select now works on big-endian machines
+ * patch7: errno may now be a macro with an lvalue
+ * patch7: ANSI strerror() is now supported
+ * patch7: Configure now detects DG/UX thingies like [sg]etpgrp2 and utime.h
+ *
+ * Revision 3.0.1.3 89/11/17 15:13:06 lwall
+ * patch5: some systems have symlink() but not lstat()
+ * patch5: some systems have dirent.h but not readdir()
+ *
+ * Revision 3.0.1.2 89/11/11 04:25:51 lwall
+ * patch2: orthogonalized the file modes some so we can have <& +<& etc.
+ * patch2: do_open() now detects sockets passed to process from parent
+ * patch2: fd's above 2 are now closed on exec
+ * patch2: csh code can now use csh from other than /bin
+ * patch2: getsockopt, get{sock,peer}name didn't define result properly
+ * patch2: warn("shutdown") was replicated
+ * patch2: gethostbyname was misdeclared
+ * patch2: telldir() is sometimes a macro
+ *
+ * Revision 3.0.1.1 89/10/26 23:10:05 lwall
+ * patch1: Configure now checks for BSD shadow passwords
+ *
* Revision 3.0 89/10/18 15:10:54 lwall
* 3.0 baseline
*
#include <netdb.h>
#endif
-#include <errno.h>
#ifdef I_PWD
#include <pwd.h>
#endif
#ifdef I_GRP
#include <grp.h>
#endif
-
-extern int errno;
+#ifdef I_UTIME
+#include <utime.h>
+#endif
+#ifdef I_FCNTL
+#include <fcntl.h>
+#endif
bool
-do_open(stab,name)
+do_open(stab,name,len)
STAB *stab;
register char *name;
+int len;
{
FILE *fp;
- int len = strlen(name);
register STIO *stio = stab_io(stab);
char *myname = savestr(name);
int result;
fp = mypopen(name,"w");
writing = 1;
}
- else if (*name == '>' && name[1] == '>') {
-#ifdef TAINT
- taintproper("Insecure dependency in open");
-#endif
- mode[0] = stio->type = 'a';
- for (name += 2; isspace(*name); name++) ;
- fp = fopen(name, mode);
- writing = 1;
- }
- else if (*name == '>' && name[1] == '&') {
-#ifdef TAINT
- taintproper("Insecure dependency in open");
-#endif
- for (name += 2; isspace(*name); name++) ;
- if (isdigit(*name))
- fd = atoi(name);
- else {
- stab = stabent(name,FALSE);
- if (stab_io(stab) && stab_io(stab)->ifp) {
- fd = fileno(stab_io(stab)->ifp);
- stio->type = stab_io(stab)->type;
- }
- else
- fd = -1;
- }
- fp = fdopen(dup(fd),stio->type == 'a' ? "a" :
- (stio->type == '<' ? "r" : "w") );
- writing = 1;
- }
else if (*name == '>') {
#ifdef TAINT
taintproper("Insecure dependency in open");
#endif
- for (name++; isspace(*name); name++) ;
- if (strEQ(name,"-")) {
- fp = stdout;
- stio->type = '-';
+ name++;
+ if (*name == '>') {
+ mode[0] = stio->type = 'a';
+ name++;
}
- else {
+ else
mode[0] = 'w';
- fp = fopen(name,mode);
- }
writing = 1;
+ if (*name == '&') {
+ duplicity:
+ name++;
+ while (isspace(*name))
+ name++;
+ if (isdigit(*name))
+ fd = atoi(name);
+ else {
+ stab = stabent(name,FALSE);
+ if (!stab || !stab_io(stab))
+ return FALSE;
+ if (stab_io(stab) && stab_io(stab)->ifp) {
+ fd = fileno(stab_io(stab)->ifp);
+ if (stab_io(stab)->type == 's')
+ stio->type = 's';
+ }
+ else
+ fd = -1;
+ }
+ fp = fdopen(dup(fd),mode);
+ }
+ else {
+ while (isspace(*name))
+ name++;
+ if (strEQ(name,"-")) {
+ fp = stdout;
+ stio->type = '-';
+ }
+ else {
+ fp = fopen(name,mode);
+ }
+ }
}
else {
if (*name == '<') {
- for (name++; isspace(*name); name++) ;
+ mode[0] = 'r';
+ name++;
+ while (isspace(*name))
+ name++;
+ if (*name == '&')
+ goto duplicity;
if (strEQ(name,"-")) {
fp = stdin;
stio->type = '-';
}
- else {
- mode[0] = 'r';
+ else
fp = fopen(name,mode);
- }
}
else if (name[len-1] == '|') {
#ifdef TAINT
(void)fclose(fp);
return FALSE;
}
- if ((statbuf.st_mode & S_IFMT) != S_IFREG &&
+ result = (statbuf.st_mode & S_IFMT);
#ifdef S_IFSOCK
- (statbuf.st_mode & S_IFMT) != S_IFSOCK &&
-#endif
-#ifdef S_IFFIFO
- (statbuf.st_mode & S_IFMT) != S_IFFIFO &&
+ if (result == S_IFSOCK || result == 0)
+ stio->type = 's'; /* in case a socket was passed in to us */
#endif
- (statbuf.st_mode & S_IFMT) != S_IFCHR) {
- (void)fclose(fp);
- return FALSE;
- }
}
+#if defined(FCNTL) && defined(F_SETFD)
+ fd = fileno(fp);
+ if (fd >= 3)
+ fcntl(fd,F_SETFD,1);
+#endif
stio->ifp = fp;
- if (writing)
- stio->ofp = fp;
+ if (writing) {
+ if (stio->type != 's')
+ stio->ofp = fp;
+ else
+ stio->ofp = fdopen(fileno(fp),"w");
+ }
return TRUE;
}
str_sset(stab_val(stab),str);
STABSET(stab_val(stab));
oldname = str_get(stab_val(stab));
- if (do_open(stab,oldname)) {
+ if (do_open(stab,oldname,stab_val(stab)->str_cur)) {
if (inplace) {
#ifdef TAINT
taintproper("Insecure dependency in inplace open");
fileuid = statbuf.st_uid;
filegid = statbuf.st_gid;
if (*inplace) {
+#ifdef SUFFIX
+ add_suffix(str,inplace);
+#else
str_cat(str,inplace);
+#endif
#ifdef RENAME
+#ifndef MSDOS
+ (void)rename(oldname,str->str_ptr);
+#else
+ do_close(stab,FALSE);
+ (void)unlink(str->str_ptr);
(void)rename(oldname,str->str_ptr);
+ do_open(stab,str->str_ptr,stab_val(stab)->str_cur);
+#endif /* MSDOS */
#else
(void)UNLINK(str->str_ptr);
(void)link(oldname,str->str_ptr);
#endif
}
else {
+#ifndef MSDOS
(void)UNLINK(oldname);
+#else
+ fatal("Can't do inplace edit without backup");
+#endif
}
str_nset(str,">",1);
str_cat(str,oldname);
errno = 0; /* in case sprintf set errno */
- if (!do_open(argvoutstab,str->str_ptr))
+ if (!do_open(argvoutstab,str->str_ptr,str->str_cur))
fatal("Can't do inplace edit");
defoutstab = argvoutstab;
#ifdef FCHMOD
#ifdef FCHOWN
(void)fchown(fileno(stab_io(argvoutstab)->ifp),fileuid,filegid);
#else
+#ifdef CHOWN
(void)chown(oldname,fileuid,filegid);
#endif
+#endif
}
str_free(str);
return stab_io(stab)->ifp;
return Nullfp;
}
+#ifdef PIPE
+void
+do_pipe(str, rstab, wstab)
+STR *str;
+STAB *rstab;
+STAB *wstab;
+{
+ register STIO *rstio;
+ register STIO *wstio;
+ int fd[2];
+
+ if (!rstab)
+ goto badexit;
+ if (!wstab)
+ goto badexit;
+
+ rstio = stab_io(rstab);
+ wstio = stab_io(wstab);
+
+ if (!rstio)
+ rstio = stab_io(rstab) = stio_new();
+ else if (rstio->ifp)
+ do_close(rstab,FALSE);
+ if (!wstio)
+ wstio = stab_io(wstab) = stio_new();
+ else if (wstio->ifp)
+ do_close(wstab,FALSE);
+
+ if (pipe(fd) < 0)
+ goto badexit;
+ rstio->ifp = fdopen(fd[0], "r");
+ wstio->ofp = fdopen(fd[1], "w");
+ wstio->ifp = wstio->ofp;
+ rstio->type = '<';
+ wstio->type = '>';
+
+ str_sset(str,&str_yes);
+ return;
+
+badexit:
+ str_sset(str,&str_undef);
+ return;
+}
+#endif
+
bool
do_close(stab,explicit)
STAB *stab;
if (stio->type == '|') {
status = mypclose(stio->ifp);
retval = (status >= 0);
- statusvalue = (unsigned)status & 0xffff;
+ statusvalue = (unsigned short)status & 0xffff;
}
else if (stio->type == '-')
retval = TRUE;
retval = 256; /* otherwise guess at what's safe */
#endif
if (argstr->str_cur < retval) {
- str_grow(argstr,retval+1);
+ Str_Grow(argstr,retval+1);
argstr->str_cur = retval;
}
else {
str_sset(statname,ary->ary_array[sp]);
statstab = Nullstab;
-#ifdef SYMLINK
+#ifdef LSTAT
if (arg->arg_type == O_LSTAT)
i = lstat(str_get(statname),&statcache);
else
}
int
+do_truncate(str,arg,gimme,arglast)
+STR *str;
+register ARG *arg;
+int gimme;
+int *arglast;
+{
+ register ARRAY *ary = stack;
+ register int sp = arglast[0] + 1;
+ off_t len = (off_t)str_gnum(ary->ary_array[sp+1]);
+ int result = 1;
+ STAB *tmpstab;
+
+#if defined(TRUNCATE) || defined(CHSIZE) || defined(F_FREESP)
+#ifdef TRUNCATE
+ if ((arg[1].arg_type & A_MASK) == A_WORD) {
+ tmpstab = arg[1].arg_ptr.arg_stab;
+ if (!stab_io(tmpstab) ||
+ ftruncate(fileno(stab_io(tmpstab)->ifp), len) < 0)
+ result = 0;
+ }
+ else if (truncate(str_get(ary->ary_array[sp]), len) < 0)
+ result = 0;
+#else
+#ifndef CHSIZE
+#define chsize(f,l) fcntl(f,F_FREESP,l)
+#endif
+ if ((arg[1].arg_type & A_MASK) == A_WORD) {
+ tmpstab = arg[1].arg_ptr.arg_stab;
+ if (!stab_io(tmpstab) ||
+ chsize(fileno(stab_io(tmpstab)->ifp), len) < 0)
+ result = 0;
+ }
+ else {
+ int tmpfd;
+
+ if ((tmpfd = open(str_get(ary->ary_array[sp]), 0)) < 0)
+ result = 0;
+ else {
+ if (chsize(tmpfd, len) < 0)
+ result = 0;
+ close(tmpfd);
+ }
+ }
+#endif
+
+ if (result)
+ str_sset(str,&str_yes);
+ else
+ str_sset(str,&str_undef);
+ STABSET(str);
+ ary->ary_array[sp] = str;
+ return sp;
+#else
+ fatal("truncate not implemented");
+#endif
+}
+
+int
looks_like_number(str)
STR *str;
{
return FALSE;
}
if (!str)
- return FALSE;
+ return TRUE;
if (ofmt &&
((str->str_nok && str->str_u.str_nval != 0.0)
- || (looks_like_number(str) && str_gnum(str) != 0.0) ) )
+ || (looks_like_number(str) && str_gnum(str) != 0.0) ) ) {
fprintf(fp, ofmt, str->str_u.str_nval);
+ return !ferror(fp);
+ }
else {
tmps = str_get(str);
if (*tmps == 'S' && tmps[1] == 't' && tmps[2] == 'a' && tmps[3] == 'b'
str = ((STAB*)str)->str_magic;
putc('*',fp);
}
- if (str->str_cur && fwrite(tmps,1,str->str_cur,fp) == 0)
+ if (str->str_cur && (fwrite(tmps,1,str->str_cur,fp) == 0 || ferror(fp)))
return FALSE;
}
return TRUE;
retval = (items <= 0);
for (; items > 0; items--,st++) {
if (retval && ofslen) {
- if (fwrite(ofs, 1, ofslen, fp) == 0) {
+ if (fwrite(ofs, 1, ofslen, fp) == 0 || ferror(fp)) {
retval = FALSE;
break;
}
break;
}
if (retval && orslen)
- if (fwrite(ors, 1, orslen, fp) == 0)
+ if (fwrite(ors, 1, orslen, fp) == 0 || ferror(fp))
retval = FALSE;
}
return retval;
return FALSE;
}
+static char **Argv = Null(char **);
+static char *Cmd = Nullch;
+
+int
+do_execfree()
+{
+ if (Argv) {
+ Safefree(Argv);
+ Argv = Null(char **);
+ }
+ if (Cmd) {
+ Safefree(Cmd);
+ Cmd = Nullch;
+ }
+}
+
bool
do_exec(cmd)
char *cmd;
{
register char **a;
register char *s;
- char **argv;
char flags[10];
#ifdef TAINT
/* save an extra exec if possible */
- if (csh > 0 && strnEQ(cmd,"/bin/csh -c",11)) {
+#ifdef CSH
+ if (strnEQ(cmd,cshname,cshlen) && strnEQ(cmd+cshlen," -c",3)) {
strcpy(flags,"-c");
- s = cmd+11;
+ s = cmd+cshlen+3;
if (*s == 'f') {
s++;
strcat(flags,"f");
*--s = '\0';
if (s[-1] == '\'') {
*--s = '\0';
- execl("/bin/csh","csh", flags,ncmd,(char*)0);
+ execl(cshname,"csh", flags,ncmd,(char*)0);
*s = '\'';
return FALSE;
}
}
}
+#endif /* CSH */
/* see if there are shell metacharacters in it */
+ for (s = cmd; *s && isalpha(*s); s++) ; /* catch VAR=val gizmo */
+ if (*s == '=')
+ goto doshell;
for (s = cmd; *s; s++) {
if (*s != ' ' && !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
if (*s == '\n' && !s[1]) {
return FALSE;
}
}
- New(402,argv, (s - cmd) / 2 + 2, char*);
-
- a = argv;
- for (s = cmd; *s;) {
+ New(402,Argv, (s - cmd) / 2 + 2, char*);
+ Cmd = nsavestr(cmd, s-cmd);
+ a = Argv;
+ for (s = Cmd; *s;) {
while (*s && isspace(*s)) s++;
if (*s)
*(a++) = s;
*s++ = '\0';
}
*a = Nullch;
- if (argv[0]) {
- execvp(argv[0],argv);
- if (errno == ENOEXEC) /* for system V NIH syndrome */
+ if (Argv[0]) {
+ execvp(Argv[0],Argv);
+ if (errno == ENOEXEC) { /* for system V NIH syndrome */
+ do_execfree();
goto doshell;
+ }
}
- Safefree(argv);
+ do_execfree();
return FALSE;
}
case O_GSOCKOPT:
st[sp] = str_2static(str_new(257));
st[sp]->str_cur = 256;
+ st[sp]->str_pok = 1;
if (getsockopt(fd, lvl, optname, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
goto nuts;
break;
nuts:
if (dowarn)
- warn("shutdown() on closed fd");
+ warn("[gs]etsockopt() on closed fd");
st[sp] = &str_undef;
return sp;
st[sp] = str_2static(str_new(257));
st[sp]->str_cur = 256;
+ st[sp]->str_pok = 1;
fd = fileno(stio->ifp);
switch (optype) {
case O_GETSOCKNAME:
if (getsockname(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
- goto nuts;
+ goto nuts2;
break;
case O_GETPEERNAME:
if (getpeername(fd, st[sp]->str_ptr, &st[sp]->str_cur) < 0)
- goto nuts;
+ goto nuts2;
break;
}
nuts:
if (dowarn)
- warn("shutdown() on closed fd");
+ warn("get{sock,peer}name() on closed fd");
+nuts2:
st[sp] = &str_undef;
return sp;
register int sp = arglast[0];
register char **elem;
register STR *str;
- struct hostent *gethostbynam();
+ struct hostent *gethostbyname();
struct hostent *gethostbyaddr();
#ifdef GETHOSTENT
struct hostent *gethostent();
return sp;
}
+#endif /* SOCKET */
+
+#ifdef SELECT
int
do_select(gimme,arglast)
int gimme;
int nfound;
struct timeval timebuf;
struct timeval *tbuf = &timebuf;
+ int growsize;
+#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
+ int masksize;
+ int offset;
+ char *fd_sets[4];
+ int k;
+
+#if BYTEORDER & 0xf0000
+#define ORDERBYTE (0x88888888 - BYTEORDER)
+#else
+#define ORDERBYTE (0x4444 - BYTEORDER)
+#endif
+
+#endif
for (i = 1; i <= 3; i++) {
- j = st[sp+i]->str_len;
+ j = st[sp+i]->str_cur;
if (maxlen < j)
maxlen = j;
}
+
+#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
+ growsize = maxlen; /* little endians can use vecs directly */
+#else
+#ifdef NFDBITS
+
+#ifndef NBBY
+#define NBBY 8
+#endif
+
+ masksize = NFDBITS / NBBY;
+#else
+ masksize = sizeof(long); /* documented int, everyone seems to use long */
+#endif
+ growsize = maxlen + (masksize - (maxlen % masksize));
+ Zero(&fd_sets[0], 4, char*);
+#endif
+
for (i = 1; i <= 3; i++) {
str = st[sp+i];
j = str->str_len;
- if (j < maxlen) {
+ if (j < growsize) {
if (str->str_pok) {
- str_grow(str,maxlen);
+ Str_Grow(str,growsize);
s = str_get(str) + j;
- while (++j <= maxlen) {
+ while (++j <= growsize) {
*s++ = '\0';
}
}
str->str_ptr = Nullch;
}
}
+#if BYTEORDER != 0x1234 && BYTEORDER != 0x12345678
+ s = str->str_ptr;
+ if (s) {
+ New(403, fd_sets[i], growsize, char);
+ for (offset = 0; offset < growsize; offset += masksize) {
+ for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
+ fd_sets[i][j+offset] = s[(k % masksize) + offset];
+ }
+ }
+#endif
}
str = st[sp+4];
if (str->str_nok || str->str_pok) {
else
tbuf = Null(struct timeval*);
+#if BYTEORDER == 0x1234 || BYTEORDER == 0x12345678
nfound = select(
maxlen * 8,
st[sp+1]->str_ptr,
st[sp+2]->str_ptr,
st[sp+3]->str_ptr,
tbuf);
+#else
+ nfound = select(
+ maxlen * 8,
+ fd_sets[1],
+ fd_sets[2],
+ fd_sets[3],
+ tbuf);
+ for (i = 1; i <= 3; i++) {
+ if (fd_sets[i]) {
+ str = st[sp+i];
+ s = str->str_ptr;
+ for (offset = 0; offset < growsize; offset += masksize) {
+ for (j = 0, k=ORDERBYTE; j < masksize; j++, (k >>= 4))
+ s[(k % masksize) + offset] = fd_sets[i][j+offset];
+ }
+ }
+ }
+#endif
st[++sp] = str_static(&str_no);
str_numset(st[sp], (double)nfound);
}
return sp;
}
+#endif /* SELECT */
+#ifdef SOCKET
int
do_spair(stab1, stab2, arglast)
STAB *stab1;
#ifdef I_PWD
register ARRAY *ary = stack;
register int sp = arglast[0];
- register char **elem;
register STR *str;
struct passwd *getpwnam();
struct passwd *getpwuid();
struct passwd *getpwent();
struct passwd *pwent;
- unsigned long len;
if (gimme != G_ARRAY) {
astore(ary, ++sp, str_static(&str_undef));
(void)astore(ary, ++sp, str = str_static(&str_no));
str_numset(str, (double)pwent->pw_gid);
(void)astore(ary, ++sp, str = str_static(&str_no));
+#ifdef PWCHANGE
+ str_numset(str, (double)pwent->pw_change);
+#else
#ifdef PWQUOTA
str_numset(str, (double)pwent->pw_quota);
#else
str_set(str, pwent->pw_age);
#endif
#endif
+#endif
(void)astore(ary, ++sp, str = str_static(&str_no));
+#ifdef PWCLASS
+ str_set(str,pwent->pw_class);
+#else
str_set(str, pwent->pw_comment);
+#endif
(void)astore(ary, ++sp, str = str_static(&str_no));
str_set(str, pwent->pw_gecos);
(void)astore(ary, ++sp, str = str_static(&str_no));
str_set(str, pwent->pw_dir);
(void)astore(ary, ++sp, str = str_static(&str_no));
str_set(str, pwent->pw_shell);
+#ifdef PWEXPIRE
+ (void)astore(ary, ++sp, str = str_static(&str_no));
+ str_numset(str, (double)pwent->pw_expire);
+#endif
}
return sp;
struct group *getgrgid();
struct group *getgrent();
struct group *grent;
- unsigned long len;
if (gimme != G_ARRAY) {
astore(ary, ++sp, str_static(&str_undef));
int gimme;
int *arglast;
{
-#ifdef DIRENT
+#if defined(DIRENT) && defined(READDIR)
register ARRAY *ary = stack;
register STR **st = ary->ary_array;
register int sp = arglast[1];
register STIO *stio;
long along;
+#ifndef telldir
long telldir();
+#endif
struct DIRENT *readdir();
register struct DIRENT *dp;
#endif
}
break;
+#if MACH
+ case O_TELLDIR:
+ case O_SEEKDIR:
+ goto nope;
+#else
case O_TELLDIR:
st[sp] = str_static(&str_undef);
str_numset(st[sp], (double)telldir(stio->dirp));
along = (long)str_gnum(st[sp+1]);
(void)seekdir(stio->dirp,along);
break;
+#endif
case O_REWINDDIR:
st[sp] = str_static(&str_undef);
(void)rewinddir(stio->dirp);
}
}
break;
+#ifdef CHOWN
case O_CHOWN:
#ifdef TAINT
taintproper("Insecure dependency in chown");
}
}
break;
+#endif
+#ifdef KILL
case O_KILL:
#ifdef TAINT
taintproper("Insecure dependency in kill");
}
}
break;
+#endif
case O_UNLINK:
#ifdef TAINT
taintproper("Insecure dependency in unlink");
tot--;
}
else { /* don't let root wipe out directories without -U */
-#ifdef SYMLINK
+#ifdef LSTAT
if (lstat(s,&statbuf) < 0 ||
#else
if (stat(s,&statbuf) < 0 ||
taintproper("Insecure dependency in utime");
#endif
if (items > 2) {
+#ifdef I_UTIME
+ struct utimbuf utbuf;
+#else
struct {
- long atime,
- mtime;
+ long actime;
+ long modtime;
} utbuf;
+#endif
- utbuf.atime = (long)str_gnum(st[++sp]); /* time accessed */
- utbuf.mtime = (long)str_gnum(st[++sp]); /* time modified */
+ Zero(&utbuf, sizeof utbuf, char);
+ utbuf.actime = (long)str_gnum(st[++sp]); /* time accessed */
+ utbuf.modtime = (long)str_gnum(st[++sp]); /* time modified */
items -= 2;
#ifndef lint
tot = items;