[comp.os.minix] statutil & lock/unlock

dono@killer.DALLAS.TX.US (Don OConnell) (01/14/89)

-----------------------------Cut Here------------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Readme lock.c statutil.c
# Wrapped by dono@killer on Sat Jan 14 03:38:27 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Readme -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Readme\"
else
echo shar: Extracting \"Readme\" \(1436 characters\)
sed "s/^X//" >Readme <<'END_OF_Readme'
XWhile re-reading Advanced Unix Programming by Marc J. Rochkind, I ran
Xacross some routines that I thought others might find useful.
X
X------------------------------------------------------------------------------
X
XThe lock and unlock functions can be used like this:
X            if (lock("database")) {
X                ... manipulate database...
X                unlock("database");
X            }
X            else
X                ...couldn't obtain lock...
X
XThe name "database" is abstract, it could have been called anything.
XIf two or more processes are concurrentlyu executing this code, the lock will
Xprevent them from simultaneously executing the protected section(manipulate
Xdatabase). All processes would have to call the lock function for this to
Xwork though.
X
XAs an enhancement you could write the pid and time on the file so other
Xprocesses could see who has it and for how long.(If this is done the permis-
Xsions should be set to octal 444 instead of 0).
X
X------------------------------------------------------------------------------
X
XStatutil.c is a program that allows you to do several different functions on
Xfiles;
X    change modification time, owner, permissions
X
X    display type of file(dir, ordinary, block, character)
X            device number(major, minor), number of links to file,
X            I-node number, Size, group id, owner, last mod. time
X
XAll done interactively.
X
END_OF_Readme
if test 1436 -ne `wc -c <Readme`; then
    echo shar: \"Readme\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f lock.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lock.c\"
else
echo shar: Extracting \"lock.c\" \(950 characters\)
sed "s/^X//" >lock.c <<'END_OF_lock.c'
X#include <errno.h>
X
Xtypedef enum { FALSE, TRUE } BOOLEAN;
X
X#define LOCKDIR "/tmp/"     /* or /usr/tmp/ as the case may be */
X#define MAXTRIES 3
X#define NAPTIME 5
X
XBOOLEAN lock(name)          /* acquire lock */
Xchar *name;
X{
X    char *path, *lockpath();
X    int fd, tries;
X    extern int errno;
X
X    path = lockpath(name);
X    tries = 0;
X    while ((fd = creat(path, 0)) == -1 && errno == EACCES)
X    {
X        if (++tries >= MAXTRIES)
X            return(FALSE);
X        sleep(NAPTIME);
X    }
X    if (fd == -1 || close(fd) == -1)
X        syserr("lock");
X    return(TRUE);
X}
X
Xvoid unlock(name)           /* free lock */
Xchar *name;
X{
X    char *lockpath();
X
X    if (unlink(lockpath(name)) == -1)
X        syserr("unlock");
X}
X
Xstatic char *lockpath(name) /* generate lock file path */
Xchar *name;
X{
X    static char path[20];
X    char *strcat();
X
X    strcpy(path, LOCKDIR);
X    return(strcat(path, name));
X}
X
END_OF_lock.c
if test 950 -ne `wc -c <lock.c`; then
    echo shar: \"lock.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f statutil.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"statutil.c\"
