DEbugging :/
[pandora-libraries.git] / lib / pnd_utility.c
1
2 #include <stdio.h> /* for FILE etc */
3 #include <stdlib.h> /* for malloc */
4 #define __USE_GNU /* for strcasestr */
5 #include <string.h> /* for making ftw.h happy */
6 #include <unistd.h> /* for fork exec */
7
8 #include <utmp.h> /* for expand-tilde below; see commentary for this about-turn */
9 #include <sys/types.h> /* ditto */
10 #include <pwd.h> /* ditto */
11
12 #include "pnd_pxml.h"
13 #include "pnd_container.h"
14 #include "pnd_utility.h"
15 #include "pnd_pndfiles.h"
16 #include "pnd_discovery.h"
17
18 unsigned char pnd_check_login ( char *r_username, unsigned int maxlen ) {
19   FILE *f;
20   struct utmp b;
21   struct passwd *pw;
22
23   f = fopen ( "/var/run/utmp", "r" );
24
25   if ( f ) {
26
27     while ( fread ( &b, sizeof(struct utmp), 1, f ) == 1 ) {
28
29       if ( b.ut_type == USER_PROCESS ) {
30
31         // ut_user contains the username ..
32         // now we need to find the path to that account.
33         while ( ( pw = getpwent() ) ) {
34
35           if ( strcmp ( pw -> pw_name, b.ut_user ) == 0 ) {
36
37             if ( r_username ) {
38               strncpy ( r_username, b.ut_user, maxlen );
39             }
40
41             fclose ( f );
42             return ( 1 );
43           } // passwd entry matches the utmp entry
44
45         } // while iteratin across passwd entries
46         endpwent();
47
48       } // utmp entry is for a user login
49
50     } // while
51
52     fclose ( f );
53   } // opened?
54
55   return ( 0 );
56 }
57
58 // a generalized variable-substitution routine might be nice; for now we need a quick tilde one,
59 // so here goes. Brute force ftw!
60 char *pnd_expand_tilde ( char *freeable_buffer ) {
61   char *p;
62   char *s = freeable_buffer;
63   char *home = getenv ( "HOME" );
64
65   //printf ( "expand tilde IN: '%s'\n", freeable_buffer );
66   //printf ( "  home was %s\n", home );
67
68   // well, as pndnotifyd (etc) may be running as _root_, while the user is logged in
69   // as 'pandora' or god knows what, this could be problematic. Other parts of the lib
70   // use wordexp() for shell-like expansion, but this funciton is (at least) used by
71   // pndnotifyd for determination of the .desktop emit path, so we need ~ to expand
72   // to the _actual user_ rather than root's homedir. Rather than run 'users' or 'who'
73   // or the like, we'll just cut to the chase..
74   ///////
75   {
76     FILE *f;
77     struct utmp b;
78     static char *florp = NULL;
79     struct passwd *pw;
80
81     f = fopen ( "/var/run/utmp", "r" );
82
83     if ( f ) {
84
85       while ( fread ( &b, sizeof(struct utmp), 1, f ) == 1 ) {
86
87         if ( b.ut_type == USER_PROCESS ) {
88
89           // ut_user contains the username ..
90           // now we need to find the path to that account.
91           while ( ( pw = getpwent() ) ) {
92
93             if ( strcmp ( pw -> pw_name, b.ut_user ) == 0 ) {
94
95               // aight, we've got a logged in user and have matched it to
96               // passwd entry, so can construct the appropriate path
97
98               if ( florp ) {
99                 free ( florp );
100               }
101               florp = strdup ( pw -> pw_dir );
102
103               home = florp;
104               printf ( "  DEBUG: home is %s (from %u)\n", home, b.ut_type );
105
106             } // passwd entry matches the utmp entry
107
108           } // while iteratin across passwd entries
109           endpwent();
110
111         } // utmp entry is for a user login
112
113       } // while
114       fclose ( f );
115     } // opened?
116
117   }
118   ///////
119
120   if ( ! home ) {
121     return ( s ); // can't succeed
122   }
123
124   printf ( "DEBUG: entering while (%s)\n", s );
125
126   while ( ( p = strchr ( s, '~' ) ) ) {
127     printf ( "DEBUG: within while (%s)\n", s );
128     char *temp = malloc ( strlen ( s ) + strlen ( home ) + 1 );
129     memset ( temp, '\0', strlen ( s ) + strlen ( home ) + 1 );
130     // copy in stuff prior to ~
131     strncpy ( temp, s, p - s );
132     // copy tilde in
133     strcat ( temp, home );
134     // copy stuff after tilde in
135     strcat ( temp, p + 1 );
136     // swap ptrs
137     free ( s );
138     s = temp;
139   } // while finding matches
140
141   printf ( "DEBUG: expand tilde OUT: '%s'\n", s );
142
143   return ( s );
144 }
145
146 void pnd_exec_no_wait_1 ( char *fullpath, char *arg1 ) {
147   int i;
148
149   if ( ( i = fork() ) < 0 ) {
150     printf ( "ERROR: Couldn't fork()\n" );
151     return;
152   }
153
154   if ( i ) {
155     return; // parent process, don't care
156   }
157
158   // child process, do something
159   if ( arg1 ) {
160     execl ( fullpath, fullpath, arg1, (char*) NULL );
161   } else {
162     execl ( fullpath, fullpath, (char*) NULL );
163   }
164
165   // getting here is an error
166   //printf ( "Error attempting to run %s\n", fullpath );
167
168   return;
169 }
170
171 pnd_pxml_handle pnd_pxml_get_by_path ( char *fullpath ) {
172   unsigned char valid = pnd_object_type_unknown;
173   pnd_pxml_handle pxmlh = 0;
174
175   // WARN: this is way too close to callback in pnd_disco .. should be refactored!
176
177   if ( strcasestr ( fullpath, PXML_FILENAME ) ) {
178     valid = pnd_object_type_directory;
179   } else if ( strcasestr ( fullpath, PND_PACKAGE_FILEEXT "\0" ) ) {
180     valid = pnd_object_type_pnd;
181   }
182
183   // if not a file of interest, just keep looking until we run out
184   if ( ! valid ) {
185     return ( 0 );
186   }
187
188   // potentially a valid application
189   if ( valid == pnd_object_type_directory ) {
190     pxmlh = pnd_pxml_fetch ( (char*) fullpath );
191
192   } else if ( valid == pnd_object_type_pnd ) {
193     FILE *f;
194     char pxmlbuf [ 32 * 1024 ]; // TBD: assuming 32k pxml accrual buffer is a little lame
195
196     // open it up..
197     f = fopen ( fullpath, "r" );
198
199     // try to locate the PXML portion
200     if ( ! pnd_pnd_seek_pxml ( f ) ) {
201       fclose ( f );
202       return ( 0 ); // pnd or not, but not to spec. Pwn'd the pnd?
203     }
204
205     // accrue it into a buffer
206     if ( ! pnd_pnd_accrue_pxml ( f, pxmlbuf, 32 * 1024 ) ) {
207       fclose ( f );
208       return ( 0 );
209     }
210
211     // by now, we have <PXML> .. </PXML>, try to parse..
212     pxmlh = pnd_pxml_fetch_buffer ( (char*) fullpath, pxmlbuf );
213
214     // done with file
215     fclose ( f );
216
217   }
218
219   // ..
220
221   return ( pxmlh );
222 }