hostres_scalars.c revision 154249
1154133Sharti/*-
2154133Sharti * Copyright (c) 2005-2006 The FreeBSD Project
3154133Sharti * All rights reserved.
4154133Sharti *
5154133Sharti * Author: Victor Cruceru <soc-victor@freebsd.org>
6154133Sharti *
7154133Sharti * Redistribution of this software and documentation and use in source and
8154133Sharti * binary forms, with or without modification, are permitted provided that
9154133Sharti * the following conditions are met:
10154133Sharti *
11154133Sharti * 1. Redistributions of source code or documentation must retain the above
12154133Sharti *    copyright notice, this list of conditions and the following disclaimer.
13154133Sharti * 2. Redistributions in binary form must reproduce the above copyright
14154133Sharti *    notice, this list of conditions and the following disclaimer in the
15154133Sharti *    documentation and/or other materials provided with the distribution.
16154133Sharti *
17154133Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18154133Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19154133Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20154133Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21154133Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22154133Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23154133Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24154133Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25154133Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26154133Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27154133Sharti * SUCH DAMAGE.
28154133Sharti *
29154133Sharti * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_scalars.c 154249 2006-01-12 07:44:40Z harti $
30154133Sharti */
31154133Sharti
32154133Sharti/*
33154133Sharti * Host Resources MIB scalars implementation for SNMPd.
34154133Sharti */
35154133Sharti
36154133Sharti#include <sys/types.h>
37154133Sharti#include <sys/sysctl.h>
38154133Sharti
39154133Sharti#include <pwd.h>
40154133Sharti#include <stdlib.h>
41154133Sharti#include <stdint.h>
42154133Sharti#include <string.h>
43154133Sharti#include <syslog.h>
44154133Sharti#include <utmp.h>
45154133Sharti
46154133Sharti#include "hostres_snmp.h"
47154133Sharti#include "hostres_oid.h"
48154133Sharti#include "hostres_tree.h"
49154133Sharti
50154133Sharti/* file pointer to keep an open instance of utmp */
51154133Shartistatic FILE *utmp_fp;
52154133Sharti
53154133Sharti/* boot timestamp in centi-seconds */
54154133Shartistatic uint64_t kernel_boot;
55154133Sharti
56154133Sharti/* physical memory size in Kb */
57154133Shartistatic uint64_t phys_mem_size;
58154133Sharti
59154133Sharti/* boot line (malloced) */
60154133Shartistatic u_char *boot_line;
61154133Sharti
62154133Sharti/* maximum number of processes */
63154133Shartistatic uint32_t max_proc;
64154133Sharti
65154133Sharti/**
66154133Sharti * Free all static data
67154133Sharti */
68154133Shartivoid
69154133Shartifini_scalars(void)
70154133Sharti{
71154133Sharti
72154133Sharti	free(boot_line);
73154133Sharti
74154133Sharti	if (utmp_fp != NULL)
75154133Sharti		(void)fclose(utmp_fp);
76154133Sharti}
77154133Sharti
78154133Sharti/**
79154133Sharti * Get system uptime in hundredths of seconds since the epoch
80154133Sharti * Returns 0 in case of an error
81154133Sharti */
82154133Shartistatic int
83154133ShartiOS_getSystemUptime(uint32_t *ut)
84154133Sharti{
85154133Sharti	struct timeval right_now;
86154133Sharti	uint64_t now;
87154133Sharti
88154133Sharti	if (kernel_boot == 0) {
89154133Sharti		/* first time, do the sysctl */
90154133Sharti		struct timeval kernel_boot_timestamp;
91154133Sharti		int mib[2] = { CTL_KERN, KERN_BOOTTIME };
92154133Sharti		size_t len = sizeof(kernel_boot_timestamp);
93154133Sharti
94154133Sharti		if (sysctl(mib, 2, &kernel_boot_timestamp,
95154133Sharti		    &len, NULL, 0) == -1) {
96154133Sharti			syslog(LOG_ERR, "sysctl KERN_BOOTTIME failed: %m");
97154133Sharti			return (SNMP_ERR_GENERR);
98154133Sharti		}
99154133Sharti
100154249Sharti		HRDBG("boot timestamp from kernel: {%lld, %ld}",
101154249Sharti		    (long long)kernel_boot_timestamp.tv_sec,
102154249Sharti		    (long)kernel_boot_timestamp.tv_usec);
103154133Sharti
104154133Sharti		kernel_boot = ((uint64_t)kernel_boot_timestamp.tv_sec * 100) +
105154133Sharti		    (kernel_boot_timestamp.tv_usec / 10000);
106154133Sharti	}
107154133Sharti
108154133Sharti	if (gettimeofday(&right_now, NULL) < 0) {
109154133Sharti		syslog(LOG_ERR, "gettimeofday failed: %m");
110154133Sharti		return (SNMP_ERR_GENERR);
111154133Sharti	}
112154133Sharti	now = ((uint64_t)right_now.tv_sec * 100) + (right_now.tv_usec / 10000);
113154133Sharti
114154133Sharti	if (now - kernel_boot > UINT32_MAX)
115154133Sharti		*ut = UINT32_MAX;
116154133Sharti	else
117154133Sharti		*ut = now - kernel_boot;
118154133Sharti
119154133Sharti	return (SNMP_ERR_NOERROR);
120154133Sharti}
121154133Sharti
122154133Sharti/**
123154133Sharti * Get system local date and time in a foramt suitable for DateAndTime TC:
124154133Sharti *           field  octets  contents                  range
125154133Sharti *           -----  ------  --------                  -----
126154133Sharti *             1      1-2   year*                     0..65536
127154133Sharti *             2       3    month                     1..12
128154133Sharti *             3       4    day                       1..31
129154133Sharti *             4       5    hour                      0..23
130154133Sharti *             5       6    minutes                   0..59
131154133Sharti *             6       7    seconds                   0..60
132154133Sharti *                          (use 60 for leap-second)
133154133Sharti *             7       8    deci-seconds              0..9
134154133Sharti *             8       9    direction from UTC        '+' / '-'
135154133Sharti *             9      10    hours from UTC*           0..13
136154133Sharti *            10      11    minutes from UTC          0..59
137154133Sharti *
138154133Sharti *           * Notes:
139154133Sharti *           - the value of year is in network-byte order
140154133Sharti *           - daylight saving time in New Zealand is +13
141154133Sharti *
142154133Sharti *           For example, Tuesday May 26, 1992 at 1:30:15 PM EDT would be
143154133Sharti *           displayed as:
144154133Sharti *
145154133Sharti *                            1992-5-26,13:30:15.0,-4:0
146154133Sharti *
147154133Sharti * Returns -1 in case of an error or the length of the string (8 or 11)
148154133Sharti * Actually returns always 11 on freebsd
149154133Sharti */
150154133Shartistatic int
151154133ShartiOS_getSystemDate(struct snmp_value *value)
152154133Sharti{
153154133Sharti	u_char s_date_time[11];
154154133Sharti	struct tm tloc_tm;
155154133Sharti	time_t tloc_time_t;
156154133Sharti	struct timeval right_now;
157154133Sharti	int string_len;
158154133Sharti
159154133Sharti	if (gettimeofday(&right_now, NULL) < 0) {
160154133Sharti		syslog(LOG_ERR, "gettimeofday failed: %m");
161154133Sharti		return (SNMP_ERR_GENERR);
162154133Sharti	}
163154133Sharti
164154133Sharti	tloc_time_t = right_now.tv_sec;
165154133Sharti
166154133Sharti	if (localtime_r(&tloc_time_t, &tloc_tm) == NULL) {
167154133Sharti		syslog(LOG_ERR, "localtime_r() failed: %m ");
168154133Sharti		return (SNMP_ERR_GENERR);
169154133Sharti	}
170154133Sharti
171154133Sharti	string_len = make_date_time(s_date_time, &tloc_tm,
172154133Sharti	    right_now.tv_usec / 100000);
173154133Sharti
174154133Sharti	return (string_get(value, s_date_time, string_len));
175154133Sharti}
176154133Sharti
177154133Sharti/**
178154133Sharti * Get kernel boot path. For FreeBSD it seems that no arguments are
179154133Sharti * present. Returns NULL if an error occured. The returned data is a
180154133Sharti * pointer to a global strorage.
181154133Sharti */
182154133Shartiint
183154133ShartiOS_getSystemInitialLoadParameters(u_char **params)
184154133Sharti{
185154133Sharti
186154133Sharti	if (boot_line == NULL) {
187154133Sharti		int mib[2] = { CTL_KERN, KERN_BOOTFILE };
188154133Sharti		char *buf;
189154133Sharti		size_t buf_len = 0;
190154133Sharti
191154133Sharti		/* get the needed buffer len */
192154133Sharti		if (sysctl(mib, 2, NULL, &buf_len, NULL, 0) != 0) {
193154133Sharti			syslog(LOG_ERR,
194154133Sharti			    "sysctl({CTL_KERN,KERN_BOOTFILE}) failed: %m");
195154133Sharti			return (SNMP_ERR_GENERR);
196154133Sharti		}
197154133Sharti
198154133Sharti		if ((buf = malloc(buf_len)) == NULL) {
199154133Sharti			syslog(LOG_ERR, "malloc failed");
200154133Sharti			return (SNMP_ERR_GENERR);
201154133Sharti		}
202154133Sharti                if (sysctl(mib, 2, buf, &buf_len, NULL, 0)) {
203154133Sharti			syslog(LOG_ERR,
204154133Sharti			    "sysctl({CTL_KERN,KERN_BOOTFILE}) failed: %m");
205154133Sharti			free(buf);
206154133Sharti			return (SNMP_ERR_GENERR);
207154133Sharti		}
208154133Sharti
209154133Sharti		boot_line = buf;
210154133Sharti		HRDBG("kernel boot file: %s", boot_line);
211154133Sharti	}
212154133Sharti
213154133Sharti	*params = boot_line;
214154133Sharti	return (SNMP_ERR_NOERROR);
215154133Sharti}
216154133Sharti
217154133Sharti/**
218154133Sharti * Get number of current users which are logged in
219154133Sharti */
220154133Shartistatic int
221154133ShartiOS_getSystemNumUsers(uint32_t *nu)
222154133Sharti{
223154133Sharti	struct utmp utmp;
224154133Sharti	static int first_time = 1;
225154133Sharti
226154133Sharti	if (utmp_fp == NULL) {
227154133Sharti		if (!first_time)
228154133Sharti			return (SNMP_ERR_GENERR);
229154133Sharti		first_time = 0;
230154133Sharti		if ((utmp_fp = fopen(_PATH_UTMP, "r")) == NULL) {
231154133Sharti			syslog(LOG_ERR, "fopen(%s) failed: %m", _PATH_UTMP);
232154133Sharti			return (SNMP_ERR_GENERR);
233154133Sharti		}
234154133Sharti	}
235154133Sharti
236154133Sharti	/* start with the begining of the utmp file */
237154133Sharti	(void)rewind(utmp_fp);
238154133Sharti
239154133Sharti	*nu = 0;
240154133Sharti	while (fread(&utmp, sizeof(utmp), 1, utmp_fp) == 1) {
241154133Sharti		if (utmp.ut_name[0] != '\0' && utmp.ut_line[0] != '\0') {
242154133Sharti			if (getpwnam(utmp.ut_name) == NULL)
243154133Sharti				continue;
244154133Sharti			(*nu)++;
245154133Sharti		}
246154133Sharti	}
247154133Sharti
248154133Sharti	return (SNMP_ERR_NOERROR);
249154133Sharti}
250154133Sharti
251154133Sharti/**
252154133Sharti * Get number of current processes existing into the system
253154133Sharti */
254154133Shartistatic int
255154133ShartiOS_getSystemProcesses(uint32_t *proc_count)
256154133Sharti{
257154133Sharti	int pc;
258154133Sharti
259154133Sharti	if (hr_kd == NULL)
260154133Sharti		return (SNMP_ERR_GENERR);
261154133Sharti
262154133Sharti	if (kvm_getprocs(hr_kd, KERN_PROC_ALL, 0, &pc) == NULL) {
263154133Sharti		syslog(LOG_ERR, "kvm_getprocs failed: %m");
264154133Sharti		return (SNMP_ERR_GENERR);
265154133Sharti	}
266154133Sharti
267154133Sharti	*proc_count = pc;
268154133Sharti	return (SNMP_ERR_NOERROR);
269154133Sharti}
270154133Sharti
271154133Sharti/**
272154133Sharti * Get maximum number of processes allowed on this system
273154133Sharti */
274154133Shartistatic int
275154133ShartiOS_getSystemMaxProcesses(uint32_t *mproc)
276154133Sharti{
277154133Sharti
278154133Sharti	if (max_proc == 0) {
279154133Sharti		int mib[2] = { CTL_KERN, KERN_MAXPROC };
280154133Sharti		int mp;
281154133Sharti		size_t len = sizeof(mp);
282154133Sharti
283154133Sharti		if (sysctl(mib, 2, &mp, &len, NULL, 0) == -1) {
284154133Sharti			syslog(LOG_ERR, "sysctl KERN_MAXPROC failed: %m");
285154133Sharti			return (SNMP_ERR_GENERR);
286154133Sharti		}
287154133Sharti		max_proc = mp;
288154133Sharti	}
289154133Sharti
290154133Sharti	*mproc = max_proc;
291154133Sharti	return (SNMP_ERR_NOERROR);
292154133Sharti}
293154133Sharti
294154133Sharti/*
295154133Sharti * Get the physical memeory size in Kbytes.
296154133Sharti * Returns SNMP error code.
297154133Sharti */
298154133Shartistatic int
299154133ShartiOS_getMemorySize(uint32_t *ms)
300154133Sharti{
301154133Sharti
302154133Sharti	if (phys_mem_size == 0) {
303154133Sharti		int mib[2] = { CTL_HW, HW_PHYSMEM };
304154133Sharti		u_long physmem;
305154133Sharti		size_t len = sizeof(physmem);
306154133Sharti
307154133Sharti		if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) {
308154133Sharti			syslog(LOG_ERR,
309154133Sharti			    "sysctl({ CTL_HW, HW_PHYSMEM }) failed: %m");
310154133Sharti			return (SNMP_ERR_GENERR);
311154133Sharti		}
312154133Sharti
313154133Sharti		phys_mem_size = physmem / 1024;
314154133Sharti	}
315154133Sharti
316154133Sharti	if (phys_mem_size > UINT32_MAX)
317154133Sharti		*ms = UINT32_MAX;
318154133Sharti	else
319154133Sharti		*ms = phys_mem_size;
320154133Sharti        return (SNMP_ERR_NOERROR);
321154133Sharti}
322154133Sharti
323154133Sharti/*
324154133Sharti * Try to use the s_date_time parameter as a DateAndTime TC to fill in
325154133Sharti * the second parameter.
326154133Sharti * Returns 0 on succes and -1 for an error.
327154133Sharti * Bug: time zone info is not used
328154133Sharti */
329154133Shartistatic struct timeval *
330154133ShartiOS_checkSystemDateInput(const u_char *str, u_int len)
331154133Sharti{
332154133Sharti	struct tm tm_to_set;
333154133Sharti	time_t t;
334154133Sharti	struct timeval *tv;
335154133Sharti
336154133Sharti	if (len != 8 && len != 11)
337154133Sharti		return (NULL);
338154133Sharti
339154133Sharti	if (str[2] == 0 || str[2] > 12 ||
340154133Sharti	    str[3] == 0 || str[3] > 31 ||
341154133Sharti	    str[4] > 23 || str[5] > 59 || str[6] > 60 || str[7] > 9)
342154133Sharti		return (NULL);
343154133Sharti
344154133Sharti	tm_to_set.tm_year = ((str[0] << 8) + str[1]) - 1900;
345154133Sharti	tm_to_set.tm_mon = str[2] - 1;
346154133Sharti	tm_to_set.tm_mday = str[3];
347154133Sharti	tm_to_set.tm_hour = str[4];
348154133Sharti	tm_to_set.tm_min = str[5];
349154133Sharti	tm_to_set.tm_sec = str[6];
350154133Sharti	tm_to_set.tm_isdst = 0;
351154133Sharti
352154133Sharti	/* now make UTC from it */
353154133Sharti	if ((t = timegm(&tm_to_set)) == (time_t)-1)
354154133Sharti		return (NULL);
355154133Sharti
356154133Sharti	/* now apply timezone if specified */
357154133Sharti	if (len == 11) {
358154133Sharti		if (str[9] > 13 || str[10] > 59)
359154133Sharti			return (NULL);
360154133Sharti		if (str[8] == '+')
361154133Sharti			t += 3600 * str[9] + 60 * str[10];
362154133Sharti		else
363154133Sharti			t -= 3600 * str[9] + 60 * str[10];
364154133Sharti	}
365154133Sharti
366154133Sharti	if ((tv = malloc(sizeof(*tv))) == NULL)
367154133Sharti		return (NULL);
368154133Sharti
369154133Sharti	tv->tv_sec = t;
370154133Sharti	tv->tv_usec = (int32_t)str[7] * 100000;
371154133Sharti
372154133Sharti	return (tv);
373154133Sharti}
374154133Sharti
375154133Sharti/*
376154133Sharti * Set system date and time. Timezone is not changed
377154133Sharti */
378154133Shartistatic int
379154133ShartiOS_setSystemDate(const struct timeval *timeval_to_set)
380154133Sharti{
381154133Sharti	if (settimeofday(timeval_to_set, NULL) == -1) {
382154133Sharti		syslog(LOG_ERR, "settimeofday failed: %m");
383154133Sharti		return (SNMP_ERR_GENERR);
384154133Sharti        }
385154133Sharti	return (SNMP_ERR_NOERROR);
386154133Sharti}
387154133Sharti
388154133Sharti/*
389154133Sharti * prototype of this function was genrated by gensnmptree tool in header file
390154133Sharti * hostres_tree.h
391154133Sharti * Returns SNMP_ERR_NOERROR on success
392154133Sharti */
393154133Shartiint
394154133Shartiop_hrSystem(struct snmp_context *ctx, struct snmp_value *value,
395154133Sharti    u_int sub, u_int iidx __unused, enum snmp_op curr_op)
396154133Sharti{
397154133Sharti	int err;
398154133Sharti	u_char *str;
399154133Sharti
400154133Sharti	switch (curr_op) {
401154133Sharti
402154133Sharti          case SNMP_OP_GET:
403154133Sharti		switch (value->var.subs[sub - 1]) {
404154133Sharti
405154133Sharti		case LEAF_hrSystemUptime:
406154133Sharti			return (OS_getSystemUptime(&value->v.uint32));
407154133Sharti
408154133Sharti		case LEAF_hrSystemDate:
409154133Sharti			return (OS_getSystemDate(value));
410154133Sharti
411154133Sharti		case LEAF_hrSystemInitialLoadDevice:
412154133Sharti			value->v.uint32 = 0; /* FIXME */
413154133Sharti			return (SNMP_ERR_NOERROR);
414154133Sharti
415154133Sharti		case LEAF_hrSystemInitialLoadParameters:
416154133Sharti			if ((err = OS_getSystemInitialLoadParameters(&str)) !=
417154133Sharti			    SNMP_ERR_NOERROR)
418154133Sharti				return (err);
419154133Sharti			return (string_get(value, str, -1));
420154133Sharti
421154133Sharti		case LEAF_hrSystemNumUsers:
422154133Sharti			return (OS_getSystemNumUsers(&value->v.uint32));
423154133Sharti
424154133Sharti		case LEAF_hrSystemProcesses:
425154133Sharti			return (OS_getSystemProcesses(&value->v.uint32));
426154133Sharti
427154133Sharti		case LEAF_hrSystemMaxProcesses:
428154133Sharti			return (OS_getSystemMaxProcesses(&value->v.uint32));
429154133Sharti		}
430154133Sharti		abort();
431154133Sharti
432154133Sharti	  case SNMP_OP_SET:
433154133Sharti		switch (value->var.subs[sub - 1]) {
434154133Sharti
435154133Sharti		case LEAF_hrSystemDate:
436154133Sharti			if ((ctx->scratch->ptr1 =
437154133Sharti			    OS_checkSystemDateInput(value->v.octetstring.octets,
438154133Sharti			    value->v.octetstring.len)) == NULL)
439154133Sharti				return (SNMP_ERR_WRONG_VALUE);
440154133Sharti
441154133Sharti			return (SNMP_ERR_NOERROR);
442154133Sharti
443154133Sharti		case LEAF_hrSystemInitialLoadDevice:
444154133Sharti		case LEAF_hrSystemInitialLoadParameters:
445154133Sharti			return (SNMP_ERR_NOT_WRITEABLE);
446154133Sharti
447154133Sharti		}
448154133Sharti		abort();
449154133Sharti
450154133Sharti	  case SNMP_OP_ROLLBACK:
451154133Sharti		switch (value->var.subs[sub - 1]) {
452154133Sharti
453154133Sharti		case LEAF_hrSystemDate:
454154133Sharti			free(ctx->scratch->ptr1);
455154133Sharti			return (SNMP_ERR_NOERROR);
456154133Sharti
457154133Sharti		case LEAF_hrSystemInitialLoadDevice:
458154133Sharti		case LEAF_hrSystemInitialLoadParameters:
459154133Sharti			abort();
460154133Sharti		}
461154133Sharti		abort();
462154133Sharti
463154133Sharti	  case SNMP_OP_COMMIT:
464154133Sharti		switch (value->var.subs[sub - 1]) {
465154133Sharti
466154133Sharti		case LEAF_hrSystemDate:
467154133Sharti			(void)OS_setSystemDate(ctx->scratch->ptr1);
468154133Sharti			free(ctx->scratch->ptr1);
469154133Sharti			return (SNMP_ERR_NOERROR);
470154133Sharti
471154133Sharti		case LEAF_hrSystemInitialLoadDevice:
472154133Sharti		case LEAF_hrSystemInitialLoadParameters:
473154133Sharti			abort();
474154133Sharti		}
475154133Sharti		abort();
476154133Sharti
477154133Sharti	  case SNMP_OP_GETNEXT:
478154133Sharti		abort();
479154133Sharti	}
480154133Sharti	abort();
481154133Sharti}
482154133Sharti
483154133Sharti/*
484154133Sharti * prototype of this function was genrated by gensnmptree tool
485154133Sharti * in the header file hostres_tree.h
486154133Sharti * Returns SNMP_ERR_NOERROR on success
487154133Sharti */
488154133Shartiint
489154133Shartiop_hrStorage(struct snmp_context *ctx __unused, struct snmp_value *value,
490154133Sharti    u_int sub, u_int iidx __unused, enum snmp_op curr_op)
491154133Sharti{
492154133Sharti
493154133Sharti	/* only GET is possible */
494154133Sharti	switch (curr_op) {
495154133Sharti
496154133Sharti	case SNMP_OP_GET:
497154133Sharti		switch (value->var.subs[sub - 1]) {
498154133Sharti
499154133Sharti		case LEAF_hrMemorySize:
500154133Sharti			return (OS_getMemorySize(&value->v.uint32));
501154133Sharti		}
502154133Sharti		abort();
503154133Sharti
504154133Sharti	case SNMP_OP_SET:
505154133Sharti		return (SNMP_ERR_NOT_WRITEABLE);
506154133Sharti
507154133Sharti	case SNMP_OP_ROLLBACK:
508154133Sharti	case SNMP_OP_COMMIT:
509154133Sharti	case SNMP_OP_GETNEXT:
510154133Sharti		abort();
511154133Sharti	}
512154133Sharti	abort();
513154133Sharti}
514