else
echo shar: Extracting \"statutil.c\" \(9217 characters\)
sed "s/^X//" >statutil.c <<'END_OF_statutil.c'
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <pwd.h>
X#include <grp.h>
X#include <time.h>
X
Xtypedef enum { FALSE, TRUE } BOOLEAN;
X
Xvoid mainloop(), help(), prompt(), status(), dspstatus(), chtime();
Xvoid chowner(), chperms(), syserrmsg();
Xlong timecvt();
X
Xmain()                  /* statutil */
X{
X    setbuf(stdout, NULL);
X    help();
X    mainloop();
X}
X
Xstatic void mainloop()  /* process commands */
X{
X    char path[50], cmd[10], shcmd[100];
X
X    while(1) {
X        prompt("Command", cmd);
X        if (strlen(cmd) > 1)
X            cmd[0] = '\1';  /* force unknown command message */
X        switch (cmd[0]) {
X        case '\0':
X        case 'q':
X            exit(0);
X        case 'm':
X            chtime(path);
X            continue;
X        case 'f':
X            prompt("File", path);
X            if (access(path, 0) == -1) {
X                printf("%s nonexistent\n", path);
X                continue;
X            }
X            status(path);
X            continue;
X        case 'o':
X            chowner(path);
X            continue;
X        case 'p':
X            chperms(path);
X            continue;
X        case 's':
X            status(path);
X            continue;
X        case '!':
X            prompt("Shell command", shcmd);
X            system(shcmd);
X            continue;
X        case '?':
X            help();
X            continue;
X        default:
X            printf("Unknown command; use ? for help");
X            continue;
X        }
X    }
X}
X
Xstatic void help()      /* display menu */
X{
X    printf("\n\n");
X    printf("DISPLAY COMMANDS\n\n");
X    printf("f   new file name\n");
X    printf("m   change modification time\n");
X    printf("o   change owner\n");
X    printf("p   change permissions\n");
X    printf("q   quit\n");
X    printf("s   display status\n");
X    printf("!   execute UNIX command\n");
X    printf("?   display command summary\n");
X    printf("\n\n");
X}
X
Xstatic void prompt(msg, result)     /* prompt user */
Xchar *msg, *result;
X{
X    printf("\n%s?", msg);
X    if (gets(result) == NULL)
X        exit(0);
X}
X
Xstatic void status(path)    /* "s" command */
Xchar *path;
X{
X    struct stat sb;
X
X    if (stat(path, &sb) == -1) {
X        syserrmsg("stat");
X        return;
X    }
X    printf("\nFILE \"%s\"\n", path);
X    dspstatus(&sb);
X}
X
Xstatic void dspstatus(sbp)  /* display status */
Xstruct stat *sbp;
X{
X    BOOLEAN isdevice = FALSE;
X    struct passwd *pw, *getpwuid();
X    struct group *gr, *getgrgid();
X    char *name, *ctime();
X
X    if ((sbp->st_mode & S_IFMT) == S_IFDIR)
X        printf("Directory\n");
X    else if ((sbp->st_mode & S_IFMT) == S_IFBLK) {
X        printf("Block special file\n");
X        isdevice = TRUE;
X    } else if ((sbp->st_mode & S_IFMT) == S_IFCHR) {
X        printf("Character special file\n");
X        isdevice = TRUE;
X    } else if ((sbp->st_mode & S_IFMT) == S_IFREG)
X        printf("Ordinary file\n");
X/*    else if ((sbp->st_mode & S_IFMT) == S_IFIFO) */ /* when fifo's added */
X/*        prinf("FIFO\n");    */
X    if (isdevice)
X        printf("Device number: %d, %d\n", (sbp->st_rdev>>8) & 0377,
X            sbp->st_rdev & 0377);
X    printf("Resides on device: %d, %d\n", (sbp->st_dev>>8) & 0377,
X        sbp->st_dev & 0377);
X    printf("I-node: %d; Links: %d; Size: %ld\n", sbp->st_ino,
X        sbp->st_nlink, sbp->st_size);
X    if ((pw = getpwuid(sbp->st_uid)) == NULL)
X        name = "???";
X    else
X        name = pw->pw_name;
X    printf("Group ID: %d; Name: %s\n", sbp->st_gid, name);
X    if ((sbp->st_mode & S_ISUID) == S_ISUID)
X        printf("Set-user-ID\n");
X    if ((sbp->st_mode & S_ISGID) == S_ISGID)
X        printf("Set-group-ID\n");
X    if ((sbp->st_mode & S_ISVTX) == S_ISVTX)
X        printf("Save swapped text after use\n");
X    printf("Permissions: %o\n", sbp->st_mode & 0777);
X    printf("Last modification:   %s", ctime(&sbp->st_mtime));
X}
X
Xstatic void chtime(path)     /* "m" command */
Xchar *path;
X{
X    char atime[20];
X    long seconds, timecvt();
X    struct stat sb;
X    long tbuf[2];
X
X    if (stat(path, &sb) == -1) {
X        syserrmsg("stat");
X        return;
X    }
X    prompt("Time (YYMMDDhhmmss)", atime);
X    if ((seconds = timecvt(atime)) <= 0)
X        return;
X    tbuf[0] = sb.st_mtime;
X    tbuf[1] = seconds;
X    if (utime(path, &tbuf) == -1)
X        syserrmsg("utime");
X}
X
Xstatic void chowner(path)       /* "o" command */
Xchar *path;
X{
X    char oname[20], gname[20];
X    int owner, group;
X    struct passwd *pw, *getpwnam();
X    struct group *gr, *getgrnam();
X
X    prompt("Owner name", oname);
X    if ((pw = getpwnam(oname)) == NULL) {
X        printf("Unknown name\n");
X        return;
X    }
X    owner = pw->pw_uid;
X    prompt("Group name", gname);
X    if ((gr = getgrnam(gname)) == NULL) {
X        printf("Unknown name\n");
X        return;
X    }
X    group = gr->gr_gid;
X    if (chown(path, owner, group) == -1)
X        syserrmsg("chown");
X}
X
Xstatic void chperms(path)       /* "p" command */
Xchar *path;
X{
X    char smode[20];
X    int mode;
X
X    prompt("Mode (up to 4 octal digits)", smode);
X    if (sscanf(smode, "%o", &mode) != 1) {
X        printf("Invalid mode\n");
X        return;
X    }
X    if (chmod(path, mode) == -1)
X        syserrmsg("chmod");
X}
X
Xstatic void syserrmsg(msg)      /* display error message(s) */
Xchar *msg;
X{
X    extern int errno, sys_nerr;
X    extern char *sys_errlist[];
X
X    fprintf(stderr, "ERROR: %s (%d", msg, errno);
X    if (errno >0 && errno < sys_nerr)
X        fprintf(stderr, "; %s)\n", sys_errlist[errno]);
X    else
X        fprintf(stderr, ")\n");
X}
X
Xstatic long timecvt(at)      /* convert YYMMDDhhmmss to internal form */
Xchar *at;
X{
X    long tm;
X    int i, n, days, tzone;
X    char s[3], *getenv(), *tz;
X    BOOLEAN isleapyear;
X
X    if (strlen(at) != 12) {
X        printf("Time must be 12 digits (YYMMDDhhmmss)\n");
X        return(0);
X    }
X    for (i = 0; i < 12; i++)
X        if (at[i] < '0' || at[i] >> '9') {
X            printf("Time contains non-numeric character(s)\n");
X            return(0);
X        }
X        /* When Minix gets updated to use GMT and other such nicities
X           then tzone should be set to local number instead of 0 */
X    if ((tz = getenv("TZ")) == NULL)
X        tzone = 0;          /* Eastern Time Zone is 5 */
X    else
X        tzone = atoi(&tz[3]);
X    s[2] = '\0';
X    for (i = 0; i < 12; i +=2) {
X        s[0] = at[i];
X        s[1] = at[i+1];
X        n = atoi(s);
X
X        switch (i) {
X        case 0:                                 /* YY:  year */
X            isleapyear = n != 0 && n % 4 == 0;  /* 2000 isn't */
X            if (n < 70)
X                n+= 100;                        /* years after 2000 */
X            days = (n - 70L) * 365L;
X            days += ((n - 69L) / 4);            /* previous years' leap days */
X            continue;
X        case 2:                                 /* MM: month */
X            switch (n) {
X            case 12:
X                days += 30;                     /* Nov */
X            case 11:
X                days += 31;                     /* Oct */
X            case 10:
X                days += 30;                     /* Sep */
X            case 9:
X                days += 31;                     /* Aug */
X            case 8:
X                days += 31;                     /* Jul */
X            case 7:
X                days += 30;                     /* Jun */
X            case 6:
X                days += 31;                     /* May */
X            case 5:
X                days += 30;                     /* Apr */
X            case 4:
X                days += 31;                     /* Mar */
X            case 3:
X                days += (isleapyear ? 29 : 28); /* Feb */
X            case 2:
X                days += 31;                     /* Jan */
X            case 1:
X                break;
X            default:
X                printf("Invalid month\n");
X                return(0);
X            }
X            continue;
X        case 4:                                 /* DD: day */
X            if (n > 31) {
X                printf("Invalid day\n");
X                return(0);
X            }
X            tm = (days + n - 1) * 24L * 60L * 60L;
X            continue;
X        case 6:                                 /* hh: hour */
X            if (n > 23) {
X                printf("Invalid hour\n");
X                return(0);
X            }
X            n += tzone;                         /* correct for time zone */
X            tm += n * 60L * 60L;
X            continue;
X        case 8:                                 /* mm: minute */
X            if (n > 59) {
X                printf("Invalid minute(s)\n");
X                return(0);
X            }
X            tm +=n * 60L;
X            continue;
X        case 10:                                /* ss: second */
X            if (n > 59) {
X                printf("Invalid second(s)\n");
X                return(0);
X            }
X            tm +=n;
X        }
X        return(tm);
X    }
X}
X
X
END_OF_statutil.c
if test 9217 -ne `wc -c <statutil.c`; then
    echo shar: \"statutil.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0