saveutil.c revision 8108eb18
18108eb18Smrg/* $Xorg: saveutil.c,v 1.5 2001/02/09 02:06:01 xorgcvs Exp $ */
28108eb18Smrg/******************************************************************************
38108eb18Smrg
48108eb18SmrgCopyright 1993, 1998  The Open Group
58108eb18Smrg
68108eb18SmrgPermission to use, copy, modify, distribute, and sell this software and its
78108eb18Smrgdocumentation for any purpose is hereby granted without fee, provided that
88108eb18Smrgthe above copyright notice appear in all copies and that both that
98108eb18Smrgcopyright notice and this permission notice appear in supporting
108108eb18Smrgdocumentation.
118108eb18Smrg
128108eb18SmrgThe above copyright notice and this permission notice shall be included in
138108eb18Smrgall copies or substantial portions of the Software.
148108eb18Smrg
158108eb18SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168108eb18SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178108eb18SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
188108eb18SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
198108eb18SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
208108eb18SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
218108eb18Smrg
228108eb18SmrgExcept as contained in this notice, the name of The Open Group shall not be
238108eb18Smrgused in advertising or otherwise to promote the sale, use or other dealings
248108eb18Smrgin this Software without prior written authorization from The Open Group.
258108eb18Smrg******************************************************************************/
268108eb18Smrg/* $XFree86: xc/programs/xsm/saveutil.c,v 1.5 2001/01/17 23:46:31 dawes Exp $ */
278108eb18Smrg
288108eb18Smrg#include "xsm.h"
298108eb18Smrg#include "log.h"
308108eb18Smrg#include "saveutil.h"
318108eb18Smrg
328108eb18Smrgchar 		 session_save_file[PATH_MAX];
338108eb18Smrg
348108eb18Smrgextern Widget manualRestartCommands;
358108eb18Smrg
368108eb18Smrg
378108eb18Smrgvoid
388108eb18Smrgset_session_save_file_name(char *session_name)
398108eb18Smrg{
408108eb18Smrg    char *p;
418108eb18Smrg
428108eb18Smrg    p = (char *) getenv ("SM_SAVE_DIR");
438108eb18Smrg    if (!p)
448108eb18Smrg    {
458108eb18Smrg	p = (char *) getenv ("HOME");
468108eb18Smrg	if (!p)
478108eb18Smrg	    p = ".";
488108eb18Smrg    }
498108eb18Smrg
508108eb18Smrg    strcpy (session_save_file, p);
518108eb18Smrg    strcat (session_save_file, "/.XSM-");
528108eb18Smrg    strcat (session_save_file, session_name);
538108eb18Smrg}
548108eb18Smrg
558108eb18Smrg
568108eb18Smrg
578108eb18Smrgint
588108eb18SmrgReadSave(char *session_name, char **sm_id)
598108eb18Smrg{
608108eb18Smrg    char		*buf;
618108eb18Smrg    int			buflen;
628108eb18Smrg    char		*p;
638108eb18Smrg    PendingClient	*c = NULL;
648108eb18Smrg    Prop		*prop = NULL;
658108eb18Smrg    PropValue		*val;
668108eb18Smrg    FILE		*f;
678108eb18Smrg    int			state, i;
688108eb18Smrg    int			version_number;
698108eb18Smrg
708108eb18Smrg    f = fopen(session_save_file, "r");
718108eb18Smrg    if(!f) {
728108eb18Smrg	if (verbose)
738108eb18Smrg	    printf("No session save file.\n");
748108eb18Smrg	*sm_id = NULL;
758108eb18Smrg	return 0;
768108eb18Smrg    }
778108eb18Smrg    if (verbose)
788108eb18Smrg	printf("Reading session save file...\n");
798108eb18Smrg
808108eb18Smrg    buf = NULL;
818108eb18Smrg    buflen = 0;
828108eb18Smrg
838108eb18Smrg    /* Read version # */
848108eb18Smrg    getnextline(&buf, &buflen, f);
858108eb18Smrg    if((p = strchr(buf, '\n'))) *p = '\0';
868108eb18Smrg    version_number = atoi (buf);
878108eb18Smrg    if (version_number > SAVEFILE_VERSION)
888108eb18Smrg    {
898108eb18Smrg	if (verbose)
908108eb18Smrg	    printf("Unsupported version number of session save file.\n");
918108eb18Smrg	*sm_id = NULL;
928108eb18Smrg	if (buf)
938108eb18Smrg	    free (buf);
948108eb18Smrg	return 0;
958108eb18Smrg    }
968108eb18Smrg
978108eb18Smrg    /* Read SM's id */
988108eb18Smrg    getnextline(&buf, &buflen, f);
998108eb18Smrg    if((p = strchr(buf, '\n'))) *p = '\0';
1008108eb18Smrg    *sm_id = XtNewString(buf);
1018108eb18Smrg
1028108eb18Smrg    /* Read number of clients running in the last session */
1038108eb18Smrg    if (version_number >= 2)
1048108eb18Smrg    {
1058108eb18Smrg	getnextline(&buf, &buflen, f);
1068108eb18Smrg	if((p = strchr(buf, '\n'))) *p = '\0';
1078108eb18Smrg	num_clients_in_last_session = atoi (buf);
1088108eb18Smrg    }
1098108eb18Smrg
1108108eb18Smrg    state = 0;
1118108eb18Smrg    while(getnextline(&buf, &buflen, f)) {
1128108eb18Smrg	if((p = strchr(buf, '\n'))) *p = '\0';
1138108eb18Smrg	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
1148108eb18Smrg	if(*p == '#') continue;
1158108eb18Smrg
1168108eb18Smrg	if(!*p)
1178108eb18Smrg	{
1188108eb18Smrg	    if (version_number >= 3 &&
1198108eb18Smrg		ListCount (PendingList) == num_clients_in_last_session)
1208108eb18Smrg	    {
1218108eb18Smrg		state = 5;
1228108eb18Smrg		break;
1238108eb18Smrg	    }
1248108eb18Smrg	    else
1258108eb18Smrg	    {
1268108eb18Smrg		state = 0;
1278108eb18Smrg		continue;
1288108eb18Smrg	    }
1298108eb18Smrg	}
1308108eb18Smrg
1318108eb18Smrg	if(!isspace(buf[0])) {
1328108eb18Smrg	    switch(state) {
1338108eb18Smrg		case 0:
1348108eb18Smrg		    c = (PendingClient *)XtMalloc(sizeof *c);
1358108eb18Smrg		    if(!c) nomem();
1368108eb18Smrg
1378108eb18Smrg		    c->clientId = XtNewString(p);
1388108eb18Smrg		    c->clientHostname = NULL;  /* set in next state */
1398108eb18Smrg
1408108eb18Smrg		    c->props = ListInit();
1418108eb18Smrg		    if(!c->props) nomem();
1428108eb18Smrg
1438108eb18Smrg		    if(!ListAddLast(PendingList, (char *)c)) nomem();
1448108eb18Smrg
1458108eb18Smrg		    state = 1;
1468108eb18Smrg		    break;
1478108eb18Smrg
1488108eb18Smrg		case 1:
1498108eb18Smrg		    c->clientHostname = XtNewString(p);
1508108eb18Smrg                    state = 2;
1518108eb18Smrg                    break;
1528108eb18Smrg
1538108eb18Smrg		case 2:
1548108eb18Smrg		case 4:
1558108eb18Smrg		    prop = (Prop *)XtMalloc(sizeof *prop);
1568108eb18Smrg		    if(!prop) nomem();
1578108eb18Smrg
1588108eb18Smrg		    prop->name = XtNewString(p);
1598108eb18Smrg		    prop->values = ListInit();
1608108eb18Smrg		    if(!prop->values) nomem();
1618108eb18Smrg
1628108eb18Smrg		    prop->type = NULL;
1638108eb18Smrg
1648108eb18Smrg		    if(!ListAddLast(c->props, (char *)prop)) nomem();
1658108eb18Smrg
1668108eb18Smrg		    state = 3;
1678108eb18Smrg		    break;
1688108eb18Smrg
1698108eb18Smrg		case 3:
1708108eb18Smrg		    prop->type = XtNewString(p);
1718108eb18Smrg		    state = 4;
1728108eb18Smrg		    break;
1738108eb18Smrg
1748108eb18Smrg		default:
1758108eb18Smrg		    fprintf(stderr, "state %d\n", state);
1768108eb18Smrg		    fprintf(stderr,
1778108eb18Smrg			    "Corrupt save file line ignored:\n%s\n", buf);
1788108eb18Smrg		    continue;
1798108eb18Smrg	    }
1808108eb18Smrg	} else {
1818108eb18Smrg	    if (state != 4) {
1828108eb18Smrg		fprintf(stderr, "Corrupt save file line ignored:\n%s\n", buf);
1838108eb18Smrg		continue;
1848108eb18Smrg	    }
1858108eb18Smrg	    val = (PropValue *)XtMalloc(sizeof *val);
1868108eb18Smrg	    if(!val) nomem();
1878108eb18Smrg
1888108eb18Smrg	    if (strcmp (prop->type, SmCARD8) == 0)
1898108eb18Smrg	    {
1908108eb18Smrg		val->length = 1;
1918108eb18Smrg		val->value = (XtPointer) XtMalloc (1);
1928108eb18Smrg		*((char *)(val->value)) = atoi (p);
1938108eb18Smrg	    }
1948108eb18Smrg	    else
1958108eb18Smrg	    {
1968108eb18Smrg		val->length = strlen(p);
1978108eb18Smrg		val->value = XtNewString(p);
1988108eb18Smrg	    }
1998108eb18Smrg
2008108eb18Smrg	    if(!ListAddLast(prop->values, (char *)val)) nomem();
2018108eb18Smrg	}
2028108eb18Smrg    }
2038108eb18Smrg
2048108eb18Smrg    /* Read commands for non-session aware clients */
2058108eb18Smrg
2068108eb18Smrg    if (state == 5)
2078108eb18Smrg    {
2088108eb18Smrg	String strbuf;
2098108eb18Smrg	int bufsize = 0;
2108108eb18Smrg
2118108eb18Smrg	getnextline(&buf, &buflen, f);
2128108eb18Smrg	if((p = strchr(buf, '\n'))) *p = '\0';
2138108eb18Smrg	non_session_aware_count = atoi (buf);
2148108eb18Smrg
2158108eb18Smrg	if (non_session_aware_count > 0)
2168108eb18Smrg	{
2178108eb18Smrg	    non_session_aware_clients = (char **) malloc (
2188108eb18Smrg	        non_session_aware_count * sizeof (char *));
2198108eb18Smrg
2208108eb18Smrg	    for (i = 0; i < non_session_aware_count; i++)
2218108eb18Smrg	    {
2228108eb18Smrg		getnextline(&buf, &buflen, f);
2238108eb18Smrg		if((p = strchr(buf, '\n'))) *p = '\0';
2248108eb18Smrg		non_session_aware_clients[i] = (char *) malloc (
2258108eb18Smrg		    strlen (buf) + 2);
2268108eb18Smrg		strcpy (non_session_aware_clients[i], buf);
2278108eb18Smrg		bufsize += (strlen (buf) + 1);
2288108eb18Smrg	    }
2298108eb18Smrg
2308108eb18Smrg	    strbuf = (String) malloc (bufsize + 1);
2318108eb18Smrg	    strbuf[0] = '\0';
2328108eb18Smrg
2338108eb18Smrg	    for (i = 0; i < non_session_aware_count; i++)
2348108eb18Smrg	    {
2358108eb18Smrg		strcat (strbuf, non_session_aware_clients[i]);
2368108eb18Smrg		strcat (strbuf, "\n");
2378108eb18Smrg	    }
2388108eb18Smrg
2398108eb18Smrg	    XtVaSetValues (manualRestartCommands,
2408108eb18Smrg	        XtNstring, strbuf,
2418108eb18Smrg	        NULL);
2428108eb18Smrg
2438108eb18Smrg	    free ((char *) strbuf);
2448108eb18Smrg	}
2458108eb18Smrg    }
2468108eb18Smrg
2478108eb18Smrg    fclose(f);
2488108eb18Smrg
2498108eb18Smrg    if (buf)
2508108eb18Smrg	free (buf);
2518108eb18Smrg
2528108eb18Smrg    return 1;
2538108eb18Smrg}
2548108eb18Smrg
2558108eb18Smrg
2568108eb18Smrg
2578108eb18Smrgstatic void
2588108eb18SmrgSaveClient(FILE *f, ClientRec *client)
2598108eb18Smrg{
2608108eb18Smrg    List *pl;
2618108eb18Smrg
2628108eb18Smrg    fprintf (f, "%s\n", client->clientId);
2638108eb18Smrg    fprintf (f, "%s\n", client->clientHostname);
2648108eb18Smrg
2658108eb18Smrg    for (pl = ListFirst (client->props); pl; pl = ListNext (pl))
2668108eb18Smrg    {
2678108eb18Smrg	Prop *pprop = (Prop *) pl->thing;
2688108eb18Smrg	List *pj, *vl;
2698108eb18Smrg	PropValue *pval;
2708108eb18Smrg
2718108eb18Smrg	fprintf (f, "%s\n", pprop->name);
2728108eb18Smrg	fprintf (f, "%s\n", pprop->type);
2738108eb18Smrg
2748108eb18Smrg	if (strcmp (pprop->type, SmCARD8) == 0)
2758108eb18Smrg	{
2768108eb18Smrg	    char *card8;
2778108eb18Smrg	    int value;
2788108eb18Smrg
2798108eb18Smrg	    vl = ListFirst (pprop->values);
2808108eb18Smrg	    pval = (PropValue *) vl->thing;
2818108eb18Smrg
2828108eb18Smrg	    card8 = pval->value;
2838108eb18Smrg	    value = *card8;
2848108eb18Smrg	    fprintf(f, "\t%d\n", value);
2858108eb18Smrg	}
2868108eb18Smrg	else
2878108eb18Smrg	{
2888108eb18Smrg	    for (pj = ListFirst (pprop->values); pj; pj = ListNext (pj))
2898108eb18Smrg	    {
2908108eb18Smrg		pval = (PropValue *) pj->thing;
2918108eb18Smrg		fprintf (f, "\t%s\n", (char *)pval->value);
2928108eb18Smrg	    }
2938108eb18Smrg	}
2948108eb18Smrg    }
2958108eb18Smrg
2968108eb18Smrg    fprintf (f, "\n");
2978108eb18Smrg}
2988108eb18Smrg
2998108eb18Smrg
3008108eb18Smrg
3018108eb18Smrgvoid
3028108eb18SmrgWriteSave(char *sm_id)
3038108eb18Smrg{
3048108eb18Smrg    ClientRec *client;
3058108eb18Smrg    FILE *f;
3068108eb18Smrg    List *cl;
3078108eb18Smrg    String commands;
3088108eb18Smrg    char *p, *c;
3098108eb18Smrg    int count;
3108108eb18Smrg
3118108eb18Smrg    f = fopen (session_save_file, "w");
3128108eb18Smrg
3138108eb18Smrg    if (!f)
3148108eb18Smrg    {
3158108eb18Smrg	char msg[256];
3168108eb18Smrg
3178108eb18Smrg	sprintf (msg, "%s: Error creating session save file %s",
3188108eb18Smrg	    Argv[0], session_save_file);
3198108eb18Smrg	add_log_text (msg);
3208108eb18Smrg	perror (msg);
3218108eb18Smrg    }
3228108eb18Smrg    else
3238108eb18Smrg    {
3248108eb18Smrg	fprintf (f, "%d\n", SAVEFILE_VERSION);
3258108eb18Smrg	fprintf (f, "%s\n", sm_id);
3268108eb18Smrg
3278108eb18Smrg	count = 0;
3288108eb18Smrg	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
3298108eb18Smrg	{
3308108eb18Smrg	    client = (ClientRec *) cl->thing;
3318108eb18Smrg
3328108eb18Smrg	    if (client->restartHint != SmRestartNever)
3338108eb18Smrg		count++;
3348108eb18Smrg	}
3358108eb18Smrg	count += ListCount (RestartAnywayList);
3368108eb18Smrg
3378108eb18Smrg	fprintf (f, "%d\n", count);
3388108eb18Smrg	if (count == 0)
3398108eb18Smrg	    fprintf (f, "\n");
3408108eb18Smrg
3418108eb18Smrg	for (cl = ListFirst (RunningList); cl; cl = ListNext (cl))
3428108eb18Smrg	{
3438108eb18Smrg	    client = (ClientRec *) cl->thing;
3448108eb18Smrg
3458108eb18Smrg	    if (client->restartHint == SmRestartNever)
3468108eb18Smrg		continue;
3478108eb18Smrg
3488108eb18Smrg	    SaveClient (f, client);
3498108eb18Smrg	}
3508108eb18Smrg
3518108eb18Smrg	for (cl = ListFirst (RestartAnywayList); cl; cl = ListNext (cl))
3528108eb18Smrg	{
3538108eb18Smrg	    client = (ClientRec *) cl->thing;
3548108eb18Smrg
3558108eb18Smrg	    SaveClient (f, client);
3568108eb18Smrg	}
3578108eb18Smrg
3588108eb18Smrg
3598108eb18Smrg	/* Save the non-session aware clients */
3608108eb18Smrg
3618108eb18Smrg	XtVaGetValues (manualRestartCommands,
3628108eb18Smrg	    XtNstring, &commands,
3638108eb18Smrg	    NULL);
3648108eb18Smrg
3658108eb18Smrg	p = c = commands;
3668108eb18Smrg	count = 0;
3678108eb18Smrg
3688108eb18Smrg	while (*p)
3698108eb18Smrg	{
3708108eb18Smrg	    if (*p == '\n')
3718108eb18Smrg	    {
3728108eb18Smrg		if (p != c)
3738108eb18Smrg		    count++;
3748108eb18Smrg		c = p + 1;
3758108eb18Smrg	    }
3768108eb18Smrg	    p++;
3778108eb18Smrg	}
3788108eb18Smrg	if (p != c)
3798108eb18Smrg	    count++;
3808108eb18Smrg
3818108eb18Smrg	fprintf (f, "%d\n", count);
3828108eb18Smrg
3838108eb18Smrg	p = c = commands;
3848108eb18Smrg
3858108eb18Smrg	while (*p)
3868108eb18Smrg	{
3878108eb18Smrg	    if (*p == '\n')
3888108eb18Smrg	    {
3898108eb18Smrg		if (p != c)
3908108eb18Smrg		{
3918108eb18Smrg		    *p = '\0';
3928108eb18Smrg		    fprintf (f, "%s\n", c);
3938108eb18Smrg		    *p = '\n';
3948108eb18Smrg		}
3958108eb18Smrg		c = p + 1;
3968108eb18Smrg	    }
3978108eb18Smrg	    p++;
3988108eb18Smrg	}
3998108eb18Smrg
4008108eb18Smrg	if (p != c)
4018108eb18Smrg	    fprintf (f, "%s\n", c);
4028108eb18Smrg
4038108eb18Smrg	fclose (f);
4048108eb18Smrg    }
4058108eb18Smrg}
4068108eb18Smrg
4078108eb18Smrg
4088108eb18Smrg
4098108eb18SmrgStatus
4108108eb18SmrgDeleteSession(char *session_name)
4118108eb18Smrg{
4128108eb18Smrg    char	*buf;
4138108eb18Smrg    int		buflen;
4148108eb18Smrg    char	*p, *dir;
4158108eb18Smrg    FILE	*f;
4168108eb18Smrg    int		state;
4178108eb18Smrg    int		foundDiscard;
4188108eb18Smrg    char	filename[256];
4198108eb18Smrg    int		version_number;
4208108eb18Smrg
4218108eb18Smrg    dir = (char *) getenv ("SM_SAVE_DIR");
4228108eb18Smrg    if (!dir)
4238108eb18Smrg    {
4248108eb18Smrg	dir = (char *) getenv ("HOME");
4258108eb18Smrg	if (!dir)
4268108eb18Smrg	    dir = ".";
4278108eb18Smrg    }
4288108eb18Smrg
4298108eb18Smrg    sprintf (filename, "%s/.XSM-%s", dir, session_name);
4308108eb18Smrg
4318108eb18Smrg    f = fopen(filename, "r");
4328108eb18Smrg    if(!f) {
4338108eb18Smrg	return (0);
4348108eb18Smrg    }
4358108eb18Smrg
4368108eb18Smrg    buf = NULL;
4378108eb18Smrg    buflen = 0;
4388108eb18Smrg
4398108eb18Smrg    /* Read version # */
4408108eb18Smrg    getnextline(&buf, &buflen, f);
4418108eb18Smrg    if((p = strchr(buf, '\n'))) *p = '\0';
4428108eb18Smrg    version_number = atoi (buf);
4438108eb18Smrg    if (version_number > SAVEFILE_VERSION)
4448108eb18Smrg    {
4458108eb18Smrg	if (verbose)
4468108eb18Smrg	    printf("Can't delete session save file - incompatible version.\n");
4478108eb18Smrg	if (buf)
4488108eb18Smrg	    free (buf);
4498108eb18Smrg	return (0);
4508108eb18Smrg    }
4518108eb18Smrg
4528108eb18Smrg    /* Skip SM's id */
4538108eb18Smrg    getnextline(&buf, &buflen, f);
4548108eb18Smrg
4558108eb18Smrg    /* Skip number of clients running in the last session */
4568108eb18Smrg    if (version_number >= 2)
4578108eb18Smrg	getnextline(&buf, &buflen, f);
4588108eb18Smrg
4598108eb18Smrg    state = 0;
4608108eb18Smrg    foundDiscard = 0;
4618108eb18Smrg    while(getnextline(&buf, &buflen, f)) {
4628108eb18Smrg	if((p = strchr(buf, '\n'))) *p = '\0';
4638108eb18Smrg	for(p = buf; *p && isspace(*p); p++) /* LOOP */;
4648108eb18Smrg	if(*p == '#') continue;
4658108eb18Smrg
4668108eb18Smrg	if(!*p) {
4678108eb18Smrg	    state = 0;
4688108eb18Smrg	    foundDiscard = 0;
4698108eb18Smrg	    continue;
4708108eb18Smrg	}
4718108eb18Smrg
4728108eb18Smrg	if(!isspace(buf[0])) {
4738108eb18Smrg	    switch(state) {
4748108eb18Smrg		case 0:
4758108eb18Smrg		    state = 1;
4768108eb18Smrg		    break;
4778108eb18Smrg
4788108eb18Smrg		case 1:
4798108eb18Smrg                    state = 2;
4808108eb18Smrg                    break;
4818108eb18Smrg
4828108eb18Smrg		case 2:
4838108eb18Smrg		case 4:
4848108eb18Smrg		    if (strcmp (p, SmDiscardCommand) == 0)
4858108eb18Smrg			foundDiscard = 1;
4868108eb18Smrg		    state = 3;
4878108eb18Smrg		    break;
4888108eb18Smrg
4898108eb18Smrg		case 3:
4908108eb18Smrg		    state = 4;
4918108eb18Smrg		    break;
4928108eb18Smrg
4938108eb18Smrg		default:
4948108eb18Smrg		    continue;
4958108eb18Smrg	    }
4968108eb18Smrg	} else {
4978108eb18Smrg	    if (state != 4) {
4988108eb18Smrg		continue;
4998108eb18Smrg	    }
5008108eb18Smrg	    if (foundDiscard)
5018108eb18Smrg	    {
5028108eb18Smrg		execute_system_command (p);	/* Discard Command */
5038108eb18Smrg		foundDiscard = 0;
5048108eb18Smrg	    }
5058108eb18Smrg	}
5068108eb18Smrg    }
5078108eb18Smrg
5088108eb18Smrg    fclose(f);
5098108eb18Smrg
5108108eb18Smrg    if (buf)
5118108eb18Smrg	free (buf);
5128108eb18Smrg
5138108eb18Smrg    return ((unlink (filename) == -1) ? 0 : 1);
5148108eb18Smrg}
5158108eb18Smrg
5168108eb18Smrg
5178108eb18Smrg
5188108eb18SmrgBool
5198108eb18Smrggetnextline(char **pbuf, int *plen, FILE *f)
5208108eb18Smrg{
5218108eb18Smrg	int c;
5228108eb18Smrg	int i;
5238108eb18Smrg
5248108eb18Smrg	i = 0;
5258108eb18Smrg	while(1) {
5268108eb18Smrg	    if(i+2 > *plen) {
5278108eb18Smrg		if(*plen) *plen *= 2;
5288108eb18Smrg		else *plen = BUFSIZ;
5298108eb18Smrg		if(*pbuf) *pbuf = (char *) realloc(*pbuf, *plen + 1);
5308108eb18Smrg		else *pbuf = (char *) malloc(*plen + 1);
5318108eb18Smrg	    }
5328108eb18Smrg	    c = getc(f);
5338108eb18Smrg	    if(c == EOF) break;
5348108eb18Smrg	    (*pbuf)[i++] = c;
5358108eb18Smrg	    if(c == '\n') break;
5368108eb18Smrg	}
5378108eb18Smrg	(*pbuf)[i] = '\0';
5388108eb18Smrg	return i;
5398108eb18Smrg}
540