Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / uss / uss_procs.c
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10 /*
11 * Implementation of basic procedures for the AFS user account
12 * facility.
13 */
14
15 /*
16 * --------------------- Required definitions ---------------------
17 */
18 #include <afsconfig.h>
19 #include <afs/param.h>
20
21 #include <roken.h>
22
23 #include <afs/kautils.h> /*MAXKTCREALMLEN*/
24
25 #include "uss_procs.h" /*Module interface */
26 #include "uss_common.h" /*Common defs & operations */
27 #include "uss_acl.h" /*ACL-related operations */
28
29 #undef USS_PROCS_DB
30 #undef USS_PROCS_DB_INSTANCE
31 #undef USS_PROCS_DB_BUILDDIR
32 #define uss_procs_MAX_SIZE 2048
33 char temp[1000];
34 extern int line;
35
36 static int Copy(char *a_from, char *a_to, int a_mode);
37 static int Echo(char *a_s, char *a_f, int a_mode);
38
39 /*-----------------------------------------------------------------------
40 * EXPORTED uss_procs_BuildDir
41 *
42 * Environment:
43 * Called from the code generated by the uss grammar.
44 *
45 * Side Effects:
46 * As advertised.
47 *------------------------------------------------------------------------*/
48
49 afs_int32
50 uss_procs_BuildDir(char *a_path, char *a_mode, char *a_owner, char *a_access)
51 { /*uss_procs_BuildDir */
52
53 int m, o;
54 char buf[1000];
55 struct uss_subdir *new_dir;
56 struct stat stbuf;
57
58 /*
59 * Don't do anything if there's already a problem.
60 */
61 if (uss_syntax_err)
62 return (1);
63
64 if (uss_verbose)
65 printf("Building directory '%s'; owner: '%s', ACL: '%s'\n", a_path,
66 a_owner, a_access);
67
68 /*
69 * If we've not been given permission to overwrite things, make sure
70 * the target doesn't exist before doing anything.
71 */
72 if (!uss_OverwriteThisOne) {
73 strcpy(temp, a_path);
74 if (!stat(temp, &stbuf)) {
75 if (uss_verbose)
76 printf("\t[Directory exists, NOT overwriting it]\n");
77 return (0);
78 }
79 }
80
81 sscanf(a_mode, "%o", &m);
82 o = uss_procs_GetOwner(a_owner);
83 #ifdef USS_PROCS_DB_BUILDDIR
84 printf("DEBUGGING: Owner '%s' is uid %d\n", a_owner, o);
85 #endif /* USS_PROCS_DB_BUILDDIR */
86
87 if (!uss_DryRun) {
88 if (mkdir(a_path, m)) {
89 /*
90 * Can't make the directory. Complain if the directory doesn't
91 * already exist.
92 */
93 if (errno != EEXIST) {
94 uss_procs_PrintErr(line,
95 "Failed to create directory '%s': %s\n",
96 a_path, strerror(errno));
97 return (1);
98 } /*Directory didn't exist */
99 } /*Create the directory */
100 } /*Not a dry run */
101 else {
102 if (uss_OverwriteThisOne)
103 fprintf(stderr, "\t[Dry run: mkdir %s, mode %o]\n", a_path, m);
104 } /*Dry run */
105
106 if (!uss_DryRun) {
107 if (chmod(a_path, m)) {
108 uss_procs_PrintErr(line,
109 "Can't chmod() directory '%s' to be '%s' : %s\n",
110 a_path, a_mode, strerror(errno));
111 return (1);
112 } /* chmod the directory */
113 if (chown(a_path, o, -1)) {
114 uss_procs_PrintErr(line,
115 "Can't chown() directory '%s' to be owned by '%s' (uid %d): %s\n",
116 a_path, a_owner, o, strerror(errno));
117 return (1);
118 } /*Couldn't chown */
119 } /*Not a dry run */
120 else {
121 fprintf(stderr,
122 "\t[Dry run: chown() directory '%s' to be owned by user]\n",
123 a_path);
124 } /*Dry run */
125
126 /*
127 * Set the ACL for this new directory so that the uss_AccountCreator
128 * is the only party that has rights. This will be corrected as the
129 * final action performed on the account.
130 */
131 sprintf(buf, "%s %s all", a_path, uss_AccountCreator);
132 if (!uss_DryRun) {
133 if (uss_verbose)
134 fprintf(stderr, "Setting ACL: '%s'\n", buf);
135 if (uss_acl_SetAccess(buf, 1, 0))
136 return (1);
137 } /*Not a dry run */
138 else {
139 fprintf(stderr, "\t[Dry run: uss_acl_SetAccess(%s) on '%s']\n", buf,
140 a_path);
141 } /*Dry run */
142
143 /*
144 * Use our linked list to remember this directory's true ACL setting so
145 * we may set it correctly at the tail end of the account creation.
146 */
147 new_dir = malloc(sizeof(struct uss_subdir));
148 new_dir->previous = uss_currentDir;
149 new_dir->path = strdup(a_path);
150 new_dir->finalACL = strdup(a_access);
151 uss_currentDir = new_dir;
152
153 /*
154 * Return the happy news.
155 */
156 return (0);
157
158 } /*uss_procs_BuildDir */
159
160
161 /*-----------------------------------------------------------------------
162 * EXPORTED uss_procs_CpFile
163 *
164 * Environment:
165 * Called from the code generated by the uss grammar.
166 *
167 * Side Effects:
168 * As advertised.
169 *------------------------------------------------------------------------*/
170
171 afs_int32
172 uss_procs_CpFile(char *a_path, char *a_mode, char *a_owner, char *a_proto)
173 { /*uss_procs_CpFile */
174
175 int m, o;
176 struct stat stbuf;
177 char *cp;
178
179 /*
180 * Don't do anything if something has already gone wrong.
181 */
182 if (uss_syntax_err)
183 return (1);
184
185 if (uss_verbose)
186 printf("Installing '%s'\n", a_path);
187
188 /*
189 * If we've not been given permission to overwrite things, make sure
190 * the target doesn't exist before doing anything.
191 */
192 if (!uss_OverwriteThisOne) {
193 strcpy(temp, a_path);
194 if (!stat(temp, &stbuf)) {
195 if (uss_verbose)
196 printf("\t[Entry exists, NOT overwriting it]\n");
197 return (0);
198 }
199 }
200
201 sscanf(a_mode, "%o", &m);
202 o = uss_procs_GetOwner(a_owner);
203
204 strcpy(temp, a_proto);
205
206 if (stat(temp, &stbuf)) {
207 uss_procs_PrintErr(line, "Failed to stat '%s': %s\n", a_proto,
208 strerror(errno));
209 return (1);
210 }
211
212 if (stbuf.st_mode & S_IFDIR) {
213 if ((cp = strrchr(a_path, '/')) == NULL) {
214 strcat(a_proto, "/");
215 strcat(a_proto, a_path);
216 } else {
217 /*
218 * Append the last part (file name).
219 */
220 strcat(a_proto, cp);
221 }
222 }
223 /*Target is a directory */
224 if (!uss_DryRun) {
225 if (Copy(a_proto, a_path, m)) {
226 uss_procs_PrintErr(line, "Failed to copy '%s' to '%s'\n", a_proto,
227 a_path);
228 return (1);
229 } /*Copy failed */
230 } /*Not a dry run */
231 else {
232 fprintf(stderr, "\t[Dry run: Copying '%s' to '%s', mode %o]\n",
233 a_proto, a_path, m);
234 }
235
236 if (!uss_DryRun) {
237 if (chown(a_path, o, -1)) {
238 uss_procs_PrintErr(line,
239 "Can't chown() file '%s' to be owned by '%s' (uid %d): %s\n",
240 a_path, a_owner, o, strerror(errno));
241 return (1);
242 } /*chown failed */
243 } /*Not a dry run */
244 else {
245 fprintf(stderr,
246 "\t[Dry run: chown() file '%s' to be owned by user]\n",
247 a_path);
248 } /*Dry run */
249
250 /*
251 * Return the happy news.
252 */
253 return (0);
254
255 } /*uss_procs_CpFile */
256
257
258 /*-----------------------------------------------------------------------
259 * EXPORTED uss_procs_EchoToFile
260 *
261 * Environment:
262 * Called from the code generated by the uss grammar.
263 *
264 * Side Effects:
265 * As advertised.
266 *------------------------------------------------------------------------*/
267
268 afs_int32
269 uss_procs_EchoToFile(char *a_path, char *a_mode, char *a_owner,
270 char *a_content)
271 { /*uss_procs_EchoToFile */
272
273 int m, o;
274 struct stat stbuf;
275
276 /*
277 * Don't do anything if something has already gone wrong.
278 */
279 if (uss_syntax_err)
280 return (1);
281
282 if (uss_verbose)
283 printf("Echoing to '%s'\n", a_path);
284
285 /*
286 * If we've not been given permission to overwrite things, make sure
287 * the target doesn't exist before doing anything.
288 */
289 if (!uss_OverwriteThisOne) {
290 strcpy(temp, a_path);
291 if (!stat(temp, &stbuf)) {
292 if (uss_verbose)
293 printf("\t[Entry exists, NOT overwriting it]\n");
294 return (0);
295 }
296 }
297
298 sscanf(a_mode, "%o", &m);
299 o = uss_procs_GetOwner(a_owner);
300
301 if (!uss_DryRun) {
302 if (Echo(a_content, a_path, m)) {
303 uss_procs_PrintErr(line,
304 "Failed to echo string '%s' to file '%s'\n",
305 a_content, a_path);
306 return (1);
307 }
308 } /*Not a dry run */
309 else {
310 fprintf(stderr, "\t[Dry run: Echoing '%s' into file '%s']\n",
311 a_content, a_path);
312 } /*Dry run */
313
314 if (!uss_DryRun) {
315 if (chown(a_path, o, -1)) {
316 uss_procs_PrintErr(line,
317 "Can't chown() file '%s' to be owned by '%s' (uid %d): %s\n",
318 a_path, a_owner, o, strerror(errno));
319 return (1);
320 }
321 } /*Not a dry run */
322 else {
323 fprintf(stderr,
324 "\t[Dry run: chown() file '%s' to be owned by user]\n",
325 a_path);
326 } /*Dry run */
327
328 /*
329 * Return the happy news.
330 */
331 return (0);
332
333 } /*uss_procs_EchoToFile */
334
335
336 /*-----------------------------------------------------------------------
337 * EXPORTED uss_procs_Exec
338 *
339 * Environment:
340 * Called from the code generated by the uss grammar, as well as
341 * from uss.c itself.
342 *
343 * Side Effects:
344 * As advertised.
345 *------------------------------------------------------------------------*/
346
347 afs_int32
348 uss_procs_Exec(char *a_command)
349 { /*uss_procs_Exec */
350
351 if (uss_verbose)
352 printf("Running '%s'\n", a_command);
353
354 if (!uss_DryRun) {
355 if (system(a_command)) {
356 uss_procs_PrintErr(line, "Failed to run the '%s' command: %s\n",
357 a_command, strerror(errno));
358 return (1);
359 }
360 } /*Not a dry run */
361 else {
362 fprintf(stderr, "\t[Dry run: executing '%s']\n", a_command);
363 } /*Dry run */
364
365 /*
366 * Return the happy news.
367 */
368 return (0);
369
370 } /*uss_procs_Exec */
371
372
373 /*-----------------------------------------------------------------------
374 * EXPORTED uss_procs_SetLink
375 *
376 * Environment:
377 * Called from the code generated by the uss grammar.
378 *
379 * Side Effects:
380 * As advertised.
381 *------------------------------------------------------------------------*/
382
383 afs_int32
384 uss_procs_SetLink(char *a_path1, char *a_path2, char a_type)
385 { /*uss_procs_SetLink */
386
387 struct stat stbuf;
388
389 if (uss_verbose)
390 printf("Setting link '%s' to '%s'\n", a_path1, a_path2);
391
392 /*
393 * If we've not been given permission to overwrite things, make sure
394 * the target doesn't exist before doing anything.
395 */
396 if (!uss_OverwriteThisOne) {
397 strcpy(temp, a_path2);
398 if (!stat(temp, &stbuf)) {
399 if (uss_verbose)
400 printf("\t[Entry exists, NOT overwriting it]\n");
401 return (0);
402 }
403 }
404
405 if (a_type == 's') {
406 /*
407 * Symbolic link.
408 */
409 if (!uss_DryRun) {
410 if (symlink(a_path1, a_path2)) {
411 uss_procs_PrintErr(line,
412 "Failed to make symlink '%s' to '%s': %s\n",
413 a_path1, a_path2, strerror(errno));
414 return (1);
415 }
416 } /*Dry run */
417 else {
418 fprintf(stderr, "\t[Dry run: Making symlink '%s' to '%s']\n",
419 a_path1, a_path2);
420 } /*Not a dry run */
421 } /*Symbolic link */
422 else {
423 /*
424 * Hard link.
425 */
426 if (!uss_DryRun) {
427 if (link(a_path1, a_path2)) {
428 uss_procs_PrintErr(line,
429 "Failed to make hard link '%s' to '%s': %s\n",
430 a_path1, a_path2, strerror(errno));
431 return (1);
432 }
433 } /*Dry run */
434 else {
435 fprintf(stderr, "\t[Dry run: Making hard link '%s' to '%s']\n",
436 a_path1, a_path2);
437 } /*Not a dry run */
438 } /*Hard link */
439
440 /*
441 * Return the happy news.
442 */
443 return (0);
444
445 } /*uss_procs_SetLink */
446
447
448 /*-----------------------------------------------------------------------
449 * EXPORTED uss_procs_GetOwner
450 *
451 * Environment:
452 * Nothing interesting.
453 *
454 * Side Effects:
455 * As advertised.
456 *------------------------------------------------------------------------*/
457
458 int
459 uss_procs_GetOwner(char *a_ownerStr)
460 { /*uss_procs_GetOwner */
461
462 struct passwd *pw; /*Ptr to password file entry */
463 int ownerID; /*Numerical owner */
464
465 ownerID = atoi(a_ownerStr);
466 if ((ownerID == 0) && (a_ownerStr[0] != '0')) {
467 /*
468 * The owner is not in numerical format
469 */
470 if ((pw = getpwnam(a_ownerStr)) == NULL) {
471 uss_procs_PrintErr(line, "Owner '%s' is an unknown user\n",
472 a_ownerStr);
473 return (1);
474 }
475 return (pw->pw_uid);
476 } else
477 return (ownerID);
478
479 } /*uss_procs_GetOwner */
480
481 /*-----------------------------------------------------------------------
482 * static Copy
483 *
484 * Description:
485 * Copies the "from" file to the "to" file and sets the mode.
486 *
487 * Arguments:
488 * a_from : File to copy from.
489 * a_to : File to copy to.
490 * a_mode : New Unix mode to set.
491 *
492 * Returns:
493 * 0 if everything went well,
494 * if there was a problem.
495 *
496 * Environment:
497 * Nothing interesting.
498 *
499 * Side Effects:
500 * As advertised.
501 *------------------------------------------------------------------------*/
502
503 static int
504 Copy(char *a_from, char *a_to, int a_mode)
505 { /*Copy */
506
507 int fd1, fd2;
508 char buf[BUFSIZ];
509 int rcnt, wcnt = -1, rc;
510
511 umask(0);
512 fd1 = open(a_to, O_EXCL | O_CREAT | O_WRONLY, a_mode);
513 if (fd1 < 0) {
514 if (errno == EEXIST) {
515 /*
516 * The file exists. Since we can only be called when overwriting
517 * has been enabled, we back off and open the file normally (not
518 * supplying O_EXCL), then continue normally.
519 */
520 fd1 = open(a_to, O_CREAT | O_WRONLY, a_mode);
521 if (fd1 < 0) {
522 uss_procs_PrintErr(line,
523 "%s: Failed to open '%s' for overwrite: %s.\n",
524 uss_whoami, a_to, strerror(errno));
525 return (1);
526 }
527 } else {
528 uss_procs_PrintErr(line, "%s: Failed to open '%s': %s.\n",
529 uss_whoami, a_to, strerror(errno));
530 return (1);
531 }
532 }
533
534 if ((fd2 = open(a_from, O_RDONLY, 0)) < 0) {
535 uss_procs_PrintErr(line, "%s: Error reading '%s': %s\n", uss_whoami,
536 a_from, strerror(errno));
537 close(fd1);
538 return (1);
539 }
540 do {
541 rcnt = read(fd2, buf, BUFSIZ);
542 if (rcnt == -1)
543 break;
544 wcnt = write(fd1, buf, rcnt);
545 } while (rcnt == BUFSIZ && rcnt == wcnt);
546 if (rcnt == -1 || wcnt != rcnt) {
547 uss_procs_PrintErr(line, "read/write error to %s\n", a_to);
548 close(fd1);
549 close(fd2);
550 return (1);
551 }
552 rc = close(fd1);
553 if (rc) {
554 uss_procs_PrintErr(line, "Failed to close '%s' %s\n", a_to,
555 strerror(errno));
556 return (1);
557 }
558 if ((rc = close(fd2)))
559 uss_procs_PrintErr(line, "Warning: Failed to close '%s': %s\n",
560 a_from, strerror(errno));
561 return (0);
562
563 } /*Copy */
564
565 /*-----------------------------------------------------------------------
566 * static Echo
567 *
568 * Description:
569 * Writes a string into a file and sets its mode.
570 *
571 * Arguments:
572 * a_s : String to write.
573 * a_f : Filename to write to.
574 * a_mode : New Unix mode to set.
575 *
576 * Returns:
577 * 0 if everything went well,
578 * if there was a problem.
579 *
580 * Environment:
581 * Nothing interesting.
582 *
583 * Side Effects:
584 * As advertised.
585 *------------------------------------------------------------------------*/
586
587 static int
588 Echo(char *a_s, char *a_f, int a_mode)
589 { /*Echo */
590
591 int fd;
592
593 umask(0);
594 fd = open(a_f, O_EXCL | O_CREAT | O_WRONLY, a_mode);
595 if (fd < 0) {
596 if (errno == EEXIST) {
597 /*
598 * The file exists. Since we can only be called when
599 * overwriting has been enabled, we back off and open the
600 * file normally (not supplying the O_EXCL), then continue
601 * normally. Notice that we must truncate the file, since
602 * if the original file is longer than the stuff we're about
603 * to put in, all the old data past the current write will
604 * still be there.
605 */
606 fd = open(a_f, O_TRUNC | O_WRONLY, a_mode);
607 if (fd < 0) {
608 uss_procs_PrintErr(line,
609 "%s: Failed to open '%s' for overwrite: %s.\n",
610 uss_whoami, a_f, strerror(errno));
611 return (1);
612 }
613 } else {
614 uss_procs_PrintErr(line, "%s: Failed to open '%s': %s. \n",
615 uss_whoami, a_f, strerror(errno));
616 return (1);
617 }
618 }
619 if (write(fd, a_s, strlen(a_s)) != strlen(a_s) ||
620 write(fd, "\n", 1) != 1) {
621 uss_procs_PrintErr(line, "Short write to '%s'\n", a_f);
622 close(fd);
623 return (1);
624 }
625 if (close(fd)) {
626 uss_procs_PrintErr(line, "Failed to close '%s': %s\n", a_f,
627 strerror(errno));
628 return (1);
629 }
630 return (0);
631
632 } /*Echo */
633
634 /*-----------------------------------------------------------------------
635 * static uss_procs_PickADir
636 *
637 * Description:
638 * Tries to replace $AUTO by a subdir. Subdirs are given by means
639 * of "G" in the configuration file. Each of the directories is
640 * examined, and the one with the inimum number of entries is
641 * picked.
642 *
643 * Arguments:
644 * a_path : ???
645 * a_cp : ???
646 *
647 * Returns:
648 * 0 if everything went well,
649 * -1 if there was a problem.
650 *
651 * Environment:
652 * Called with THREE parameters from lex.c!
653 *
654 * Side Effects:
655 * As advertised.
656 *------------------------------------------------------------------------*/
657
658 afs_int32
659 uss_procs_PickADir(char *path, char *cp)
660 { /*uss_procs_PickADir */
661
662 char cd[300]; /*Current directory for search */
663
664 int i, count, MinIndex = 0, mina = 10000;
665 struct dirent *dp;
666 DIR *dirp;
667 char dirname[300];
668
669 if (uss_NumGroups == 0) {
670 fprintf(stderr, "%s: No choice yet given to replace $AUTO\n",
671 uss_whoami);
672 fprintf(stderr, "%s: Use the G command before $AUTO in config file\n",
673 uss_whoami);
674 return (-1);
675 }
676
677 if (uss_Auto[0] != '\0')
678 return (0); /* we have already done this for this user */
679
680 if (*(cp - 1) == '/') { /*it's ..../$AUTO */
681 for (i = 0; &path[i] != cp; i++)
682 cd[i] = path[i];
683 cd[i] = '\0';
684 } else {
685 if (path != cp) {
686 fprintf(stderr,
687 "%s: $AUTO must be used to replace the whole path or the whole name of a subdirectory. Found: %s$AUTO\n",
688 uss_whoami, path);
689 return (-1);
690 }
691 cd[0] = '/';
692 cd[1] = '\0';
693 }
694
695 /*
696 * We now have the current dir (cd). Search all of the given
697 * subdirs (by G in template), count the number of entries in
698 * each and pick the minimum.
699 */
700 for (i = 0; i < uss_NumGroups; i++) {
701 sprintf(dirname, "%s/%s", cd, uss_DirPool[i]);
702 if ((dirp = opendir(dirname)) == NULL) {
703 if (errno != ENOTDIR)
704 fprintf(stderr,
705 "%s: Warning: Can't open dir '%s' (errno=%d). Skipped.\n",
706 uss_whoami, dirname, errno);
707 continue; /*Skip and continue anyway */
708 }
709 count = 0;
710 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
711 if (dp->d_name[0] != '.')
712 count++; /* forget about files starting with . */
713 #ifdef USS_PROCS_DB
714 printf("debug: Dir '%s' has %d entries\n", dirname, count);
715 #endif /* USS_PROCS_DB */
716 if (count < mina) {
717 mina = count;
718 MinIndex = i;
719 }
720 closedir(dirp);
721 }
722 if (mina == 10000) { /* We found nothing */
723 fprintf(stderr, "%s: Warning: No valid choice to replace $AUTO\n",
724 uss_whoami);
725 uss_Auto[0] = '\0';
726 } else {
727 strcpy(uss_Auto, uss_DirPool[MinIndex]);
728 if (uss_verbose)
729 printf("Picking dir w/minimum number of entries: '%s'\n",
730 uss_Auto);
731 }
732 return (0);
733
734 } /*uss_procs_PickADir */
735
736 /*-----------------------------------------------------------------------
737 * EXPORTED uss_procs_AddToDirPool
738 *
739 * Environment:
740 * Called from the code generated by the uss grammar.
741 *
742 * Side Effects:
743 * As advertised.
744 *------------------------------------------------------------------------*/
745
746 int
747 uss_procs_AddToDirPool(char *a_dirToAdd)
748 {
749 if (uss_NumGroups > 99) {
750 return (-1);
751 }
752 strcpy(uss_DirPool[uss_NumGroups++], a_dirToAdd);
753 return 0;
754 }
755
756 /*-----------------------------------------------------------------------
757 * EXPORTED uss_procs_FindAndOpen
758 *
759 * Environment:
760 * Nothing interesting.
761 *
762 * Side Effects:
763 * As advertised.
764 *------------------------------------------------------------------------*/
765
766 FILE *
767 uss_procs_FindAndOpen(char *a_fileToOpen)
768 { /*uss_procs_FindAndOpen */
769
770 #define NUM_TPL_PATHS 3
771
772 FILE *rv; /*Template file descriptor */
773 int i; /*Loop counter */
774 char tmp_str[uss_MAX_SIZE]; /*Tmp string */
775 static char
776 TemplatePath[NUM_TPL_PATHS][1024]; /*Template directories */
777 int cant_read; /*Can't read the file? */
778
779 /*
780 * If a full pathname was given, just take it as is.
781 */
782 if (strchr(a_fileToOpen, '/')) {
783 strcpy(tmp_str, a_fileToOpen);
784 rv = fopen(a_fileToOpen, "r");
785 } else {
786 /*
787 * A relative pathname was given. Try to find the file in each of
788 * the default template directories.
789 */
790 cant_read = 0;
791
792 sprintf(TemplatePath[0], "%s", ".");
793 sprintf(TemplatePath[1], "/afs/%s/common/uss", uss_Cell);
794 sprintf(TemplatePath[2], "%s", "/etc");
795
796 for (i = 0; i < NUM_TPL_PATHS; i++) {
797 sprintf(tmp_str, "%s/%s", TemplatePath[i], a_fileToOpen);
798 if ((rv = fopen(tmp_str, "r")) != NULL)
799 break;
800
801 /*
802 * If the file was there but couldn't be opened, we have
803 * to report this.
804 */
805 if (errno != ENOENT) {
806 cant_read = 1;
807 break;
808 }
809 } /*Look in template directories */
810
811 /*
812 * If we found and opened the file, we're happy. Otherwise,
813 * print out what went wrong.
814 */
815 if (rv != NULL) {
816 if (uss_verbose)
817 fprintf(stderr, "Using template '%s'\n", tmp_str);
818 } /*Got it */
819 else {
820 /*
821 * Check to see if we specifically found the file but
822 * couldn't read it.
823 */
824 if (cant_read)
825 fprintf(stderr, "%s: Can't open template '%s': %s\n",
826 uss_whoami, tmp_str, strerror(errno));
827 else {
828 fprintf(stderr, "%s: Can't find template '%s' in searchlist",
829 uss_whoami, a_fileToOpen);
830 for (i = 0; i < NUM_TPL_PATHS; i++)
831 fprintf(stderr, " '%s'", TemplatePath[i]);
832 fprintf(stderr, "\n");
833 } /*Can't find template */
834 } /*Didn't get it */
835 } /*Relative pathname given */
836
837 /*
838 * Whatever happened, return what we got.
839 */
840 return (rv);
841
842 } /*uss_procs_FindAndOpen */
843
844
845 /*-----------------------------------------------------------------------
846 * EXPORTED uss_procs_PrintErr
847 *
848 * Environment:
849 * Nothing interesting.
850 *
851 * Side Effects:
852 * As advertised.
853 *------------------------------------------------------------------------*/
854
855 void
856 uss_procs_PrintErr(int a_lineNum, char *a_fmt, ... )
857 { /*uss_procs_PrintErr */
858 va_list ap;
859
860 va_start(ap, a_fmt);
861 uss_syntax_err++;
862 fprintf(stderr, "%s: Template file, line %d: ", uss_whoami, a_lineNum);
863 vfprintf(stderr, a_fmt, ap);
864 va_end(ap);
865 } /*uss_procs_PrintErr */