2.9BSD/usr/src/ucb/vsh/file.c

#include "hd.h"
#include "mydir.h"
#include "strings.h"
#include "classify.h"

/* File gets a file name, converts it into a full path name, and
   selects that file.  */

file (argv) char **argv; {	/* Select specific file */

	char nname [STRMAX];

	if (*argv == CNULL) putmsg ("File:  ");
	if (getfname (*argv, nname) == FAILURE) return FAILURE;

	return (enterfile (nname));
}

/* Create accepts a file name, creats that file, and then enters it.  */
create () {

	char nname [STRMAX], oname [STRMAX];
	register char ch;  char *cp; int class;

	putmsg ("Create:  ");
	if (getfname (CNULL, nname) == FAILURE) return FAILURE;

	if (!access (nname, 0)) {
		putmsg (nname);  printf (":  Already exists");
		return FAILURE;
	}

	todotdot (nname);
	class = classify (nname);

	if (class == CL_NULL || access (nname, 3)) {
		myperror (nname);  return FAILURE;
	}
	else if (class != CL_DIR) {
		putmsg (nname);  printf (":  Not a directory");
		return FAILURE;
	}

	/* Un do effect of todotdot */
	for (cp = nname; *cp++;);
	*--cp = '/';

	erase ();  printf ("Creating %s\n\nSelect:\n\n", nname);

	printf
	("1  Text\n2  Directory\n3  Copy a file\n4  Link a file\n\n");

	ch = getch ();  putch (LF);
	if (ch == '1') {
		f_exec (EDITOR, EDITOR, nname, 0);
	}
	else if (ch == '2') {
		if (f_exec ("/bin/mkdir", "mkdir", nname, 0)) getrtn ();
		return enterdir (nname) | REPLOT;
	}
	else if (ch == '3' || ch == '4') {
		printf ("From:  ");
		if (getfname (CNULL, oname) == FAILURE) return REPLOT;

		switch (classify (oname)) {

			case CL_NULL:  case CL_PROTPLN:
			myperror (oname);  break;

			case CL_DIR:
			printf ("Cannot copy or link to directories");
			break;

			default:
			if (ch == '3') f_exec
				("/bin/cp", "cp", oname, nname, 0);
			if (ch == '4') {
				printf ("Linking\n");
				if (link (oname, nname))
					myperror ("Link failed");
			}
			at (1501);
			if (!access (nname, 0)) {
				printf ("File created.\
  Do you wish to examine it?  ");
				if (getch() == 'y') {
					putch (LF);
					return
					enterfile (nname) | REPLOT;
				}
				return REPLOT;
			}
		}
		at (1501);
		printf ("File not created. ");
		getrtn ();
	}
	return REPLOT;
}

/* Getfname takes two character arrays as parameters.
   Inname is the partial pathname of a file.  If inname == CNULL,
   getfname will instead read the partial pathname from the terminal.
   The full pathname is returned in outname.
   Getfname has a return value of SUCCESS or FAILURE.
*/
getfname (inname, outname) char *inname, *outname; {
	char inword [STRMAX];  int ilen;

	if (inname == CNULL) {
		tty_push (COOKEDMODE);
		ilen = getword (inword);
		tty_pop ();
		if (ilen <= 0) {
			clearmsg (0);
			return FAILURE;
		}
		inname = inword;
	}
	if (pathgen (wdname, inname, outname)) {
		putmsg ("Path name too long");
		return FAILURE;
	}
	return SUCCESS;
}

/* If one is in dir with pathname "old", and does a chdir "change",
   one ends up in directory "new".  Exception: ".." always breaks
   through to the root.
*/
pathgen (old, change, new) char *old, *change, *new; {

char element [DIRSIZ + 1];
char chgbuf  [STRMAX];
register len;

if (change [0] == '/') strcpy (new, SLASH);
else strcpy (new, old);

strcpy (chgbuf, change);	/* So change is not modified */

while (*chgbuf) {

	extract (element, chgbuf);
	if (compe (DOT, element));
	else if (compe (DOTDOT, element)) todotdot (new);

	else {
		len = strlen (new);
		if (len > LPLEN) return 1;
		else if (len > 1) strcat (new, SLASH);
		strcat (new, element);
	}
}
return 0;
}

extract (element, path) char *element, *path; {

register char *cp;
int eltlen;

for (cp = path; *cp != 0 && *cp != '/'; cp++);

eltlen = cp - path;
if (eltlen == 0) {
	strcpy (element, DOT);
}
else {
	strncpy (element, path, DIRSIZ);
	element [min (eltlen, DIRSIZ)] = 0;
}
if (*cp) shift (path, eltlen + 1);
else path [0] = 0;
}

shift (path, length) char *path;  int length; {

register char *cp;

for (cp = path + length; cp [-1];) *path++ = *cp++;
}