home *** CD-ROM | disk | FTP | other *** search
- /*
- * give -- a paranoid's cat program
- */
- #include <stdio.h>
- #include <pwd.h>
- #include <fcntl.h>
- #include <sys/param.h>
- #include <sys/types.h>
- #include <sys/stat.h>
-
- #ifdef DEBUG
- #define INSTANTIATE"
- #endif
- #include "debug.h"
-
- #define PR (void) fprintf(stderr,
- #define EQ(a,b) strcmp(a,b) == 0
- #define ERR (-1)
- #define EOS '\0'
- #define YES 1 /* Function returns. */
- #define NO 0
- #define OK 0 /* Program exit codes */
- #define BAD 1
- #define AWFULL 3
-
- typedef struct {
- char *dptr;
- int dsize;
- } DATUM;
-
- char *ProgName = NULL;
- usage() {
- PR "Usage: %s [person] file...\n",ProgName);
- }
-
-
- main(argc,argv) int argc; char *argv[]; {
- void give(), take(), remove(), exit();
-
- begin("main");
- ProgName = argv[0];
- if (argc < 2) {
- if (exists(".give.dir")) {
- /* Say what we've got. */
- printDB();
- }
- else {
- /* Tell the user the usage. */
- usage();
- exit(BAD);
- }
- }
- else if (argv[1][0] == '-') {
- switch (toupper(argv[1][1])) {
- case 'D': /* Its the owner doing cleanup. */
- remove(argc-2,(char **)&argv[2]);
- break;
- case 'T': /* Force it to "take". */
- take(argc-2,(char **)&argv[2]);
- break;
- default: /* Error in usage. */
- usage();
- exit(BAD);
- }
- }
- else if (ownerIsRunningMe()) {
- /* Its a give-to-someone (nonsetuid) request. */
- give(argc-1,(char **)&argv[1]);
- }
- else {
- /* Its a setuid-owner cat request. */
- take(argc-1,(char **)&argv[1]);
-
- }
- end();
- exit(OK);
- }
-
- /*
- * take -- cat the file, if both it and the user match up
- */
- void
- take(count, arg) int count; char *arg[]; {
- int i;
- char *userName, *getUserId();
- char *path, *absPath();
-
- begin("take");
- /* Find the caller's userid. */
- userName = getUserId();
- pr1("I am %s\n",userName);
- pr1("count is %d\n",count);
-
- for (i=0; i < count; i++) {
- /* Read the database, and see if we get a match. */
- if ((path= absPath(arg[i])) == NULL) {
- PR "%s: could not get the absolute path of \"%s\",",
- ProgName,arg[i]);
- PR " is it elsewhere or does it contains a ..?\n");
- continue;
- }
- if (searchDB(userName,path)) {
- cat(path);
- }
- }
- end();
- }
-
-
- /*
- * give -- put the person and file in the .give database
- */
- void
- give(count, arg) int count; char *arg[]; {
- int i;
- char *absPath();
- char *userName;
- char *path;
-
- begin("give");
- /* Break the user name out of the args vector. */
- userName = arg[0];
- count--;
- arg = (char **)&arg[1];
-
- /* Find if the named person has a userid. */
- if (validateUserId(userName) == 0) {
- PR "%s: %s is not a known user-id on this system\n",
- ProgName, userName);
- exit(BAD);
- }
-
- /* And process each of the files in order. */
- for (i=0; i < count; i++) {
- /* Find the absolute pathname of the file. */
- if ((path= absPath(arg[i])) == NULL) {
- PR "%s: file \"%s\" not found, ignored.\n",
- ProgName, arg[i]);
- }
- else {
- /* Put them in the database. */
- addDB(userName,path);
- }
- }
- end();
- }
-
- /*
- * remove -- remove a person-filename pair from the database
- */
- void
- remove(count, arg) int count; char **arg; {
- int i;
- char *absPath();
- char *userName;
- char *path;
-
- begin("give");
- /* Break the user name out of the args vector. */
- userName = arg[0];
- count--;
- arg = (char **)&arg[1];
-
- /* And remove each of the files in order. */
- for (i=0; i < count; i++) {
- /* Find the absolute pathname of the file. */
- if ((path= absPath(arg[i])) == NULL) {
- PR "%s: file \"%s\" not found, ignored.\n",
- ProgName, arg[i]);
- }
- else {
- /* Take them out of the database. */
- removeDB(userName,path);
- }
- }
- end();
- }
-
-
- /*
- ** Filesystem functions
- **
- */
-
- /*
- * absPath -- find the absolute pathname of a file, return NULL
- * if it doesn't have (a canonical and unique) one.
- */
- char *
- absPath(name) char *name; {
- static char path[MAXPATHLEN*2];
- char *getcwd(), *strcat(), *strcpy();
-
- begin("abspath");
- if (*name == '/') {
- /* Its an absolute path. */
- (void) strcpy(path,name);
- }
- else {
- /* Its a relative path: prefix the working directory. */
- if (getcwd(path,MAXPATHLEN) == NULL) {
- PR "%s: can't find working directory, halting\n",
- ProgName);
- exit(AWFULL);
- }
- (void) strcat(strcat(path,"/"),name);
- }
- if (!canonical(path)) {
- ret(NULL);
- }
- else if (exists(path) == NO) {
- ret(NULL);
- }
- else {
- ret(path);
- }
- }
-
- /*
- * canonical -- test a pathname for a ".." sequence.
- */
- int
- canonical(name) char *name; {
- char *p, *strchr();
-
- begin("canonical");
- p = name;
- while ((p=strchr(p+1,'.')) != NULL) {
- if (p[1] == '.') {
- ret(NO);
- }
- }
- ret(YES);
- }
-
- /*
- * exists -- stat a file for presence/absence
- */
- int
- exists(path) char *path; {
- struct stat buf;
-
- return (stat(path, &buf) != ERR);
- }
-
-
- /*
- ** userid functions
- **
- */
-
- /*
- * getUserId -- Find the user's userid.
- */
- char *
- getUserId() {
- struct passwd *p, *getpwuid();
- unsigned short getuid();
-
- begin("getUserId");
- if ((p=getpwuid((int)getuid())) == NULL) {
- ret(NULL);
- }
- else {
- ret(p->pw_name);
- }
- }
-
- /*
- * validateUserId -- Find if the named person has a userid.
- */
- int
- validateUserId(name) char *name; {
- struct passwd *getpwnam();
-
- return (getpwnam(name) != NULL);
- }
-
- /*
- * ownerIsRunningMe -- return YES if the owner of the program is running it
- */
- int
- ownerIsRunningMe() {
- unsigned short getuid(), geteuid();
-
- return (getuid() == geteuid());
- }
-
-
-
- /*
- ** database functions -- these happen to use dbm(3x), but anything is
- ** acceptable that can provide the primitives. Ingres would be
- ** somewhat nicer...
- */
- #define MAXNAME 100
-
- /*
- * addDB -- add a person-filename pair.
- */
- addDB(person,file) char *person, *file; {
- DATUM key,
- content;
- char record[MAXNAME+MAXPATHLEN],
- *strcat(), *strcpy();
-
- begin("addDB");
- initDB();
- key.dptr = strcat(strcat(strcpy(record,person)," "),file);
- key.dsize = strlen(record)+1;
- content.dptr = " ";
- content.dsize = 2;
- pr1("key is '%s'\n",record);
- if (store(key,content) < 0) {
- PR "%s: database failed on a store, halting\n",
- ProgName);
- exit(AWFULL);
- }
- end();
- }
-
- /*
- * searchDB -- see if a person-filename pair is present.
- */
- int
- searchDB(person,file) char *person, *file; {
- DATUM key, content, fetch();
- char record[MAXNAME+MAXPATHLEN],
- *strcat(), *strcpy();
-
- begin("searchDB");
- initDB();
- key.dptr = strcat(strcat(strcpy(record,person)," "),file);
- key.dsize = strlen(record)+1;
- pr1("key is '%s'\n",record);
- content = fetch(key);
- pr2("content = '%s' (0x%X)\n",content.dptr,content.dptr);
- ret(content.dptr != NULL);
- }
-
- /*
- * removeDB -- remove a person-filename pair
- */
- removeDB(person,file) char *person, *file; {
- DATUM key;
- char record[MAXNAME+MAXPATHLEN],
- *strcat(), *strcpy();
- int rc;
-
- begin("removeDB");
- initDB();
- key.dptr = strcat(strcat(strcpy(record,person)," "),file);
- key.dsize = strlen(record)+1;
- pr1("key is '%s'\n",record);
- rc = delete(key);
- pr1("rc = %d\n",rc);
- if (rc < 0) {
- PR "%s: could not remove \"%s\" from database\n",
- ProgName,record);
- exit(AWFULL);
- }
- end();
- }
-
- /*
- * printDB -- print all person-filename pairs in the database
- */
- printDB() {
- DATUM key, firstkey(), nextkey();
-
- begin("printDB");
- initDB();
- key = firstkey();
- if (key.dptr == NULL) {
- usage();
- }
- else {
- for (; key.dptr != NULL; key=nextkey(key))
- (void) printf("%s\n",key.dptr);
- }
- end();
- }
-
- /*
- * initDB -- open the db file
- */
- static
- initDB() {
- static openRqd = YES;
-
- begin("initDB");
- if (openRqd) {
- if (exists(".give.pag") == NO) {
- (void) creat(".give.dir",0755);
- (void) creat(".give.pag",0755);
- /* Success test is the dbminit... */
- }
- if (dbminit(".give") < 0) {
- PR "%s: cannot open .give.[dir|pag] file, halting\n",
- ProgName);
- exit(AWFULL);
- }
- }
- openRqd = NO;
- end();
- }
-
- /*
- * cat -- send a file to stdout.
- */
- #define BLOCKSIZE 1024
- cat(p) char *p; {
- char block[BLOCKSIZE];
- int fd,
- i;
-
- begin("cat");
- pr1("p is '%s'\n",p);
- if ((fd=open(p,O_RDONLY)) == ERR) {
- PR "%s: can't open %s (inpossible!)\n",
- ProgName, p);
- exit(AWFULL);
- }
- while ((i=read(fd,block,(unsigned)BLOCKSIZE)) != 0)
- (void) write(1,block,(unsigned)i);
- (void) close(fd);
- }
-