- Fixed error when -d flag specified with volume name -- now ignored.

- Ran sources through indent(1).
- Separated out library routines.
This commit is contained in:
gdr 1996-09-03 03:55:00 +00:00
parent f8c4d4b6d5
commit 469a09b80b
10 changed files with 265 additions and 912 deletions

16
usr.bin/install/README Normal file
View File

@ -0,0 +1,16 @@
$Id: README,v 1.1 1996/09/03 03:54:55 gdr Exp $
As the describe file says, install(1) is a utility similar to cp(1),
except that it does a few more things and is intended for use in
makefiles and scripts.
To install install, type "dmake doinstall". By default, it places the
binary in /usr/bin and the man page in /usr/man/man1. If you don't
like these locations, either modify the makefile or copy the two files
by hand. There are no support files.
As usual, please email me or post to comp.sys.apple2.gno if you
encounter problems or bugs.
Devin Reade
March 1996

View File

@ -1,70 +0,0 @@
/*
* Copyright 1996 Devin Reade <gdr@myrias.com>.
* All rights reserved.
*
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: basename.c,v 1.1 1996/03/31 23:38:30 gdr Exp $
*/
#include <string.h>
#include <stdio.h>
#include "install.h"
/*
* basename
*
* returns the filename component of <path>. If <path> contains colons,
* they are assumed to be the directory separators, otherwise any '/' is
* assumed to be a directory separator.
*
* If no directory separators are found, then the full path is returned.
*
* No check is done as to whether the pathname is valid on the any
* given filesystem.
*/
char *
basename (char *path)
{
char delim, *p;
delim = strchr(path,':') ? ':' : '/';
p = strrchr(path,delim);
return p ? p+1 : path;
}
/*
* dirname
*
* Returns a pointer to an internal buffer that contains a string that
* matches the directory component
* of <path>. If <path> contains at least one ':', then it is assumed
* that colons are directory separators, otherwise any '/' character
* is treated as a directory separator.
*
* If <path> contains no pathname separators, then dirname() will
* return an empty (zero-length) string.
*
* No check is done as to whether the pathname is valid on the any
* given filesystem.
*/
char *
dirname (char *path)
{
char delim, *p;
static char dir[FILENAME_MAX];
strncpy(dir,path,FILENAME_MAX-1);
dir[FILENAME_MAX-1] = '\0';
delim = strchr(dir,':') ? ':' : '/';
p = strchr(dir,delim);
if (p == NULL) {
*dir = '\0';
} else {
*p = '\0';
}
return dir;
}

View File

@ -1,37 +0,0 @@
/*
* Copyright 1996 Devin Reade <gdr@myrias.com>.
* All rights reserved.
*
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: c2gs.c,v 1.1 1996/03/31 23:38:31 gdr Exp $
*/
#include <types.h>
#include <gsos.h>
#include <string.h>
#include "install.h"
/*
* __C2GS
*
* Converts a null-terminated C string into a class 1 GS/OS string.
* Space for the GS/OS string must already be allocated, and the
* length of s must not be more than 255 chars.
*
* If the s is too long, __C2GS will return NULL, otherwise it will
* return the GS/OS string g.
*/
GSString255Ptr
__C2GS(char *s, GSString255Ptr g)
{
size_t len;
len = strlen(s);
if (len > 255) return NULL; /* the string won't fit */
g->length = len;
strncpy(g->text,s,255);
return g;
}

View File

