home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume3 / give < prev    next >
Internet Message Format  |  1986-11-30  |  8KB

  1. From: philabs!mcnc!ikonas!!roger
  2. Newsgroups: mod.sources
  3. Subject: give: change owner/group of files
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 3, Issue 44
  7. Submitted by: philabs!mcnc!ikonas!!roger
  8.  
  9.  
  10. [ moderators note:   This program ONLY works properly on System III/V
  11.   where chown(3) allows you to give away ownership of a file.  It might
  12.   be useful to superusers on V7/BSD type systems, perhaps?
  13. ]
  14.  
  15.     Wednesday, 13 November 1985, 5:32 p.m.
  16.  
  17.     Enclosed find the manual page and C source for a program
  18.     to change owner and group id's for one or more files. If
  19.     a named file is a directory, the entire tree beginning
  20.     with (and including) that directory is descended and changed.
  21.  
  22.     Roger L. Cordes, Jr.
  23.     William G. Daniel & Associates
  24.     ...!mcnc!ikonas!dedalus!roger
  25.  
  26. #!/bin/sh
  27. #    This is a shar archive: extract with sh, not csh.
  28. #    This archive contains:
  29. #        give.1
  30. #        give.c
  31. echo x - give.1
  32. cat > give.1 << '!Funky!Stuff!'
  33. .TH GIVE sd
  34. .SH NAME
  35. give \- change owner and group information for one or more files
  36. .SH SYNOPSIS
  37. .B give
  38. .I file...
  39. .B to
  40. .I user
  41. [\c
  42. .I group\c
  43. ]
  44. .SH DESCRIPTION
  45. .B Give
  46. will change ownership and group information for the files specified.
  47. If any of the files is a directory,
  48. .B give
  49. will descend and change the entire directory tree, including the named
  50. directory.
  51. .sp
  52. AS might be expected,
  53. .B give
  54. will only work for the current owner of the named files or root.
  55. .SH DIAGNOSTICS
  56. .B Give
  57. will exit with a descriptive error message if any of the
  58. following occur:
  59. .br
  60. .in +0.5i
  61. access to /etc/passwd (and /etc/group, if applicable) is denied
  62. .br
  63. the named user (group) does not occur in the file
  64. .br
  65. files specified cannot be accessed or modified
  66. .in -0.5i
  67. .SH FILES
  68. /etc/passwd \- user list
  69. .br
  70. /etc/group \- group list
  71. .br
  72. !Funky!Stuff!
  73. echo x - give.c
  74. cat > give.c << '!Funky!Stuff!'
  75. #
  76.  
  77. /****
  78.  ****    Wednesday, 13 November 1985, 1:29 p.m.
  79.  ****    give: change owner and group for one or more files as indicated:
  80.  ****        usage:
  81.  ****            give file... to user [group]
  82.  ****        - may be used succesfully only by current owner or root
  83.  ****        - if file is a directory, descend and change the entire tree
  84.  ****          beginning with (including) the named directory
  85.  ****        compile:
  86.  ****            cc -O -o give give.c
  87.  ****/
  88.  
  89. main(argc,argv)
  90. int    argc;
  91. char    *argv[];
  92. {
  93.     int    i, to, uid = -1, gid = -1;
  94. /*
  95.  *    find end of filename list in argv[] and verify command-line syntax:
  96.  *    must say at least: "give SOMETHING to SOMEBODY"
  97.  */
  98.     for ( i=0; i<argc; i++ )
  99.         if ( !strcmp(argv[i],"to") )
  100.         {
  101.             to = i;
  102.             break;
  103.         }
  104.     if ( (argc<4) || (to<2) || (to==(argc-1)) || (argc<4) )
  105.         exit(printf("usage: %s File... to User [Group]\n",argv[0]));
  106.  
  107. /*
  108.  *    get target integer user id
  109.  */
  110.     if ( (uid=getuser(argv[to+1])) < 0 )
  111.         exit(printf("unknown user: `%s'...\n",argv[to+1]));
  112.  
  113. /*
  114.  *    get target integer group id (if applicable)
  115.  */
  116.     if ( (to<(argc-2)) && ((gid=getgroup(argv[to+2]))<0) )
  117.         exit(printf("unknown group: `%s'...\n",argv[to+2]));
  118.  
  119.     give(&argv[1],(to-1),uid,gid,0);
  120. }
  121.  
  122. #include <stdio.h>
  123.  
  124. /*
  125.  *    getuser: get integer user id: returns -1 if unknown
  126.  */
  127.  
  128. #define    is_digit(C)    ( ((C)>='0') && ((C)<='9') )
  129. char    line[256], *c = (char *)0, *strchr();
  130.  
  131. getuser(name)
  132. char    *name;
  133. {
  134.     FILE    *file;
  135.     int    uid = -1, i, len, strlen(), intname = 1;
  136.  
  137.     len = strlen(name);
  138.  
  139.     for ( i=0; i<len; i++ )
  140.         if ( !is_digit(name[i]) )
  141.             intname = 0;
  142.  
  143.     if ( !(file=fopen("/etc/passwd","r")) )
  144.         exit(printf("cannot read user name list...\n"));
  145.  
  146.     while ( fgets(line,128,file) )
  147.         if ( intname || !strncmp(line,name,len) )
  148.         {
  149.             c = line;
  150.             for ( i=0; i<2; i++ )
  151.                 if ( !(c=strchr((c+1),':')) )
  152.                     if ( intname )
  153.                         break;
  154.                     else
  155.                         goto out;
  156.             if ( !intname || !strncmp((c+1),name,len) )
  157.             {
  158.                 sscanf((c+1),"%d",&uid);
  159.                 break;
  160.             }
  161.         }
  162. out:
  163.     fclose(file);
  164.     return(uid);
  165. }
  166.  
  167. /*
  168.  *    getgroup: get integer group id: returns -1 on error
  169.  */
  170.  
  171. getgroup(name)
  172. char    *name;
  173. {
  174.     int    i, gid = -1, intname = 1, len;
  175.     FILE    *file;
  176.  
  177.     len = strlen(name);
  178.  
  179.     for ( i=0; i<len; i++ )
  180.         if ( !is_digit(name[i]) )
  181.             intname = 0;
  182.  
  183.     if ( !(file=fopen("/etc/group","r")) )
  184.         return(-1);
  185.  
  186.     while ( fgets(line,128,file) )
  187.         if ( intname || !strncmp(line,name,len) )
  188.         {
  189.             if ( !(c=strchr(line,':')) )
  190.                 goto out;
  191.             if ( !(c=strchr((c+1),':')) )
  192.                 goto out;
  193.             if ( intname && strncmp((c+1),name,len) )
  194.                 continue;
  195.             sscanf((c+1),"%d",&gid);
  196.         }
  197. out:
  198.     fclose(file);
  199.     return(gid);
  200. }
  201.  
  202. /*
  203.  *    give: recursively descend a directory structure changing
  204.  *          owner and group ids.
  205.  */
  206.  
  207. #include <sys/types.h>
  208. #include <sys/stat.h>
  209.  
  210. #define    indent()    for ( j=0; j<pass; j++ ) printf("    ")
  211. #define    is_dir()    ((st.st_mode&S_IFDIR)==S_IFDIR)
  212.  
  213. give(names,n,uid,gid,pass)
  214. char    **names;
  215. int    n, uid, gid, pass;
  216. {
  217.     int        i, j, grp, nn = 0, stat();
  218.     struct stat    st;
  219.     char        **next;
  220.  
  221.     for ( i=0; i<n; i++ )
  222.     {
  223.         if ( stat(names[i],&st) < 0 )
  224.         {
  225.             indent();
  226.             printf("`%s': cannot stat...\n",names[i]);
  227.             continue;
  228.         }
  229.  
  230.         if ( gid < 0 )
  231.             grp = st.st_gid;
  232.         else
  233.             grp = gid;
  234.  
  235.         if ( is_dir() )
  236.         {
  237.             indent();
  238.             printf("%s:\n",names[i]);
  239.             if ( chdir(names[i]) < 0 )
  240.             {
  241.                 indent();
  242.                 printf("cannot cd to `%s'...\n",
  243.                     names[i]);
  244.                 continue;
  245.             }
  246.             if ( !(nn=getflist(&next)) )
  247.             {
  248.                 indent();
  249.                 printf("cannot ls `%s'...\n",names[i]);
  250.             }
  251.             else
  252.                 give(next,nn,uid,gid,(pass+1));
  253.  
  254.             if ( chdir("..") < 0 )
  255.             {
  256.                 indent();
  257.                 printf("cannot cd to `..'...\n");
  258.                 exit(3);
  259.             }
  260.         }
  261.  
  262.         if ( chown(names[i],uid,grp) < 0 )
  263.         {
  264.             indent();
  265.             printf("`%s': cannot change...\n",names[i]);
  266.         }
  267.     }
  268. }
  269.  
  270. /*
  271.  *    getflist: get names of files in current working directory
  272.  */
  273.  
  274. #include <sys/dir.h>
  275.  
  276. char    ln[4096], *strcat();
  277.  
  278. getflist(names)
  279. char    ***names;
  280. {
  281.     int    n = 0;
  282.     struct direct    dir;
  283.     FILE    *file;
  284.  
  285.     if ( !(file=fopen(".","r")) )
  286.         return(0);
  287.  
  288.     ln[0] = 0;
  289.  
  290.     while ( fread(&dir,sizeof(struct direct),1,file) )
  291.         if ( !strcmp(dir.d_name,".") || !strcmp(dir.d_name,"..") )
  292.             continue;
  293.         else if ( dir.d_ino )
  294.         {
  295.             strcat(ln,dir.d_name);
  296.             strcat(ln," ");
  297.         }
  298.  
  299.     fclose(file);
  300.  
  301.     n = get_words(ln,names);
  302.  
  303.     return(n);
  304. }
  305.  
  306. /*
  307.  *    get_words: split a character string into individual words
  308.  */
  309.  
  310. #define    is_white(C)    ( ((C)==' ') || ((C)=='\t') )
  311.  
  312. int    get_words(line,wordlist)
  313. char    *line;
  314. char    ***wordlist;
  315. {
  316.     int    i, j, k, nwords = 0, len = 0, longest = 0;
  317.     char    *c, **words, *malloc(), was_white = 0, got_a_word = 0;
  318.  
  319. /*
  320.  *    count words, find longest word
  321.  */
  322.     for ( c=line; *c; c++ )
  323.         if ( is_white(*c) )
  324.         {
  325.             if ( got_a_word && !was_white )
  326.             {
  327.                 if ( len > longest )
  328.                     longest = len;
  329.                 len = 0;
  330.                 nwords++;
  331.             }
  332.             was_white = 1;
  333.         }
  334.         else
  335.         {
  336.             was_white = 0;
  337.             got_a_word = 1;
  338.             len++;
  339.         }
  340.  
  341.     if ( got_a_word && !was_white )
  342.     {
  343.         if ( len > longest )
  344.             longest = len;
  345.         len = 0;
  346.         nwords++;
  347.     }
  348.  
  349.     if ( !nwords )
  350.         return(0);
  351.  
  352. /*
  353.  *    allocate the array of individual words
  354.  */
  355.     if ( !(words=(char **)malloc(nwords*sizeof(char *))) )
  356.     {
  357.         printf("cannot create the word list...\n");
  358.         return(0);
  359.     }
  360.  
  361.     longest++;    /* plus '\0' */
  362.  
  363.     for ( i=0; i<nwords; i++ )
  364.         if ( (words[i]=malloc(longest*sizeof(char))) == NULL )
  365.         {
  366.             printf("cannot allocate an individual word...\n");
  367.             for ( --i; i>=0; i-- )
  368.                 free(words[i]);
  369.             free((char *)words);
  370.             return(0);
  371.         }
  372.  
  373. /*
  374.  *    load the array of individual words
  375.  */
  376.     got_a_word = was_white = j = k = 0;
  377.  
  378.     for ( i=0; line[i]!='\0'; i++ )
  379.         if ( !is_white(line[i]) )
  380.         {
  381.             got_a_word = 1;
  382.             words[j][k] = line[i];
  383.             was_white = 0;
  384.             k++;
  385.         }
  386.         else if ( got_a_word && !was_white )
  387.         {
  388.             words[j][k] = '\0';
  389.             was_white = 1;
  390.             k = 0;
  391.             j++;
  392.         }
  393.  
  394.     if ( got_a_word && !was_white )
  395.         words[j][k] = '\0';
  396.     *wordlist = words;
  397.     return(nwords);
  398. }
  399.  
  400. !Funky!Stuff!
  401.  
  402.  
  403.  
  404.