Refreshed pnd_run and sudoers scripts from wiki
[pandora-libraries.git] / lib / pnd_pndfiles.c
1
2 #include <stdio.h> /* for FILE etc */
3 #include <stdlib.h> /* for malloc */
4 #include <ctype.h> /* for isprint */
5 #include <unistd.h> /* for fork/exec */
6
7 #define __USE_GNU
8 #include <string.h> /* for making strcasestr happy */
9
10 #include "pnd_container.h"
11 #include "pnd_pxml.h"
12 #include "pnd_apps.h"
13 #include "pnd_pndfiles.h"
14
15 unsigned char pnd_pnd_seek_pxml ( FILE *f ) {
16   char *b;                // buffer
17   char *match;            // match within buffer
18   unsigned int len;       // length of file (not suporting 'big files' 2GB..)
19   unsigned int pos;       // current tape head
20   unsigned int readable;  // amount to read (for small files/chunks)
21
22   b = malloc ( PND_PXML_WINDOW_SIZE + 1 );
23
24   if ( ! b ) {
25     return ( 0 );
26   }
27
28   memset ( b, '\0', PND_PXML_WINDOW_SIZE + 1 );
29
30   // determine length of file
31   fseek ( f, 0, SEEK_END );
32   len = ftell ( f );
33   fseek ( f, 0, SEEK_SET );
34
35   /* ready to scan through the file, backwards
36    */
37
38   // easy case or no?
39   if ( len <= PND_PXML_WINDOW_SIZE ) {
40     pos = 0;
41     readable = len;
42   } else {
43     pos = len - PND_PXML_WINDOW_SIZE;
44     readable = PND_PXML_WINDOW_SIZE;
45   }
46
47   while ( 1 ) {
48
49     //printf ( "find pxml; pos %u readable %u\n", pos, readable );
50
51     // seek into this blocks position
52     fseek ( f, pos, SEEK_SET );
53
54     // read
55     fread ( b, 1, readable, f );
56
57     // find the head tag here? now, there are serious heavy duty algorithyms for locating
58     // strings within an arbitrary buffer. Thats needs to be done. This is the worst
59     // performing brute force strategy here.
60     if ( ( match = pnd_match_binbuf ( b, readable, PXML_TAGHEAD ) ) ) {
61       fseek ( f, pos + ( match - b ), SEEK_SET );
62       //printf ( "  match found at %u\n", pos + ( match - b ) );
63       free ( b );
64       return ( 1 );
65     }
66
67     // no match, so we need to back up another chunk; if we can't
68     // back up that much, we're on our last check. if we can't back
69     // up at all, we've already been here and time to fail
70     if ( pos == 0 ) {
71       break; // done, FAIL
72     } else if ( pos > PND_PXML_WINDOW_FRACTIONAL ) {
73       pos -= PND_PXML_WINDOW_FRACTIONAL;
74       readable = PND_PXML_WINDOW_SIZE;
75     } else {
76       readable = PND_PXML_WINDOW_SIZE - pos;
77       memset ( b + pos, '\0', PND_PXML_WINDOW_SIZE - pos );
78       pos = 0;
79     }
80
81   } // while
82
83   // exeunt, with alarums
84   free ( b );
85   return ( 0 );
86 }
87
88 unsigned char pnd_pnd_accrue_pxml ( FILE *f, char *target, unsigned int maxlen ) {
89   char inbuf [ 1024 ]; // TBD: love all these assumptions? noob!
90   char *insert = target;
91   unsigned int l;
92
93   while ( fgets ( inbuf, 1023, f ) ) {
94
95     // copy inbuf onto end of target
96 #if 1
97     strncpy ( insert, inbuf, maxlen );
98     // reduce counter for max size so we can avoid buffer overruns
99     l = strlen ( inbuf );
100     maxlen -= l; // reduce
101     insert += l; // increment
102 #else
103     strncat ( target, inbuf, maxlen );
104 #endif
105
106     if ( strcasestr ( inbuf, PXML_TAGFOOT ) ) {
107       return ( 1 );
108     }
109
110   } // while
111
112   return ( 0 );
113 }
114
115 char *pnd_match_binbuf ( char *haystack, unsigned int maxlen, char *needle ) {
116   char *end = haystack + maxlen - strlen ( needle );
117   unsigned int needlelen = strlen ( needle );
118
119   while ( haystack < end ) {
120
121     if ( isprint(*haystack) ) {
122
123       if ( strncasecmp ( haystack, needle, needlelen ) == 0 ) {
124         //printf ( "haystack %s\n", haystack );
125         return ( haystack );
126       }
127
128     }
129
130     haystack += 1;
131   }
132
133   return ( NULL );
134 }
135
136 void pnd_get_mountpoint ( char *unique_id, char *r_mountpoint, unsigned int mountpoint_len ) {
137
138   if ( ! r_mountpoint ) {
139     return; // sillyness
140   }
141
142   snprintf ( r_mountpoint, mountpoint_len, "%s/%s", PND_MOUNT_PATH, unique_id );
143
144   return;
145 }
146
147 static unsigned char pnd_pnd_mountie ( char *pndrun, char *fullpath, char *unique_id, unsigned char do_mount ) {
148   char *argv [ 20 ];
149   int f;
150
151   if ( ! pndrun ) {
152     return ( 0 );
153   }
154
155   if ( ! fullpath ) {
156     return ( 0 );
157   }
158
159   if ( ! unique_id ) {
160     return ( 0 );
161   }
162
163 #if 0
164   printf ( "  runscript: %s\n", pndrun );
165   printf ( "  path: %s\n", fullpath );
166   printf ( "  id: %s\n", unique_id );
167 #endif
168
169   memset ( argv, '\0', sizeof(char*) * 20 );
170
171   // normal stuff
172   f = 0;
173   argv [ f++ ] = pndrun;
174   argv [ f++ ] = "-p";
175   argv [ f++ ] = fullpath;
176   argv [ f++ ] = "-b";
177   argv [ f++ ] = unique_id;
178
179   // mount-only
180   if ( do_mount ) {
181     argv [ f++ ] = "-m";
182   } else {
183     argv [ f++ ] = "-u";
184   }
185
186   // finish
187   argv [ f++ ] = NULL; // for execv
188
189   // debug
190 #if 0
191   int i;
192   for ( i = 0; i < f; i++ ) {
193     printf ( "exec's argv %u [ %s ]\n", i, argv [ i ] );
194   }
195 #endif
196
197   // invoke it!
198
199   if ( ( f = fork() ) < 0 ) {
200     // error forking
201   } else if ( f > 0 ) {
202     // parent
203   } else {
204     // child, do it
205     execv ( pndrun, argv );
206   } 
207
208   return ( 1 );
209 }
210
211 unsigned char pnd_pnd_mount ( char *pndrun, char *fullpath, char *unique_id ) {
212   return ( pnd_pnd_mountie ( pndrun, fullpath, unique_id, 1 ) );
213 }
214
215 unsigned char pnd_pnd_unmount ( char *pndrun, char *fullpath, char *unique_id ) {
216   return ( pnd_pnd_mountie ( pndrun, fullpath, unique_id, 0 ) );
217 }