@ -1,284 +0,0 @@
/*
* Copyright 1996 Devin Reade <gdr@myrias.com>.
* All rights reserved.
*
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: copyfile.c,v 1.1 1996/03/31 23:38:31 gdr Exp $
*/
#include <errno.h>
#include <gsos.h>
#include <orca.h>
#include <string.h>
#include <stdlib.h>
#include "install.h"
/* the chunk size in which we copy files */
#define COPY_BUFFER_SIZE 1024
/*
* copyfile
*
* copy a file from the pathname <from> to the location <to>, which
* may be a directory. Ensure that file types and other information
* (except for the backup bit) is matched.
*
* Returns NULL and sets errno on failure. On success, returns a
* pointer to an internal buffer containing the final pathname.
*
* +++ THIS ROUTINE IS NOT REENTRANT +++
*/
char *
copyfile (char *from, char *to)
{
static char buffer[COPY_BUFFER_SIZE];
static FileInfoRecGS inforec;
static OpenRecGS openrec;
static ExpandPathRecGS expandrec;
static ResultBuf255 resultbuf;
static struct {
Word pCount;
Word refNum;
Longword dataBuffer;
Longword requestCount;
Longword transferCount;
Word cachePriority;
} iobuf;
static struct {
Word pCount;
Word refNum;
} closerec;
static GSString255 fromGS, toGS;
static char *result = NULL; /* we only use this if our path is */
/* exactly 255 chars long */
size_t len1, len2;
Word refNumIn, refNumOut; /* GS/OS ref numbers for I/O */
int isDir, i, j, k, done;
char *p, *q, *r;
/* concheck and convert filenames to GSString255 type */
if (!from || !to ||
((len1 = strlen(from)) > 254) ||
((len2 = strlen(to)) > 254) )
{
errno = EINVAL;
return NULL;
}
fromGS.length = len1;
toGS.length = len2;
strcpy(fromGS.text,from);
strcpy(toGS.text,to);
/* expand the original file name */
expandrec.pCount = 3;
expandrec.inputPath = &fromGS;
expandrec.outputPath = &resultbuf;
expandrec.flags = 0x0000;
resultbuf.bufSize = 255;
ExpandPathGS(&expandrec);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
strcpyGSString255(&fromGS,&(resultbuf.bufString));
/* expand the destination name */
expandrec.pCount = 3;
expandrec.inputPath = &toGS;
expandrec.outputPath = &resultbuf;
expandrec.flags = 0x0000;
resultbuf.bufSize = 255;
ExpandPathGS(&expandrec);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
strcpyGSString255(&toGS,&(resultbuf.bufString));
/* find out if <to> is a directory */
inforec.pCount = 5;
inforec.pathname = &toGS;
GetFileInfoGS(&inforec);
i = toolerror();
switch(i) {
case 0:
isDir = ((inforec.storageType == 0x0D) ||
(inforec.storageType == 0x0F)) ? 1 : 0;
break;
case fileNotFound:
isDir = 0;
break;
default:
errno = _mapErr(i);
return NULL;
}
/* it's a directory? tack on the file name */
if (isDir) {
/* expand the directory name */
expandrec.pCount = 3;
expandrec.inputPath = &toGS;
expandrec.outputPath = &resultbuf;
expandrec.flags = 0x0000;
resultbuf.bufSize = 255;
ExpandPathGS(&expandrec);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
/* tack on the final component */
p = basename(from);
len1 = strlen(p);
if (len1 + toGS.length + 1 > 255) {
errno = EINVAL;
return NULL;
}
q = &(toGS.text[toGS.length]);
r = p;
*q++ = ':';
for (i=0; i<len1; i++) {
*q++ = *r++;
}
toGS.length += len1 + 1;
}
/* check to see it's not the same file */
if (strcmpGSString255(&fromGS, &toGS) == 0) {
errno = EINVAL;
return NULL;
}
/* get the file info of the original file */
inforec.pCount = 7;
inforec.pathname = &fromGS;
GetFileInfoGS(&inforec);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
/* destroy the old target file if it exists */
inforec.pCount = 1;
inforec.pathname = &toGS; DestroyGS(&inforec);
i = toolerror();
switch(i) {
case 0:
case fileNotFound:
break;
default:
errno = _mapErr(i);
return NULL;
}
/* create the new file */
inforec.pCount = 5;
inforec.pathname = &toGS;
CreateGS(&inforec);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
/* copy both forks, if necessary */
for (i=0; i< ((inforec.storageType == extendedFile) ? 2 : 1); i++) {
/* open the input file */
openrec.pCount = 4;
openrec.pathname = &fromGS;
openrec.requestAccess = readEnable;
switch (i) {
case 0:
openrec.resourceNumber = 0x0000;
break;
case 1:
openrec.resourceNumber = 0x0000;
break;
}
OpenGS(&openrec);
if ((j = toolerror()) != 0) {
errno = _mapErr(j);
return NULL;
}
refNumIn = openrec.refNum;
/* open the output file */
openrec.pathname = &toGS;
openrec.requestAccess = writeEnable;
OpenGS(&openrec);
if ((j = toolerror()) != 0) {
closerec.pCount = 1;
closerec.refNum = refNumIn;
CloseGS(&closerec);
errno = _mapErr(j);
return NULL;
}
refNumOut = openrec.refNum;
/* transfer the data */
done = 0;
iobuf.pCount = 5;
iobuf.dataBuffer = (Longword) &buffer;
iobuf.cachePriority = cacheOn;
while (!done) {
iobuf.refNum = refNumIn;
iobuf.requestCount = COPY_BUFFER_SIZE;
ReadGS(&iobuf);
k = toolerror();
switch (k) {
case 0:
break;
case eofEncountered:
done = 1;
break;
default:
closerec.pCount = 1;
closerec.refNum = refNumIn;
CloseGS(&closerec);
closerec.refNum = refNumOut;
CloseGS(&closerec);
errno = _mapErr(k);
return NULL;
}
iobuf.refNum = refNumOut;
iobuf.requestCount = iobuf.transferCount;
WriteGS(&iobuf);
if ((k = toolerror()) != 0) {
closerec.pCount = 1;
closerec.refNum = refNumIn;
CloseGS(&closerec);
closerec.refNum = refNumOut;
CloseGS(&closerec);
errno = _mapErr(k);
return NULL;
}
} /* end loop over buffering */
closerec.pCount = 1;
closerec.refNum = refNumIn;
CloseGS(&closerec);
closerec.refNum = refNumOut;
CloseGS(&closerec);
} /* end loop over forks */
/* set file information to match original file */
inforec.pCount = 7;
inforec.pathname = &toGS;
SetFileInfoGS(&inforec);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
if (toGS.length == 255) {
if (result) free(result);
result = __GS2CMALLOC(&toGS);
return result;
}
toGS.text[toGS.length]='\0';
return toGS.text;
}

