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>