Merge branch 'master' into rorcz
[girocco.git] / src / can_user_push_http.c
blobf40748a2a7cdb9e10aeb817ab03e0323e59f243c
1 /*
3 can_user_push_http.c -- check project membership in group file
4 Copyright (c) 2014 Kyle J. McKay. All rights reserved.
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 USAGE: can_user_push_http groupname username
24 Exit code 0 for yes, non-zero for no
25 If username is an explicit member of groupname returns yes
26 Wrong number of or bad arguments exits with non-zero
27 Directly reads compiled in GROUP_FILE location
30 #ifndef GROUP_FILE
31 #error GROUP_FILE must be defined to a string which is the full pathname to\
32 the /etc/group format file to read
33 #endif
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
39 #define BADCHARS ":,# \t\r\n"
40 #define MAX_LINE_SIZE 16384 /* includes trailing \n and \0 */
41 #define MAX_NAME_LEN 64
43 static char linebuffer[MAX_LINE_SIZE];
44 static char membersearch[1+MAX_NAME_LEN+1+1];
46 int is_valid_name(const char *name)
48 size_t len;
50 if (!name || !*name)
51 return 0;
52 len = strlen(name);
53 if (len > MAX_NAME_LEN || strcspn(name, BADCHARS) != len)
54 return 0;
55 return 1;
58 int main(int argc, char *argv[])
60 FILE *groupfile;
61 size_t len;
63 if (argc != 3)
64 return EXIT_FAILURE;
65 if (!is_valid_name(argv[1]) || !is_valid_name(argv[2]))
66 return EXIT_FAILURE;
68 len = strlen(argv[2]);
69 membersearch[0] = ',';
70 strncpy(membersearch+1, argv[2], len);
71 membersearch[len+1] = ',';
72 membersearch[len+2] = '\0';
74 groupfile = fopen(GROUP_FILE, "r");
75 if (!groupfile)
76 return EXIT_FAILURE;
77 while (fgets(linebuffer, sizeof(linebuffer)-1, groupfile)) {
78 char *trimmed, *members;
79 size_t len = strlen(linebuffer);
81 if (len >= sizeof(linebuffer) - 2)
82 return EXIT_FAILURE;
83 if (len && linebuffer[len-1] == '\n')
84 linebuffer[--len] = '\0';
85 trimmed = linebuffer + strspn(linebuffer, " \t");
86 if (!*trimmed || *trimmed == '#')
87 continue;
88 if (trimmed != linebuffer)
89 return EXIT_FAILURE;
90 trimmed = strchr(linebuffer, ':');
91 if (!trimmed)
92 return EXIT_FAILURE;
93 *trimmed = '\0';
94 if (strcmp(linebuffer, argv[1]))
95 continue; /* not the group we're looking for */
96 trimmed = strchr(trimmed + 1, ':');
97 if (!trimmed)
98 return EXIT_FAILURE;
99 trimmed = strchr(trimmed + 1, ':');
100 if (!trimmed)
101 return EXIT_FAILURE;
102 *trimmed = ',';
103 members = trimmed;
104 trimmed = strchr(trimmed + 1, ':');
105 if (!trimmed)
106 trimmed = linebuffer + len;
107 *trimmed++ = ',';
108 *trimmed = '\0';
109 return strstr(members, membersearch) ? EXIT_SUCCESS : EXIT_FAILURE;
111 return EXIT_FAILURE;