View File

@ -1,125 +0,0 @@
/*
* Copyright 1996 Devin Reade <gdr@myrias.com>.
* All rights reserved.
*
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: errnoGS.c,v 1.1 1996/03/31 23:38:31 gdr Exp $
*/
#include <gsos.h>
#include <stdarg.h>
#include <stdio.h>
#include "install.h"
#pragma lint -1
#pragma debug 0
#pragma optimize -1
#define NONE "no error"
#define UNKNOWN "unknown error"
segment "errnoGS___";
typedef struct errEntry {
unsigned short num;
char *str;
} errEntry;
static errEntry
sys_errlistGS[] = {
{ badSystemCall, "bad system call number" },
{ invalidPcount, "invalid parameter count" },
{ gsosActive, "GS/OS already active" },
{ devNotFound, "device not found" },
{ invalidDevNum, "invalid device number" },
{ drvrBadReq, "bad request or command" },
{ drvrBadCode, "bad control or status code" },
{ drvrBadParm, "bad call parameter" },
{ drvrNotOpen, "character device not open" },
{ drvrPriorOpen, "character device already open" },
{ irqTableFull, "interrupt table full" },
{ drvrNoResrc, "resources not available" },
{ drvrIOError, "I/O error" },
{ drvrNoDevice, "device not connected" },
{ drvrBusy, "call aborted; driver is busy" },
{ drvrWrtProt, "device is write protected" },
{ drvrBadCount, "invalid byte count" },
{ drvrBadBlock, "invalid block address" },
{ drvrDiskSwitch, "disk has been switched" },
{ drvrOffLine, "device off line/ no media present" },
{ badPathSyntax, "invalid pathname syntax" },
{ tooManyFilesOpen, "too many files open on server volume" },
{ invalidRefNum, "invalid reference number" },
{ pathNotFound, "subdirectory does not exist" },
{ volNotFound, "volume not found" },
{ fileNotFound, "file not found" },
{ dupPathname, "create or rename with existing name" },
{ volumeFull, "volume full error" },
{ volDirFull, "volume directory full" },
{ badFileFormat, "version error (incompatible file format)" },
{ badStoreType, "unsupported (or incorrect) storage type" },
{ eofEncountered, "end-of-file encountered" },
{ outOfRange, "position out of range" },
{ invalidAccess, "access not allowed" },
{ buffTooSmall, "buffer too small" },
{ fileBusy, "file is already open" },
{ dirError, "directory error" },
{ unknownVol, "unknown volume type" },
{ paramRangeErr, "parameter out of range" },
{ outOfMem, "out of memory" },
{ dupVolume, "duplicate volume name" },
{ notBlockDev, "not a block device" },
{ invalidLevel, "specifield level outside legal range" },
{ damagedBitMap, "block number too large" },
{ badPathNames, "invalid pathnames for ChangePath" },
{ notSystemFile, "not an executable file" },
{ osUnsupported, "Operating System not supported" },
{ stackOverflow, "too many applications on stack" },
{ dataUnavail, "data unavailable" },
{ endOfDir, "end of directory has been reached" },
{ invalidClass, "invalid FST call class" },
{ resForkNotFound, "file does not contain required resource" },
{ invalidFSTID, "error - FST ID is invalid" },
{ invalidFSTop, "invalid FST operation" },
{ fstCaution, "FST handled call, but result is weird" },
{ devNameErr, "device exists with same name as replacement name" },
{ defListFull, "device list is full" },
{ supListFull, "supervisor list is full" },
{ fstError, "generic FST error" },
{ resExistsErr, "cannot expand file, resource already exists" },
{ resAddErr, "cannot add resource fork to this type file" },
{ networkError, "generic network error" },
{ 0, NONE } /* we shouldn't see this */
};
unsigned short errnoGS = 0;
char *
strerrorGS(unsigned short num)
{
int i;
if (num == 0) return NONE;
i = 0;
while (sys_errlistGS[i].num) {
if (sys_errlistGS[i].num == num) {
return sys_errlistGS[i].str;
}
i++;
}
return UNKNOWN;
}
void
perrorGS(char *format, ...)
{
va_list ap;
va_start(ap,format);
vfprintf(stderr,format,ap);
fprintf(stderr,": %s\n",strerrorGS(errnoGS));
va_end(ap);
return;
}

