Subversion Repositories public

Rev

Rev 57 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 57 Rev 58
1
1
2
/// inotify cron table manipulator classes implementation
2
/// inotify cron table manipulator classes implementation
3
/**
3
/**
4
 * \file incrontab.cpp
4
 * \file incrontab.cpp
5
 *
5
 *
6
 * inotify cron system
6
 * inotify cron system
7
 *
7
 *
8
 * Copyright (C) 2006 Lukas Jelinek, <lukas@aiken.cz>
8
 * Copyright (C) 2006 Lukas Jelinek, <lukas@aiken.cz>
9
 *
9
 *
10
 * This program is free software; you can use it, redistribute
10
 * This program is free software; you can use it, redistribute
11
 * it and/or modify it under the terms of the GNU General Public
11
 * it and/or modify it under the terms of the GNU General Public
12
 * License, version 2 (see LICENSE-GPL).
12
 * License, version 2 (see LICENSE-GPL).
13
 *  
13
 *  
14
 */
14
 */
15
15
16
16
17
#include <sstream>
17
#include <sstream>
18
#include <stdio.h>
18
#include <stdio.h>
19
#include <errno.h>
19
#include <errno.h>
20
20
21
#include "inotify-cxx.h"
21
#include "inotify-cxx.h"
22
22
23
#include "incrontab.h"
23
#include "incrontab.h"
24
24
25
25
26
/// Allowed users
26
/// Allowed users
27
#define INCRON_ALLOW_PATH "/etc/incron.allow"
27
#define INCRON_ALLOW_PATH "/etc/incron.allow"
28
28
29
/// Denied users
29
/// Denied users
30
#define INCRON_DENY_PATH "/etc/incron.deny"
30
#define INCRON_DENY_PATH "/etc/incron.deny"
31
31
32
/*
32
/*
33
 * ALLOW/DENY SEMANTICS
33
 * ALLOW/DENY SEMANTICS
34
 *
34
 *
35
 * If /etc/incron.allow exists ONLY users contained here
35
 * If /etc/incron.allow exists ONLY users contained here
36
 * are allowed to use incron.
36
 * are allowed to use incron.
37
 *
37
 *
38
 * Otherwise, if /etc/incron.deny exists only user NOT
38
 * Otherwise, if /etc/incron.deny exists only user NOT
39
 * contained here are allowed to use incron.
39
 * contained here are allowed to use incron.
40
 *
40
 *
41
 * Otherwise all users may use incron.
41
 * Otherwise all users may use incron.
42
 *
42
 *
43
 */
43
 */
44
44
45
45
46
46
47
InCronTabEntry::InCronTabEntry()
47
InCronTabEntry::InCronTabEntry()
48
: m_uMask(0),
48
: m_uMask(0),
49
  m_fNoLoop(false)
49
  m_fNoLoop(false)
50
{
50
{
51
 
51
 
52
}
52
}
53
53
54
InCronTabEntry::InCronTabEntry(const std::string& rPath, uint32_t uMask, const std::string& rCmd)
54
InCronTabEntry::InCronTabEntry(const std::string& rPath, uint32_t uMask, const std::string& rCmd)
55
: m_path(rPath),
55
: m_path(rPath),
56
  m_uMask(uMask),
56
  m_uMask(uMask),
57
  m_cmd(rCmd)
57
  m_cmd(rCmd)
