[BACK]Return to fam.c++ CVS log [TXT][DIR] Up to [Development] / fam / libfam

Annotation of fam/libfam/fam.c++, Revision 1.1.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>