Xinu7/src/cmd/download/OLD/getdev.c

Compare this file to the similar file:
Show the results in this format:

/* getdev.c  -  procedure that automatically selects a device		*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include "getdev.h"

char	tmpuser[MAXNAMELEN];	/* name of file containing name of	*/
				/*  user's currently locked device	*/
char	tmplock[MAXNAMELEN];	/* lock file name template		*/
char	devname[MAXNAMELEN];	/* device name template			*/
char	dev[MAXNAMELEN];	/* device name				*/


/************************************************************************/
/*									*/
/*  getdev  -- get the LSI a user has already reserved, or one that is	*/
/*		free							*/
/*									*/
/************************************************************************/

getdev(useclass, class, request, devfd, locknm)
int	useclass;		/* FALSE => use previous class if avail.*/
char	*class;			/* which group of machines?		*/
int	request;		/* # of machine to allocate, ANYDEV, ...*/
int	*devfd;			/* place to store device file descriptor*/
char	*locknm;		/* place to store lock file name	*/
{
	char	*getlogin();
	char	*loginid;
	char	oldclass[MAXNAMELEN];	/* class on reserve		*/
	int	machnum;

	*locknm = '\0';
	if ( (loginid=getlogin()) == NULL || *loginid == '\0')
		loginid = (getpwuid(getuid()))->pw_name;

	if (request != TTYNAME)
		sprintf(tmpuser, TMPUSER, TMPDIR, loginid);
	else if ((*devfd=open(class, 2)) >= 0)
		return(0);
	else {
		fprintf(stderr, "Cannot open device %s\n", class);
		return(-1);
	}

	if ((machnum=getclass(oldclass)) > 0 &&
			(!useclass || request == MYDEV))
		strcpy(class, oldclass);

	/* Create file name templates.					*/

	sprintf(tmplock, DEVNAME, TMPDIR, class);
	sprintf(devname, DEVNAME, DEVDIR, class);

	/* either get specified device, the one this user has reserved,	*/
	/*  or any device, depending on 'request'			*/

	switch (request) {
	case MYDEV:
		machnum = olddev(machnum, locknm);
		break;
	case ANYDEV:
		if ((useclass && strcmp(class, oldclass) != 0) ||
			(machnum=olddev(machnum, locknm)) < 0)
			machnum = newdev(request, locknm);
		break;
	default:
		machnum = newdev(request, locknm);
		break;
	}

	/* if successful, machnum contains (positive) number of lsi	*/
	/*  that was allocated.  Else it is -1				*/

	if (machnum > 0) {
		if ( (*devfd = open(dev, 2)) < 0) {
		    fprintf(stderr,"Cannot open %s\n",dev);
		    unlink(locknm);
		    unlink(tmpuser);
		    return(-1);
		}
		touch(locknm);
		return(machnum);
	}
	if (request > 0)
		fprintf(stderr, "%s #%d unavailable.\n", class, request);
	else if (request == MYDEV)
		fprintf(stderr,"No %s on reserve for you.\n", class);
	else if (request == ANYDEV)
		fprintf(stderr, "No %s available.\n", class);
	else
		fprintf(stderr, "Unintelligible request: %d\n", request);
	return(-1);
}


/*------------------------------------------------------------------------
 *  getclass  --  return the class and number of the last used machine
 *------------------------------------------------------------------------
 */
getclass(class)
char	*class;
{
	char	*rindex();
	int	fd;
	char	oldname[MAXNAMELEN];
	int	len;
	int	oldnum;

	if ( (fd=open(tmpuser, 2)) < 0)	/* user has no reservation	*/
		return(-1);
	len = read(fd, oldname, sizeof(oldname));
	close(fd);
	oldname[len - 1] = '\0';	/* last character was a newline	*/

	if (len < 3 || access(sprintf(dev, "%s/%s", DEVDIR, oldname), 0) < 0
		|| sscanf(rindex(oldname, '.'), ".%d", &oldnum) != 1) {
		unlink(tmpuser);
		return(-1);
	}
	strcpy(class, oldname);
	*rindex(class, '.') = '\0';
	return(oldnum);
}


/*
 *  olddev  --  return id of device already allocated to this user
 */
olddev(machnum, locknm)
int	machnum;		/* number of requested machine		*/
char	*locknm;		/* place to store lock file name	*/
{
	if (machnum < 0)
		return(-1);
	else
		return(trydev(machnum, locknm));
}

newdev(machnum, locknm)
int	machnum;		/* place to store lsi number used	*/
char	*locknm;		/* place to store lock file name	*/
{
	int	i;

	if (machnum >= 0)
		return(trydev(machnum, locknm));
	for (i = 1 ; access(sprintf(dev, devname, i), 0) == 0 ; i++) {
		if (trydev(i, locknm) >= 0)
			return(i);
	}
	return(-1);
}


struct	stat	sbuf;

/*
 * trydev -- see if a given device is available
 */
trydev(machnum, locknm)
int	machnum;
char	*locknm;
{
	long	time();
	long	now;
	int	fd;
	int	len;
	char	lname[MAXNAMELEN];
	char	oldlock[MAXNAMELEN];

	if (access(sprintf(dev, devname, machnum), 0) < 0)
		return(-1);
	if ((fd=creat(sprintf(locknm, tmplock, machnum), 0600)) < 0) {
		stat(locknm, &sbuf);
		now = time(0L);
		if ( (int)(now-sbuf.st_mtime) > TIMEOUT * 60)
			unlink(locknm);
		else
			return(-1);
		if ((fd=creat(locknm,0600)) < 0) {
			fprintf(stderr,"Can't create lock\n");
			exit(-1);
		}
	}
	close(fd);			/* device is locked		*/
	if ((fd=open(tmpuser, 2)) >= 0) { /* remove my previous lock	*/
		len = read(fd, lname, sizeof(lname));
		close(fd);
		lname[len - 1] = '\0';
		if (strcmp(locknm, sprintf(oldlock,"%s/%s",TMPDIR,lname))==0)
			return(machnum);
		else if (access(oldlock, 4|2) == 0)	/* it's my lock	*/
			unlink(oldlock);
	}
	unlink(tmpuser);
	if ( (fd=creat(tmpuser,0666)) < 0) {
		perror("Can't create tmp userid file");
		exit(1);
	}
	write(fd, dev + strlen(DEVDIR)+1, strlen(dev) - strlen(DEVDIR)-1);
	write(fd, "\n", 1);
	close(fd);
	return(machnum);
}


touch(locknm)
char	*locknm;			/* name of file to touch	*/
{
	close(creat(locknm, 0600));
}