58
{
58
{
59
 
59
 
60
}
60
}
61
61
62
std::string InCronTabEntry::ToString() const
62
std::string InCronTabEntry::ToString() const
63
{
63
{
64
  std::ostringstream ss;
64
  std::ostringstream ss;
65
 
65
 
66
  std::string m;
66
  std::string m;
67
 
67
 
68
  InotifyEvent::DumpTypes(m_uMask, m);
68
  InotifyEvent::DumpTypes(m_uMask, m);
69
  if (m.empty()) {
69
  if (m.empty()) {
70
    m = m_fNoLoop ? "IN_NO_LOOP" : "0";
70
    m = m_fNoLoop ? "IN_NO_LOOP" : "0";
71
  }
71
  }
72
  else {
72
  else {
73
    if (m_fNoLoop)
73
    if (m_fNoLoop)
74
      m.append(",IN_NO_LOOP");
74
      m.append(",IN_NO_LOOP");
75
  }
75
  }
76
 
76
 
77
  ss << GetSafePath(m_path) << " " << m << " " << m_cmd;
77
  ss << GetSafePath(m_path) << " " << m << " " << m_cmd;
78
  return ss.str();
78
  return ss.str();
79
}
79
}
80
80
81
bool InCronTabEntry::Parse(const std::string& rStr, InCronTabEntry& rEntry)
81
bool InCronTabEntry::Parse(const std::string& rStr, InCronTabEntry& rEntry)
82
{
82
{
83
  unsigned long u;
83
  unsigned long u;
84
  std::string s1, s2, s3;
84
  std::string s1, s2, s3;
85
 
85
 
86
  StringTokenizer tok(rStr, ' ', '\\');
86
  StringTokenizer tok(rStr, ' ', '\\');
87
  if (!tok.HasMoreTokens())
87
  if (!tok.HasMoreTokens())
88
    return false;
88
    return false;
89
   
89
   
90
  s1 = tok.GetNextToken(true);
90
  s1 = tok.GetNextToken(true);
91
  if (!tok.HasMoreTokens())
91
  if (!tok.HasMoreTokens())
92
    return false;
92
    return false;
93
   
93
   
94
  s2 = tok.GetNextToken(true);
94
  s2 = tok.GetNextToken(true);
95
  if (!tok.HasMoreTokens())
95
  if (!tok.HasMoreTokens())
96
    return false;
96
    return false;
97
 
97
 
98
  tok.SetNoPrefix();
98
  tok.SetNoPrefix();
99
  s3 = tok.GetRemainder();
99
  s3 = tok.GetRemainder();
100
  SIZE len = s3.length();
100
  SIZE len = s3.length();
101
  if (len > 0 && s3[len-1] == '\n')
101
  if (len > 0 && s3[len-1] == '\n')
102
    s3.resize(len-1);
102
    s3.resize(len-1);
103
 
103
 
104
  rEntry.m_path = s1;
104
  rEntry.m_path = s1;
105
  rEntry.m_cmd = s3;
105
  rEntry.m_cmd = s3;
106
  rEntry.m_uMask = 0;
106
  rEntry.m_uMask = 0;
107
  rEntry.m_fNoLoop = false;
107
  rEntry.m_fNoLoop = false;
108
 
108
 
109
  if (sscanf(s2.c_str(), "%lu", &u) == 1) {
109
  if (sscanf(s2.c_str(), "%lu", &u) == 1) {
110
    rEntry.m_uMask = (uint32_t) u;
110
    rEntry.m_uMask = (uint32_t) u;
111
  }
111
  }
112
  else {
112
  else {
113
    StringTokenizer tok(s2);
113
    StringTokenizer tok(s2);
114
    while (tok.HasMoreTokens()) {
114
    while (tok.HasMoreTokens()) {
115
      std::string s(tok.GetNextToken());
115
      std::string s(tok.GetNextToken());
116
      if (s == "IN_NO_LOOP")
116
      if (s == "IN_NO_LOOP")
117
        rEntry.m_fNoLoop = true;
117
        rEntry.m_fNoLoop = true;
118
      else
118
      else
119
        rEntry.m_uMask |= InotifyEvent::GetMaskByName(s);
119
        rEntry.m_uMask |= InotifyEvent::GetMaskByName(s);
120
    }
120
    }
121
  }
121
  }
122
 
122
 
123
  return true;
123
  return true;
124
}
124
}
125
125
126
std::string InCronTabEntry::GetSafePath(const std::string& rPath)
126
std::string InCronTabEntry::GetSafePath(const std::string& rPath)
127
{
127
{
128
  std::ostringstream stream;
128
  std::ostringstream stream;
129
 
129
 
130
  SIZE len = rPath.length();
130
  SIZE len = rPath.length();
131
  for (SIZE i = 0; i < len; i++) {
131
  for (SIZE i = 0; i < len; i++) {
132
    if (rPath[i] == ' ') {
132
    if (rPath[i] == ' ') {
133
      stream << "\\ ";
133
      stream << "\\ ";
134
    }
134
    }
135
    else if (rPath[i] == '\\') {
135
    else if (rPath[i] == '\\') {
136
      stream << "\\\\";
136
      stream << "\\\\";
137
    }
137
    }
138
    else {
138
    else {
139
      stream << rPath[i];
139
      stream << rPath[i];
140
    }
140
    }
141
  }
141
  }
142
 
142
 
143
  return stream.str();
143
  return stream.str();
144
}
144
}
145
145
146
bool InCronTab::Load(const std::string& rPath)
146
bool InCronTab::Load(const std::string& rPath)
147
{
147
{
148
  m_tab.clear();
148
  m_tab.clear();
149
 
149
 
150
  FILE* f = fopen(rPath.c_str(), "r");
150
  FILE* f = fopen(rPath.c_str(), "r");
151
  if (f == NULL)
151
  if (f == NULL)
152
    return false;
152
    return false;
153
 
153
 
154
  char s[1000];
154
  char s[1000];
155
  InCronTabEntry e;
155
  InCronTabEntry e;
156
  while (fgets(s, 1000, f) != NULL) {
156
  while (fgets(s, 1000, f) != NULL) {
157
    if (InCronTabEntry::Parse(s, e)) {
157
    if (InCronTabEntry::Parse(s, e)) {
158
      m_tab.push_back(e);
158
      m_tab.push_back(e);
159
    }
159
    }
160
  }
160
  }
161
 
161
 
162
  fclose(f);
162
  fclose(f);
163
 
163
 
164
  return true;
164
  return true;
165
}
165
}
166
166
167
bool InCronTab::Save(const std::string& rPath)
167
bool InCronTab::Save(const std::string& rPath)
168
{
168
{
169
  FILE* f = fopen(rPath.c_str(), "w");
169
  FILE* f = fopen(rPath.c_str(), "w");
170
  if (f == NULL)
170
  if (f == NULL)
171
    return false;
171
    return false;
172
 
172
 
173
  std::deque<InCronTabEntry>::iterator it = m_tab.begin();
173
  std::deque<InCronTabEntry>::iterator it = m_tab.begin();
174
  while (it != m_tab.end()) {
174
  while (it != m_tab.end()) {
175
    fputs((*it).ToString().c_str(), f);
175
    fputs((*it).ToString().c_str(), f);
176
    fputs("\n", f);
176
    fputs("\n", f);
177
    it++;
177
    it++;
178
  }
178
  }
179
 
179
 
180
  fclose(f);
180
  fclose(f);
181
 
181
 
182
  return true;
182
  return true;
183
}
183
}
184
184
185
bool InCronTab::CheckUser(const std::string& rUser)
185
bool InCronTab::CheckUser(const std::string& rUser)
186
{
186
{
187
  char s[100], u[100];
187
  char s[100], u[100];
188
 
188
 
189
  FILE* f = fopen(INCRON_ALLOW_PATH, "r");
189
  FILE* f = fopen(INCRON_ALLOW_PATH, "r");
190
  if (f == NULL) {
190
  if (f == NULL) {
191
    if (errno == ENOENT) {
191
    if (errno == ENOENT) {
192
      f = fopen(INCRON_DENY_PATH, "r");
192
      f = fopen(INCRON_DENY_PATH, "r");
193
      if (f == NULL) {
193
      if (f == NULL) {
194
        return errno == ENOENT;
194
        return errno == ENOENT;
195
      }
195
      }
196
      while (fgets(s, 100, f) != NULL) {
196
      while (fgets(s, 100, f) != NULL) {
197
        if (sscanf(s, "%s", u) == 1) {
197
        if (sscanf(s, "%s", u) == 1) {
198
          if (rUser == u) {
198
          if (rUser == u) {
199
            fclose(f);
199
            fclose(f);
200
            return false;
200
            return false;
201
          }
201
          }
202
        }
202
        }
203
      }
203
      }
204
      fclose(f);
204
      fclose(f);
205
      return true;
205
      return true;
206
    }
206
    }
207
   
207
   
208
    return false;
208
    return false;
209
  }
209
  }
210
210
211
  while (fgets(s, 100, f) != NULL) {
211
  while (fgets(s, 100, f) != NULL) {
212
    if (sscanf(s, "%s", u) == 1) {
212
    if (sscanf(s, "%s", u) == 1) {
213
      if (rUser == u) {
213
      if (rUser == u) {
214
        fclose(f);
214
        fclose(f);
215
        return true;
215
        return true;
216
      }
216
      }
217
    }
217
    }
218
  }
218
  }
219
 
219
 
220
  fclose(f);
220
  fclose(f);
221
  return false;
221
  return false;
222
}
222
}
223
223
224
std::string InCronTab::GetUserTablePath(const std::string& rUser)
224
std::string InCronTab::GetUserTablePath(const std::string& rUser)
225
{
225
{
226
  std::string s(INCRON_TABLE_BASE);
226
  std::string s(INCRON_TABLE_BASE);
227
  s.append(rUser);
227
  s.append(rUser);
228
  return s;
228
  return s;
229
}
229
}
230
230
231
231
232
232
233
 
233