View File

@ -1,53 +0,0 @@
/*
* Copyright 1996 Devin Reade <gdr@myrias.com>.
* All rights reserved.
*
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: expandpath.c,v 1.1 1996/03/31 23:38:32 gdr Exp $
*/
#include <types.h>
#include <gsos.h>
#include <errno.h>
#include <orca.h>
#include "install.h"
/*
* expandpath
*
* Uses the GS/OS facilities to expand the pathname <path>. On
* success, returns a pointer to the malloc'd expanded path. On
* failure it will return NULL and set errno.
*
* Note that in using this function, all directory separators will
* be converted to colons.
*
* Unfortunately, this routine uses a little over 0.5k of stack space ...
*/
char *
expandpath (char *path)
{
ExpandPathRecGS expand;
GSString255 inStr;
ResultBuf255 outBuf;
int i;
if (__C2GS(path,&inStr) == NULL) {
errno = EINVAL;
return NULL;
}
expand.pCount = 3;
expand.inputPath = &inStr;
expand.outputPath = &outBuf;
expand.flags = 0x0000;
outBuf.bufSize = 255;
ExpandPathGS(&expand);
if ((i = toolerror()) != 0) {
errno = _mapErr(i);
return NULL;
}
return __GS2CMALLOC(&(outBuf.bufString));
}

View File

