+ extern int errno;
+
+ exit_val = 1;
+ (void)fprintf(stderr, "cp: %s: %s\n", s, strerror(errno));
+}
+
+/********************************************************************
+ * Path Manipulation Routines.
+ ********************************************************************/
+
+/*
+ * These functions manipulate paths in "path_t" structures.
+ *
+ * They eliminate multiple slashes in paths when they notice them, and keep
+ * the path non-slash terminated.
+ *
+ * Both path_set() and path_append() return 0 if the requested name
+ * would be too long.
+ */
+
+#define STRIP_TRAILING_SLASH(p) { \
+ while ((p)->p_end > (p)->p_path && (p)->p_end[-1] == '/') \
+ *--(p)->p_end = 0; \
+ }
+
+/*
+ * Move specified string into path. Convert "" to "." to handle BSD
+ * semantics for a null path. Strip trailing slashes.
+ */
+path_set(p, string)
+ register path_t *p;
+ char *string;
+{
+ if (strlen(string) > MAXPATHLEN) {
+ fprintf(stderr, "cp: %s: name too long.\n", string);
+ exit_val = 1;
+ return(0);
+ }
+
+ (void)strcpy(p->p_path, string);
+ p->p_end = p->p_path + strlen(p->p_path);
+
+ if (p->p_path == p->p_end) {
+ *p->p_end++ = '.';
+ *p->p_end = 0;
+ }
+
+ STRIP_TRAILING_SLASH(p);
+ return(1);
+}
+
+/*
+ * Append specified string to path, inserting '/' if necessary. Return a
+ * pointer to the old end of path for restoration.
+ */
+char *
+path_append(p, name, len)
+ register path_t *p;
+ char *name;
+ int len;
+{
+ char *old;
+
+ old = p->p_end;
+ if (len == -1)
+ len = strlen(name);
+
+ /*
+ * The final "+ 1" accounts for the '/' between old path and name.
+ */
+ if ((len + p->p_end - p->p_path + 1) > MAXPATHLEN) {
+ fprintf(stderr,
+ "cp: %s/%s: name too long.\n", p->p_path, name);
+ exit_val = 1;
+ return(0);
+ }
+
+ /*
+ * This code should always be executed, since paths shouldn't
+ * end in '/'.
+ */
+ if (p->p_end[-1] != '/') {
+ *p->p_end++ = '/';
+ *p->p_end = 0;
+ }
+
+ (void)strncat(p->p_end, name, len);
+ p->p_end += len;
+ *p->p_end = 0;