1 /* my.c:
2  *
3  ****************************************************************
4  * Copyright (C) 2003 Tom Lord
5  *
6  * See the file "COPYING" for further information about
7  * the copyright and warranty status of this work.
8  */
9 
10 
11 #include "hackerlab/os/stdlib.h"
12 #include "hackerlab/os/errno.h"
13 #include "hackerlab/os/errno-to-string.h"
14 #include "hackerlab/bugs/panic.h"
15 #include "hackerlab/char/str.h"
16 #include "hackerlab/fs/file-names.h"
17 #include "hackerlab/fs/cwd.h"
18 #include "hackerlab/vu/safe.h"
19 #include "tla/libfsutils/ensure-dir.h"
20 #include "tla/libfsutils/read-line.h"
21 #include "tla/libfsutils/file-contents.h"
22 #include "tla/libarch/namespace.h"
23 #include "tla/libarch/my.h"
24 
25 
26 
27 t_uchar *
arch_my_arch_params(void)28 arch_my_arch_params (void)
29 {
30   t_uchar * home;
31   t_uchar * answer;
32 
33   home = getenv ("HOME");
34 
35   invariant (!!home);
36   answer = file_name_in_vicinity (0, home, ".arch-params");
37 
38   return answer;
39 }
40 
41 
42 void
arch_ensure_my_arch_params(void)43 arch_ensure_my_arch_params (void)
44 {
45   int errn;
46   t_uchar * dir = 0;
47 
48   dir = arch_my_arch_params ();
49 
50   if (vu_mkdir (&errn, dir, 0700) && errn != EEXIST)
51     {
52       safe_printfmt (2, "arch: unable to create directory %s\n", dir);
53       exit (2);
54     }
55 
56   lim_free (0, dir);
57 }
58 
59 
60 
61 t_uchar *
arch_my_hook_script(void)62 arch_my_hook_script (void)
63 {
64   t_uchar * params_dir;
65   t_uchar * hook_script;
66 
67   params_dir = arch_my_arch_params ();
68   hook_script = file_name_in_vicinity (0, params_dir, "hook");
69 
70   {
71     int euid;
72     int egid;
73     struct stat stat;
74     int stat_ok;
75     int errn;
76 
77     euid = geteuid ();
78     egid = getegid ();
79 
80     stat_ok = vu_stat (&errn, hook_script, &stat);
81     if (stat_ok
82         || !(((euid == stat.st_uid) && (stat.st_mode & S_IXUSR))
83              || ((egid == stat.st_gid) && (stat.st_mode & S_IXGRP))
84              || (stat.st_mode & S_IXOTH)))
85       {
86         lim_free (0, hook_script);
87         hook_script = 0;
88       }
89   }
90 
91   lim_free (0, params_dir);
92   return hook_script;
93 }
94 
95 
96 
97 static t_uchar * my_id = 0;
98 
99 t_uchar *
arch_my_id_file(void)100 arch_my_id_file (void)
101 {
102   t_uchar * params_dir;
103   t_uchar * id_file;
104 
105   params_dir = arch_my_arch_params ();
106   id_file = file_name_in_vicinity (0, params_dir, "=id");
107   lim_free (0, params_dir);
108 
109   return id_file;
110 }
111 
112 
113 void
arch_set_my_id(const t_uchar * id)114 arch_set_my_id (const t_uchar * id)
115 {
116   t_uchar * id_file;
117   int out_fd;
118 
119   if (my_id)
120     lim_free (0, my_id);
121 
122   invariant (arch_valid_id (id));
123 
124   id_file = arch_my_id_file ();
125 
126   arch_ensure_my_arch_params ();
127 
128   out_fd = safe_open (id_file, O_WRONLY | O_CREAT, 0666);
129   safe_ftruncate (out_fd, 0L);
130   safe_printfmt (out_fd, "%s\n", id);
131   safe_close (out_fd);
132   lim_free (0, id_file);
133 
134   my_id = str_save (0, id);
135 }
136 
137 
138 t_uchar *
arch_my_id(void)139 arch_my_id (void)
140 {
141   int errn;
142   t_uchar * id_file;
143   int in_fd;
144   t_uchar * id_contents;
145   size_t len;
146   t_uchar * eoid;
147 
148   if (my_id)
149     return str_save (0, my_id);
150 
151   id_file = arch_my_id_file ();
152   in_fd = vu_open (&errn, id_file, O_RDONLY, 0);
153   if (in_fd < 0)
154     {
155       if (errn == ENOENT)
156         safe_printfmt (2, "arch: no arch user id set\n");
157       else
158         safe_printfmt (2, "arch: i/o error for file %s (%s)\n", id_file, errno_to_string (errn));
159       exit (2);
160     }
161   lim_free (0, id_file);
162 
163   id_contents = 0;
164   len = 0;
165   safe_file_to_string (&id_contents, &len, in_fd);
166   safe_close (in_fd);
167 
168   eoid = str_chr_index_n (id_contents, len, '\n');
169   if (!eoid)
170     eoid = id_contents + len;
171 
172   my_id = str_save_n (0, id_contents, eoid - id_contents);
173 
174   lim_free (0, id_contents);
175 
176   return str_save (0, my_id);
177 }
178 
179 
180 t_uchar *
arch_my_id_uid(void)181 arch_my_id_uid (void)
182 {
183   t_uchar * id = 0;
184   t_uchar * lb;
185   t_uchar * rb;
186   t_uchar * answer = 0;
187 
188   id = arch_my_id ();
189   if (!id)
190     return 0;
191 
192   lb = str_chr_rindex (id, '<');
193   rb = str_chr_rindex (id, '>');
194 
195   invariant (lb && rb && ((lb + 1) < rb));
196 
197   answer = str_save_n (0, (lb + 1), rb - (lb + 1));
198 
199   lim_free (0, id);
200 
201   return answer;
202 }
203 
204 
205 
206 
207 static t_uchar * my_home_archive = 0;
208 
209 t_uchar *
arch_my_default_archive(const t_uchar * default_archive)210 arch_my_default_archive (const t_uchar * default_archive)
211 {
212   t_uchar * params_dir = 0;
213   t_uchar * default_archive_file = 0;
214   int in_fd;
215   t_uchar * default_archive_file_contents = 0;
216   size_t archive_contents_len;
217   t_uchar * nl_pos;
218   t_uchar * answer = 0;
219   int errn;
220 
221   /* This does away with the arch conventions of using $ARCHIVE
222    * and has no support for -R
223    */
224 
225   if (default_archive)
226     {
227       if (!arch_valid_archive_name (default_archive))
228         {
229           safe_printfmt (2, "invalid archive name %s\n", default_archive);
230           exit (2);
231         }
232       return str_save (0, default_archive);
233     }
234 
235   if (my_home_archive)
236     return str_save (0, my_home_archive);
237 
238 
239   params_dir = arch_my_arch_params ();
240   default_archive_file = file_name_in_vicinity (0, params_dir, "=default-archive");
241 
242   in_fd = vu_open (&errn, default_archive_file, O_RDONLY, 0);
243 
244   if (in_fd < 0)
245     {
246       if (errn != ENOENT)
247         {
248           safe_printfmt (2, "arch: error opening %s\n", default_archive_file);
249           exit (2);
250         }
251       answer = 0;
252     }
253   else
254     {
255       safe_file_to_string (&default_archive_file_contents, &archive_contents_len, in_fd);
256 
257       safe_close (in_fd);
258 
259       nl_pos = str_chr_index_n (default_archive_file_contents, archive_contents_len, '\n');
260       if (!nl_pos)
261         nl_pos = default_archive_file_contents + archive_contents_len;
262 
263       answer = str_save_n (0, default_archive_file_contents, nl_pos - default_archive_file_contents);
264     }
265 
266   lim_free (0, default_archive_file_contents);
267   lim_free (0, default_archive_file);
268   lim_free (0, params_dir);
269 
270   if (answer)
271     {
272       lim_free (0, my_home_archive);
273       my_home_archive = str_save (0, answer);
274     }
275 
276   return answer;
277 }
278 
279 
280 void
arch_set_my_default_archive(const t_uchar * archive)281 arch_set_my_default_archive (const t_uchar * archive)
282 {
283   t_uchar * arch_params_dir;
284   t_uchar * default_archive_file;
285   int out_fd;
286 
287   invariant (arch_valid_archive_name (archive));
288 
289   if (my_home_archive)
290     {
291       lim_free (0, my_home_archive);
292       my_home_archive = 0;
293     }
294 
295   arch_ensure_my_arch_params ();
296   arch_params_dir = arch_my_arch_params ();
297   default_archive_file = file_name_in_vicinity (0, arch_params_dir, "=default-archive");
298 
299   out_fd = safe_open (default_archive_file, O_WRONLY | O_CREAT, 0666);
300 
301   safe_ftruncate (out_fd, (long)0);
302   safe_write_retry (out_fd, archive, str_length (archive));
303   safe_close (out_fd);
304 
305   lim_free (0, arch_params_dir);
306   lim_free (0, default_archive_file);
307 
308   my_home_archive = str_save (0, archive);
309 }
310 
311 
312 void
arch_delete_my_default_archive(void)313 arch_delete_my_default_archive (void)
314 {
315   t_uchar * params_dir;
316   t_uchar * default_archive_file;
317   int errn;
318 
319   if (my_home_archive)
320     {
321       lim_free (0, my_home_archive);
322       my_home_archive = 0;
323     }
324 
325   params_dir = arch_my_arch_params ();
326   default_archive_file = file_name_in_vicinity (0, params_dir, "=default-archive");
327 
328   if (vu_unlink (&errn, default_archive_file) && (errn != ENOENT))
329     {
330       panic ("unable to delete ~/.arch-params/=default-archive");
331     }
332 
333   lim_free (0, params_dir);
334   lim_free (0, default_archive_file);
335 }
336 
337 
338 
339 t_uchar *
arch_my_archive_locations_dir(void)340 arch_my_archive_locations_dir (void)
341 {
342   t_uchar * arch_params_path = 0;
343   t_uchar * answer = 0;
344 
345   arch_params_path = arch_my_arch_params ();
346   answer = file_name_in_vicinity (0, arch_params_path, "=locations");
347 
348   lim_free (0, arch_params_path);
349   return answer;
350 }
351 
352 
353 
354 
355 static t_uchar *
arch_my_default_library_file(void)356 arch_my_default_library_file (void)
357 {
358   t_uchar * params_dir;
359   t_uchar * lib_file;
360 
361   params_dir = arch_my_arch_params ();
362   lib_file = file_name_in_vicinity (0, params_dir, "=revision-library");
363 
364   lim_free (0, params_dir);
365 
366   return lib_file;
367 }
368 
369 static t_uchar *
arch_my_default_library_add_file(void)370 arch_my_default_library_add_file (void)
371 {
372   t_uchar * params_dir;
373   t_uchar * lib_file;
374 
375   params_dir = arch_my_arch_params ();
376   lib_file = file_name_in_vicinity (0, params_dir, "=revision-library-adds");
377 
378   lim_free (0, params_dir);
379 
380   return lib_file;
381 }
382 
383 
384 rel_table
arch_my_library_path(enum arch_library_path_type path_type)385 arch_my_library_path (enum arch_library_path_type path_type)
386 {
387   t_uchar * first_file = 0;
388   t_uchar * second_file = 0;
389   rel_table answer = rel_table_nil;
390 
391   switch (path_type)
392     {
393     case arch_library_path_search_only:
394       {
395         first_file = arch_my_default_library_file ();
396         break;
397       }
398     case arch_library_path_add_only:
399       {
400         first_file = arch_my_default_library_add_file ();
401         break;
402       }
403     case arch_library_path_search_order:
404       {
405         first_file = arch_my_default_library_file ();
406         second_file = arch_my_default_library_add_file ();
407         break;
408       }
409     case arch_library_path_add_order:
410       {
411         second_file = arch_my_default_library_file ();
412         first_file = arch_my_default_library_add_file ();
413         break;
414       }
415     }
416 
417   if (first_file && !safe_access (first_file, F_OK))
418     {
419       int fd;
420 
421       fd = safe_open (first_file, O_RDONLY, 0);
422       answer = rel_read_table (fd, 1, "tla", first_file);
423       safe_close (fd);
424     }
425 
426   if (second_file && !safe_access (second_file, F_OK))
427     {
428       int fd;
429       rel_table answer2 = rel_table_nil;
430 
431       fd = safe_open (second_file, O_RDONLY, 0);
432       answer2 = rel_read_table (fd, 1, "tla", second_file);
433       safe_close (fd);
434       rel_append_x (&answer, answer2);
435       rel_free_table (answer2);
436     }
437 
438   lim_free (0, first_file);
439   lim_free (0, second_file);
440 
441   return answer;
442 }
443 
444 
445 void
arch_set_my_library_path(enum arch_library_path_type path_type,enum arch_library_edit_op op,const t_uchar * dir_spec)446 arch_set_my_library_path (enum arch_library_path_type path_type,
447                           enum arch_library_edit_op op,
448                           const t_uchar * dir_spec)
449 {
450   t_uchar * dir = 0;
451   t_uchar * lib_file = 0;
452   rel_table old_path = rel_table_nil;
453   rel_table new_path = rel_table_nil;
454   int out_fd;
455 
456   if (file_name_is_absolute (dir_spec))
457     {
458       dir = str_save (0, dir_spec);
459     }
460   else if (dir_spec)
461     {
462       t_uchar * here = 0;
463       here = safe_current_working_directory ();
464       dir = file_name_in_vicinity (0, here, dir_spec);
465       lim_free (0, here);
466     }
467 
468   switch (path_type)
469     {
470     case arch_library_path_search_order:
471     case arch_library_path_search_only:
472       {
473         lib_file = arch_my_default_library_file ();
474         old_path = arch_my_library_path (arch_library_path_search_only);
475         break;
476       }
477     case arch_library_path_add_order:
478     case arch_library_path_add_only:
479       {
480         lib_file = arch_my_default_library_add_file ();
481         old_path = arch_my_library_path (arch_library_path_add_only);
482         break;
483       }
484     }
485 
486 
487   /* install first if appropriate
488    */
489   if (dir_spec && (op == arch_library_first))
490     {
491       rel_add_records (&new_path, rel_singleton_record_taking (rel_make_field_str (dir)), rel_record_null);
492     }
493 
494   /* copy the old path, removing dir_spec (if any)
495    */
496   if (dir_spec)
497     {
498       int x;
499 
500       for (x = 0; x < rel_n_records (old_path); ++x)
501         {
502           if (str_cmp (rel_peek_str (old_path, x, 0), dir))
503             {
504               rel_add_records (&new_path, rel_singleton_record_taking (rel_get_field (old_path, x, 0)), rel_record_null);
505             }
506         }
507     }
508 
509   /* install last if appropriate
510    */
511   if (dir_spec && (op == arch_library_last))
512     {
513       rel_add_records (&new_path, rel_singleton_record_taking (rel_make_field_str (dir)), rel_record_null);
514     }
515 
516 
517   /* install the new path
518    */
519   arch_ensure_my_arch_params ();
520 
521   out_fd = safe_open (lib_file, O_WRONLY | O_CREAT, 0666);
522   safe_ftruncate (out_fd, 0L);
523   rel_print_table (out_fd, new_path);
524   safe_close (out_fd);
525 
526 
527   lim_free (0, dir);
528   lim_free (0, lib_file);
529   rel_free_table (old_path);
530   rel_free_table (new_path);
531 }
532 
533 
534 
535 
536 t_uchar *
arch_my_util_path_file(void)537 arch_my_util_path_file (void)
538 {
539   t_uchar * params_dir;
540   t_uchar * path_file;
541 
542   params_dir = arch_my_arch_params ();
543   path_file = file_name_in_vicinity (0, params_dir, "path");
544   lim_free (0, params_dir);
545 
546   return path_file;
547 }
548 
549 
550 t_uchar **
arch_my_util_path(void)551 arch_my_util_path (void)
552 {
553   t_uchar * path_file = 0;
554   t_uchar ** answer = 0;
555 
556   path_file = arch_my_util_path_file ();
557   if (!safe_access (path_file, F_OK))
558     {
559       t_uchar * contents = 0;
560 
561       contents = file_contents_trimming (path_file);
562       answer = path_parse (0, contents);
563 
564       lim_free (0, contents);
565     }
566 
567   lim_free (0, path_file);
568   return answer;
569 }
570 
571 
572 
573 
574 t_uchar *
arch_my_metadata_rules_file(void)575 arch_my_metadata_rules_file (void)
576 {
577   t_uchar * params_dir;
578   t_uchar * path_file;
579 
580   params_dir = arch_my_arch_params ();
581   path_file = file_name_in_vicinity (0, params_dir, "metadata-rules");
582   lim_free (0, params_dir);
583 
584   return path_file;
585 }
586 
587 
588 int
arch_my_allow_full_meta(void)589 arch_my_allow_full_meta (void)
590 {
591   t_uchar * rules_file = 0;
592   struct stat statb;
593   int errn = 0;
594   int answer;
595 
596   rules_file = arch_my_metadata_rules_file ();
597 
598   if (0 == vu_stat (&errn, rules_file, &statb))
599     {
600       if (statb.st_size != 0)
601         {
602           safe_printfmt (2, "illegal ~/.arch-params/metadata-rules file (non-empty)\n  file: %s\n", rules_file);
603           panic ("abort");
604         }
605 
606       answer = 1;
607     }
608   else
609     {
610       if (errn == ENOENT)
611         answer = 0;
612       else
613         panic ("strange i/o error");
614     }
615 
616   lim_free (0, rules_file);
617   return answer;
618 }
619 
620 
621 
622 
623 /* tag: Tom Lord Mon May 12 15:01:17 2003 (my.c)
624  */
625