chmod args

David C Lawrence tale at pawl.rpi.edu
Sat Jun 3 18:13:46 AEST 1989


/*                               -*- Mode: C -*- 
 * permit.c --- change the permission of a file/directory using long form
 * Author          : David C Lawrence          <tale at pawl.rpi.edu>
 * Created On      : Sat Jun  3 03:32:10 1989
 * Last Modified By: David C Lawrence
 * Last Modified On: Sat Jun  3 04:04:08 1989
 * Update Count    : 4
 * Status          : Works just fine for BSD/Sun, maybe SYSV
 */

/*
 * Usage is: permit rwxrwxrwx-pattern file(s)
 *
 * This deals fine with all current permission schemes on Sun/BSD
 * (and mostly on SYSV) systems of which I am aware. I'm not sure
 * how portable it is beyond that.
 *
 * It will accept patterns like rwsr-S--t (bozotic, I realize) without
 * complaint and try to permit accordingly. It even gives you a warning
 * message if you try to set the sticky bit on a file without being
 * the superuser (the regular chmod doesn't).
 *
 * Caveat: I couldn't get to a SYSV machine to try this out; I
 * have a feeling sticky bit stuff might be wrong there, but I am
 * not sure.
 *
 * BUGS: none that I know of at the moment, but it does have really
 *       dorky error messages.
 */

#include <malloc.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

char *pname;                    /* for the programme name (error messages) */
extern int errno;
extern char *sys_errlist[];
extern char *strcpy();

int
decipher_permission(perm_str)
     char *perm_str;

{
  int loop, ch, perm=0;
  
  for (loop=0;loop<9;loop++) {
    ch=perm_str[loop];
    switch (ch) {               /* A switch statement probably isn't the   */
    case 'r':                   /* most efficient, but it only gets called */
      if (loop%3 != 0) {        /* nine times anyway. */
        (void)fprintf(stderr,"%s: 'r'ead permission misplaced\n",pname);
        exit(99);
      }
      perm |= S_IREAD >> ((int)(loop/3))*3;
      break;
    case 'w':
      if (loop%3 != 1) {
        (void)fprintf(stderr,"%s: 'w'rite permission misplaced\n",pname);
        exit(99);
      }
      perm |= S_IWRITE >> ((int)(loop/3))*3;
      break;
    case 'x':
      if (loop%3 != 2) {
        (void)fprintf(stderr,"%s: e'x'ecute permisson misplaced\n",pname);
        exit(99);
      }
      perm |= S_IEXEC >> ((int)(loop/3))*3;
      break;
    case 'S':
    case 's':
    case 'l':                   /* 'l' is SYSV 'S' for setgid (?) */
      if (loop%3 != 2 || loop == 8 || (ch == 'l' && loop != 5)) {
        (void)fprintf(stderr,"%s: 's'et[ug]id permission misplaced\n",pname);
        exit(99);
      }
      perm |= (loop==2 ? S_ISUID : S_ISGID);
      /* add execute permission, too */
      if (ch == 's') perm |= S_IEXEC >> ((int)(loop/3))*3;
      break;
    case 'T':
    case 't':
      if (loop != 8) {
        (void)fprintf(stderr,"%s: s't'icky permission misplaced\n",pname);
        exit(99);
      }
      perm |= S_ISVTX;
      /* add execute permission, too */
      if (ch == 't') perm |= S_IXOTH;
      break;
    case '-':
      break;
    default:
      (void)fprintf(stderr,"%s: unknown permission: %c\n",pname,ch);
      exit(99);
    }
  }
  return(perm);
}

int
main(argc,argv)
     int argc;
     char **argv;

{
  int permission, rc=0;
  struct stat *statbuf;

  if (argc < 3 || strlen(argv[1]) != 9) {
    (void)fprintf(stderr,"Usage: %s 9-char-permission file(s)\n",argv[0]);
    exit(101);
  }
  if((pname=malloc((unsigned)strlen(argv[0])+1))==NULL) {
    (void)fprintf(stderr,"%s: malloc: couldn't allocate space\n",argv[0]);
    exit(102);
  }
  (void)strcpy(pname,argv[0]);
  permission=decipher_permission(argv[1]);
  for(argc--;argc>1;argc--) {
    if (chmod(argv[argc],permission) == -1) {
      (void)fprintf(stderr,"%s: %s: %s\n",pname,argv[argc],sys_errlist[errno]);
      rc++;
    } else {
      (void)stat(argv[argc], statbuf); /* since chmod succeeded, stat should */
      /* could possibly check here for clearing of setgid, too */
      if ((geteuid() != 0) && (permission & S_ISVTX) &&
          !(statbuf->st_mode & S_IFDIR)) {
        (void)fprintf(stderr,
                      "%s: couldn't set sticky bit for %s\n",pname,argv[argc]);
        rc++;
      }
    }
  }
  /* exit with the number of files we were not able to permit as requested */
  exit(rc);
}
--
 (setq mail '("tale at pawl.rpi.edu" "tale at itsgw.rpi.edu" "tale at rpitsmts.bitnet"))



More information about the Alt.sources mailing list