@ -5,7 +5,7 @@
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: inst.c,v 1.1 1996/03/31 23:38:33 gdr Exp $
* $Id: inst.c,v 1.2 1996/09/03 03:54:58 gdr Exp $
*/
#include <stdio.h>
@ -16,9 +16,14 @@
#include <assert.h>
#include <string.h>
#include <types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <orca.h>
#include "install.h"
#include <gsos.h>
extern int _mapErr(int);
#include "contrib.h"
/* actions */
#define NOCHANGE 0
@ -44,12 +49,12 @@
#define EMAIL "<gdr@myrias.com>"
char *versionMsg = "Version %s by Devin Reade %s\n";
int dFlag;
int dFlag;
extern int mkdir(const char *);
extern int needsgno(void);
extern void begin_stack_check(void);
extern int end_stack_check(void);
extern int end_stack_check(void);
/*
* usage
@ -58,21 +63,21 @@ extern int end_stack_check(void);
*/
void
usage (void)
usage(void)
{
fputs("Usage: install [-cdhsv] [-o owner] [-g group] [-m mode] ",stderr);
fputs("source [...] dest\n\n",stderr);
fputs("Options:\n",stderr);
fputs("\t-c Ignored. (Backwards Unix compatibility)\n",stderr);
fputs("\t-d Create the specified directories\n",stderr);
fputs("\t-g group Specify group id (not implemented)\n",stderr);
fputs("\t-h Show usage information and exit.\n",stderr);
fputs("\t-m mode Specify (Unix) access mode\n",stderr);
fputs("\t-o owner Specify owner id (not implemented)\n",stderr);
fputs("\t-s Strip binary (not implemented)\n",stderr);
fputs("\t-v Show version number\n\n",stderr);
fprintf(stderr,versionMsg,VERSION,EMAIL);
exit(1);
fputs("Usage: install [-cdhsv] [-o owner] [-g group] [-m mode] ", stderr);
fputs("source [...] dest\n\n", stderr);
fputs("Options:\n", stderr);
fputs("\t-c Ignored. (Backwards Unix compatibility)\n", stderr);
fputs("\t-d Create the specified directories\n", stderr);
fputs("\t-g group Specify group id (not implemented)\n", stderr);
fputs("\t-h Show usage information and exit.\n", stderr);
fputs("\t-m mode Specify (Unix) access mode\n", stderr);
fputs("\t-o owner Specify owner id (not implemented)\n", stderr);
fputs("\t-s Strip binary (not implemented)\n", stderr);
fputs("\t-v Show version number\n\n", stderr);
fprintf(stderr, versionMsg, VERSION, EMAIL);
exit(1);
}
/*
@ -93,9 +98,9 @@ usage (void)
*/
int
getmode (char *str, unsigned long *mode, int *action)
getmode(char *str, unsigned long *mode, int *action)
{
unsigned long who = 0L;
unsigned long who = 0L;
unsigned long perm = 0L;
char *p, *q;
@ -103,47 +108,48 @@ getmode (char *str, unsigned long *mode, int *action)
if (isdigit(*str)) {
*action = ASSIGN;
errno = 0;
*mode = strtoul(str,NULL,8);
*mode = strtoul(str, NULL, 8);
return errno;
}
/* it's not an absolute octal; treat as a string */
if (((p = strchr(str,'+')) == NULL) &&
((p = strchr(str,'-')) == NULL) &&
((p = strchr(str,'=')) == NULL)) {
if (((p = strchr(str, '+')) == NULL) &&
((p = strchr(str, '-')) == NULL) &&
((p = strchr(str, '=')) == NULL)) {
errno = EINVAL;
return errno;
}
switch (*p) {
case '+': *action = ADD; break;
case '-': *action = REMOVE; break;
case '=': *action = ASSIGN; break;
default: assert(0);
case '+': *action = ADD; break;
case '-': *action = REMOVE; break;
case '=': *action = ASSIGN; break;
default: assert(0);
}
/*
* this condition should really be deduced from the umask, if it
* were supported.
*/
if (str == p) who |= S_USER;
if (str == p) {
who |= S_USER;
}
for (q = str; q<p; q++) {
for (q = str; q < p; q++) {
switch (*q) {
case 'u': who |= S_USER; break;
case 'g': who |= S_GROUP; break;
case 'o': who |= S_OTHER; break;
case 'a': who |= S_ALL; break;
default: errno = EINVAL; return errno;
case 'u': who |= S_USER; break;
case 'g': who |= S_GROUP; break;
case 'o': who |= S_OTHER; break;
case 'a': who |= S_ALL; break;
default: errno = EINVAL; return errno;
}
}
for (q = p+1; *q; q++) {
for (q = p + 1; *q; q++) {
switch (*q) {
case 'r': perm |= S_READ; break;
case 'w': perm |= S_WRITE; break;
case 'x': perm |= S_EXECUTE; break;
case 's': /* ignored */ break;
default: errno = EINVAL; return errno;
case 'r': perm |= S_READ; break;
case 'w': perm |= S_WRITE; break;
case 'x': perm |= S_EXECUTE; break;
case 's': /* ignored */ break;
default: errno = EINVAL; return errno;
}
}
@ -151,7 +157,6 @@ getmode (char *str, unsigned long *mode, int *action)
if (!(who & S_USER)) {
*action = NOCHANGE;
}
*mode = who & perm;
return 0;
}
@ -168,85 +173,88 @@ getmode (char *str, unsigned long *mode, int *action)
*/
int
mkdirs (int argc, char **argv)
mkdirs(int argc, char **argv)
{
static struct stat statbuf; /* reduce stack space */
char *path, *p;
static struct stat statbuf; /* reduce stack space */
char *path, *p;
size_t pathlen;
int result = 0;
int makeit; /* do we try a mkdir()? */
int abortpath; /* we saw an error; don't both with rest of path */
int i,j;
int makeit; /* do we try a mkdir()? */
int abortpath; /* we saw an error; don't both with rest of path */
int i, j;
int coloncount;
/* loop over each of the pathnames in the array */
for (i=0; i<argc; i++) {
for (i = 0; i < argc; i++) {
/* expand to a full pathname */
if ((path = expandpath(argv[i]))==NULL) {
perror(argv[i]);
continue;
}
pathlen = strlen(path);
/* is this pathname legal? */
/* place a call to JudgeName() [custom] here */
/* expand to a full pathname */
if ((path = expandpath(argv[i])) == NULL) {
perror(argv[i]);
continue;
}
pathlen = strlen(path);
/* find out how many path components there are */
coloncount = 0;
p = path;
while (*p) {
if (*p == ':') {
coloncount++;
}
p++;
}
p = path + 1;
/* is this pathname legal? */
/* place a call to JudgeName() [custom] here */
/* skip the volume name */
assert((p = strchr(p,':'))!=NULL);
/* find out how many path components there are */
coloncount = 0;
p = path;
while (*p) {
if (*p == ':') {
coloncount++;
}
p++;
--coloncount;
}
p = path + 1;
/* create each component in path */
abortpath = 0;
for (j=0; !abortpath && j<coloncount; j++) {
if ((p = strchr(p,':')) == NULL) {
p = path + pathlen;
}
*p = '\0';
/* skip the volume name */
if ((p = strchr(p, ':')) == NULL) {
/* only the volume name was given; skip it */
free(path);
continue;
}
p++;
--coloncount;
if (stat(path,&statbuf) != 0) {
if (errno == ENOENT) {
makeit = 1;
} else {
perror(path);
makeit = 0;
abortpath = 1;
result = 1;
}
} else {
makeit = 0;
if (statbuf.st_mode & S_IFDIR == 0) {
fprintf(stderr,"%s exists and is not a directory\n",path);
abortpath = 1;
result = 1;
} /* else it exists and is a directory */
}
/* go ahead and create the directory */
if (makeit && mkdir(path)) {
perror(path);
abortpath = 1;
result = 1;
}
/* create each component in path */
abortpath = 0;
for (j = 0; !abortpath && j < coloncount; j++) {
if ((p = strchr(p, ':')) == NULL) {
p = path + pathlen;
}
*p = '\0';
/* reinstate the ':' that we "nulled-out" */
if (p != path + pathlen) {
*p++ = ':';
}
}
free(path);
if (stat(path, &statbuf) != 0) {
if (errno == ENOENT) {
makeit = 1;
} else {
perror(path);
makeit = 0;
abortpath = 1;
result = 1;
}
} else {
makeit = 0;
if (statbuf.st_mode & S_IFDIR == 0) {
fprintf(stderr, "%s exists and is not a directory\n", path);
abortpath = 1;
result = 1;
} /* else it exists and is a directory */
}
/* go ahead and create the directory */
if (makeit && mkdir(path)) {
perror(path);
abortpath = 1;
result = 1;
}
/* reinstate the ':' that we "nulled-out" */
if (p != path + pathlen) {
*p++ = ':';
}
}
free(path);
}
return result;
}
@ -269,111 +277,115 @@ mkdirs (int argc, char **argv)
*/
static int
copyfiles (int argc, char **argv, int action, unsigned long mode)
copyfiles(int argc, char **argv, int action, unsigned long mode)
{
static FileInfoRecGS inforec;
static GSString255 filenameGS;
int i,j;
int result=0;
static FileInfoRecGS inforec;
static GSString255 filenameGS;
int i, j;
int result = 0;
char *destination;
Word newaccess;
if (argc < 2) {
errno = EINVAL;
perror("internal error: not enough arguments to copyfiles()");
return errno;
errno = EINVAL;
perror("internal error: not enough arguments to copyfiles()");
return errno;
}
if (argc > 2) {
/* find out if argv[argc-1] is a directory */
if (__C2GS(argv[argc-1], &filenameGS) == NULL) {
errno = EINVAL;
perror("destination path too long");
return errno;
}
inforec.pCount = 5;
inforec.pathname = &filenameGS;
GetFileInfoGS(&inforec);
if ((errnoGS = toolerror()) != 0) {
perrorGS("%s",argv[argc-1]);
errno = _mapErr(errnoGS);
/* find out if argv[argc-1] is a directory */
if (__C2GS(argv[argc - 1], &filenameGS) == NULL) {
errno = EINVAL;
perror("destination path too long");
return errno;
}
inforec.pCount = 5;
inforec.pathname = &filenameGS;
GetFileInfoGS(&inforec);
if ((errnoGS = toolerror()) != 0) {
perrorGS("%s", argv[argc - 1]);
errno = _mapErr(errnoGS);
return -1;
}
if ((inforec.storageType != 0x0D) && (inforec.storageType != 0x0F)) {
errno = ENOTDIR;
perror(argv[argc-1]);
return errno;
}
}
}
if ((inforec.storageType != 0x0D) && (inforec.storageType != 0x0F)) {
errno = ENOTDIR;
perror(argv[argc - 1]);
return errno;
}
}
--argc;
for (i=0; i<argc; i++) {
if ((destination = copyfile (argv[i],argv[argc])) == NULL) {
errnoGS = toolerror();
perrorGS("install of %s to %s",argv[i],argv[argc]);
result = errno = _mapErr(errnoGS);
for (i = 0; i < argc; i++) {
if ((destination = copyfile(argv[i], argv[argc])) == NULL) {
errnoGS = toolerror();
perrorGS("install of %s to %s", argv[i], argv[argc]);
result = errno = _mapErr(errnoGS);
}
if (action == NOCHANGE) {
continue;
}
/* get the file info for the source file */
if (__C2GS(argv[i], &filenameGS) == NULL) {
assert(0);
}
inforec.pCount = 7;
inforec.pathname = &filenameGS;
GetFileInfoGS(&inforec);
if ((errnoGS = toolerror()) != 0) {
perrorGS("GetFileInfo for %s failed", argv[i]);
result = errno = _mapErr(errnoGS);
}
/* modify the permissions as necessary */
switch (action) {
case ASSIGN:
newaccess = 0xFFFF;
if (!(mode & S_READ)) newaccess &= ~readEnable;
if (!(mode & S_WRITE)) newaccess &= ~writeEnable;
inforec.access &= newaccess;
if ((mode & S_EXECUTE) &&
(inforec.fileType == TYPE_TXT) || (inforec.fileType == TYPE_SRC)) {
inforec.fileType = TYPE_SRC;
inforec.auxType = TYPE_EXEC;
}
if (action == NOCHANGE) continue;
break;
/* get the file info for the source file */
assert(__C2GS(argv[i],&filenameGS));
inforec.pCount = 7;
inforec.pathname = &filenameGS;
GetFileInfoGS(&inforec);
if ((errnoGS = toolerror()) != 0) {
perrorGS("GetFileInfo for %s failed",argv[i]);
result = errno = _mapErr(errnoGS);
}
case ADD:
if (mode & S_READ) inforec.access |= readEnable;
if (mode & S_WRITE) inforec.access |= writeEnable;
/* modify the permissions as necessary */
switch (action) {
case ASSIGN:
newaccess = 0xFFFF;
if (!(mode & S_READ)) newaccess &= ~readEnable;
if (!(mode & S_WRITE)) newaccess &= ~writeEnable;
inforec.access &= newaccess;
if ((mode & S_EXECUTE) &&
(inforec.fileType == TYPE_TXT) || (inforec.fileType == TYPE_SRC)) {
inforec.fileType = TYPE_SRC;
inforec.auxType = TYPE_EXEC;
}
break;
if ((mode & S_EXECUTE) &&
(inforec.fileType == TYPE_TXT) || (inforec.fileType == TYPE_SRC)) {
inforec.fileType = TYPE_SRC;
inforec.auxType = TYPE_EXEC;
}
break;
case REMOVE:
if (mode & S_READ) inforec.access &= ~readEnable;
if (mode & S_WRITE) inforec.access &= ~writeEnable;
case ADD:
if (mode & S_READ) inforec.access |= readEnable;
if (mode & S_WRITE) inforec.access |= writeEnable;
if ((mode & S_EXECUTE) &&
(inforec.fileType == TYPE_TXT) || (inforec.fileType == TYPE_SRC)) {
inforec.fileType = TYPE_TXT;
inforec.auxType = TYPE_NONE;
}
break;
if ((mode & S_EXECUTE) &&
(inforec.fileType == TYPE_TXT) || (inforec.fileType == TYPE_SRC)) {
inforec.fileType = TYPE_SRC;
inforec.auxType = TYPE_EXEC;
}
break;
default:
assert(0);
}
case REMOVE:
if (mode & S_READ) inforec.access &= ~readEnable;
if (mode & S_WRITE) inforec.access &= ~writeEnable;
if ((mode & S_EXECUTE) &&
(inforec.fileType == TYPE_TXT) || (inforec.fileType == TYPE_SRC)) {
inforec.fileType = TYPE_TXT;
inforec.auxType = TYPE_NONE;
}
break;
default:
assert(0);
}
/* set the modified file info for the destination file */
assert(__C2GS(destination,&filenameGS));
SetFileInfoGS(&inforec);
if ((errnoGS = toolerror()) != 0) {
perrorGS("SetFileInfo for %s failed",destination);
result = errno = _mapErr(errnoGS);
}
/* set the modified file info for the destination file */
if (__C2GS(destination, &filenameGS) == NULL) {
assert(0);
}
SetFileInfoGS(&inforec);
if ((errnoGS = toolerror()) != 0) {
perrorGS("SetFileInfo for %s failed", destination);
result = errno = _mapErr(errnoGS);
}
}
return result;
}
@ -383,61 +395,66 @@ copyfiles (int argc, char **argv, int action, unsigned long mode)
*/
int
main (int argc, char **argv)
main(int argc, char **argv)
{
unsigned long mode;
int c, nfiles;
int action = NOCHANGE;
int action = NOCHANGE;
#ifdef CHECK_STACK
begin_stack_check();
begin_stack_check();
#endif
if (needsgno()==0) {
fprintf(stderr,"Requires GNO/ME\n");
exit(1);
if (needsgno() == 0) {
fprintf(stderr, "Requires GNO/ME\n");
exit(1);
}
/* initialize */
dFlag = 0;
mode = 0L;
dFlag = 0;
mode = 0L;
/* parse command line */
while ((c = getopt(argc,argv,"cdg:hm:o:sv")) != EOF) {
while ((c = getopt(argc, argv, "cdg:hm:o:sv")) != EOF) {
switch (c) {
case 'v':
fprintf(stderr,versionMsg,VERSION,EMAIL);
fprintf(stderr, versionMsg, VERSION, EMAIL);
exit(1);
break;
case 'm':
if (getmode(optarg,&mode,&action)) usage();
if (getmode(optarg, &mode, &action)) {
usage();
}
break;
case 'd': dFlag++;
case 'c': /* not implemented */
case 'g': /* not implemented */
case 'o': /* not implemented */
case 's': /* not implemented */
case 'c': /* not implemented */
case 'g': /* not implemented */
case 'o': /* not implemented */
case 's': /* not implemented */
break;
case 'h':
default: usage();
default: usage();
}
}
nfiles = argc - optind;
if (dFlag) {
if (nfiles < 1) usage();
c = mkdirs(nfiles,&argv[optind]);
if (nfiles < 1) {
usage();
}
c = mkdirs(nfiles, &argv[optind]);
} else {
if (nfiles < 2) usage();
if (nfiles < 2) {
usage();
}
c = copyfiles(nfiles, &argv[optind], action, mode);
}
#ifdef CHECK_STACK
fprintf(stderr,"stack usage: %d bytes\n",end_stack_check());
fprintf(stderr, "stack usage: %d bytes\n", end_stack_check());
#endif
return c;

View File

@ -5,7 +5,7 @@
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: install.h,v 1.1 1996/03/31 23:38:33 gdr Exp $
* $Id: install.h,v 1.2 1996/09/03 03:54:59 gdr Exp $
*/
#ifndef __GSOS__
@ -17,27 +17,3 @@ extern GSString255Ptr __C2GSMALLOC (char *s);
extern char * __GS2CMALLOC (GSString255Ptr g);
extern char * __GS2C (char *s, GSString255Ptr g);
extern int _mapErr (int err);
/* from basename.c */
extern char *dirname (char *path);
extern char *basename (char *path);
/* from c2gs.c */
extern GSString255Ptr __C2GS(char *s, GSString255Ptr g);
/* from copyfile.c */
extern char *copyfile (char *from, char *to);
/* from errnoGS.c */
extern unsigned short errnoGS;
extern char *strerrorGS (unsigned short num);
extern void perrorGS (char *format, ...);
/* from expandpath.c */
extern char *expandpath (char *path);
/* from stringGS.c */
extern void strcpyGSString255 (GSString255Ptr to, GSString255Ptr from);
extern void strcatGSString255 (GSString255Ptr to, GSString255Ptr from);
extern int strcmpGSString255 (GSString255Ptr a, GSString255Ptr b);

View File

@ -1,40 +1,31 @@
#
# This makefile is for use with dmake(1).
#
# $Id: makefile.mk,v 1.1 1996/03/31 23:38:34 gdr Exp $
# $Id: makefile.mk,v 1.2 1996/09/03 03:54:59 gdr Exp $
#
DEFINES = -DCHECK_STACK
DEFINES = -D__GNO__ # -DCHECK_STACK
INCLUDES = -I ../contrib/src
STACK = -s1280
MAINFLAGS = $(DEFINES) $(STACK) -w -O
CFLAGS = $(DEFINES) $(STACK) -w -O -r
CFLAGS = $(DEFINES) $(INCLUDES) $(STACK) -w -O -v
LDFLAGS = -v
LDLIBS = -l/usr/lib/stack
LDLIBS = -l ../contrib/src/lcontrib \
-l ../contrib/src/libc2 \
# -l/usr/lib/stack
BINDIR = /usr/bin
MANDIR = /usr/man
OBJS = install.o basename.o c2gs.o copyfile.o errnoGS.o \
expandpath.o stringGS.o
OBJS = install.o
install: $(OBJS) install.r
$(CC) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $@
copyfork install.r install -r
@echo 'type \"dmake doinstall\" to install this program'
install.o: install.c install.h
$(CC) -c $(MAINFLAGS) install.c -o $@
doinstall:
./install -d $(BINDIR) $(MANDIR)/man1
./install -m755 -obin -gsys ./install $(BINDIR)
./install -m644 -obin -gsys ./install.1 $(MANDIR)/man1
clean clobber:
$(RM) $(OBJS) install.root install.r
basename.o :: install.h
c2gs.o :: install.h
copyfile.o :: install.h
errnoGS.o :: install.h
expandpath.o :: install.h
stringGS.o :: install.h

View File

@ -1,78 +0,0 @@
/*
* Copyright 1996 Devin Reade <gdr@myrias.com>.
* All rights reserved.
*
* For copying and distribution information, see the file "COPYING"
* accompanying this file.
*
* $Id: stringGS.c,v 1.1 1996/03/31 23:38:34 gdr Exp $
*/
#include <gsos.h>
#include "install.h"
/*
* strcpyGSString255
*
* copies the GSString255 pointed to by <from> to that pointed
* to by <to>
*/
void
strcpyGSString255 (GSString255Ptr to, GSString255Ptr from)
{
int i;
char *p = from->text;
char *q = to->text;
for (i=0; i<from->length; i++) *q++ = *p++;
to->length = from->length;
return;
}
/*
* strcatGSString255
*
* concatenates the string <from> onto <to>, to a maximum of 255
* chars total in <to>.
*/
void
strcatGSString255 (GSString255Ptr to, GSString255Ptr from)
{
int i, count;
char *p = from->text;
char *q = to->text;
q+= to->length;
count = from->length;
if (count > 255 - to->length) count = 255 - to->length;
for (i=0; i<count; i++) {
*q++ = *p++;
}
to->length += count;
return;
}
/*
* like strcmp(3), but for GSString255Ptr args.
*/
int
strcmpGSString255 (GSString255Ptr a, GSString255Ptr b)
{
int i, count;
char *p, *q;
count = a->length - b->length;
if (count) return count;
p = a->text;
q = b->text;
for (i=0; i<count; i++, p++, q++) {
if (*p == *q) continue;
else if (*p > *q) return 1;
else return -1;
}
return 0;
}