prototyp/prototyp.sql
author František Kučera <franta-hg@frantovo.cz>
Tue, 02 Sep 2014 10:25:23 +0200
changeset 13 552252ca87db
parent 12 c6688467d03c
permissions -rw-r--r--
prototyp: align code
     1 -- SQL-UNIX-API (prototype)
     2 -- Copyright © 2014 František Kučera (frantovo.cz)
     3 -- 
     4 -- This program is free software: you can redistribute it and/or modify
     5 -- it under the terms of the GNU General Public License as published by
     6 -- the Free Software Foundation, either version 3 of the License, or
     7 -- (at your option) any later version.
     8 -- 
     9 -- This program is distributed in the hope that it will be useful,
    10 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
    11 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12 -- GNU General Public License for more details.
    13 -- 
    14 -- You should have received a copy of the GNU General Public License
    15 -- along with this program. If not, see <http://www.gnu.org/licenses/>.
    16 
    17 
    18 
    19 -- CREATE SCHEMA unix_sql_api;
    20 
    21 SET search_path TO unix_sql_api;
    22 
    23 
    24 -- fstab: --------------------------------------------------------------------
    25 
    26 DROP VIEW IF EXISTS fstab;
    27 DROP FUNCTION IF EXISTS fstab();
    28 DROP TYPE IF EXISTS unix_sql_api_fstab;
    29 
    30 CREATE TYPE unix_sql_api_fstab AS (
    31 	device         VARCHAR,
    32 	device_type    VARCHAR,
    33 	device_value   VARCHAR,
    34 	mount_point    VARCHAR,
    35 	type           VARCHAR,
    36 	types          VARCHAR[],
    37 	options        VARCHAR[],
    38 	dump           INTEGER,
    39 	pass           INTEGER
    40 );
    41 
    42 CREATE OR REPLACE FUNCTION fstab()
    43 RETURNS SETOF unix_sql_api_fstab AS $$
    44 	use strict;
    45 	use warnings;
    46 	
    47 	open(FSTAB, "<", "/etc/fstab") or die $!;
    48 	
    49 	while (<FSTAB>) {
    50 		if (/^([^\s#]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+(\d+)\s+(\d+)\s*$/) {
    51 			
    52 			my $device_spec_type;
    53 			my $device_spec_value;
    54 			{
    55 				if ($1 =~ /([^=]+)=(.*)/) {
    56 					($device_spec_type, $device_spec_value) = ($1, $2);
    57 				}
    58 			}
    59 			
    60 			return_next({
    61 				device => $1,
    62 				device_type => $device_spec_type,
    63 				device_value => $device_spec_value,
    64 				mount_point => $2,
    65 				type => $3,
    66 				types => [split(",", $3)],
    67 				options => [split(",", $4)],
    68 				dump => $5,
    69 				pass => $6
    70 			});
    71 		}
    72 	}
    73 	
    74 	return undef;
    75 $$ LANGUAGE plperlu;
    76 
    77 CREATE OR REPLACE VIEW fstab AS
    78 	SELECT * FROM fstab()
    79 ;
    80 
    81 
    82 -- user groups: --------------------------------------------------------------
    83 
    84 DROP VIEW IF EXISTS users_groups;
    85 
    86 DROP VIEW IF EXISTS groups;
    87 DROP FUNCTION IF EXISTS groups();
    88 DROP TYPE IF EXISTS unix_sql_api_groups;
    89 
    90 CREATE TYPE unix_sql_api_groups AS (
    91 	id        INTEGER,
    92 	name      VARCHAR,
    93 	members   VARCHAR[]
    94 );
    95 
    96 CREATE OR REPLACE FUNCTION groups()
    97 RETURNS SETOF unix_sql_api_groups STABLE AS $$
    98 	use strict;
    99 	use warnings;
   100 
   101 	use User::grent;
   102 	
   103 	setgrent();
   104 	while (my $group = getgrent()) {
   105 		return_next({
   106 			id => $group->gid,
   107 			name => $group->name,
   108 			members => [@{$group->members}]
   109 		});
   110 	}
   111 	endgrent();
   112 	
   113 	return undef;
   114 $$ LANGUAGE plperlu;
   115 
   116 CREATE OR REPLACE VIEW groups AS
   117 	SELECT * FROM groups()
   118 ;
   119 COMMENT ON COLUMN groups.members IS 'does not contain users who have this group as primary one – see view: users_groups';
   120 
   121 
   122 -- users: --------------------------------------------------------------------
   123 
   124 DROP VIEW IF EXISTS users;
   125 DROP FUNCTION IF EXISTS users();
   126 DROP TYPE IF EXISTS unix_sql_api_users;
   127 
   128 CREATE TYPE unix_sql_api_users AS (
   129 	id           INTEGER,
   130 	gid          INTEGER,
   131 	name         VARCHAR,
   132 	-- comment   VARCHAR,
   133 	gecos        VARCHAR[],
   134 	home         VARCHAR,
   135 	shell        VARCHAR
   136 	-- expire    VARCHAR
   137 );
   138 
   139 CREATE OR REPLACE FUNCTION users()
   140 RETURNS SETOF unix_sql_api_users STABLE AS $$
   141 	use strict;
   142 	use warnings;
   143 	
   144 	use encoding "UTF-8";
   145 	use User::pwent;
   146 	
   147 	setpwent();
   148 	while (my $user = getpwent()) {
   149 		return_next({
   150 			id => $user->uid,
   151 			gid => $user->gid,
   152 			name => $user->name,
   153 			# comment => $user->comment,
   154 			gecos => [split(",", $user->gecos)],
   155 			home => $user->dir,
   156 			shell => $user->shell,
   157 			# expire => $user->expire
   158 		});
   159 	}
   160 	endpwent();
   161 	
   162 	return undef;
   163 $$ LANGUAGE plperlu;
   164 
   165 CREATE OR REPLACE VIEW users AS
   166 	SELECT * FROM users()
   167 ;
   168 
   169 
   170 -- users_groups: -------------------------------------------------------------
   171 
   172 CREATE OR REPLACE VIEW users_groups AS
   173 	SELECT
   174 		u.id     AS uid,
   175 		u.gid    AS gid,
   176 		u.name   AS user,
   177 		g.name   AS group,
   178 		true     AS initial
   179 	FROM users AS u
   180 	JOIN groups AS g ON (u.gid = g.id)
   181 	UNION
   182 	SELECT
   183 		u.id     AS uid,
   184 		g.*,
   185 		false    AS initial
   186 	FROM
   187 		(SELECT
   188 			id                AS gid,
   189 			unnest(members)   AS user,
   190 			name              AS group
   191 		FROM groups) AS g
   192 	JOIN users AS u ON (u.name = g.user)
   193 ;
   194 COMMENT ON COLUMN users_groups.initial IS 'whether this group is the „initial login group“ of given user (the primary group)';
   195 
   196 
   197 -- processes: ----------------------------------------------------------------
   198 
   199 DROP VIEW IF EXISTS processes;
   200 DROP FUNCTION IF EXISTS processes();
   201 DROP TYPE IF EXISTS unix_sql_api_processes;
   202 
   203 CREATE TYPE unix_sql_api_processes AS (
   204 	id            INTEGER,
   205 	owner         INTEGER,
   206 	command       VARCHAR,
   207 	arguments     VARCHAR[],
   208 	working_dir   VARCHAR
   209 );
   210 
   211 CREATE OR REPLACE FUNCTION processes()
   212 RETURNS SETOF unix_sql_api_processes STABLE AS $$
   213 	use strict;
   214 	use warnings;
   215 	
   216 	# There is a library…
   217 	# aptitude install libproc-processtable-perl
   218 	# use Proc::ProcessTable::Process;
   219 	# But there can be found:
   220 	# /* replace all '\0' with spaces (except for the last one */
   221 	# for (cur = cmndline_text; cur < cmndline_text + cmndline_off - 1; cur++) {
   222 	# if (*cur == '\0')
   223 	# 	*cur = ' ';
   224 	# }
   225 	# which wipes boundaries between arguments (that can also contain spaces)
   226 	# So wait until the patch https://rt.cpan.org/Public/Bug/Display.html?id=52442 will be integrated
   227 	
   228 	my $dir = "/proc";
   229 	
   230 	opendir(DIR, $dir) or die $!;
   231 	while (readdir(DIR)) {
   232 		if (/\d+/) {
   233 			my $pid = $_;
   234 			my @process_dir_stat = stat("$dir/$pid") or next;
   235 			my $uid = $process_dir_stat[4];
   236 			
   237 			open(CMDLINE, "<$dir/$pid/cmdline");
   238 			binmode CMDLINE;
   239 			my @cmdline = split("\x00", <CMDLINE>);
   240 			
   241 			return_next({
   242 				id => $pid,
   243 				owner => $uid,
   244 				command => shift(@cmdline),
   245 				arguments => [@cmdline],
   246 				working_dir => readlink("$dir/$pid/cwd")
   247 			});
   248 		}
   249 	}
   250 	
   251 	return undef;
   252 $$ LANGUAGE plperlu;
   253 
   254 CREATE OR REPLACE VIEW processes AS
   255 	SELECT * FROM processes()
   256 ;
   257