Annotation of fam/libfam/fam.c++, Revision 1.1
1.1 ! trev 1: // Copyright (C) 1999 Silicon Graphics, Inc. All Rights Reserved.
! 2: //
! 3: // This program is free software; you can redistribute it and/or modify it
! 4: // under the terms of version 2.1 of the GNU Lesser General Public License
! 5: // as published by the Free Software Foundation.
! 6: //
! 7: // This program is distributed in the hope that it would be useful, but
! 8: // WITHOUT ANY WARRANTY; without even the implied warranty of
! 9: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Further, any
! 10: // license provided herein, whether implied or otherwise, is limited to
! 11: // this program in accordance with the express provisions of the GNU Lesser
! 12: // General Public License. Patent licenses, if any, provided herein do not
! 13: // apply to combinations of this program with other product or programs, or
! 14: // any other product whatsoever. This program is distributed without any
! 15: // warranty that the program is delivered free of the rightful claim of any
! 16: // third person by way of infringement or the like. See the GNU Lesser
! 17: // General Public License for more details.
! 18: //
! 19: // You should have received a copy of the GNU General Public License along
! 20: // with this program; if not, write the Free Software Foundation, Inc., 59
! 21: // Temple Place - Suite 330, Boston MA 02111-1307, USA.
! 22:
! 23: #include <sys/types.h>
! 24: #include <rpc/rpc.h>
! 25: #include <sys/time.h>
! 26: #include <unistd.h>
! 27: #include <stdlib.h>
! 28: #include <stdio.h>
! 29: #include <string.h>
! 30: #include <sys/param.h>
! 31: #include <syslog.h>
! 32: #include <errno.h>
! 33: #include <netinet/in.h>
! 34: #include <netdb.h>
! 35:
! 36: #include "fam.h"
! 37: #include "Client.h"
! 38:
! 39: //#define DEBUG
! 40:
! 41:
! 42: // Some libserver stuff
! 43: #define FAMNUMBER 391002 // This is the official rpc number for fam.
! 44: #define FAMNAME "sgi_fam"
! 45: #define FAMVERS 2
! 46: #define LOCALHOSTNUMBER 0x7f000001 // Internet number for loopback.
! 47:
! 48: // Error variables - XXX currently not dealt with
! 49: #define FAM_NUM_ERRORS 1
! 50: int FAMErrno;
! 51: char *FamErrlist[FAM_NUM_ERRORS];
! 52:
! 53: struct GroupStuff
! 54: {
! 55: GroupStuff();
! 56: ~GroupStuff() { delete [] groups; }
! 57: int groupString(char *buf, int buflen);
! 58:
! 59: gid_t *groups;
! 60: int ngroups;
! 61: };
! 62:
! 63: static int findFreeReqnum();
! 64: static int checkRequest(FAMRequest *fr, const char *filename);
! 65: static int sendSimpleMessage(char code, FAMConnection *fc, const FAMRequest *fr);
! 66:
! 67: /**************************************************************************
! 68: * FAMOpen, FAMClose - opening, closing FAM connections
! 69: **************************************************************************/
! 70:
! 71: int FAMOpen2(FAMConnection* fc, const char* appName)
! 72: {
! 73: int famnumber = FAMNUMBER, famversion = FAMVERS;
! 74: struct rpcent *fament = getrpcbyname(FAMNAME);
! 75: if(fament != NULL)
! 76: {
! 77: famnumber = fament->r_number;
! 78: }
! 79:
! 80: // Try to connect.
! 81: fc->client = new Client(LOCALHOSTNUMBER, famnumber, famversion);
! 82: fc->fd = ((Client *)fc->client)->getSock();
! 83: if (fc->fd < 0) {
! 84: delete (Client *)fc->client;
! 85: fc->client = NULL;
! 86: return(-1);
! 87: }
! 88:
! 89: // Send App name
! 90: if (appName) {
! 91: char msg[200];
! 92: snprintf(msg, sizeof(msg), "N0 %d %d %s\n", geteuid(), getegid(), appName);
! 93: ((Client *)fc->client)->writeToServer(msg, strlen(msg)+1);
! 94: }
! 95:
! 96: return(0);
! 97: }
! 98:
! 99: int FAMOpen(FAMConnection* fc)
! 100: {
! 101: return FAMOpen2(fc, NULL);
! 102: }
! 103:
! 104: int FAMClose(FAMConnection* fc)
! 105: {
! 106: delete (Client *)fc->client;
! 107: return(0);
! 108: }
! 109:
! 110:
! 111:
! 112: /**************************************************************************
! 113: * FAMMonitorDirectory, FAMMonitorFile - monitor directory or file
! 114: **************************************************************************/
! 115:
! 116: #define ILLEGAL_REQUEST -1
! 117:
! 118: static int FAMMonitor(FAMConnection *fc, const char *filename, FAMRequest* fr,
! 119: void* userData, int code)
! 120: {
! 121:
! 122: if (!filename || filename[0] != '/')
! 123: return -1;
! 124:
! 125: int reqnum = fr->reqnum;
! 126: Client *client = (Client *)fc->client;
! 127: // store user data if necessary
! 128: if(userData != NULL) client->storeUserData(reqnum, userData);
! 129:
! 130: GroupStuff groups;
! 131: char msg[MSGBUFSIZ];
! 132: int msgLen;
! 133: snprintf(msg, MSGBUFSIZ, "%c%d %d %d %s\n", code, reqnum, geteuid(),
! 134: groups.groups[0], filename);
! 135: msgLen = strlen(msg) + 1; // include terminating \0 in msg
! 136: if(groups.ngroups > 1)
! 137: {
! 138: msgLen += groups.groupString(msg + msgLen, MSGBUFSIZ - msgLen);
! 139: ++msgLen; // include terminating \0
! 140: }
! 141:
! 142: // Send to FAM
! 143: client->writeToServer(msg, msgLen);
! 144: return(0);
! 145: }
! 146: int FAMMonitorDirectory(FAMConnection *fc,
! 147: const char *filename,
! 148: FAMRequest* fr,
! 149: void* userData)
! 150: {
! 151: if(checkRequest(fr, filename) != 0) return -1;
! 152:
! 153: #ifdef DEBUG
! 154: printf("FAMMonitorDirectory filename:%s, reqnum:%d, ud:%d\n", filename, fr->reqnum, (int) userData);
! 155: #endif
! 156: return FAMMonitor(fc, filename, fr, userData, 'M');
! 157: }
! 158: int FAMMonitorDirectory2(FAMConnection *fc,
! 159: const char *filename,
! 160: FAMRequest* fr)
! 161: {
! 162: return FAMMonitor(fc, filename, fr, NULL, 'M');
! 163: }
! 164:
! 165: int FAMMonitorFile(FAMConnection *fc,
! 166: const char *filename,
! 167: FAMRequest* fr,
! 168: void* userData)
! 169: {
! 170: if(checkRequest(fr, filename) != 0) return -1;
! 171:
! 172: #ifdef DEBUG
! 173: printf("FAMMonitorFile filename:%s, reqnum:%d, ud:%d\n", filename, fr->reqnum, (int) userData);
! 174: #endif
! 175: return FAMMonitor(fc, filename, fr, userData, 'W');
! 176: }
! 177: int FAMMonitorFile2(FAMConnection *fc,
! 178: const char *filename,
! 179: FAMRequest* fr)
! 180: {
! 181: return FAMMonitor(fc, filename, fr, NULL, 'W');
! 182: }
! 183:
! 184:
! 185: int
! 186: FAMMonitorCollection(FAMConnection* fc,
! 187: const char* filename,
! 188: FAMRequest* fr,
! 189: void* userData,
! 190: int depth,
! 191: const char* mask)
! 192: {
! 193: if(checkRequest(fr, filename) != 0) return -1;
! 194:
! 195: Client *client = (Client *)fc->client;
! 196:
! 197: // store user data if necessary
! 198: if (userData) client->storeUserData(fr->reqnum, userData);
! 199:
! 200: GroupStuff groups;
! 201: char msg[MSGBUFSIZ];
! 202: int msgLen;
! 203: snprintf(msg, MSGBUFSIZ, "F%d %d %d %s\n", fr->reqnum, geteuid(),
! 204: groups.groups[0], filename);
! 205: msgLen = strlen(msg) + 1; // include terminating \0 in msg
! 206:
! 207: if(groups.ngroups > 1)
! 208: {
! 209: msgLen += groups.groupString(msg + msgLen, MSGBUFSIZ - msgLen);
! 210: }
! 211:
! 212: snprintf(msg + msgLen, MSGBUFSIZ - msgLen, "0 %d %s\n", depth, mask);
! 213: ++msgLen; // include terminating \0
! 214:
! 215: // Send to FAM
! 216: client->writeToServer(msg, msgLen);
! 217: return(0);
! 218: }
! 219:
! 220:
! 221: /**************************************************************************
! 222: * FAMSuspendMonitor, FAMResumeMonitor - suspend FAM monitoring
! 223: **************************************************************************/
! 224:
! 225: int FAMSuspendMonitor(FAMConnection *fc, const FAMRequest *fr)
! 226: {
! 227: return sendSimpleMessage('S', fc, fr);
! 228: }
! 229:
! 230: int FAMResumeMonitor(FAMConnection *fc, const FAMRequest *fr)
! 231: {
! 232: return sendSimpleMessage('U', fc, fr);
! 233: }
! 234:
! 235:
! 236:
! 237: /**************************************************************************
! 238: * FAMCancelMonitor - cancel FAM monitoring
! 239: **************************************************************************/
! 240:
! 241: int FAMCancelMonitor(FAMConnection *fc, const FAMRequest* fr)
! 242: {
! 243: #ifdef DEBUG
! 244: printf("FAMCancelMonitor reqnum:%d\n", fr->reqnum);
! 245: #endif
! 246: // Remove from user Data array
! 247: // Actually, we will do this when we receive the ack back from fam
! 248: // FAMFreeRequest(fr->reqnum);
! 249:
! 250: return sendSimpleMessage('C', fc, fr);
! 251: }
! 252:
! 253:
! 254: /**************************************************************************
! 255: * FAMNextEvent() - find the next fam event
! 256: * FAMPending() - return if events are ready yet
! 257: **************************************************************************/
! 258:
! 259: // FAMNextEvent tries to read one complete message into the input buffer.
! 260: // If it's successful, it parses the message and returns 1.
! 261: // Otherwise (EOF or errors), it returns -1.
! 262:
! 263: int FAMNextEvent(FAMConnection* fc, FAMEvent* fe)
! 264: {
! 265: fe->fc = fc;
! 266: return ((Client *)fc->client)->nextEvent(fe);
! 267: }
! 268:
! 269: // FAMPending tries to read one complete message into the input buffer.
! 270: // If it's successful, then it returns true. Also, if it reads EOF, it
! 271: // returns true.
! 272:
! 273: int FAMPending(FAMConnection* fc)
! 274: {
! 275: return ((Client *)fc->client)->eventPending();
! 276: }
! 277:
! 278:
! 279:
! 280: /**************************************************************************
! 281: * FAMDebugLevel() - doesn't do anything
! 282: **************************************************************************/
! 283: int FAMDebugLevel(FAMConnection*, int)
! 284: {
! 285: return(1);
! 286: }
! 287:
! 288:
! 289:
! 290: /**************************************************************************
! 291: * Support Functions
! 292: **************************************************************************/
! 293:
! 294: static int
! 295: findFreeReqnum()
! 296: {
! 297: static int reqnum=1;
! 298: return(reqnum++);
! 299: }
! 300:
! 301: static int
! 302: checkRequest(FAMRequest *fr, const char *filename)
! 303: {
! 304: // Fill out request structure
! 305: int reqnum;
! 306: if ((reqnum = findFreeReqnum()) == ILLEGAL_REQUEST) {
! 307: return(-1);
! 308: }
! 309: fr->reqnum = reqnum;
! 310:
! 311: // Check path length of file
! 312: if (strlen(filename) > MAXPATHLEN) {
! 313: syslog(LOG_ALERT, "path too long\n");
! 314: errno = ENAMETOOLONG;
! 315: return (-1);
! 316: }
! 317: return 0;
! 318: }
! 319:
! 320: static int
! 321: sendSimpleMessage(char code, FAMConnection *fc, const FAMRequest *fr)
! 322: {
! 323: // Create FAM String
! 324: char msg[MSGBUFSIZ];
! 325: snprintf(msg, MSGBUFSIZ, "%c%d %d %d\n", code, fr->reqnum, geteuid(), getegid());
! 326:
! 327: // Send to FAM
! 328: ((Client *)fc->client)->writeToServer(msg, strlen(msg)+1);
! 329: return(0);
! 330: }
! 331:
! 332: GroupStuff::GroupStuff()
! 333: {
! 334: ngroups = sysconf(_SC_NGROUPS_MAX);
! 335: groups = new gid_t[ngroups];
! 336: ngroups = getgroups(ngroups, groups);
! 337: }
! 338:
! 339: int
! 340: GroupStuff::groupString(char *buf, int buflen)
! 341: {
! 342: if(ngroups < 2) return 0;
! 343: const int GROUP_STRLEN = 8; // max length of " %d" output, we hope
! 344: if(buflen < (ngroups * GROUP_STRLEN)) return 0;
! 345: //XXX that should create some error condition
! 346:
! 347: char *p = buf;
! 348: snprintf(p, GROUP_STRLEN, "%d", ngroups - 1);
! 349: p += strlen(p);
! 350: for(int i = 1; i < ngroups; ++i) // group[0] doesn't go in string
! 351: {
! 352: snprintf(p, GROUP_STRLEN, " %d", groups[i]);
! 353: p += strlen(p);
! 354: }
! 355: *p = '\0';
! 356:
! 357: return p - buf;
! 358: }
! 359:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>