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