diff --git a/WEGA/contrib/lcc/lib/libc/port/gen/getut.c b/WEGA/contrib/lcc/lib/libc/port/gen/getut.c new file mode 100644 index 0000000..d12e62e --- /dev/null +++ b/WEGA/contrib/lcc/lib/libc/port/gen/getut.c @@ -0,0 +1,360 @@ +/* Routines to read and write the /etc/utmp file. */ +/* */ + +#include +#include +#include +#include + +#define TRUE 1 +#define FALSE 0 +#define FAILURE -1 + +#define NULL 0 + +#define MAXFILE 79 /* Maximum pathname length for "utmp" file */ + +#ifdef DEBUG + +#undef UTMP_FILE +#define UTMP_FILE "utmp" + +#endif + +static int fd = FAILURE ; /* File descriptor for the utmp file. */ +static char utmpfile[MAXFILE+1] = UTMP_FILE ; /* Name of the current + * "utmp" like file. + */ +static char utmplock[MAXFILE+5] ; +static long loc_utmp ; /* Where in "utmp" the current "ubuf" was + * found. + */ +static struct utmp ubuf ; /* Copy of last entry read in. */ + +/* "getutent" gets the next entry in the utmp file. */ + +struct utmp *getutent() + { + extern int fd ; + extern char utmpfile[] ; + extern struct utmp ubuf ; + extern long loc_utmp,lseek() ; + extern int errno ; + register char *u ; + register int i ; + +/* If the "utmp" file is not open, attempt to open it for */ +/* reading. If there is no file, attempt to create one. If */ +/* both attempts fail, return NULL. If the file exists, but */ +/* isn't readable and writeable, do not attempt to create. */ + + if (fd == FAILURE) + { + if ((fd = open(&utmpfile[0],2)) == FAILURE) + { +/* If the open failed because the file didn't exist, then try to */ +/* create one. */ + + if (errno == ENOENT) + { + if (creat(&utmpfile[0],0644) == FAILURE) return(NULL) ; + close(fd) ; + if ((fd = open(&utmpfile[0],2)) == FAILURE) return(NULL) ; + } + +/* If the open failed for permissions, try opening it only for */ +/* reading. All "pututline()" later will fail the writes. */ + + else if (errno == EACCES) + { + if ((fd = open(&utmpfile[0],0)) == FAILURE) return(NULL) ; + } + + else return(NULL) ; + } + } + +/* Try to read in the next entry from the utmp file. If the */ +/* read fails, return NULL. */ + + if (read(fd,&ubuf,sizeof(ubuf)) != sizeof(ubuf)) + { + +/* Make sure ubuf is zeroed. */ + + for (i=0,u= (char *)(&ubuf); i < sizeof(ubuf) + ; i++) *u++ = '\0' ; + loc_utmp = 0 ; + return(NULL) ; + } + +/* Save the location in the file where this entry was found. */ + + loc_utmp = lseek(fd,0L,1) - (long)(sizeof(struct utmp)) ; + return(&ubuf) ; + } + +/* "getutid" finds the specified entry in the utmp file. If */ +/* it can't find it, it returns NULL. */ + +struct utmp *getutid(entry) + +register struct utmp *entry ; + + { + extern struct utmp ubuf ; + struct utmp *getutent() ; + register short type ; + +/* Start looking for entry. Look in our current buffer before */ +/* reading in new entries. */ + + do + { +/* If there is no entry in "ubuf", skip to the read. */ + + if (ubuf.ut_time != 0) + { + if (strncmp(ubuf.ut_name,entry->ut_name,8)==0) + return(&ubuf) ; + break ; + } + } + while (getutent() != NULL) ; + +/* Return NULL since the proper entry wasn't found. */ + + return(NULL) ; + } + +/* "getutline" searches the "utmp" file for a LOGIN_PROCESS or */ +/* USER_PROCESS with the same "line" as the specified "entry". */ + +struct utmp *getutline(entry) + +register struct utmp *entry ; + + { + extern struct utmp ubuf,*getutent() ; + register struct utmp *cur ; + +/* Start by using the entry currently incore. This prevents */ +/* doing reads that aren't necessary. */ + + cur = &ubuf ; + do + { +/* If the current entry is the one we are interested in, return */ +/* a pointer to it. */ + + if (strncmp(entry->ut_line,cur->ut_line,8) == 0) return(cur) ; + } + while ((cur = getutent()) != NULL) ; + +/* Since entry wasn't found, return NULL. */ + + return(NULL) ; + } + +/* "pututline" writes the structure sent into the utmp file. */ +/* If there is already an entry with the same id, then it is */ +/* overwritten, otherwise a new entry is made at the end of the */ +/* utmp file. */ + +struct utmp *pututline(entry) + +struct utmp *entry ; + + { + register int i,type ; + struct utmp *answer ; + struct stat statbuf ; + extern long time() ; + extern struct utmp ubuf ; + extern long loc_utmp,lseek() ; + extern struct utmp *getutid() ; + extern int fd,errno ; + struct utmp tmpbuf ; + +/* Copy the user supplied entry into our temporary buffer to */ +/* avoid the possibility that the user is actually passing us */ +/* the address of "ubuf". */ + + tmpbuf = *entry ; + +/* Create a lock link file before attempting to modify the utmp */ +/* file. Wait for up to sixty seconds, but then continue */ +/* regardless of the lock file. If sixty seconds isn't enough time,*/ +/* the original creator of the lock probably has died. */ + + sprintf(&utmplock[0],"%s.lck",&utmpfile[0]) ; + while (link(&utmpfile[0],&utmplock[0]) == FAILURE) + { + if (errno == EEXIST) + { + if (stat(&utmpfile[0],&statbuf) != FAILURE) + { + if (time(0) - statbuf.st_ctime > 60) unlink(&utmplock[0]) ; + else sleep(3) ; + } + } + else if (errno == ENOENT) + { +/* If the utmp file doesn't exist, make one by trying to find the */ +/* entry of interest. "getutent()" will create the file. */ + + getutent() ; + if (fd == FAILURE) + { +#ifdef ERRDEBUG + gdebug("pututline: Unable to create utmp file.\n") ; +#endif + return((struct utmp *)NULL) ; + } + } + else + { +#ifdef ERRDEBUG + gdebug("pututline failed: link of lock file failed-%d",errno) ; +#endif + return((struct utmp *)NULL) ; + } + } + +/* Find the proper entry in the utmp file. Start at the current */ +/* location. If it isn't found from here to the end of the */ +/* file, then reset to the beginning of the file and try again. */ +/* If it still isn't found, then write a new entry at the end of */ +/* the file. (Making sure the location is an integral number of */ +/* utmp structures into the file incase the file is scribbled.) */ + + if (getutid(&tmpbuf) == NULL) + { +#ifdef ERRDEBUG + gdebug("First getutid() failed. fd: %d",fd) ; +#endif + setutent() ; + if (getutid(&tmpbuf) == NULL) + { + loc_utmp = lseek(fd,0L,1) ; + loc_utmp -= loc_utmp % sizeof(struct utmp) ; +#ifdef ERRDEBUG + gdebug("Second getutid() failed. fd: %d loc_utmp: %ld\n", + fd,loc_utmp) ; +#endif + } + } + +/* Seek to the proper place on the file descriptor for writing. */ + + lseek(fd,loc_utmp,0) ; + +/* Write out the user supplied structure. If the write fails, */ +/* then the user probably doesn't have permission to write the */ +/* utmp file. */ + + if (write(fd,&tmpbuf,sizeof(tmpbuf)) != sizeof(tmpbuf)) + { +#ifdef ERRDEBUG + gdebug("pututline failed: write-%d\n",errno) ; +#endif + answer = (struct utmp *)NULL ; + } + else + { +/* Copy the user structure into ubuf so that it will be up to */ +/* date in the future. */ + + ubuf = tmpbuf ; + answer = &ubuf ; + +#ifdef ERRDEBUG + gdebug("id: %c%c loc: %x\n",ubuf.ut_id[0],ubuf.ut_id[1], + ubuf.ut_id[2],ubuf.ut_id[3],loc_utmp) ; +#endif + } + +/* Remove the lock file (even if it wasn't your own creation). */ + + unlink(&utmplock[0]) ; + return(answer) ; + } + +/* "setutent" just resets the utmp file back to the beginning. */ + +setutent() + { + register char *ptr ; + register int i ; + extern int fd ; + extern struct utmp ubuf ; + extern long loc_utmp ; + + if (fd != FAILURE) lseek(fd,0L,0) ; + +/* Zero the stored copy of the last entry read, since we are */ +/* resetting to the beginning of the file. */ + + for (i=0,ptr=(char*)&ubuf; i < sizeof(ubuf) ;i++) *ptr++ = '\0' ; + loc_utmp = 0L ; + } + +/* "endutent" closes the utmp file. */ + +endutent() + { + extern int fd ; + extern long loc_utmp ; + extern struct utmp ubuf ; + register char *ptr ; + register int i ; + + if (fd != FAILURE) close(fd) ; + fd = FAILURE ; + loc_utmp = 0 ; + for (i=0,ptr= (char *)(&ubuf); i < sizeof(ubuf) ;i++) *ptr++ = '\0' ; + } + +/* "utmpname" allows the user to read a file other than the */ +/* normal "utmp" file. */ + +utmpname(newfile) + +char *newfile ; + + { + extern char utmpfile[] ; + +/* Determine if the new filename will fit. If not, return FALSE. */ + + if (strlen(newfile) > MAXFILE) return (FALSE) ; + +/* Otherwise copy in the new file name. */ + + else strcpy(&utmpfile[0],newfile) ; + +/* Make sure everything is reset to the beginning state. */ + + endutent() ; + + return(TRUE) ; + } +#ifdef ERRDEBUG +#include + +gdebug(format,arg1,arg2,arg3,arg4,arg5,arg6) + +char *format ; +int arg1,arg2,arg3,arg4,arg5,arg6 ; + + { + register FILE *fp ; + register int errnum ; + extern int errno ; + + if ((fp = fopen("/etc/dbg.getut","a+")) == NULL) return ; + + fprintf(fp,format,arg1,arg2,arg3,arg4,arg5,arg6) ; + fclose(fp) ; + } +#endif