break out special local mail processing (e.g., mapping to the
[unix-history] / usr / src / bin / cp / path.c
CommitLineData
8d4509b6
KB
1/*-
2 * Copyright (c) 1991 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
c69482b5 9static char sccsid[] = "@(#)path.c 5.2 (Berkeley) %G%";
8d4509b6
KB
10#endif /* not lint */
11
12#include <sys/param.h>
8d4509b6 13#include <string.h>
c69482b5 14#include "extern.h"
8d4509b6
KB
15
16/*
17 * These functions manipulate paths in PATH_T structures.
18 *
19 * They eliminate multiple slashes in paths when they notice them,
20 * and keep the path non-slash terminated.
21 *
22 * Both path_set() and path_append() return 0 if the requested name
23 * would be too long.
24 */
25
26#define STRIP_TRAILING_SLASH(p) { \
27 while ((p)->p_end > (p)->p_path && (p)->p_end[-1] == '/') \
28 *--(p)->p_end = 0; \
29}
30
31/*
32 * Move specified string into path. Convert "" to "." to handle BSD
33 * semantics for a null path. Strip trailing slashes.
34 */
c69482b5 35int
8d4509b6
KB
36path_set(p, string)
37 register PATH_T *p;
38 char *string;
39{
40 if (strlen(string) > MAXPATHLEN) {
c69482b5 41 err("%s: name too long", string);
8d4509b6
KB
42 return(0);
43 }
44
45 (void)strcpy(p->p_path, string);
46 p->p_end = p->p_path + strlen(p->p_path);
47
48 if (p->p_path == p->p_end) {
49 *p->p_end++ = '.';
50 *p->p_end = 0;
51 }
52
53 STRIP_TRAILING_SLASH(p);
54 return(1);
55}
56
57/*
58 * Append specified string to path, inserting '/' if necessary. Return a
59 * pointer to the old end of path for restoration.
60 */
61char *
62path_append(p, name, len)
63 register PATH_T *p;
64 char *name;
65 int len;
66{
67 char *old;
68
69 old = p->p_end;
70 if (len == -1)
71 len = strlen(name);
72
73 /* The "+ 1" accounts for the '/' between old path and name. */
74 if ((len + p->p_end - p->p_path + 1) > MAXPATHLEN) {
c69482b5 75 err("%s/%s: name too long", p->p_path, name);
8d4509b6
KB
76 return(0);
77 }
78
79 /*
80 * This code should always be executed, since paths shouldn't
81 * end in '/'.
82 */
83 if (p->p_end[-1] != '/') {
84 *p->p_end++ = '/';
85 *p->p_end = 0;
86 }
87
88 (void)strncat(p->p_end, name, len);
89 p->p_end += len;
90 *p->p_end = 0;
91
92 STRIP_TRAILING_SLASH(p);
93 return(old);
94}
95
96/*
97 * Restore path to previous value. (As returned by path_append.)
98 */
99void
100path_restore(p, old)
101 PATH_T *p;
102 char *old;
103{
104 p->p_end = old;
105 *p->p_end = 0;
106}
107
108/*
109 * Return basename of path.
110 */
111char *
112path_basename(p)
113 PATH_T *p;
114{
115 char *basename;
116
117 basename = rindex(p->p_path, '/');
118 return(basename ? basename + 1 : p->p_path);
119}