17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * Copyright (c) 2000-2001, 2004 Sendmail, Inc. and its suppliers. 37c478bd9Sstevel@tonic-gate * All rights reserved. 47c478bd9Sstevel@tonic-gate * Copyright (c) 1990, 1993 57c478bd9Sstevel@tonic-gate * The Regents of the University of California. All rights reserved. 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate * This code is derived from software contributed to Berkeley by 87c478bd9Sstevel@tonic-gate * Chris Torek. 97c478bd9Sstevel@tonic-gate * 107c478bd9Sstevel@tonic-gate * By using this file, you agree to the terms and conditions set 117c478bd9Sstevel@tonic-gate * forth in the LICENSE file which can be found at the top level of 127c478bd9Sstevel@tonic-gate * the sendmail distribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include <sm/gen.h> 18*49218d4fSjbeck SM_RCSID("@(#)$Id: fpos.c,v 1.39 2005/06/14 23:07:20 ca Exp $") 197c478bd9Sstevel@tonic-gate #include <errno.h> 207c478bd9Sstevel@tonic-gate #include <setjmp.h> 21*49218d4fSjbeck #include <sm/time.h> 227c478bd9Sstevel@tonic-gate #include <sm/heap.h> 237c478bd9Sstevel@tonic-gate #include <sm/signal.h> 247c478bd9Sstevel@tonic-gate #include <sm/clock.h> 257c478bd9Sstevel@tonic-gate #include <sm/io.h> 267c478bd9Sstevel@tonic-gate #include <sm/assert.h> 277c478bd9Sstevel@tonic-gate #include "local.h" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate static void tellalrm __P((int)); 307c478bd9Sstevel@tonic-gate static jmp_buf TellTimeOut; 317c478bd9Sstevel@tonic-gate 327c478bd9Sstevel@tonic-gate /* 337c478bd9Sstevel@tonic-gate ** TELLALRM -- handler when timeout activated for sm_io_tell() 347c478bd9Sstevel@tonic-gate ** 357c478bd9Sstevel@tonic-gate ** Returns flow of control to where setjmp(TellTimeOut) was set. 367c478bd9Sstevel@tonic-gate ** 377c478bd9Sstevel@tonic-gate ** Parameters: 387c478bd9Sstevel@tonic-gate ** sig -- unused 397c478bd9Sstevel@tonic-gate ** 407c478bd9Sstevel@tonic-gate ** Returns: 417c478bd9Sstevel@tonic-gate ** does not return 427c478bd9Sstevel@tonic-gate ** 437c478bd9Sstevel@tonic-gate ** Side Effects: 447c478bd9Sstevel@tonic-gate ** returns flow of control to setjmp(TellTimeOut). 457c478bd9Sstevel@tonic-gate ** 467c478bd9Sstevel@tonic-gate ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 477c478bd9Sstevel@tonic-gate ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 487c478bd9Sstevel@tonic-gate ** DOING. 497c478bd9Sstevel@tonic-gate */ 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* ARGSUSED0 */ 527c478bd9Sstevel@tonic-gate static void 537c478bd9Sstevel@tonic-gate tellalrm(sig) 547c478bd9Sstevel@tonic-gate int sig; 557c478bd9Sstevel@tonic-gate { 567c478bd9Sstevel@tonic-gate longjmp(TellTimeOut, 1); 577c478bd9Sstevel@tonic-gate } 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate /* 607c478bd9Sstevel@tonic-gate ** SM_IO_TELL -- position the file pointer 617c478bd9Sstevel@tonic-gate ** 627c478bd9Sstevel@tonic-gate ** Paramters: 637c478bd9Sstevel@tonic-gate ** fp -- the file pointer to get repositioned 647c478bd9Sstevel@tonic-gate ** timeout -- time to complete the tell (milliseconds) 657c478bd9Sstevel@tonic-gate ** 667c478bd9Sstevel@tonic-gate ** Returns: 677c478bd9Sstevel@tonic-gate ** Success -- the repositioned location. 687c478bd9Sstevel@tonic-gate ** Failure -- -1 (minus 1) and sets errno 697c478bd9Sstevel@tonic-gate */ 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate long 727c478bd9Sstevel@tonic-gate sm_io_tell(fp, timeout) 737c478bd9Sstevel@tonic-gate register SM_FILE_T *fp; 747c478bd9Sstevel@tonic-gate int SM_NONVOLATILE timeout; 757c478bd9Sstevel@tonic-gate { 767c478bd9Sstevel@tonic-gate register off_t pos; 777c478bd9Sstevel@tonic-gate SM_EVENT *evt = NULL; 787c478bd9Sstevel@tonic-gate 797c478bd9Sstevel@tonic-gate SM_REQUIRE_ISA(fp, SmFileMagic); 807c478bd9Sstevel@tonic-gate if (fp->f_seek == NULL) 817c478bd9Sstevel@tonic-gate { 827c478bd9Sstevel@tonic-gate errno = ESPIPE; /* historic practice */ 837c478bd9Sstevel@tonic-gate return -1L; 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate if (timeout == SM_TIME_DEFAULT) 877c478bd9Sstevel@tonic-gate timeout = fp->f_timeout; 887c478bd9Sstevel@tonic-gate if (timeout == SM_TIME_IMMEDIATE) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate /* 917c478bd9Sstevel@tonic-gate ** Filling the buffer will take time and we are wanted to 927c478bd9Sstevel@tonic-gate ** return immediately. So... 937c478bd9Sstevel@tonic-gate */ 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate errno = EAGAIN; 967c478bd9Sstevel@tonic-gate return -1L; 977c478bd9Sstevel@tonic-gate } 987c478bd9Sstevel@tonic-gate 997c478bd9Sstevel@tonic-gate /* 1007c478bd9Sstevel@tonic-gate ** Find offset of underlying I/O object, then adjust byte position 1017c478bd9Sstevel@tonic-gate ** may adjust seek offset on append stream 1027c478bd9Sstevel@tonic-gate */ 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate (void) sm_flush(fp, (int *) &timeout); 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate /* This is where we start the timeout */ 1077c478bd9Sstevel@tonic-gate if (timeout != SM_TIME_FOREVER) 1087c478bd9Sstevel@tonic-gate { 1097c478bd9Sstevel@tonic-gate if (setjmp(TellTimeOut) != 0) 1107c478bd9Sstevel@tonic-gate { 1117c478bd9Sstevel@tonic-gate errno = EAGAIN; 1127c478bd9Sstevel@tonic-gate return -1L; 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate evt = sm_seteventm(timeout, tellalrm, 0); 1167c478bd9Sstevel@tonic-gate } 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate if (fp->f_flags & SMOFF) 1197c478bd9Sstevel@tonic-gate pos = fp->f_lseekoff; 1207c478bd9Sstevel@tonic-gate else 1217c478bd9Sstevel@tonic-gate { 1227c478bd9Sstevel@tonic-gate /* XXX only set the timeout here? */ 1237c478bd9Sstevel@tonic-gate pos = (*fp->f_seek)(fp, (off_t) 0, SM_IO_SEEK_CUR); 1247c478bd9Sstevel@tonic-gate if (pos == -1L) 1257c478bd9Sstevel@tonic-gate goto clean; 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate if (fp->f_flags & SMRD) 1287c478bd9Sstevel@tonic-gate { 1297c478bd9Sstevel@tonic-gate /* 1307c478bd9Sstevel@tonic-gate ** Reading. Any unread characters (including 1317c478bd9Sstevel@tonic-gate ** those from ungetc) cause the position to be 1327c478bd9Sstevel@tonic-gate ** smaller than that in the underlying object. 1337c478bd9Sstevel@tonic-gate */ 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate pos -= fp->f_r; 1367c478bd9Sstevel@tonic-gate if (HASUB(fp)) 1377c478bd9Sstevel@tonic-gate pos -= fp->f_ur; 1387c478bd9Sstevel@tonic-gate } 1397c478bd9Sstevel@tonic-gate else if (fp->f_flags & SMWR && fp->f_p != NULL) 1407c478bd9Sstevel@tonic-gate { 1417c478bd9Sstevel@tonic-gate /* 1427c478bd9Sstevel@tonic-gate ** Writing. Any buffered characters cause the 1437c478bd9Sstevel@tonic-gate ** position to be greater than that in the 1447c478bd9Sstevel@tonic-gate ** underlying object. 1457c478bd9Sstevel@tonic-gate */ 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate pos += fp->f_p - fp->f_bf.smb_base; 1487c478bd9Sstevel@tonic-gate } 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate clean: 1517c478bd9Sstevel@tonic-gate /* We're back. So undo our timeout and handler */ 1527c478bd9Sstevel@tonic-gate if (evt != NULL) 1537c478bd9Sstevel@tonic-gate sm_clrevent(evt); 1547c478bd9Sstevel@tonic-gate return pos; 1557c478bd9Sstevel@tonic-gate } 156